diff options
Diffstat (limited to 'OpenSim/Grid/NewAssetServer/Extensions/OpenSimInventoryFrontend.cs')
-rw-r--r-- | OpenSim/Grid/NewAssetServer/Extensions/OpenSimInventoryFrontend.cs | 636 |
1 files changed, 636 insertions, 0 deletions
diff --git a/OpenSim/Grid/NewAssetServer/Extensions/OpenSimInventoryFrontend.cs b/OpenSim/Grid/NewAssetServer/Extensions/OpenSimInventoryFrontend.cs new file mode 100644 index 0000000..a559f19 --- /dev/null +++ b/OpenSim/Grid/NewAssetServer/Extensions/OpenSimInventoryFrontend.cs | |||
@@ -0,0 +1,636 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008 Intel Corporation | ||
3 | * All rights reserved. | ||
4 | * Redistribution and use in source and binary forms, with or without | ||
5 | * modification, are permitted provided that the following conditions | ||
6 | * are met: | ||
7 | * | ||
8 | * -- Redistributions of source code must retain the above copyright | ||
9 | * notice, this list of conditions and the following disclaimer. | ||
10 | * -- Redistributions in binary form must reproduce the above copyright | ||
11 | * notice, this list of conditions and the following disclaimer in the | ||
12 | * documentation and/or other materials provided with the distribution. | ||
13 | * -- Neither the name of the Intel Corporation nor the names of its | ||
14 | * contributors may be used to endorse or promote products derived from | ||
15 | * this software without specific prior written permission. | ||
16 | * | ||
17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
18 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
19 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A | ||
20 | * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL OR ITS | ||
21 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||
22 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||
23 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||
24 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
25 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||
26 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
27 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
28 | */ | ||
29 | |||
30 | using System; | ||
31 | using System.Collections.Generic; | ||
32 | using System.Net; | ||
33 | using System.IO; | ||
34 | using System.Xml; | ||
35 | using ExtensionLoader; | ||
36 | using OpenMetaverse; | ||
37 | using OpenMetaverse.StructuredData; | ||
38 | using HttpServer; | ||
39 | |||
40 | namespace AssetServer.Extensions | ||
41 | { | ||
42 | public class OpenSimInventoryFrontend : IExtension<AssetServer> | ||
43 | { | ||
44 | AssetServer server; | ||
45 | Utils.InventoryItemSerializer itemSerializer = new Utils.InventoryItemSerializer(); | ||
46 | Utils.InventoryFolderSerializer folderSerializer = new Utils.InventoryFolderSerializer(); | ||
47 | Utils.InventoryCollectionSerializer collectionSerializer = new Utils.InventoryCollectionSerializer(); | ||
48 | |||
49 | public OpenSimInventoryFrontend() | ||
50 | { | ||
51 | } | ||
52 | |||
53 | public void Start(AssetServer server) | ||
54 | { | ||
55 | this.server = server; | ||
56 | |||
57 | server.HttpServer.AddHandler("post", null, @"^/GetInventory/", GetInventoryHandler); | ||
58 | server.HttpServer.AddHandler("post", null, @"^/CreateInventory/", CreateInventoryHandler); | ||
59 | server.HttpServer.AddHandler("post", null, @"^/NewFolder/", NewFolderHandler); | ||
60 | server.HttpServer.AddHandler("post", null, @"^/UpdateFolder/", UpdateFolderHandler); | ||
61 | server.HttpServer.AddHandler("post", null, @"^/MoveFolder/", MoveFolderHandler); | ||
62 | server.HttpServer.AddHandler("post", null, @"^/PurgeFolder/", PurgeFolderHandler); | ||
63 | server.HttpServer.AddHandler("post", null, @"^/NewItem/", NewItemHandler); | ||
64 | server.HttpServer.AddHandler("post", null, @"^/DeleteItem/", DeleteItemHandler); | ||
65 | server.HttpServer.AddHandler("post", null, @"^/RootFolders/", RootFoldersHandler); | ||
66 | server.HttpServer.AddHandler("post", null, @"^/ActiveGestures/", ActiveGesturesHandler); | ||
67 | } | ||
68 | |||
69 | public void Stop() | ||
70 | { | ||
71 | } | ||
72 | |||
73 | bool GetInventoryHandler(IHttpClientContext client, IHttpRequest request, IHttpResponse response) | ||
74 | { | ||
75 | UUID sessionID, agentID; | ||
76 | UUID ownerID = DeserializeUUID(request.Body, out agentID, out sessionID); | ||
77 | |||
78 | if (ownerID != UUID.Zero) | ||
79 | { | ||
80 | Logger.Log.Warn("GetInventory is not scalable on some inventory backends, avoid calling it wherever possible"); | ||
81 | |||
82 | Uri owner = Utils.GetOpenSimUri(ownerID); | ||
83 | InventoryCollection inventory; | ||
84 | BackendResponse storageResponse = server.InventoryProvider.TryFetchInventory(owner, out inventory); | ||
85 | |||
86 | if (storageResponse == BackendResponse.Success) | ||
87 | { | ||
88 | collectionSerializer.Serialize(response.Body, inventory); | ||
89 | response.Body.Flush(); | ||
90 | } | ||
91 | else if (storageResponse == BackendResponse.NotFound) | ||
92 | { | ||
93 | // Return an empty inventory set to mimic OpenSim.Grid.InventoryServer.exe | ||
94 | inventory = new InventoryCollection(); | ||
95 | inventory.UserID = ownerID; | ||
96 | inventory.Folders = new Dictionary<UUID, InventoryFolder>(); | ||
97 | inventory.Items = new Dictionary<UUID, InventoryItem>(); | ||
98 | collectionSerializer.Serialize(response.Body, inventory); | ||
99 | response.Body.Flush(); | ||
100 | } | ||
101 | else | ||
102 | { | ||
103 | response.Status = HttpStatusCode.InternalServerError; | ||
104 | } | ||
105 | } | ||
106 | else | ||
107 | { | ||
108 | response.Status = HttpStatusCode.BadRequest; | ||
109 | } | ||
110 | |||
111 | return true; | ||
112 | } | ||
113 | |||
114 | bool CreateInventoryHandler(IHttpClientContext client, IHttpRequest request, IHttpResponse response) | ||
115 | { | ||
116 | UUID ownerID = DeserializeUUID(request.Body); | ||
117 | |||
118 | if (ownerID != UUID.Zero) | ||
119 | { | ||
120 | Uri owner = Utils.GetOpenSimUri(ownerID); | ||
121 | Logger.Log.DebugFormat("Created URI {0} for inventory creation", owner); | ||
122 | |||
123 | InventoryFolder rootFolder = new InventoryFolder("My Inventory", ownerID, UUID.Zero, (short)AssetType.Folder); | ||
124 | BackendResponse storageResponse = server.InventoryProvider.TryCreateInventory(owner, rootFolder); | ||
125 | if (storageResponse == BackendResponse.Success) | ||
126 | { | ||
127 | CreateFolder("Animations", ownerID, rootFolder.ID, AssetType.Animation); | ||
128 | CreateFolder("Body Parts", ownerID, rootFolder.ID, AssetType.Bodypart); | ||
129 | CreateFolder("Calling Cards", ownerID, rootFolder.ID, AssetType.CallingCard); | ||
130 | CreateFolder("Clothing", ownerID, rootFolder.ID, AssetType.Clothing); | ||
131 | CreateFolder("Gestures", ownerID, rootFolder.ID, AssetType.Gesture); | ||
132 | CreateFolder("Landmarks", ownerID, rootFolder.ID, AssetType.Landmark); | ||
133 | CreateFolder("Lost and Found", ownerID, rootFolder.ID, AssetType.LostAndFoundFolder); | ||
134 | CreateFolder("Notecards", ownerID, rootFolder.ID, AssetType.Notecard); | ||
135 | CreateFolder("Objects", ownerID, rootFolder.ID, AssetType.Object); | ||
136 | CreateFolder("Photo Album", ownerID, rootFolder.ID, AssetType.SnapshotFolder); | ||
137 | CreateFolder("Scripts", ownerID, rootFolder.ID, AssetType.LSLText); | ||
138 | CreateFolder("Sounds", ownerID, rootFolder.ID, AssetType.Sound); | ||
139 | CreateFolder("Textures", ownerID, rootFolder.ID, AssetType.Texture); | ||
140 | CreateFolder("Trash", ownerID, rootFolder.ID, AssetType.TrashFolder); | ||
141 | |||
142 | SerializeBool(response.Body, true); | ||
143 | return true; | ||
144 | } | ||
145 | } | ||
146 | |||
147 | SerializeBool(response.Body, false); | ||
148 | return true; | ||
149 | } | ||
150 | |||
151 | bool NewFolderHandler(IHttpClientContext client, IHttpRequest request, IHttpResponse response) | ||
152 | { | ||
153 | UUID agentID, sessionID; | ||
154 | InventoryFolder folder = DeserializeFolder(request.Body, out agentID, out sessionID); | ||
155 | |||
156 | if (folder != null) | ||
157 | { | ||
158 | Uri owner = Utils.GetOpenSimUri(folder.Owner); | ||
159 | |||
160 | // Some calls that are moving or updating a folder instead of creating a new one | ||
161 | // will pass in an InventoryFolder without the name set. If this is the case we | ||
162 | // need to look up the name first | ||
163 | if (String.IsNullOrEmpty(folder.Name)) | ||
164 | { | ||
165 | InventoryFolder oldFolder; | ||
166 | if (server.InventoryProvider.TryFetchFolder(owner, folder.ID, out oldFolder) == BackendResponse.Success) | ||
167 | folder.Name = oldFolder.Name; | ||
168 | } | ||
169 | |||
170 | BackendResponse storageResponse = server.InventoryProvider.TryCreateFolder(owner, folder); | ||
171 | |||
172 | if (storageResponse == BackendResponse.Success) | ||
173 | { | ||
174 | SerializeBool(response.Body, true); | ||
175 | return true; | ||
176 | } | ||
177 | } | ||
178 | |||
179 | SerializeBool(response.Body, false); | ||
180 | return true; | ||
181 | } | ||
182 | |||
183 | bool UpdateFolderHandler(IHttpClientContext client, IHttpRequest request, IHttpResponse response) | ||
184 | { | ||
185 | return NewFolderHandler(client, request, response); | ||
186 | } | ||
187 | |||
188 | bool MoveFolderHandler(IHttpClientContext client, IHttpRequest request, IHttpResponse response) | ||
189 | { | ||
190 | return NewFolderHandler(client, request, response); | ||
191 | } | ||
192 | |||
193 | bool PurgeFolderHandler(IHttpClientContext client, IHttpRequest request, IHttpResponse response) | ||
194 | { | ||
195 | UUID agentID, sessionID; | ||
196 | InventoryFolder folder = DeserializeFolder(request.Body, out agentID, out sessionID); | ||
197 | |||
198 | if (folder != null) | ||
199 | { | ||
200 | Uri owner = Utils.GetOpenSimUri(folder.Owner); | ||
201 | BackendResponse storageResponse = server.InventoryProvider.TryPurgeFolder(owner, folder.ID); | ||
202 | |||
203 | if (storageResponse == BackendResponse.Success) | ||
204 | { | ||
205 | SerializeBool(response.Body, true); | ||
206 | return true; | ||
207 | } | ||
208 | } | ||
209 | |||
210 | SerializeBool(response.Body, false); | ||
211 | return true; | ||
212 | } | ||
213 | |||
214 | bool NewItemHandler(IHttpClientContext client, IHttpRequest request, IHttpResponse response) | ||
215 | { | ||
216 | UUID agentID, sessionID; | ||
217 | InventoryItem item = DeserializeItem(request.Body, out agentID, out sessionID); | ||
218 | |||
219 | if (item != null) | ||
220 | { | ||
221 | Uri owner = Utils.GetOpenSimUri(agentID); | ||
222 | BackendResponse storageResponse = server.InventoryProvider.TryCreateItem(owner, item); | ||
223 | |||
224 | if (storageResponse == BackendResponse.Success) | ||
225 | { | ||
226 | SerializeBool(response.Body, true); | ||
227 | return true; | ||
228 | } | ||
229 | } | ||
230 | |||
231 | SerializeBool(response.Body, false); | ||
232 | return true; | ||
233 | } | ||
234 | |||
235 | bool DeleteItemHandler(IHttpClientContext client, IHttpRequest request, IHttpResponse response) | ||
236 | { | ||
237 | UUID agentID, sessionID; | ||
238 | InventoryItem item = DeserializeItem(request.Body, out agentID, out sessionID); | ||
239 | |||
240 | if (item != null) | ||
241 | { | ||
242 | Uri owner = Utils.GetOpenSimUri(item.Owner); | ||
243 | BackendResponse storageResponse = server.InventoryProvider.TryDeleteItem(owner, item.ID); | ||
244 | |||
245 | if (storageResponse == BackendResponse.Success) | ||
246 | { | ||
247 | SerializeBool(response.Body, true); | ||
248 | return true; | ||
249 | } | ||
250 | } | ||
251 | |||
252 | SerializeBool(response.Body, false); | ||
253 | return true; | ||
254 | } | ||
255 | |||
256 | bool RootFoldersHandler(IHttpClientContext client, IHttpRequest request, IHttpResponse response) | ||
257 | { | ||
258 | UUID ownerID = DeserializeUUID(request.Body); | ||
259 | |||
260 | if (ownerID != UUID.Zero) | ||
261 | { | ||
262 | Uri owner = Utils.GetOpenSimUri(ownerID); | ||
263 | List<InventoryFolder> skeleton; | ||
264 | BackendResponse storageResponse = server.InventoryProvider.TryFetchFolderList(owner, out skeleton); | ||
265 | |||
266 | if (storageResponse == BackendResponse.Success) | ||
267 | { | ||
268 | SerializeFolderList(response.Body, skeleton); | ||
269 | } | ||
270 | else if (storageResponse == BackendResponse.NotFound) | ||
271 | { | ||
272 | // Return an empty set of inventory so the requester knows that | ||
273 | // an inventory needs to be created for this agent | ||
274 | SerializeFolderList(response.Body, new List<InventoryFolder>(0)); | ||
275 | } | ||
276 | else | ||
277 | { | ||
278 | response.Status = HttpStatusCode.InternalServerError; | ||
279 | } | ||
280 | } | ||
281 | else | ||
282 | { | ||
283 | response.Status = HttpStatusCode.BadRequest; | ||
284 | } | ||
285 | |||
286 | return true; | ||
287 | } | ||
288 | |||
289 | bool ActiveGesturesHandler(IHttpClientContext client, IHttpRequest request, IHttpResponse response) | ||
290 | { | ||
291 | UUID ownerID = DeserializeUUID(request.Body); | ||
292 | |||
293 | if (ownerID != UUID.Zero) | ||
294 | { | ||
295 | Uri owner = Utils.GetOpenSimUri(ownerID); | ||
296 | List<InventoryItem> gestures; | ||
297 | BackendResponse storageResponse = server.InventoryProvider.TryFetchActiveGestures(owner, out gestures); | ||
298 | |||
299 | if (storageResponse == BackendResponse.Success) | ||
300 | { | ||
301 | SerializeItemList(response.Body, gestures); | ||
302 | } | ||
303 | else if (storageResponse == BackendResponse.NotFound) | ||
304 | { | ||
305 | // Return an empty set of gestures to match OpenSim.Grid.InventoryServer.exe behavior | ||
306 | SerializeItemList(response.Body, new List<InventoryItem>(0)); | ||
307 | } | ||
308 | else | ||
309 | { | ||
310 | response.Status = HttpStatusCode.InternalServerError; | ||
311 | } | ||
312 | } | ||
313 | else | ||
314 | { | ||
315 | response.Status = HttpStatusCode.BadRequest; | ||
316 | } | ||
317 | |||
318 | return true; | ||
319 | } | ||
320 | |||
321 | BackendResponse CreateFolder(string name, UUID ownerID, UUID parentID, AssetType assetType) | ||
322 | { | ||
323 | InventoryFolder folder = new InventoryFolder(name, ownerID, parentID, (short)assetType); | ||
324 | Uri owner = Utils.GetOpenSimUri(ownerID); | ||
325 | return server.InventoryProvider.TryCreateFolder(owner, folder); | ||
326 | } | ||
327 | |||
328 | UUID DeserializeUUID(Stream stream) | ||
329 | { | ||
330 | UUID id = UUID.Zero; | ||
331 | |||
332 | try | ||
333 | { | ||
334 | using (XmlReader reader = XmlReader.Create(stream)) | ||
335 | { | ||
336 | reader.MoveToContent(); | ||
337 | UUID.TryParse(reader.ReadElementContentAsString("guid", String.Empty), out id); | ||
338 | } | ||
339 | } | ||
340 | catch (Exception ex) | ||
341 | { | ||
342 | Logger.Log.Warn("Failed to parse POST data (expecting guid): " + ex.Message); | ||
343 | } | ||
344 | |||
345 | return id; | ||
346 | } | ||
347 | |||
348 | UUID DeserializeUUID(Stream stream, out UUID agentID, out UUID sessionID) | ||
349 | { | ||
350 | UUID id; | ||
351 | |||
352 | try | ||
353 | { | ||
354 | using (XmlReader reader = XmlReader.Create(stream)) | ||
355 | { | ||
356 | reader.MoveToContent(); | ||
357 | reader.ReadStartElement("RestSessionObjectOfGuid"); | ||
358 | UUID.TryParse(reader.ReadElementContentAsString("SessionID", String.Empty), out sessionID); | ||
359 | UUID.TryParse(reader.ReadElementContentAsString("AvatarID", String.Empty), out agentID); | ||
360 | UUID.TryParse(reader.ReadElementContentAsString("Body", String.Empty), out id); | ||
361 | reader.ReadEndElement(); | ||
362 | } | ||
363 | } | ||
364 | catch (Exception ex) | ||
365 | { | ||
366 | Logger.Log.Warn("Failed to parse GetInventory POST data: " + ex.Message); | ||
367 | agentID = UUID.Zero; | ||
368 | sessionID = UUID.Zero; | ||
369 | return UUID.Zero; | ||
370 | } | ||
371 | |||
372 | return id; | ||
373 | } | ||
374 | |||
375 | InventoryFolder DeserializeFolder(Stream stream, out UUID agentID, out UUID sessionID) | ||
376 | { | ||
377 | InventoryFolder folder = new InventoryFolder(); | ||
378 | |||
379 | try | ||
380 | { | ||
381 | using (XmlReader reader = XmlReader.Create(stream)) | ||
382 | { | ||
383 | reader.MoveToContent(); | ||
384 | reader.ReadStartElement("RestSessionObjectOfInventoryFolderBase"); | ||
385 | UUID.TryParse(reader.ReadElementContentAsString("SessionID", String.Empty), out sessionID); | ||
386 | UUID.TryParse(reader.ReadElementContentAsString("AvatarID", String.Empty), out agentID); | ||
387 | reader.ReadStartElement("Body"); | ||
388 | if (reader.Name == "Name") | ||
389 | folder.Name = reader.ReadElementContentAsString("Name", String.Empty); | ||
390 | else | ||
391 | folder.Name = String.Empty; | ||
392 | ReadUUID(reader, "Owner", out folder.Owner); | ||
393 | ReadUUID(reader, "ParentID", out folder.ParentID); | ||
394 | ReadUUID(reader, "ID", out folder.ID); | ||
395 | Int16.TryParse(reader.ReadElementContentAsString("Type", String.Empty), out folder.Type); | ||
396 | UInt16.TryParse(reader.ReadElementContentAsString("Version", String.Empty), out folder.Version); | ||
397 | reader.ReadEndElement(); | ||
398 | reader.ReadEndElement(); | ||
399 | } | ||
400 | } | ||
401 | catch (Exception ex) | ||
402 | { | ||
403 | Logger.Log.Warn("Failed to parse POST data (expecting InventoryFolderBase): " + ex.Message); | ||
404 | agentID = UUID.Zero; | ||
405 | sessionID = UUID.Zero; | ||
406 | return null; | ||
407 | } | ||
408 | |||
409 | return folder; | ||
410 | } | ||
411 | |||
412 | InventoryItem DeserializeItem(Stream stream, out UUID agentID, out UUID sessionID) | ||
413 | { | ||
414 | InventoryItem item = new InventoryItem(); | ||
415 | |||
416 | try | ||
417 | { | ||
418 | using (XmlReader reader = XmlReader.Create(stream)) | ||
419 | { | ||
420 | reader.MoveToContent(); | ||
421 | reader.ReadStartElement("RestSessionObjectOfInventoryItemBase"); | ||
422 | UUID.TryParse(reader.ReadElementContentAsString("SessionID", String.Empty), out sessionID); | ||
423 | UUID.TryParse(reader.ReadElementContentAsString("AvatarID", String.Empty), out agentID); | ||
424 | reader.ReadStartElement("Body"); | ||
425 | ReadUUID(reader, "ID", out item.ID); | ||
426 | Int32.TryParse(reader.ReadElementContentAsString("InvType", String.Empty), out item.InvType); | ||
427 | ReadUUID(reader, "Folder", out item.Folder); | ||
428 | ReadUUID(reader, "Owner", out item.Owner); | ||
429 | ReadUUID(reader, "Creator", out item.Creator); | ||
430 | item.Name = reader.ReadElementContentAsString("Name", String.Empty); | ||
431 | item.Description = reader.ReadElementContentAsString("Description", String.Empty); | ||
432 | UInt32.TryParse(reader.ReadElementContentAsString("NextPermissions", String.Empty), out item.NextPermissions); | ||
433 | UInt32.TryParse(reader.ReadElementContentAsString("CurrentPermissions", String.Empty), out item.CurrentPermissions); | ||
434 | UInt32.TryParse(reader.ReadElementContentAsString("BasePermissions", String.Empty), out item.BasePermissions); | ||
435 | UInt32.TryParse(reader.ReadElementContentAsString("EveryOnePermissions", String.Empty), out item.EveryOnePermissions); | ||
436 | UInt32.TryParse(reader.ReadElementContentAsString("GroupPermissions", String.Empty), out item.GroupPermissions); | ||
437 | Int32.TryParse(reader.ReadElementContentAsString("AssetType", String.Empty), out item.AssetType); | ||
438 | ReadUUID(reader, "AssetID", out item.AssetID); | ||
439 | ReadUUID(reader, "GroupID", out item.GroupID); | ||
440 | Boolean.TryParse(reader.ReadElementContentAsString("GroupOwned", String.Empty), out item.GroupOwned); | ||
441 | Int32.TryParse(reader.ReadElementContentAsString("SalePrice", String.Empty), out item.SalePrice); | ||
442 | Byte.TryParse(reader.ReadElementContentAsString("SaleType", String.Empty), out item.SaleType); | ||
443 | UInt32.TryParse(reader.ReadElementContentAsString("Flags", String.Empty), out item.Flags); | ||
444 | Int32.TryParse(reader.ReadElementContentAsString("CreationDate", String.Empty), out item.CreationDate); | ||
445 | reader.ReadEndElement(); | ||
446 | reader.ReadEndElement(); | ||
447 | } | ||
448 | } | ||
449 | catch (Exception ex) | ||
450 | { | ||
451 | Logger.Log.Warn("Failed to parse POST data (expecting InventoryItemBase): " + ex.Message); | ||
452 | agentID = UUID.Zero; | ||
453 | sessionID = UUID.Zero; | ||
454 | return null; | ||
455 | } | ||
456 | |||
457 | return item; | ||
458 | } | ||
459 | |||
460 | void SerializeBool(Stream stream, bool value) | ||
461 | { | ||
462 | using (XmlWriter writer = XmlWriter.Create(stream)) | ||
463 | { | ||
464 | writer.WriteStartDocument(); | ||
465 | writer.WriteStartElement("boolean"); | ||
466 | writer.WriteAttributeString("xmlns", "xsi", null, "http://www.w3.org/2001/XMLSchema-instance"); | ||
467 | writer.WriteAttributeString("xmlns", "xsd", null, "http://www.w3.org/2001/XMLSchema"); | ||
468 | writer.WriteString(value.ToString().ToLower()); | ||
469 | writer.WriteEndElement(); | ||
470 | writer.WriteEndDocument(); | ||
471 | writer.Flush(); | ||
472 | } | ||
473 | |||
474 | stream.Flush(); | ||
475 | } | ||
476 | |||
477 | void SerializeFolderList(Stream stream, List<InventoryFolder> folders) | ||
478 | { | ||
479 | using (XmlWriter writer = XmlWriter.Create(stream)) | ||
480 | { | ||
481 | writer.WriteStartDocument(); | ||
482 | writer.WriteStartElement("ArrayOfInventoryFolderBase"); | ||
483 | writer.WriteAttributeString("xmlns", "xsi", null, "http://www.w3.org/2001/XMLSchema-instance"); | ||
484 | writer.WriteAttributeString("xmlns", "xsd", null, "http://www.w3.org/2001/XMLSchema"); | ||
485 | |||
486 | if (folders != null) | ||
487 | { | ||
488 | foreach (InventoryFolder folder in folders) | ||
489 | { | ||
490 | writer.WriteStartElement("InventoryFolderBase"); | ||
491 | writer.WriteElementString("Name", folder.Name); | ||
492 | WriteUUID(writer, "Owner", folder.Owner); | ||
493 | WriteUUID(writer, "ParentID", folder.ParentID); | ||
494 | WriteUUID(writer, "ID", folder.ID); | ||
495 | writer.WriteElementString("Type", XmlConvert.ToString(folder.Type)); | ||
496 | writer.WriteElementString("Version", XmlConvert.ToString(folder.Version)); | ||
497 | writer.WriteEndElement(); | ||
498 | } | ||
499 | } | ||
500 | |||
501 | writer.WriteEndElement(); | ||
502 | writer.WriteEndDocument(); | ||
503 | |||
504 | writer.Flush(); | ||
505 | } | ||
506 | |||
507 | stream.Flush(); | ||
508 | } | ||
509 | |||
510 | void SerializeItemList(Stream stream, List<InventoryItem> items) | ||
511 | { | ||
512 | using (XmlWriter writer = XmlWriter.Create(stream)) | ||
513 | { | ||
514 | writer.WriteStartDocument(); | ||
515 | writer.WriteStartElement("ArrayOfInventoryItemBase"); | ||
516 | writer.WriteAttributeString("xmlns", "xsi", null, "http://www.w3.org/2001/XMLSchema-instance"); | ||
517 | writer.WriteAttributeString("xmlns", "xsd", null, "http://www.w3.org/2001/XMLSchema"); | ||
518 | |||
519 | if (items != null) | ||
520 | { | ||
521 | foreach (InventoryItem item in items) | ||
522 | { | ||
523 | writer.WriteStartElement("InventoryItemBase"); | ||
524 | WriteUUID(writer, "ID", item.ID); | ||
525 | writer.WriteElementString("InvType", XmlConvert.ToString(item.InvType)); | ||
526 | WriteUUID(writer, "Folder", item.Folder); | ||
527 | WriteUUID(writer, "Owner", item.Owner); | ||
528 | WriteUUID(writer, "Creator", item.Creator); | ||
529 | writer.WriteElementString("Name", item.Name); | ||
530 | writer.WriteElementString("Description", item.Description); | ||
531 | writer.WriteElementString("NextPermissions", XmlConvert.ToString(item.NextPermissions)); | ||
532 | writer.WriteElementString("CurrentPermissions", XmlConvert.ToString(item.CurrentPermissions)); | ||
533 | writer.WriteElementString("BasePermissions", XmlConvert.ToString(item.BasePermissions)); | ||
534 | writer.WriteElementString("EveryOnePermissions", XmlConvert.ToString(item.EveryOnePermissions)); | ||
535 | writer.WriteElementString("GroupPermissions", XmlConvert.ToString(item.GroupPermissions)); | ||
536 | writer.WriteElementString("AssetType", XmlConvert.ToString(item.AssetType)); | ||
537 | WriteUUID(writer, "AssetID", item.AssetID); | ||
538 | WriteUUID(writer, "GroupID", item.GroupID); | ||
539 | writer.WriteElementString("GroupOwned", XmlConvert.ToString(item.GroupOwned)); | ||
540 | writer.WriteElementString("SalePrice", XmlConvert.ToString(item.SalePrice)); | ||
541 | writer.WriteElementString("SaleType", XmlConvert.ToString(item.SaleType)); | ||
542 | writer.WriteElementString("Flags", XmlConvert.ToString(item.Flags)); | ||
543 | writer.WriteElementString("CreationDate", XmlConvert.ToString(item.CreationDate)); | ||
544 | writer.WriteEndElement(); | ||
545 | } | ||
546 | } | ||
547 | |||
548 | writer.WriteEndElement(); | ||
549 | writer.WriteEndDocument(); | ||
550 | |||
551 | writer.Flush(); | ||
552 | } | ||
553 | |||
554 | stream.Flush(); | ||
555 | } | ||
556 | |||
557 | void WriteUUID(XmlWriter writer, string name, UUID id) | ||
558 | { | ||
559 | writer.WriteStartElement(name); | ||
560 | writer.WriteElementString("Guid", XmlConvert.ToString(id.Guid)); | ||
561 | writer.WriteEndElement(); | ||
562 | } | ||
563 | |||
564 | void ReadUUID(XmlReader reader, string name, out UUID id) | ||
565 | { | ||
566 | reader.ReadStartElement(name); | ||
567 | UUID.TryParse(reader.ReadElementContentAsString("Guid", String.Empty), out id); | ||
568 | reader.ReadEndElement(); | ||
569 | } | ||
570 | } | ||
571 | |||
572 | #region OpenSim AssetType | ||
573 | |||
574 | /// <summary> | ||
575 | /// The different types of grid assets | ||
576 | /// </summary> | ||
577 | public enum AssetType : sbyte | ||
578 | { | ||
579 | /// <summary>Unknown asset type</summary> | ||
580 | Unknown = -1, | ||
581 | /// <summary>Texture asset, stores in JPEG2000 J2C stream format</summary> | ||
582 | Texture = 0, | ||
583 | /// <summary>Sound asset</summary> | ||
584 | Sound = 1, | ||
585 | /// <summary>Calling card for another avatar</summary> | ||
586 | CallingCard = 2, | ||
587 | /// <summary>Link to a location in world</summary> | ||
588 | Landmark = 3, | ||
589 | // <summary>Legacy script asset, you should never see one of these</summary> | ||
590 | //[Obsolete] | ||
591 | //Script = 4, | ||
592 | /// <summary>Collection of textures and parameters that can be | ||
593 | /// worn by an avatar</summary> | ||
594 | Clothing = 5, | ||
595 | /// <summary>Primitive that can contain textures, sounds, | ||
596 | /// scripts and more</summary> | ||
597 | Object = 6, | ||
598 | /// <summary>Notecard asset</summary> | ||
599 | Notecard = 7, | ||
600 | /// <summary>Holds a collection of inventory items</summary> | ||
601 | Folder = 8, | ||
602 | /// <summary>Root inventory folder</summary> | ||
603 | RootFolder = 9, | ||
604 | /// <summary>Linden scripting language script</summary> | ||
605 | LSLText = 10, | ||
606 | /// <summary>LSO bytecode for a script</summary> | ||
607 | LSLBytecode = 11, | ||
608 | /// <summary>Uncompressed TGA texture</summary> | ||
609 | TextureTGA = 12, | ||
610 | /// <summary>Collection of textures and shape parameters that can | ||
611 | /// be worn</summary> | ||
612 | Bodypart = 13, | ||
613 | /// <summary>Trash folder</summary> | ||
614 | TrashFolder = 14, | ||
615 | /// <summary>Snapshot folder</summary> | ||
616 | SnapshotFolder = 15, | ||
617 | /// <summary>Lost and found folder</summary> | ||
618 | LostAndFoundFolder = 16, | ||
619 | /// <summary>Uncompressed sound</summary> | ||
620 | SoundWAV = 17, | ||
621 | /// <summary>Uncompressed TGA non-square image, not to be used as a | ||
622 | /// texture</summary> | ||
623 | ImageTGA = 18, | ||
624 | /// <summary>Compressed JPEG non-square image, not to be used as a | ||
625 | /// texture</summary> | ||
626 | ImageJPEG = 19, | ||
627 | /// <summary>Animation</summary> | ||
628 | Animation = 20, | ||
629 | /// <summary>Sequence of animations, sounds, chat, and pauses</summary> | ||
630 | Gesture = 21, | ||
631 | /// <summary>Simstate file</summary> | ||
632 | Simstate = 22, | ||
633 | } | ||
634 | |||
635 | #endregion OpenSim AssetType | ||
636 | } | ||