aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/ApplicationPlugins/Rest/Inventory/RestAssetServices.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/ApplicationPlugins/Rest/Inventory/RestAssetServices.cs383
1 files changed, 0 insertions, 383 deletions
diff --git a/OpenSim/ApplicationPlugins/Rest/Inventory/RestAssetServices.cs b/OpenSim/ApplicationPlugins/Rest/Inventory/RestAssetServices.cs
deleted file mode 100644
index 4ba3d77..0000000
--- a/OpenSim/ApplicationPlugins/Rest/Inventory/RestAssetServices.cs
+++ /dev/null
@@ -1,383 +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 OpenMetaverse;
31using OpenSim.Framework;
32using OpenSim.Framework.Servers;
33using OpenSim.Framework.Servers.HttpServer;
34
35namespace OpenSim.ApplicationPlugins.Rest.Inventory
36{
37 public class RestAssetServices : IRest
38 {
39 private bool enabled = false;
40 private string qPrefix = "assets";
41
42 // A simple constructor is used to handle any once-only
43 // initialization of working classes.
44
45 public RestAssetServices()
46 {
47 Rest.Log.InfoFormat("{0} Asset services initializing", MsgId);
48 Rest.Log.InfoFormat("{0} Using REST Implementation Version {1}", MsgId, Rest.Version);
49
50 // If the handler specifies a relative path for its domain
51 // then we must add the standard absolute prefix, e.g. /admin
52
53 if (!qPrefix.StartsWith(Rest.UrlPathSeparator))
54 {
55 Rest.Log.InfoFormat("{0} Prefixing domain name ({1})", MsgId, qPrefix);
56 qPrefix = String.Format("{0}{1}{2}", Rest.Prefix, Rest.UrlPathSeparator, qPrefix);
57 Rest.Log.InfoFormat("{0} Fully qualified domain name is <{1}>", MsgId, qPrefix);
58 }
59
60 // Register interface using the fully-qualified prefix
61
62 Rest.Plugin.AddPathHandler(DoAsset, qPrefix, Allocate);
63
64 // Activate if all went OK
65
66 enabled = true;
67
68 Rest.Log.InfoFormat("{0} Asset services initialization complete", MsgId);
69 }
70
71 // Post-construction, pre-enabled initialization opportunity
72 // Not currently exploited.
73
74 public void Initialize()
75 {
76 }
77
78 // Called by the plug-in to halt REST processing. Local processing is
79 // disabled, and control blocks until all current processing has
80 // completed. No new processing will be started
81
82 public void Close()
83 {
84 enabled = false;
85 Rest.Log.InfoFormat("{0} Asset services ({1}) closing down", MsgId, qPrefix);
86 }
87
88 // Properties
89
90 internal string MsgId
91 {
92 get { return Rest.MsgId; }
93 }
94
95 #region Interface
96
97 private RequestData Allocate(OSHttpRequest request, OSHttpResponse response, string prefix)
98 {
99 return (RequestData) new AssetRequestData(request, response, prefix);
100 }
101
102 // Asset Handler
103
104 private void DoAsset(RequestData rparm)
105 {
106 if (!enabled) return;
107
108 AssetRequestData rdata = (AssetRequestData) rparm;
109
110 Rest.Log.DebugFormat("{0} REST Asset handler ({1}) ENTRY", MsgId, qPrefix);
111
112 // Now that we know this is a serious attempt to
113 // access inventory data, we should find out who
114 // is asking, and make sure they are authorized
115 // to do so. We need to validate the caller's
116 // identity before revealing anything about the
117 // status quo. Authenticate throws an exception
118 // via Fail if no identity information is present.
119 //
120 // With the present HTTP server we can't use the
121 // builtin authentication mechanisms because they
122 // would be enforced for all in-bound requests.
123 // Instead we look at the headers ourselves and
124 // handle authentication directly.
125
126 try
127 {
128 if (!rdata.IsAuthenticated)
129 {
130 rdata.Fail(Rest.HttpStatusCodeNotAuthorized, String.Format("user \"{0}\" could not be authenticated"));
131 }
132 }
133 catch (RestException e)
134 {
135 if (e.statusCode == Rest.HttpStatusCodeNotAuthorized)
136 {
137 Rest.Log.WarnFormat("{0} User not authenticated", MsgId);
138 Rest.Log.DebugFormat("{0} Authorization header: {1}", MsgId,
139 rdata.request.Headers.Get("Authorization"));
140 }
141 else
142 {
143 Rest.Log.ErrorFormat("{0} User authentication failed", MsgId);
144 Rest.Log.DebugFormat("{0} Authorization header: {1}", MsgId,
145 rdata.request.Headers.Get("Authorization"));
146 }
147 throw (e);
148 }
149
150 // Remove the prefix and what's left are the parameters. If we don't have
151 // the parameters we need, fail the request. Parameters do NOT include
152 // any supplied query values.
153
154 if (rdata.Parameters.Length > 0)
155 {
156 switch (rdata.method)
157 {
158 case "get" :
159 DoGet(rdata);
160 break;
161 case "put" :
162 DoPut(rdata);
163 break;
164 case "post" :
165 DoPost(rdata);
166 break;
167 case "delete" :
168 default :
169 Rest.Log.WarnFormat("{0} Asset: Method not supported: {1}",
170 MsgId, rdata.method);
171 rdata.Fail(Rest.HttpStatusCodeBadRequest,String.Format("method <{0}> not supported", rdata.method));
172 break;
173 }
174 }
175 else
176 {
177 Rest.Log.WarnFormat("{0} Asset: No agent information provided", MsgId);
178 rdata.Fail(Rest.HttpStatusCodeBadRequest, "no agent information provided");
179 }
180
181 Rest.Log.DebugFormat("{0} REST Asset handler EXIT", MsgId);
182 }
183
184 #endregion Interface
185
186 /// <summary>
187 /// The only parameter we recognize is a UUID.If an asset with this identification is
188 /// found, it's content, base-64 encoded, is returned to the client.
189 /// </summary>
190
191 private void DoGet(AssetRequestData rdata)
192 {
193 Rest.Log.DebugFormat("{0} REST Asset handler, Method = <{1}> ENTRY", MsgId, rdata.method);
194
195 if (rdata.Parameters.Length == 1)
196 {
197 UUID uuid = new UUID(rdata.Parameters[0]);
198 AssetBase asset = Rest.AssetServices.Get(uuid.ToString());
199
200 if (asset != null)
201 {
202 Rest.Log.DebugFormat("{0} Asset located <{1}>", MsgId, rdata.Parameters[0]);
203
204 rdata.initXmlWriter();
205
206 rdata.writer.WriteStartElement(String.Empty,"Asset",String.Empty);
207
208 rdata.writer.WriteAttributeString("id", asset.ID);
209 rdata.writer.WriteAttributeString("name", asset.Name);
210 rdata.writer.WriteAttributeString("desc", asset.Description);
211 rdata.writer.WriteAttributeString("type", asset.Type.ToString());
212 rdata.writer.WriteAttributeString("local", asset.Local.ToString());
213 rdata.writer.WriteAttributeString("temporary", asset.Temporary.ToString());
214
215 rdata.writer.WriteBase64(asset.Data,0,asset.Data.Length);
216
217 rdata.writer.WriteFullEndElement();
218
219 }
220 else
221 {
222 Rest.Log.DebugFormat("{0} Invalid parameters: <{1}>", MsgId, rdata.path);
223 rdata.Fail(Rest.HttpStatusCodeNotFound, "invalid parameters");
224 }
225 }
226
227 rdata.Complete();
228 rdata.Respond(String.Format("Asset <{0}> : Normal completion", rdata.method));
229
230 }
231
232 /// <summary>
233 /// UPDATE existing item, if it exists. URI identifies the item in question.
234 /// The only parameter we recognize is a UUID. The enclosed asset data (base-64 encoded)
235 /// is decoded and stored in the database, identified by the supplied UUID.
236 /// </summary>
237 private void DoPut(AssetRequestData rdata)
238 {
239 bool modified = false;
240 bool created = false;
241
242 AssetBase asset = null;
243
244 Rest.Log.DebugFormat("{0} REST Asset handler, Method = <{1}> ENTRY", MsgId, rdata.method);
245
246 if (rdata.Parameters.Length == 1)
247 {
248
249 rdata.initXmlReader();
250 XmlReader xml = rdata.reader;
251
252 if (!xml.ReadToFollowing("Asset"))
253 {
254 Rest.Log.DebugFormat("{0} Invalid request data: <{1}>", MsgId, rdata.path);
255 rdata.Fail(Rest.HttpStatusCodeBadRequest,"invalid request data");
256 }
257
258 UUID uuid = new UUID(rdata.Parameters[0]);
259 asset = Rest.AssetServices.Get(uuid.ToString());
260
261 modified = (asset != null);
262 created = !modified;
263
264 asset = new AssetBase(uuid, xml.GetAttribute("name"), SByte.Parse(xml.GetAttribute("type")), UUID.Zero.ToString());
265 asset.Description = xml.GetAttribute("desc");
266 asset.Local = Int32.Parse(xml.GetAttribute("local")) != 0;
267 asset.Temporary = Int32.Parse(xml.GetAttribute("temporary")) != 0;
268 asset.Data = Convert.FromBase64String(xml.ReadElementContentAsString("Asset", ""));
269
270 if (asset.ID != rdata.Parameters[0])
271 {
272 Rest.Log.WarnFormat("{0} URI and payload disagree on UUID U:{1} vs P:{2}",
273 MsgId, rdata.Parameters[0], asset.ID);
274 }
275
276 Rest.AssetServices.Store(asset);
277
278 }
279 else
280 {
281 Rest.Log.DebugFormat("{0} Invalid parameters: <{1}>", MsgId, rdata.path);
282 rdata.Fail(Rest.HttpStatusCodeNotFound, "invalid parameters");
283 }
284
285 if (created)
286 {
287 rdata.appendStatus(String.Format("<p> Created asset {0}, UUID {1} <p>", asset.Name, asset.FullID));
288 rdata.Complete(Rest.HttpStatusCodeCreated);
289 }
290 else
291 {
292 if (modified)
293 {
294 rdata.appendStatus(String.Format("<p> Modified asset {0}, UUID {1} <p>", asset.Name, asset.FullID));
295 rdata.Complete(Rest.HttpStatusCodeOK);
296 }
297 else
298 {
299 rdata.Complete(Rest.HttpStatusCodeNoContent);
300 }
301 }
302
303 rdata.Respond(String.Format("Asset {0} : Normal completion", rdata.method));
304
305 }
306
307 /// <summary>
308 /// CREATE new item, replace if it exists. URI identifies the context for the item in question.
309 /// No parameters are required for POST, just thepayload.
310 /// </summary>
311
312 private void DoPost(AssetRequestData rdata)
313 {
314
315 bool modified = false;
316 bool created = false;
317
318 Rest.Log.DebugFormat("{0} REST Asset handler, Method = <{1}> ENTRY", MsgId, rdata.method);
319
320 if (rdata.Parameters.Length != 0)
321 {
322 Rest.Log.WarnFormat("{0} Parameters ignored <{1}>", MsgId, rdata.path);
323 Rest.Log.InfoFormat("{0} POST of an asset has no parameters", MsgId, rdata.path);
324 }
325
326 rdata.initXmlReader();
327 XmlReader xml = rdata.reader;
328
329 if (!xml.ReadToFollowing("Asset"))
330 {
331 Rest.Log.DebugFormat("{0} Invalid request data: <{1}>", MsgId, rdata.path);
332 rdata.Fail(Rest.HttpStatusCodeBadRequest,"invalid request data");
333 }
334
335 UUID uuid = new UUID(xml.GetAttribute("id"));
336 AssetBase asset = Rest.AssetServices.Get(uuid.ToString());
337
338 modified = (asset != null);
339 created = !modified;
340
341 asset = new AssetBase(uuid, xml.GetAttribute("name"), SByte.Parse(xml.GetAttribute("type")), UUID.Zero.ToString());
342 asset.Description = xml.GetAttribute("desc");
343 asset.Local = Int32.Parse(xml.GetAttribute("local")) != 0;
344 asset.Temporary = Int32.Parse(xml.GetAttribute("temporary")) != 0;
345 asset.Data = Convert.FromBase64String(xml.ReadElementContentAsString("Asset", ""));
346
347 Rest.AssetServices.Store(asset);
348
349 if (created)
350 {
351 rdata.appendStatus(String.Format("<p> Created asset {0}, UUID {1} <p>", asset.Name, asset.FullID));
352 rdata.Complete(Rest.HttpStatusCodeCreated);
353 }
354 else
355 {
356 if (modified)
357 {
358 rdata.appendStatus(String.Format("<p> Modified asset {0}, UUID {1} <p>", asset.Name, asset.FullID));
359 rdata.Complete(Rest.HttpStatusCodeOK);
360 }
361 else
362 {
363 rdata.Complete(Rest.HttpStatusCodeNoContent);
364 }
365 }
366
367 rdata.Respond(String.Format("Asset {0} : Normal completion", rdata.method));
368
369 }
370
371 /// <summary>
372 /// Asset processing has no special data area requirements.
373 /// </summary>
374
375 internal class AssetRequestData : RequestData
376 {
377 internal AssetRequestData(OSHttpRequest request, OSHttpResponse response, string prefix)
378 : base(request, response, prefix)
379 {
380 }
381 }
382 }
383}