annotate Net/HTTP.cs @ 0:3ab940a0c7a0

Initial commit
author Ivo Smits <Ivo@UCIS.nl>
date Tue, 11 Sep 2012 16:28:53 +0200
parents
children 0cc7be03775f
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1 ???using System;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
2 using System.Collections.Generic;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
3 using System.IO;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
4 using System.Text;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
5 using System.Threading;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
6
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
7 namespace UCIS.Net.HTTP {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
8 public class HTTPServer : TCPServer.IModule {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
9 public Dictionary<string, HTTPContent> Content = new Dictionary<string, HTTPContent>(StringComparer.InvariantCultureIgnoreCase);
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
10 public HTTPContent DefaultContent = null;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
11
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
12 public bool Accept(TCPStream Stream) {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
13 StreamReader StreamReader = new StreamReader(Stream, Encoding.ASCII);
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
14 String Line = StreamReader.ReadLine();
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
15 String[] Request = Line.Split(' ');
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
16
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
17 //Console.WriteLine("HTTP.Server.Accept Request: " + Line);
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
18
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
19 if (Request == null || Request.Length < 2 || Request[0] != "GET" || Request[1][0] != '/') {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
20 //Console.WriteLine("HTTP.Server.Start Bad request");
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
21 SendError(Stream, 400);
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
22 return true;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
23 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
24
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
25 Request = Request[1].Split(new Char[] { '?' }, 2);
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
26 HTTPContent content;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
27 if (Content.TryGetValue(Request[0], out content)) {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
28 } else if (DefaultContent != null) {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
29 content = DefaultContent;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
30 } else {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
31 SendError(Stream, 404);
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
32 return true;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
33 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
34 HTTPContext Context = new HTTPContext();
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
35 Context.Stream = Stream;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
36 Context.Request = new HTTPRequest();
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
37 Context.Request.Method = Method.GET;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
38 Context.Request.Path = Request[0];
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
39 if (Request.Length == 2) {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
40 Context.Request.Query = Request[1];
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
41 } else {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
42 Context.Request.Query = null;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
43 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
44 HTTPContent.Result ServeResult = content.Serve(Context);
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
45
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
46 if (ServeResult == HTTPContent.Result.OK_KEEPALIVE) {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
47 return false;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
48 } else if (!(ServeResult == HTTPContent.Result.OK_CLOSE)) {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
49 SendError(Stream, (int)ServeResult);
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
50 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
51 return true;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
52 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
53
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
54 public static void SendError(Stream Stream, int ErrorCode) {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
55 string ErrorText = null;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
56 switch (ErrorCode) {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
57 case 400:
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
58 ErrorText = "The request could not be understood by the server due to malformed syntax.";
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
59 break;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
60 case 404:
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
61 ErrorText = "The requested file can not be found.";
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
62 break;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
63 default:
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
64 ErrorText = "Unknown error code: " + ErrorCode.ToString() + ".";
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
65 break;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
66 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
67 SendHeader(Stream, ErrorCode, "text/plain", ErrorText.Length);
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
68 WriteLine(Stream, ErrorText);
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
69 Thread.Sleep(100);
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
70 return;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
71 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
72
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
73 public static void SendHeader(Stream Stream, int ResultCode, string ContentType) {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
74 SendHeader(Stream, ResultCode, ContentType, -1);
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
75 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
76 public static void SendHeader(Stream Stream, int ResultCode, string ContentType, int ContentLength) {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
77 //ResultCode = 200, ContentType = null, ContentLength = -1
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
78 string ResultString;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
79 switch (ResultCode) {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
80 case 200: ResultString = "OK"; break;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
81 case 400: ResultString = "Bad Request"; break;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
82 case 404: ResultString = "Not found"; break;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
83 default: ResultString = "Unknown"; break;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
84 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
85 WriteLine(Stream, "HTTP/1.1 " + ResultCode.ToString() + " " + ResultString);
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
86 WriteLine(Stream, "Expires: Mon, 26 Jul 1990 05:00:00 GMT");
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
87 WriteLine(Stream, "Cache-Control: no-store, no-cache, must-revalidate");
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
88 WriteLine(Stream, "Cache-Control: post-check=0, pre-check=0");
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
89 WriteLine(Stream, "Pragma: no-cache");
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
90 WriteLine(Stream, "Server: UCIS Simple Webserver");
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
91 WriteLine(Stream, "Connection: Close");
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
92 if ((ContentType != null)) WriteLine(Stream, "Content-Type: " + ContentType);
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
93 if (ContentLength != -1) WriteLine(Stream, "Content-Length: " + ContentLength.ToString());
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
94 WriteLine(Stream, "");
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
95 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
96
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
97 public static void WriteLine(Stream Stream, string Line) {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
98 byte[] Buffer = null;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
99 Buffer = Encoding.ASCII.GetBytes(Line);
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
100 Stream.Write(Buffer, 0, Buffer.Length);
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
101 Stream.WriteByte(13);
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
102 Stream.WriteByte(10);
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
103 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
104 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
105
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
106 public abstract class HTTPContent {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
107 public abstract Result Serve(HTTPContext Context);
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
108 public enum Result : int {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
109 OK_CLOSE = -2,
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
110 OK_KEEPALIVE = -1,
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
111 ERR_NOTFOUND = 404
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
112 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
113 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
114
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
115 public class HTTPFileContent : HTTPContent {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
116 public string Filename { get; private set; }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
117 public string ContentType { get; private set; }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
118
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
119 public HTTPFileContent(string Filename) : this(Filename, "application/octet-stream") { }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
120 public HTTPFileContent(string Filename, string ContentType) {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
121 this.Filename = Filename;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
122 this.ContentType = ContentType;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
123 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
124
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
125 public override Result Serve(HTTPContext Context) {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
126 if (!File.Exists(Filename)) return Result.ERR_NOTFOUND;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
127
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
128 using (FileStream FileStream = File.OpenRead(Filename)) {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
129 HTTPServer.SendHeader(Context.Stream, 200, ContentType, (int)FileStream.Length);
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
130 byte[] Buffer = new byte[1025];
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
131 while (FileStream.CanRead) {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
132 int Length = FileStream.Read(Buffer, 0, Buffer.Length);
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
133 if (Length <= 0) break;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
134 Context.Stream.Write(Buffer, 0, Length);
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
135 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
136 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
137 return Result.OK_CLOSE;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
138 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
139 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
140
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
141 public class HTTPContext {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
142 public HTTPRequest Request { get; internal set; }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
143 public TCPStream Stream { get; internal set; }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
144 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
145
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
146 public enum Method {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
147 GET = 0,
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
148 HEAD = 1,
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
149 POST = 2,
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
150 PUT = 3
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
151 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
152
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
153 public class HTTPRequest {
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
154 public HTTP.Method Method { get; internal set; }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
155 public string Path { get; internal set; }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
156 public string Query { get; internal set; }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
157 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
158 }