Update pascalgen to match newer output format requirements.
[versaplex.git] / wvdotnet / wvhttpserver.cs
blobe35f32578b1c5b9b3abb36c6396b676f24a63ba8
1 using System;
2 using System.IO;
3 using System.Net.Sockets;
4 using System.Collections.Specialized;
5 using System.Collections.Generic;
6 using System.Data;
7 using System.Web;
8 using Wv;
9 using Wv.Extensions;
11 namespace Wv
13 public class WvHttpSession : Dictionary<string,string>
15 WvLog log = new WvLog("session");
16 WvDbi dbi;
17 string _sessid;
18 public string sessid { get { return _sessid; } }
20 public WvHttpSession(WvDbi dbi, string sessid)
22 this.dbi = dbi;
23 this._sessid = sessid;
24 load();
27 public WvHttpSession(WvDbi dbi)
29 this.dbi = dbi;
30 this._sessid = new_sessid();
31 dbi.execute("insert into Session (ixSession, dtSaved, bData) "
32 + "values (?, ?, ?) ", sessid, DateTime.Now, "");
35 static string new_sessid()
37 return wv.randombytes(20).ToHex();
40 void load()
42 log.print("Loading session '{0}'\n", sessid);
44 // There should actually be only one row
45 foreach (var r in
46 dbi.select("select dtSaved, bData from Session "
47 + "where ixSession=? ",
48 sessid))
50 DateTime dt = r[0];
51 if (dt + TimeSpan.FromSeconds(60*60) >= DateTime.Now)
52 wv.urlsplit(this, r[1]);
56 public void save()
58 List<string> l = new List<string>();
59 foreach (string k in Keys)
60 l.Add(HttpUtility.UrlEncode(k)
61 + "="
62 + HttpUtility.UrlEncode(this[k]));
63 string data = l.join("&");
65 try
67 dbi.execute("insert into Session (ixSession, dtSaved, bData) "
68 + "values (?, ?, ?)",
69 sessid, DateTime.Now, "");
71 catch { }
73 dbi.execute("update Session set bData=?, dtSaved=? "
74 + "where ixSession=?", data, DateTime.Now, sessid);
78 public interface IWvHttpRequest
80 string request_uri { get; }
81 Web.Cgi.Method request_method { get; }
82 string path { get; }
83 string query_string { get; }
84 Dictionary<string,string> headers { get; }
85 // FIXME: This sucks, it should really be a Dictionary<string,string>
86 // to match the headers, but Wv.Cgi already has this as a
87 // NameValueCollection
88 NameValueCollection request { get; }
91 public class WvHttpRequest : IWvHttpRequest
93 public string _request_uri;
94 public string request_uri
96 get { return _request_uri; }
97 set { _request_uri = value; }
100 public Web.Cgi.Method request_method
102 get { return Web.Cgi.Method.Get; }
105 public string path
107 get { return request_uri.Split(new char[] {'?'}, 2)[0]; }
110 public string query_string
114 string[] parts = request_uri.Split(new char[] {'?'}, 2);
115 if (parts.Length >= 2)
116 return parts[1];
117 else
118 return "";
122 public Dictionary<string,string> _headers
123 = new Dictionary<string,string>();
124 public Dictionary<string,string> headers
126 get { return _headers; }
129 public NameValueCollection request
131 get { return null; }
134 public WvHttpRequest() { }
136 public WvHttpRequest(string s)
138 parse_request(wv.fmt("GET {0} HTTP/1.0", s));
141 public void parse_request(string s)
143 string[] parts = s.Split(new char[] {' '}, 3);
144 if (parts.Length < 3)
145 throw new Exception("Not enough words in request!");
146 if (parts[0] != "GET")
147 throw new Exception("Request should start with GET");
148 request_uri = parts[1];
151 public void parse_header(string s)
153 if (s == "") return;
155 string[] parts = s.Split(new char[] {':'}, 2,
156 StringSplitOptions.None);
157 string key = parts[0].ToLower();
158 headers.Remove(key);
159 if (parts.Length < 2)
160 headers.Add(key, "");
161 else
162 headers.Add(key, parts[1].Trim());
166 public class WvHttpCgiRequest : IWvHttpRequest
168 Web.Cgi cgi;
170 public string request_uri
172 get { return cgi.cgivars["REQUEST_URI"]; }
175 public Web.Cgi.Method request_method
177 get { return cgi.method; }
180 public string path
182 get { return cgi.script_name; }
185 public string query_string
187 get { return cgi.query_string; }
190 public Dictionary<string,string> _headers
191 = new Dictionary<string,string>();
192 public Dictionary<string,string> headers
194 get { return _headers; }
197 public NameValueCollection request
199 get { return cgi.request; }
202 public WvHttpCgiRequest()
204 cgi = new Web.Cgi();
206 foreach (string key in cgi.cgivars)
208 if (key.StartsWith("HTTP_"))
210 // Turn "HTTP_HEADER_NAME" into "header-name"
211 headers.Add(
212 key.Substring(5).ToLower().Replace('_', '-'),
213 cgi.cgivars[key]);
219 public class WvHttpServer
221 TcpListener server;
222 WvLog log = new WvLog("HTTP Server", WvLog.L.Info);
224 public delegate void Responder(WvHttpRequest req, Stream s);
225 Responder responder;
227 public WvHttpServer(int port, Responder responder)
229 this.responder = responder;
230 log.print("World's dumbest http server initializing. (and how!)\n");
231 log.print("Trying port {0}.\n", port);
232 server = new TcpListener(port);
233 server.Start();
234 log.print("Listening on {0}\n", server.LocalEndpoint);
237 public void runonce()
239 TcpClient client = server.AcceptTcpClient();
240 log.print("Incoming connection.\n");
242 NetworkStream stream = client.GetStream();
243 StreamReader r = new StreamReader(stream);
245 WvHttpRequest req = new WvHttpRequest();
246 string s = r.ReadLine();
247 log.print("Got request line: '{0}'\n", s);
248 req.parse_request(s);
249 log.print("Path is: '{0}'\n", req.request_uri);
252 s = r.ReadLine();
253 log.print("Got header line: '{0}'\n", s);
254 req.parse_header(s);
256 while (s != "");
258 responder(req, stream);
260 log.print("Closing connection.\n");
261 client.Close();