1: #line 15 "./lpsrc/flx_faio_tools.pak"
2:
3:
4:
5: include "flx_faio_posix";
6:
7:
8:
9:
10: include "flx_socket";
11: open Flx_socket;
12:
13: include "flx_stream";
14: open Flx_stream;
15:
16: open TerminalIByteStream[fd_t];
17: open TerminalIOByteStream[socket_t];
18:
19: macro fun dbg(x) = { fprint (cerr,x); };
20:
21:
22:
23:
24:
25:
26:
27: open TerminalIByteStream[socket_t];
28:
29: header = """
30: string
31: getline_to_url(const string& get)
32: {
33: // chomp off "GET " (should check it)
34: if(get.length() < 4) return "";
35:
36: std::size_t pos = get.substr(4).find(' ');
37:
38: if(pos == string::npos) return "";
39:
40: return get.substr(4, pos);
41: }
42:
43: // split url into base and file name http://foo.com/file.html
44: // -> http://foo.com + file.html. failure returns nothing.
45: bool
46: split_url(const string& inurl, string& base, string& file)
47: {
48: // munch leading http:// if present
49: string url;
50: if(inurl.length() >= 7 && inurl.substr(0, 7) == "http://")
51: url = inurl.substr(7);
52: else
53: url = inurl;
54:
55: std::size_t pos = url.find('/');
56:
57: if(string::npos == pos) return false; // all bad
58:
59: base = url.substr(0, pos);
60: file = url.substr(pos+1);
61: return true; // all good
62: }
63:
64: bool
65: split_getline(const string& get, string& base, string& file)
66: {
67: return split_url(getline_to_url(get), base, file);
68: }
69: """;
70:
71: proc parse_get_line: string*lvalue[bool]*lvalue[string]*lvalue[string]
72: = '$2 = split_getline($1, $3, $4);';
73:
74: fun substr: string*int -> string = "$1.substr($2)";
75:
76:
77:
78:
79: val html_header = """HTTP/0.9 200 OK\r
80: Date: Tue, 25 Apr 2006 00:16:12 GMT\r
81: Server: felix web server\r
82: Last-Modified: Wed, 01 Feb 2006 18:51:37 GMT\r
83: Connection: close\r
84: Content-Type: text/html\r
85: \r
86: """;
87:
88: val gif_header = """HTTP/0.9 200 OK\r
89: Date: Sun, 30 Apr 2006 07:14:50 GMT\r
90: Server: felix web server\r
91: Last-Modified: Sun, 28 Nov 2004 18:59:31 GMT\r
92: Connection: close\r
93: Content-Type: image/gif\r
94: \r
95: """;
96:
97: val css_header = """HTTP/0.9 200 OK\r
98: Date: Sun, 30 Apr 2006 07:14:50 GMT\r
99: Server: felix web server\r
100: Last-Modified: Sun, 28 Nov 2004 18:59:31 GMT\r
101: Connection: close\r
102: Content-Type: text/css\r
103: \r
104: """;
105:
106:
107: val notfound_header = """HTTP/0.9 404 Not Found\r
108: Date: Sun, 30 Apr 2006 07:14:50 GMT\r
109: Server: felix web server\r
110: Last-Modified: Sun, 28 Nov 2004 18:59:31 GMT\r
111: Connection: close\r
112: Content-Type: text/html\r
113: \r
114: PAGE NOT FOUND:
115: """;
116:
117:
118: proc substitute(s: string, a: char, b: char, res: &string)
119: {
120: var s2: string;
121: var slen = len s;
122: var i: int;
123:
124: for_each{i=0;}{i<slen}{i++;}
125: {
126: if s.[i] == a then
127: { s2 += b; } else
128: { s2 += s.[i]; } endif;
129:
130: };
131:
132: *res = s2;
133: }
134:
135: proc serve_file(infname: string, s: socket_t)
136: {
137: var fname: string;
138:
139:
140:
141:
142: if "" == infname then { fname = "index.html"; }else{ fname = infname;}endif;
143:
144:
145:
146: print "serve file: "; print fname; endl;
147:
148:
149:
150:
151:
152: var suffix: string;
153: var dotpos = stl_rfind(fname, char ".");
154:
155: if stl_npos != dotpos then { suffix = substr(fname, dotpos+1); }
156: else {} endif;
157:
158: print "suffix is "; print suffix; endl;
159:
160: #if WIN32
161: var wname: string;
162:
163:
164: substitute(fname, char '/', char '\\', &wname);
165: print "mapped "; print fname; print " -> "; print wname; endl;
166:
167:
168: var wf: WFILE <- OpenFile(wname);
169:
170: if wf == INVALID_HANDLE_VALUE then
171: {
172: print "BUGGER: OpenFile failed: "; print (GetLastError()); endl;
173: } else {
174: print "opened "; print wname; endl;
175:
176:
177: if("gif" == suffix) then { write_string(s, gif_header); }
178: elif("css" == suffix) then { write_string(s, css_header); }
179: else { write_string(s, html_header); } endif;
180:
181: print "Transmitting file!\n";
182: TransmitFile(s, wf);
183:
184:
185: CloseFile(wf);
186: } endif;
187: #elif POSIX
188:
189:
190:
191: var fd = Faio_posix::ropen(fname);
192:
193: if Faio_posix::invalid fd then
194: {
195: print "BUGGER, posix open failed\n";
196: write_string(s, notfound_header);
197: write_string(s, fname+"\r\n\n");
198: } else {
199: print "got fd="; print$ str fd; endl;
200:
201:
202:
203: if("gif" == suffix) then { write_string(s, gif_header); }
204: elif("css" == suffix) then { write_string(s, css_header); }
205: else { write_string(s, html_header); } endif;
206:
207: var from_strm: Faio_posix::fd_t = fd;
208: var to_strm: socket_t = s;
209: Flx_stream::cat(from_strm, to_strm);
210:
211: dbg q"close file $from_strm\n";
212: iclose(from_strm);
213: } endif;
214:
215:
216:
217:
218:
219:
220: #endif
221: }
222:
223: val webby_port = 1234;
224:
225: print "FLX WEB!!! listening on port "; print webby_port; endl;
226:
227:
228: var p = webby_port;
229: var listener: socket_t;
230: mk_listener(&listener, &p, 10);
231:
232: proc forever {
233: var s: socket_t;
234: accept(listener, &s);
235: dbg q"got connection $s\n";
236:
237:
238: print "spawning fthread to handle connection\n";
239: spawn_fthread {
240:
241:
242: var line: string;
243: get_line(s, &line);
244:
245: val poo =
246: if "GET " == line.[0 to 4] then line.[4 to ] else "" endif;
247: print ("poo="poo); endl;
248:
249:
250: print "got line: "; print line; endl;
251:
252:
253:
254: var succ: bool;
255: var base: string;
256: var file: string;
257:
258: parse_get_line(line, succ, base, file);
259:
260:
261: if succ then {
262: print "well formed get...\n";
263: print "base="; print base; endl;
264: print "file="; print file; endl;
265:
266: serve_file(file, s);
267: } else {
268: print "BAD get line: "; print line; endl;
269: } endif;
270:
271:
272:
273:
274: Faio_posix::shutdown(s, 1);
275: cat(s, DEVNULL);
276:
277: fprint$ cerr,q"closing socket $s\n";
278: ioclose(s);
279:
280: };
281: collect();
282: forever;
283: };
284: forever;
285:
286: iclose(listener);
287: