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 = """
80: HTTP/0.9 200 OK\r
81: Date: Tue, 25 Apr 2006 00:16:12 GMT\r
82: Server: felix web server\r
83: Last-Modified: Wed, 01 Feb 2006 18:51:37 GMT\r
84: Connection: close\r
85: Content-Type: text/html\r
86: \r
87: """;
88:
89: val gif_header = """
90: HTTP/0.9 200 OK\r
91: Date: Sun, 30 Apr 2006 07:14:50 GMT\r
92: Server: felix web server\r
93: Last-Modified: Sun, 28 Nov 2004 18:59:31 GMT\r
94: Connection: close\r
95: Content-Type: image/gif\r
96: \r
97: """;
98:
99: val css_header = """
100: HTTP/0.9 200 OK\r
101: Date: Sun, 30 Apr 2006 07:14:50 GMT\r
102: Server: felix web server\r
103: Last-Modified: Sun, 28 Nov 2004 18:59:31 GMT\r
104: Connection: close\r
105: Content-Type: text/css\r
106: \r
107: """;
108:
109:
110: val notfound_header = """
111: HTTP/0.9 404 Not Found\r
112: Date: Sun, 30 Apr 2006 07:14:50 GMT\r
113: Server: felix web server\r
114: Last-Modified: Sun, 28 Nov 2004 18:59:31 GMT\r
115: Connection: close\r
116: Content-Type: text/html\r
117: \r
118: PAGE NOT FOUND:
119: """;
120:
121:
122: proc substitute(s: string, a: char, b: char, res: &string)
123: {
124: var s2: string;
125: var slen = len s;
126: var i: int;
127:
128: for_each{i=0;}{i<slen}{i++;}
129: {
130: if s.[i] == a then
131: { s2 += b; } else
132: { s2 += s.[i]; } endif;
133:
134: };
135:
136: *res = s2;
137: }
138:
139: proc serve_file(infname: string, s: socket_t)
140: {
141: var fname: string;
142:
143:
144:
145:
146: if "" == infname then { fname = "index.html"; }else{ fname = infname;}endif;
147:
148:
149:
150: print "serve file: "; print fname; endl;
151:
152:
153:
154:
155:
156: var suffix: string;
157: var dotpos = stl_rfind(fname, char ".");
158:
159: if stl_npos != dotpos then { suffix = substr(fname, dotpos+1); }
160: else {} endif;
161:
162: print "suffix is "; print suffix; endl;
163:
164: #if WIN32
165: var wname: string;
166:
167:
168: substitute(fname, char '/', char '\\', &wname);
169: print "mapped "; print fname; print " -> "; print wname; endl;
170:
171:
172: var wf: WFILE <- OpenFile(wname);
173:
174: if wf == INVALID_HANDLE_VALUE then
175: {
176: print "BUGGER: OpenFile failed: "; print (GetLastError()); endl;
177: } else {
178: print "opened "; print wname; endl;
179:
180:
181: if("gif" == suffix) then { write_string(s, gif_header); }
182: elif("css" == suffix) then { write_string(s, css_header); }
183: else { write_string(s, html_header); } endif;
184:
185: print "Transmitting file!\n";
186: TransmitFile(s, wf);
187:
188:
189: CloseFile(wf);
190: } endif;
191: #elif POSIX
192:
193:
194:
195: var fd = Faio_posix::ropen(fname);
196:
197: if Faio_posix::invalid fd then
198: {
199: print "BUGGER, posix open failed\n";
200: write_string(s, notfound_header);
201: write_string(s, fname+"\r\n\n");
202: } else {
203: print "got fd="; print$ str fd; endl;
204:
205:
206:
207: if("gif" == suffix) then { write_string(s, gif_header); }
208: elif("css" == suffix) then { write_string(s, css_header); }
209: else { write_string(s, html_header); } endif;
210:
211: var from_strm: Faio_posix::fd_t = fd;
212: var to_strm: socket_t = s;
213: Flx_stream::cat(from_strm, to_strm);
214:
215: dbg q"close file $from_strm\n";
216: iclose(from_strm);
217: } endif;
218:
219:
220:
221:
222:
223:
224: #endif
225: }
226:
227: val webby_port = 1234;
228:
229: print "FLX WEB!!! listening on port "; print webby_port; endl;
230:
231:
232: var p = webby_port;
233: var listener: socket_t;
234: mk_listener(&listener, &p, 10);
235:
236: proc forever {
237: var s: socket_t;
238: accept(listener, &s);
239: dbg q"got connection $s\n";
240:
241:
242: print "spawning fthread to handle connection\n";
243: spawn_fthread {
244:
245:
246: var line: string;
247: get_line(s, &line);
248:
249: val poo =
250: if "GET " == line.[0 to 4] then line.[4 to ] else "" endif;
251: print ("poo="poo); endl;
252:
253:
254: print "got line: "; print line; endl;
255:
256:
257:
258: var succ: bool;
259: var base: string;
260: var file: string;
261:
262: parse_get_line(line, succ, base, file);
263:
264:
265: if succ then {
266: print "well formed get...\n";
267: print "base="; print base; endl;
268: print "file="; print file; endl;
269:
270: serve_file(file, s);
271: } else {
272: print "BAD get line: "; print line; endl;
273: } endif;
274:
275: fprint$ cerr,q"closing socket $s\n";
276: ioclose(s);
277:
278: };
279: collect();
280: forever;
281: };
282: forever;
283:
284: iclose(listener);
285: