aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Server/Handlers/Web/WebServerConnector.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Server/Handlers/Web/WebServerConnector.cs')
-rw-r--r--OpenSim/Server/Handlers/Web/WebServerConnector.cs368
1 files changed, 368 insertions, 0 deletions
diff --git a/OpenSim/Server/Handlers/Web/WebServerConnector.cs b/OpenSim/Server/Handlers/Web/WebServerConnector.cs
new file mode 100644
index 0000000..2607386
--- /dev/null
+++ b/OpenSim/Server/Handlers/Web/WebServerConnector.cs
@@ -0,0 +1,368 @@
1using System;
2using System.Collections;
3using System.Collections.Generic;
4using System.IO;
5using System.Net;
6using System.Reflection;
7using System.Security;
8using System.Text;
9using log4net;
10using Nini.Config;
11using OpenMetaverse;
12using OpenMetaverse.StructuredData;
13using OpenSim.Data.MySQL;
14using OpenSim.Framework;
15using OpenSim.Framework.Servers.HttpServer;
16using OpenSim.Server.Handlers.Base;
17
18namespace OpenSim.Server.Handlers.Web
19{
20 public class WebServerConnector : ServiceConnector
21 {
22 // This is all slow and clunky, it's not a real web server, just something to use if you don't want a real one.
23 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
24 private IConfigSource m_Config;
25 protected MySQLRaw m_database = null;
26 private Hashtable mime = new Hashtable();
27 private Hashtable ssi = new Hashtable();
28
29 public WebServerConnector(IConfigSource config, IHttpServer server, string configName) : base(config, server, configName)
30 {
31 string dllName = String.Empty;
32 string connString = String.Empty;
33
34 m_Config = config;
35
36 // Try reading the [DatabaseService] section, if it exists
37 IConfig dbConfig = m_Config.Configs["DatabaseService"];
38 if (dbConfig != null)
39 {
40 if (dllName == String.Empty)
41 dllName = dbConfig.GetString("StorageProvider", String.Empty);
42 if (connString == String.Empty)
43 connString = dbConfig.GetString("ConnectionString", String.Empty);
44 }
45 if (dllName.Equals(String.Empty))
46 throw new Exception("No StorageProvider configured");
47
48//// TODO - Should do the plugin thing to pick between database backends.
49//// Or not, we are all using MariaDB anyway.
50// m_Database = LoadPlugin<SQLGenericHandler>(dllName, new Object[] { connString });
51
52 m_database = new MySQLRaw(connString);
53
54 mime.Add(".gz", "application/gzip");
55 mime.Add(".js", "application/javascript");
56 mime.Add(".json", "application/json");
57 mime.Add(".pdf", "application/pdf");
58 mime.Add(".rtf", "application/rtf");
59 mime.Add(".zip", "application/zip");
60 mime.Add(".xz", "application/x-xz");
61 mime.Add(".gif", "image/gif");
62 mime.Add(".png", "image/png");
63 mime.Add(".jp2", "image/jp2");
64 mime.Add(".jpg2", "image/jp2");
65 mime.Add(".jpe", "image/jpeg");
66 mime.Add(".jpg", "image/jpeg");
67 mime.Add(".jpeg", "image/jpeg");
68 mime.Add(".svg", "image/svg+xml");
69 mime.Add(".svgz", "image/svg+xml");
70 mime.Add(".tif", "image/tiff");
71 mime.Add(".tiff", "image/tiff");
72 mime.Add(".css", "text/css");
73 mime.Add(".html", "text/html");
74 mime.Add(".htm", "text/html");
75 mime.Add(".shtml", "text/html");
76// mime.Add(".md", "text/markdown");
77// mime.Add(".markdown","text/markdown");
78 mime.Add(".txt", "text/plain");
79
80 IConfig cfg = m_Config.Configs["GridInfoService"];
81 string HomeURI = Util.GetConfigVarFromSections<string>(m_Config, "HomeURI", new string[] { "Startup", "Hypergrid" }, String.Empty);
82 ssi.Add("grid", cfg.GetString("gridname", "my grid"));
83 ssi.Add("uri", cfg.GetString("login", HomeURI));
84 ssi.Add("version", VersionInfo.Version);
85 server.AddHTTPHandler("/web/", WebRequestHandler);
86 }
87
88 private Hashtable WebRequestHandler(Hashtable request)
89 {
90 long locIn = m_database.Count("Presence", "RegionID != '00000000-0000-0000-0000-000000000000'"); // Locals online but not HGing, and HGers in world.
91 long HGin = m_database.Count("Presence", "UserID NOT IN (SELECT PrincipalID FROM UserAccounts)"); // HGers in world.
92 long locOut = m_database.Count("hg_traveling_data", "GridExternalName != '" + ssi["uri"] + "'"); // Locals that are HGing.
93 Hashtable reply = new Hashtable();
94 ssi["members"] = m_database.Count("UserAccounts").ToString();
95 ssi["sims"] = m_database.Count("regions").ToString();
96 ssi["inworld"] = (locIn - HGin).ToString();
97 ssi["outworld"] = locOut.ToString();
98 ssi["hgers"] = HGin.ToString();
99 ssi["month"] = m_database.Count("GridUser", "Login > UNIX_TIMESTAMP(FROM_UNIXTIME(UNIX_TIMESTAMP(now()) - 2419200))").ToString();
100
101 string reqpath = (string) request["uri"];
102 string[] query = (string[]) request["querystringkeys"];
103 Hashtable headers = (Hashtable) request["headers"];
104 string method = (string) request["http-method"];
105 string type = (string) request["content-type"];
106 string body = (string) request["body"];
107 string file = reqpath.Remove(0, 5);
108 string path = Path.Combine(Util.webDir(), file);
109
110 m_log.InfoFormat("[WEB SERVICE]: {0} method path {1} type {2} body {3}.", method, reqpath, type, body);
111 foreach (DictionaryEntry h in headers)
112 m_log.InfoFormat("[WEB SERVICE]: {0} method path {1} header {2} = {3}", method, reqpath, (string) h.Key, (string) h.Value);
113 foreach (String q in query)
114 m_log.InfoFormat("[WEB SERVICE]: {0} method path {1} query {2} value {3}", method, reqpath, q, (string) request[q]);
115
116 reply["int_response_code"] = 200;
117 if ("GET" == method)
118 {
119 if (File.Exists(path))
120 {
121 string m = (string) mime[Path.GetExtension(path).ToLower()];
122 reply["content_type"] = m;
123 if ((null == m) || ("text/" != m.Substring(0, 5)))
124 reply["bin_response_data"] = File.ReadAllBytes(path);
125 else
126 {
127 StreamReader csr = File.OpenText(path);
128 string content = csr.ReadToEnd();
129 // Slow and wasteful, but I'm expecting only tiny web files, not accessed very often.
130 foreach (DictionaryEntry v in ssi)
131 {
132 content = content.Replace("<!--#echo var=\"" + ((string) v.Key) + "\" -->", (string) v.Value);
133 }
134 reply["str_response_string"] = content;
135 csr.Close();
136 }
137 }
138 else
139 {
140 if ("account.html" == file)
141 reply["str_response_string"] = loginPage(null, "");
142 else
143 {
144 m_log.ErrorFormat("[WEB SERVICE]: Unable to read {0}.", path);
145 reply["int_response_code"] = 404;
146 reply["content_type"] = "text/html";
147 reply["str_response_string"] = "<html><title>404 Unknown page</title><head></head><body bgcolor=\"black\" text=\"white\" alink=\"red\" link=\"blue\" vlink=\"purple\">" +
148 "404 error, can't find the " + reqpath + " page.<p>&nbsp;</p></body></html>";
149 }
150 }
151 }
152 else if ("POST" == method)
153 {
154 Hashtable fields = new Hashtable();
155 string[] bdy = body.Split('&');
156 body = "";
157 foreach (String bd in bdy)
158 {
159 string[] b = bd.Split('=');
160 if (b.Length == 0)
161 continue;
162 String n = System.Web.HttpUtility.UrlDecode(b[0]);
163 String v = "";
164 if (b.Length > 1)
165 v = System.Web.HttpUtility.UrlDecode(b[1]);
166 fields[n] = v;
167 body = body + "<p>" + n + " = " + v + "</p>\n";
168 }
169
170 if ("account.html" == file)
171 {
172 if ("logout" == fields["doit"].ToString())
173 reply["str_response_string"] = loginPage(null, "Logged out.");
174 else if ("create" == fields["doit"].ToString())
175 {
176 if ("" == fields["email"].ToString())
177 reply["str_response_string"] = loginPage(fields, "Please supply an email address when creating an account.");
178 else
179 {
180 reply["str_response_string"] = loggedOnPage(body, fields);
181 }
182 }
183 else if ("list" == fields["doit"].ToString())
184 {
185 List< Hashtable > rows = m_database.Select("UserAccounts",
186 "CONCAT(FirstName,' ',LastName) as Name,UserTitle as Title,UserLevel as Level,UserFlags as Flags,PrincipalID as UUID",
187 "", "Name");
188 reply["str_response_string"] = "<html><title>member accounts</title><head></head><body bgcolor=\"black\" text=\"white\" alink=\"red\" link=\"blue\" vlink=\"purple\">" +
189 table(rows, new string[5] {"Name", "Title", "Level", "Flags", "UUID"}, "member accounts",
190 "account.html?doit=edit&token=" + fields["token"].ToString(), "UUID") + "<p>" + button("my account") + "</p></body></html>";
191 }
192 else
193 {
194 reply["str_response_string"] = loggedOnPage(body, fields);
195 }
196 }
197 else
198 {
199 m_log.ErrorFormat("[WEB SERVICE]: No such POST target {0}.", path);
200 reply["int_response_code"] = 404;
201 reply["content_type"] = "text/html";
202 reply["str_response_string"] = "<html><title>404 Unknown page</title><head></head><body bgcolor=\"black\" text=\"white\" alink=\"red\" link=\"blue\" vlink=\"purple\">" +
203 "404 error, can't find the " + reqpath + " page.<p>&nbsp;</p></body></html>";
204 }
205 }
206 else
207 {
208 m_log.ErrorFormat("[WEB SERVICE]: UNKNOWN method {0} path {1}.", method, reqpath);
209 reply["int_response_code"] = 404;
210 reply["content_type"] = "text/html";
211 reply["str_response_string"] = "<html><title>Unknown method</title><head></head><body bgcolor=\"black\" text=\"white\" alink=\"red\" link=\"blue\" vlink=\"purple\">" +
212 "HUH! For " + reqpath + " page.<p>&nbsp;</p></body></html>";
213 }
214
215 m_log.Info("[WEB SERVICE]: ");
216 return reply;
217 }
218
219 private string loginPage(Hashtable fields, string message)
220 {
221 string f = "";
222 string l = "";
223 string e = "";
224 if (null != fields)
225 {
226 f = fields["firstName"].ToString();
227 l = fields["lastName"].ToString();
228 e = fields["email"].ToString();
229 }
230 return header(ssi["grid"] + " account")
231 + form("account.html", "",
232 text("text", "first name", "firstName", f, 16, true)
233 + text("text", "last name", "lastName", l, 16, true)
234 + text("email", "email", "email", e, 0, false)
235 + text("password", "password", "password", "", 14,true)
236 + button("create")
237 + button("login")
238 )
239 + "<p>" + message + "</p>"
240 + footer();
241 }
242
243 private string loggedOnPage(string body, Hashtable fields)
244 {
245 return header(ssi["grid"] + " account")
246 + "<h1>" + ssi["grid"] + " account for " + fields["firstName"].ToString() + " " + fields["lastName"].ToString() + "</h1>"
247 + form("account.html", fields["token"].ToString(),
248 hidden("firstName", fields["firstName"].ToString())
249 + hidden("lastName", fields["lastName"].ToString())
250// + hidden("UUID", fields["UUID"].ToString())
251 + text("email", "email", "email", fields["email"].ToString(), 0, false)
252 + text("password", "password", "password", "", 14, false)
253// + text("title", "text", "title", fields["title"].ToString(), 0, false)
254 + select("type", "type",
255 option("", false)
256 + option("approved", true)
257 + option("disabled", false)
258 + option("god", false)
259 )
260 + button("delete")
261 + button("list")
262 + button("logout")
263// + button("read")
264 + button("update")
265 )
266 + body
267 + footer();
268 }
269
270 private string header(string title)
271 {
272 return "<html>\n <head>\n <title>" + title + "</title>\n </head>\n <body>\n";
273 }
274
275 private string table(List< Hashtable > rows, string[] fields, string caption, string URL, string id)
276 {
277 string tbl = "<table border=\"1\"><caption>" + caption + "</caption>";
278 bool head = true;
279 string address = "";
280 string addrend = "";
281 foreach (Hashtable row in rows)
282 {
283 if (0 == fields.Length)
284 {
285 int c = 0;
286 foreach (DictionaryEntry r in row)
287 c++;
288 fields = new string[c];
289 c = 0;
290 foreach (DictionaryEntry r in row)
291 fields[c++] = (string) r.Key;
292 }
293 string line = "<tr>";
294 address = "";
295 if ("" != URL)
296 {
297 address = "<a href=\"" + URL;
298 addrend = "</a>";
299 }
300 if ("" != id)
301 address = address + "&" + id + "=" + row[id] + "\">";
302 if (head)
303 {
304 foreach (string s in fields)
305 line = line + "<th>" + s + "</th>";
306 tbl = tbl + line + "</tr>\n";
307 head = false;
308 }
309 line = "<tr>";
310 foreach (string s in fields)
311 {
312 if (s == id)
313 line = line + "<td>" + address + row[s] + addrend + "</td>";
314 else
315 line = line + "<td>" + row[s] + "</td>";
316 }
317 tbl = tbl + line + "</tr>\n";
318 }
319 return tbl + "</table>";
320 }
321
322 private string form(string action, string token, string form)
323 {
324 return " <form action=\"" + action + "\" method=\"POST\">\n" + hidden("token", token) + form + " </form>\n";
325 }
326
327 private string hidden(string name, string val)
328 {
329 return " <input type=\"hidden\" name=\"" + name + "\" value=\"" + val + "\">\n";
330 }
331
332 private string text(string type, string title, string name, string val, int max, bool required)
333 {
334 string extra = "";
335 if (0 < max)
336 extra = extra + " maxlength=\"" + max.ToString() + "\"";
337 if (required)
338 extra = extra + " required";
339 if ("" != val)
340 val = "value=\"" + val + "\"";
341 return " <p>" + title + " : <input type=\"" + type + "\" name=\"" + name + "\"" + val + extra + "></p>\n";
342 }
343
344 private string select(string title, string name, string options)
345 {
346 return " <p>" + title + " : \n <select name=\"" + name + "\">\n" + options + " </select>\n </p>\n";
347 }
348
349 private string option(string title, bool selected)
350 {
351 string sel = "";
352 if (selected)
353 sel = " selected";
354 return " <option value=\"" + title + "\"" + sel + ">" + title + "</option>\n";
355 }
356
357 private string button(string title)
358 {
359 return " <button type=\"submit\" name=\"doit\" value=\"" + title + "\">" + title + "</button>\n";
360 }
361
362 private string footer()
363 {
364 return " </body>\n</html>\n";
365 }
366
367 }
368}