aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/ApplicationPlugins/Rest/Inventory/RestFileServices.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/ApplicationPlugins/Rest/Inventory/RestFileServices.cs')
-rw-r--r--OpenSim/ApplicationPlugins/Rest/Inventory/RestFileServices.cs448
1 files changed, 0 insertions, 448 deletions
diff --git a/OpenSim/ApplicationPlugins/Rest/Inventory/RestFileServices.cs b/OpenSim/ApplicationPlugins/Rest/Inventory/RestFileServices.cs
deleted file mode 100644
index e79d2bd..0000000
--- a/OpenSim/ApplicationPlugins/Rest/Inventory/RestFileServices.cs
+++ /dev/null
@@ -1,448 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Xml;
30using System.IO;
31using OpenMetaverse;
32using OpenSim.Framework;
33using OpenSim.Framework.Servers;
34using OpenSim.Framework.Servers.HttpServer;
35
36namespace OpenSim.ApplicationPlugins.Rest.Inventory
37{
38 public class RestFileServices : IRest
39 {
40 private bool enabled = false;
41 private string qPrefix = "files";
42
43 // A simple constructor is used to handle any once-only
44 // initialization of working classes.
45
46 public RestFileServices()
47 {
48 Rest.Log.InfoFormat("{0} File services initializing", MsgId);
49 Rest.Log.InfoFormat("{0} Using REST Implementation Version {1}", MsgId, Rest.Version);
50
51 // If the handler specifies a relative path for its domain
52 // then we must add the standard absolute prefix, e.g. /admin
53
54 if (!qPrefix.StartsWith(Rest.UrlPathSeparator))
55 {
56 Rest.Log.InfoFormat("{0} Prefixing domain name ({1})", MsgId, qPrefix);
57 qPrefix = String.Format("{0}{1}{2}", Rest.Prefix, Rest.UrlPathSeparator, qPrefix);
58 Rest.Log.InfoFormat("{0} Fully qualified domain name is <{1}>", MsgId, qPrefix);
59 }
60
61 // Register interface using the fully-qualified prefix
62
63 Rest.Plugin.AddPathHandler(DoFile, qPrefix, Allocate);
64
65 // Activate if all went OK
66
67 enabled = true;
68
69 Rest.Log.InfoFormat("{0} File services initialization complete", MsgId);
70 }
71
72 // Post-construction, pre-enabled initialization opportunity
73 // Not currently exploited.
74
75 public void Initialize()
76 {
77 }
78
79 // Called by the plug-in to halt REST processing. Local processing is
80 // disabled, and control blocks until all current processing has
81 // completed. No new processing will be started
82
83 public void Close()
84 {
85 enabled = false;
86 Rest.Log.InfoFormat("{0} File services ({1}) closing down", MsgId, qPrefix);
87 }
88
89 // Properties
90
91 internal string MsgId
92 {
93 get { return Rest.MsgId; }
94 }
95
96 #region Interface
97
98 private RequestData Allocate(OSHttpRequest request, OSHttpResponse response, string prefix)
99 {
100 return (RequestData) new FileRequestData(request, response, prefix);
101 }
102
103 // Asset Handler
104
105 private void DoFile(RequestData rparm)
106 {
107 if (!enabled) return;
108
109 FileRequestData rdata = (FileRequestData) rparm;
110
111 Rest.Log.DebugFormat("{0} REST File handler ({1}) ENTRY", MsgId, qPrefix);
112
113 // Now that we know this is a serious attempt to
114 // access file data, we should find out who
115 // is asking, and make sure they are authorized
116 // to do so. We need to validate the caller's
117 // identity before revealing anything about the
118 // status quo. Authenticate throws an exception
119 // via Fail if no identity information is present.
120 //
121 // With the present HTTP server we can't use the
122 // builtin authentication mechanisms because they
123 // would be enforced for all in-bound requests.
124 // Instead we look at the headers ourselves and
125 // handle authentication directly.
126
127 try
128 {
129 if (!rdata.IsAuthenticated)
130 {
131 rdata.Fail(Rest.HttpStatusCodeNotAuthorized, String.Format("user \"{0}\" could not be authenticated"));
132 }
133 }
134 catch (RestException e)
135 {
136 if (e.statusCode == Rest.HttpStatusCodeNotAuthorized)
137 {
138 Rest.Log.WarnFormat("{0} User not authenticated", MsgId);
139 Rest.Log.DebugFormat("{0} Authorization header: {1}", MsgId,
140 rdata.request.Headers.Get("Authorization"));
141 }
142 else
143 {
144 Rest.Log.ErrorFormat("{0} User authentication failed", MsgId);
145 Rest.Log.DebugFormat("{0} Authorization header: {1}", MsgId,
146 rdata.request.Headers.Get("Authorization"));
147 }
148 throw (e);
149 }
150
151 // Remove the prefix and what's left are the parameters. If we don't have
152 // the parameters we need, fail the request. Parameters do NOT include
153 // any supplied query values.
154
155 if (rdata.Parameters.Length > 0)
156 {
157 switch (rdata.method)
158 {
159 case "get" :
160 DoGet(rdata);
161 break;
162 case "put" :
163 DoPut(rdata);
164 break;
165 case "post" :
166 DoPost(rdata);
167 break;
168 case "delete" :
169 DoDelete(rdata);
170 break;
171 default :
172 Rest.Log.WarnFormat("{0} File: Method not supported: {1}",
173 MsgId, rdata.method);
174 rdata.Fail(Rest.HttpStatusCodeBadRequest,String.Format("method <{0}> not supported", rdata.method));
175 break;
176 }
177 }
178 else
179 {
180 Rest.Log.WarnFormat("{0} File: No agent information provided", MsgId);
181 rdata.Fail(Rest.HttpStatusCodeBadRequest, "no agent information provided");
182 }
183
184 Rest.Log.DebugFormat("{0} REST File handler EXIT", MsgId);
185
186 }
187
188 #endregion Interface
189
190 /// <summary>
191 /// The only parameter we recognize is a UUID.If an asset with this identification is
192 /// found, it's content, base-64 encoded, is returned to the client.
193 /// </summary>
194
195 private void DoGet(FileRequestData rdata)
196 {
197
198 string path = String.Empty;
199
200 Rest.Log.DebugFormat("{0} REST File handler, Method = <{1}> ENTRY", MsgId, rdata.method);
201
202 if (rdata.Parameters.Length > 1)
203 {
204 try
205 {
206 path = rdata.path.Substring(rdata.Parameters[0].Length+qPrefix.Length+2);
207 if (File.Exists(path))
208 {
209 Rest.Log.DebugFormat("{0} File located <{1}>", MsgId, path);
210 Byte[] data = File.ReadAllBytes(path);
211 rdata.initXmlWriter();
212 rdata.writer.WriteStartElement(String.Empty,"File",String.Empty);
213 rdata.writer.WriteAttributeString("name", path);
214 rdata.writer.WriteBase64(data,0,data.Length);
215 rdata.writer.WriteFullEndElement();
216 }
217 else
218 {
219 Rest.Log.DebugFormat("{0} Invalid parameters: <{1}>", MsgId, path);
220 rdata.Fail(Rest.HttpStatusCodeNotFound, String.Format("invalid parameters : {0}", path));
221 }
222 }
223 catch (Exception e)
224 {
225 Rest.Log.DebugFormat("{0} Invalid parameters: <{1}>", MsgId, e.Message);
226 rdata.Fail(Rest.HttpStatusCodeNotFound, String.Format("invalid parameters : {0} {1}",
227 path, e.Message));
228 }
229 }
230
231 rdata.Complete();
232 rdata.Respond(String.Format("File <{0}> : Normal completion", rdata.method));
233
234 }
235
236 /// <summary>
237 /// UPDATE existing item, if it exists. URI identifies the item in question.
238 /// The only parameter we recognize is a UUID. The enclosed asset data (base-64 encoded)
239 /// is decoded and stored in the database, identified by the supplied UUID.
240 /// </summary>
241 private void DoPut(FileRequestData rdata)
242 {
243 bool modified = false;
244 bool created = false;
245 string path = String.Empty;
246
247 Rest.Log.DebugFormat("{0} REST File handler, Method = <{1}> ENTRY", MsgId, rdata.method);
248
249 if (rdata.Parameters.Length > 1)
250 {
251 try
252 {
253 path = rdata.path.Substring(rdata.Parameters[0].Length+qPrefix.Length+2);
254 bool maymod = File.Exists(path);
255
256 rdata.initXmlReader();
257 XmlReader xml = rdata.reader;
258
259 if (!xml.ReadToFollowing("File"))
260 {
261 Rest.Log.DebugFormat("{0} Invalid request data: <{1}>", MsgId, rdata.path);
262 rdata.Fail(Rest.HttpStatusCodeBadRequest,"invalid request data");
263 }
264
265 Byte[] data = Convert.FromBase64String(xml.ReadElementContentAsString("File", ""));
266
267 File.WriteAllBytes(path,data);
268 modified = maymod;
269 created = ! maymod;
270 }
271 catch (Exception e)
272 {
273 Rest.Log.DebugFormat("{0} Exception during file processing : {1}", MsgId,
274 e.Message);
275 }
276 }
277 else
278 {
279 Rest.Log.DebugFormat("{0} Invalid parameters: <{1}>", MsgId, rdata.path);
280 rdata.Fail(Rest.HttpStatusCodeNotFound, "invalid parameters");
281 }
282
283 if (created)
284 {
285 rdata.appendStatus(String.Format("<p> Created file {0} <p>", path));
286 rdata.Complete(Rest.HttpStatusCodeCreated);
287 }
288 else
289 {
290 if (modified)
291 {
292 rdata.appendStatus(String.Format("<p> Modified file {0} <p>", path));
293 rdata.Complete(Rest.HttpStatusCodeOK);
294 }
295 else
296 {
297 rdata.Complete(Rest.HttpStatusCodeNoContent);
298 }
299 }
300
301 rdata.Respond(String.Format("File {0} : Normal completion", rdata.method));
302
303 }
304
305 /// <summary>
306 /// CREATE new item, replace if it exists. URI identifies the context for the item in question.
307 /// No parameters are required for POST, just thepayload.
308 /// </summary>
309
310 private void DoPost(FileRequestData rdata)
311 {
312
313 bool modified = false;
314 bool created = false;
315 string path = String.Empty;
316
317 Rest.Log.DebugFormat("{0} REST File handler, Method = <{1}> ENTRY", MsgId, rdata.method);
318
319 if (rdata.Parameters.Length > 1)
320 {
321 try
322 {
323 path = rdata.path.Substring(rdata.Parameters[0].Length+qPrefix.Length+2);
324 bool maymod = File.Exists(path);
325
326 rdata.initXmlReader();
327 XmlReader xml = rdata.reader;
328
329 if (!xml.ReadToFollowing("File"))
330 {
331 Rest.Log.DebugFormat("{0} Invalid request data: <{1}>", MsgId, rdata.path);
332 rdata.Fail(Rest.HttpStatusCodeBadRequest,"invalid request data");
333 }
334
335 Byte[] data = Convert.FromBase64String(xml.ReadElementContentAsString("File", ""));
336
337 File.WriteAllBytes(path,data);
338 modified = maymod;
339 created = ! maymod;
340 }
341 catch (Exception e)
342 {
343 Rest.Log.DebugFormat("{0} Exception during file processing : {1}", MsgId,
344 e.Message);
345 }
346 }
347 else
348 {
349 Rest.Log.DebugFormat("{0} Invalid parameters: <{1}>", MsgId, rdata.path);
350 rdata.Fail(Rest.HttpStatusCodeNotFound, "invalid parameters");
351 }
352
353 if (created)
354 {
355 rdata.appendStatus(String.Format("<p> Created file {0} <p>", path));
356 rdata.Complete(Rest.HttpStatusCodeCreated);
357 }
358 else
359 {
360 if (modified)
361 {
362 rdata.appendStatus(String.Format("<p> Modified file {0} <p>", path));
363 rdata.Complete(Rest.HttpStatusCodeOK);
364 }
365 else
366 {
367 rdata.Complete(Rest.HttpStatusCodeNoContent);
368 }
369 }
370
371 rdata.Respond(String.Format("File {0} : Normal completion", rdata.method));
372
373 }
374
375 /// <summary>
376 /// CREATE new item, replace if it exists. URI identifies the context for the item in question.
377 /// No parameters are required for POST, just thepayload.
378 /// </summary>
379
380 private void DoDelete(FileRequestData rdata)
381 {
382
383 bool modified = false;
384 bool created = false;
385 string path = String.Empty;
386
387 Rest.Log.DebugFormat("{0} REST File handler, Method = <{1}> ENTRY", MsgId, rdata.method);
388
389 if (rdata.Parameters.Length > 1)
390 {
391 try
392 {
393 path = rdata.path.Substring(rdata.Parameters[0].Length+qPrefix.Length+2);
394
395 if (File.Exists(path))
396 {
397 File.Delete(path);
398 }
399 }
400 catch (Exception e)
401 {
402 Rest.Log.DebugFormat("{0} Exception during file processing : {1}", MsgId,
403 e.Message);
404 rdata.Fail(Rest.HttpStatusCodeNotFound, String.Format("invalid parameters : {0} {1}",
405 path, e.Message));
406 }
407 }
408 else
409 {
410 Rest.Log.DebugFormat("{0} Invalid parameters: <{1}>", MsgId, rdata.path);
411 rdata.Fail(Rest.HttpStatusCodeNotFound, "invalid parameters");
412 }
413
414 if (created)
415 {
416 rdata.appendStatus(String.Format("<p> Created file {0} <p>", path));
417 rdata.Complete(Rest.HttpStatusCodeCreated);
418 }
419 else
420 {
421 if (modified)
422 {
423 rdata.appendStatus(String.Format("<p> Modified file {0} <p>", path));
424 rdata.Complete(Rest.HttpStatusCodeOK);
425 }
426 else
427 {
428 rdata.Complete(Rest.HttpStatusCodeNoContent);
429 }
430 }
431
432 rdata.Respond(String.Format("File {0} : Normal completion", rdata.method));
433
434 }
435
436 /// <summary>
437 /// File processing has no special data area requirements.
438 /// </summary>
439
440 internal class FileRequestData : RequestData
441 {
442 internal FileRequestData(OSHttpRequest request, OSHttpResponse response, string prefix)
443 : base(request, response, prefix)
444 {
445 }
446 }
447 }
448}