3 * Copyright (C)2007-2008 Versabanq Innovations Inc. and contributors.
4 * See the included file named LICENSE for license information.
8 using System
.Net
.Sockets
;
9 using System
.Collections
.Specialized
;
10 using System
.Collections
.Generic
;
18 public class WvHttpSession
: Dictionary
<string,string>
20 WvLog log
= new WvLog("session");
23 public string sessid { get { return _sessid; }
}
25 public WvHttpSession(WvDbi dbi
, string sessid
)
28 this._sessid
= sessid
;
32 public WvHttpSession(WvDbi dbi
)
35 this._sessid
= new_sessid();
36 dbi
.execute("insert into Session (ixSession, dtSaved, bData) "
37 + "values (?, ?, ?) ", sessid
, DateTime
.Now
, "");
40 static string new_sessid()
42 return wv
.randombytes(20).ToHex();
47 log
.print("Loading session '{0}'\n", sessid
);
49 // There should actually be only one row
51 dbi
.select("select dtSaved, bData from Session "
52 + "where ixSession=? ",
56 if (dt
+ TimeSpan
.FromSeconds(60*60) >= DateTime
.Now
)
57 wv
.urlsplit(this, r
[1]);
63 List
<string> l
= new List
<string>();
64 foreach (string k
in Keys
)
65 l
.Add(HttpUtility
.UrlEncode(k
)
67 + HttpUtility
.UrlEncode(this[k
]));
68 string data
= l
.join("&");
72 dbi
.execute("insert into Session (ixSession, dtSaved, bData) "
74 sessid
, DateTime
.Now
, "");
78 dbi
.execute("update Session set bData=?, dtSaved=? "
79 + "where ixSession=?", data
, DateTime
.Now
, sessid
);
83 public interface IWvHttpRequest
85 string request_uri { get; }
86 Web
.Cgi
.Method request_method { get; }
88 string query_string { get; }
89 Dictionary
<string,string> headers { get; }
90 // FIXME: This sucks, it should really be a Dictionary<string,string>
91 // to match the headers, but Wv.Cgi already has this as a
92 // NameValueCollection
93 NameValueCollection request { get; }
96 public class WvHttpRequest
: IWvHttpRequest
98 public string _request_uri
;
99 public string request_uri
101 get { return _request_uri; }
102 set { _request_uri = value; }
105 public Web
.Cgi
.Method request_method
107 get { return Web.Cgi.Method.Get; }
112 get { return request_uri.Split(new char[] {'?'}
, 2)[0]; }
115 public string query_string
119 string[] parts
= request_uri
.Split(new char[] {'?'}
, 2);
120 if (parts
.Length
>= 2)
127 public Dictionary
<string,string> _headers
128 = new Dictionary
<string,string>();
129 public Dictionary
<string,string> headers
131 get { return _headers; }
134 public NameValueCollection request
139 public WvHttpRequest() { }
141 public WvHttpRequest(string s
)
143 parse_request(wv
.fmt("GET {0} HTTP/1.0", s
));
146 public void parse_request(string s
)
148 string[] parts
= s
.Split(new char[] {' '}
, 3);
149 if (parts
.Length
< 3)
150 throw new Exception("Not enough words in request!");
151 if (parts
[0] != "GET")
152 throw new Exception("Request should start with GET");
153 request_uri
= parts
[1];
156 public void parse_header(string s
)
160 string[] parts
= s
.Split(new char[] {':'}
, 2,
161 StringSplitOptions
.None
);
162 string key
= parts
[0].ToLower();
164 if (parts
.Length
< 2)
165 headers
.Add(key
, "");
167 headers
.Add(key
, parts
[1].Trim());
171 public class WvHttpCgiRequest
: IWvHttpRequest
175 public string request_uri
177 get { return cgi.cgivars["REQUEST_URI"]; }
180 public Web
.Cgi
.Method request_method
182 get { return cgi.method; }
187 get { return cgi.script_name; }
190 public string query_string
192 get { return cgi.query_string; }
195 public Dictionary
<string,string> _headers
196 = new Dictionary
<string,string>();
197 public Dictionary
<string,string> headers
199 get { return _headers; }
202 public NameValueCollection request
204 get { return cgi.request; }
207 public WvHttpCgiRequest()
211 foreach (string key
in cgi
.cgivars
)
213 if (key
.StartsWith("HTTP_"))
215 // Turn "HTTP_HEADER_NAME" into "header-name"
217 key
.Substring(5).ToLower().Replace('_', '-'),
224 public class WvHttpServer
227 WvLog log
= new WvLog("HTTP Server", WvLog
.L
.Info
);
229 public delegate void Responder(WvHttpRequest req
, Stream s
);
232 public WvHttpServer(int port
, Responder responder
)
234 this.responder
= responder
;
235 log
.print("World's dumbest http server initializing. (and how!)\n");
236 log
.print("Trying port {0}.\n", port
);
237 server
= new TcpListener(port
);
239 log
.print("Listening on {0}\n", server
.LocalEndpoint
);
242 public void runonce()
244 TcpClient client
= server
.AcceptTcpClient();
245 log
.print("Incoming connection.\n");
247 NetworkStream stream
= client
.GetStream();
248 StreamReader r
= new StreamReader(stream
);
250 WvHttpRequest req
= new WvHttpRequest();
251 string s
= r
.ReadLine();
252 log
.print("Got request line: '{0}'\n", s
);
253 req
.parse_request(s
);
254 log
.print("Path is: '{0}'\n", req
.request_uri
);
258 log
.print("Got header line: '{0}'\n", s
);
263 responder(req
, stream
);
265 log
.print("Closing connection.\n");