diff options
Diffstat (limited to 'OpenSim/ApplicationPlugins/Rest/Inventory/RestAssetServices.cs')
-rw-r--r-- | OpenSim/ApplicationPlugins/Rest/Inventory/RestAssetServices.cs | 257 |
1 files changed, 257 insertions, 0 deletions
diff --git a/OpenSim/ApplicationPlugins/Rest/Inventory/RestAssetServices.cs b/OpenSim/ApplicationPlugins/Rest/Inventory/RestAssetServices.cs new file mode 100644 index 0000000..839e0f2 --- /dev/null +++ b/OpenSim/ApplicationPlugins/Rest/Inventory/RestAssetServices.cs | |||
@@ -0,0 +1,257 @@ | |||
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 OpenSim 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 | */ | ||
28 | |||
29 | using libsecondlife; | ||
30 | using Nini.Config; | ||
31 | using System; | ||
32 | using System.Collections.Generic; | ||
33 | using System.IO; | ||
34 | using System.Threading; | ||
35 | using System.Xml; | ||
36 | using OpenSim.Framework; | ||
37 | using OpenSim.Framework.Servers; | ||
38 | using OpenSim.Framework.Communications; | ||
39 | using OpenSim.Framework.Communications.Cache; | ||
40 | |||
41 | namespace OpenSim.ApplicationPlugins.Rest.Inventory | ||
42 | { | ||
43 | |||
44 | public class RestAssetServices : IRest | ||
45 | { | ||
46 | |||
47 | private string key = "assets"; | ||
48 | private bool enabled = false; | ||
49 | private string qPrefix = "assets"; | ||
50 | |||
51 | // A simple constructor is used to handle any once-only | ||
52 | // initialization of working classes. | ||
53 | |||
54 | public RestAssetServices(RestHandler p_rest) | ||
55 | { | ||
56 | |||
57 | Rest.Log.InfoFormat("{0} Asset services initializing", MsgId); | ||
58 | Rest.Log.InfoFormat("{0} Using REST Implementation Version {1}", MsgId, Rest.Version); | ||
59 | |||
60 | // Integrate domain | ||
61 | |||
62 | if (!qPrefix.StartsWith(Rest.UrlPathSeparator)) | ||
63 | { | ||
64 | qPrefix = Rest.Prefix + Rest.UrlPathSeparator + qPrefix; | ||
65 | } | ||
66 | |||
67 | // Authentication domain | ||
68 | |||
69 | Rest.Domains.Add(key,Rest.Config.GetString("asset-domain",qPrefix)); | ||
70 | |||
71 | // Register interface | ||
72 | |||
73 | Rest.Plugin.AddPathHandler(DoAsset, qPrefix, Allocate); | ||
74 | |||
75 | // Activate | ||
76 | |||
77 | enabled = true; | ||
78 | |||
79 | Rest.Log.InfoFormat("{0} Asset services initialization complete", MsgId); | ||
80 | |||
81 | } | ||
82 | |||
83 | // Post-construction, pre-enabled initialization opportunity | ||
84 | // Not currently exploited. | ||
85 | |||
86 | public void Initialize() | ||
87 | { | ||
88 | } | ||
89 | |||
90 | // Called by the plug-in to halt REST processing. Local processing is | ||
91 | // disabled, and control blocks until all current processing has | ||
92 | // completed. No new processing will be started | ||
93 | |||
94 | public void Close() | ||
95 | { | ||
96 | enabled = false; | ||
97 | Rest.Log.InfoFormat("{0} Asset services closing down", MsgId); | ||
98 | } | ||
99 | |||
100 | // Properties | ||
101 | |||
102 | internal string MsgId | ||
103 | { | ||
104 | get { return Rest.MsgId; } | ||
105 | } | ||
106 | |||
107 | #region Interface | ||
108 | |||
109 | private RequestData Allocate(OSHttpRequest request, OSHttpResponse response) | ||
110 | { | ||
111 | return (RequestData) new AssetRequestData(request, response, qPrefix); | ||
112 | } | ||
113 | |||
114 | // Asset Handler | ||
115 | |||
116 | private void DoAsset(RequestData rparm) | ||
117 | { | ||
118 | |||
119 | if (!enabled) return; | ||
120 | |||
121 | AssetRequestData rdata = (AssetRequestData) rparm; | ||
122 | |||
123 | Rest.Log.DebugFormat("{0} REST Asset handler ENTRY", MsgId); | ||
124 | |||
125 | // Now that we know this is a serious attempt to | ||
126 | // access inventory data, we should find out who | ||
127 | // is asking, and make sure they are authorized | ||
128 | // to do so. We need to validate the caller's | ||
129 | // identity before revealing anything about the | ||
130 | // status quo. Authenticate throws an exception | ||
131 | // via Fail if no identity information is present. | ||
132 | // | ||
133 | // With the present HTTP server we can't use the | ||
134 | // builtin authentication mechanisms because they | ||
135 | // would be enforced for all in-bound requests. | ||
136 | // Instead we look at the headers ourselves and | ||
137 | // handle authentication directly. | ||
138 | |||
139 | try | ||
140 | { | ||
141 | if (!rdata.IsAuthenticated) | ||
142 | { | ||
143 | rdata.Fail(Rest.HttpStatusCodeNotAuthorized, Rest.HttpStatusDescNotAuthorized); | ||
144 | } | ||
145 | } | ||
146 | catch (RestException e) | ||
147 | { | ||
148 | if (e.statusCode == Rest.HttpStatusCodeNotAuthorized) | ||
149 | { | ||
150 | Rest.Log.WarnFormat("{0} User not authenticated", MsgId); | ||
151 | Rest.Log.DebugFormat("{0} Authorization header: {1}", MsgId, | ||
152 | rdata.request.Headers.Get("Authorization")); | ||
153 | } | ||
154 | else | ||
155 | { | ||
156 | Rest.Log.ErrorFormat("{0} User authentication failed", MsgId); | ||
157 | Rest.Log.DebugFormat("{0} Authorization header: {1}", MsgId, | ||
158 | rdata.request.Headers.Get("Authorization")); | ||
159 | } | ||
160 | throw (e); | ||
161 | } | ||
162 | |||
163 | // Remove the prefix and what's left are the parameters. If we don't have | ||
164 | // the parameters we need, fail the request. Parameters do NOT include | ||
165 | // any supplied query values. | ||
166 | |||
167 | if (rdata.parameters.Length > 0) | ||
168 | { | ||
169 | switch (rdata.method) | ||
170 | { | ||
171 | case "get" : | ||
172 | DoGet(rdata); | ||
173 | break; | ||
174 | case "put" : | ||
175 | case "post" : | ||
176 | case "delete" : | ||
177 | default : | ||
178 | Rest.Log.WarnFormat("{0} Asset: Method not supported: {1}", | ||
179 | MsgId, rdata.method); | ||
180 | rdata.Fail(Rest.HttpStatusCodeBadRequest, | ||
181 | Rest.HttpStatusDescBadRequest); | ||
182 | break; | ||
183 | } | ||
184 | } | ||
185 | else | ||
186 | { | ||
187 | Rest.Log.WarnFormat("{0} Asset: No agent information provided", MsgId); | ||
188 | rdata.Fail(Rest.HttpStatusCodeBadRequest, Rest.HttpStatusDescBadRequest); | ||
189 | } | ||
190 | |||
191 | Rest.Log.DebugFormat("{0} REST Asset handler EXIT", MsgId); | ||
192 | |||
193 | } | ||
194 | |||
195 | #endregion Interface | ||
196 | |||
197 | private void DoGet(AssetRequestData rdata) | ||
198 | { | ||
199 | |||
200 | bool istexture = false; | ||
201 | |||
202 | Rest.Log.DebugFormat("{0} REST Asset handler, Method = <{1}> ENTRY", MsgId, rdata.method); | ||
203 | |||
204 | // The only parameter we accept is an LLUUID for | ||
205 | // the asset | ||
206 | |||
207 | if (rdata.parameters.Length == 1) | ||
208 | { | ||
209 | |||
210 | LLUUID uuid = new LLUUID(rdata.parameters[0]); | ||
211 | AssetBase asset = Rest.AssetServices.GetAsset(uuid, istexture); | ||
212 | |||
213 | if (asset != null) | ||
214 | { | ||
215 | |||
216 | Rest.Log.DebugFormat("{0} Asset located <{1}>", MsgId, rdata.parameters[0]); | ||
217 | |||
218 | rdata.initXmlWriter(); | ||
219 | |||
220 | rdata.writer.WriteStartElement(String.Empty,"Asset",String.Empty); | ||
221 | |||
222 | rdata.writer.WriteAttributeString("id", asset.ID.ToString()); | ||
223 | rdata.writer.WriteAttributeString("name", asset.Name); | ||
224 | rdata.writer.WriteAttributeString("desc", asset.Description); | ||
225 | rdata.writer.WriteAttributeString("type", asset.Type.ToString()); | ||
226 | rdata.writer.WriteAttributeString("invtype", asset.InvType.ToString()); | ||
227 | rdata.writer.WriteAttributeString("local", asset.Local.ToString()); | ||
228 | rdata.writer.WriteAttributeString("temporary", asset.Temporary.ToString()); | ||
229 | |||
230 | rdata.writer.WriteBase64(asset.Data,0,asset.Data.Length); | ||
231 | |||
232 | rdata.writer.WriteFullEndElement(); | ||
233 | |||
234 | } | ||
235 | else | ||
236 | { | ||
237 | Rest.Log.DebugFormat("{0} Invalid parameters: <{1}>", MsgId, rdata.path); | ||
238 | rdata.Fail(Rest.HttpStatusCodeNotFound, | ||
239 | Rest.HttpStatusDescNotFound); | ||
240 | } | ||
241 | } | ||
242 | |||
243 | rdata.Complete(); | ||
244 | rdata.Respond("Asset " + rdata.method + ": Normal completion"); | ||
245 | |||
246 | } | ||
247 | |||
248 | internal class AssetRequestData : RequestData | ||
249 | { | ||
250 | internal AssetRequestData(OSHttpRequest request, OSHttpResponse response, string prefix) | ||
251 | : base(request, response, prefix) | ||
252 | { | ||
253 | } | ||
254 | } | ||
255 | |||
256 | } | ||
257 | } | ||