opensim – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 eva 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  
28 using System;
29 using System.Collections.Generic;
30 using System.Collections.Specialized;
31 using System.Reflection;
32 using log4net;
33 using Mono.Addins;
34 using Nini.Config;
35 using OpenMetaverse;
36 using OpenMetaverse.StructuredData;
37 using OpenSim.Framework;
38 using OpenSim.Region.Framework.Interfaces;
39 using OpenSim.Region.Framework.Scenes;
40 using OpenSim.Services.Interfaces;
41 using PermissionMask = OpenSim.Framework.PermissionMask;
42  
43 namespace OpenSim.Services.Connectors.SimianGrid
44 {
45 /// <summary>
46 /// Permissions bitflags
47 /// </summary>
48 /*
49 [Flags]
50 public enum PermissionMask : uint
51 {
52 None = 0,
53 Transfer = 1 << 13,
54 Modify = 1 << 14,
55 Copy = 1 << 15,
56 Move = 1 << 19,
57 Damage = 1 << 20,
58 All = 0x7FFFFFFF
59 }
60 */
61  
62 /// <summary>
63 /// Connects avatar inventories to the SimianGrid backend
64 /// </summary>
65 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SimianInventoryServiceConnector")]
66 public class SimianInventoryServiceConnector : IInventoryService, ISharedRegionModule
67 {
68 private static readonly ILog m_log =
69 LogManager.GetLogger(
70 MethodBase.GetCurrentMethod().DeclaringType);
71  
72 private string m_serverUrl = String.Empty;
73 private string m_userServerUrl = String.Empty;
74 // private object m_gestureSyncRoot = new object();
75 private bool m_Enabled = false;
76  
77 #region ISharedRegionModule
78  
79 public Type ReplaceableInterface { get { return null; } }
80 public void RegionLoaded(Scene scene) { }
81 public void PostInitialise() { }
82 public void Close() { }
83  
84 public SimianInventoryServiceConnector() { }
85 public string Name { get { return "SimianInventoryServiceConnector"; } }
86 public void AddRegion(Scene scene) { if (m_Enabled) { scene.RegisterModuleInterface<IInventoryService>(this); } }
87 public void RemoveRegion(Scene scene) { if (m_Enabled) { scene.UnregisterModuleInterface<IInventoryService>(this); } }
88  
89 #endregion ISharedRegionModule
90  
91 public SimianInventoryServiceConnector(IConfigSource source)
92 {
93 CommonInit(source);
94 }
95  
96 public SimianInventoryServiceConnector(string url)
97 {
98 if (!url.EndsWith("/") && !url.EndsWith("="))
99 url = url + '/';
100 m_serverUrl = url;
101  
102 }
103  
104 public void Initialise(IConfigSource source)
105 {
106 IConfig moduleConfig = source.Configs["Modules"];
107 if (moduleConfig != null)
108 {
109 string name = moduleConfig.GetString("InventoryServices", "");
110 if (name == Name)
111 CommonInit(source);
112 }
113 }
114  
115 private void CommonInit(IConfigSource source)
116 {
117 IConfig gridConfig = source.Configs["InventoryService"];
118 if (gridConfig != null)
119 {
120 string serviceUrl = gridConfig.GetString("InventoryServerURI");
121 if (!String.IsNullOrEmpty(serviceUrl))
122 {
123 if (!serviceUrl.EndsWith("/") && !serviceUrl.EndsWith("="))
124 serviceUrl = serviceUrl + '/';
125 m_serverUrl = serviceUrl;
126  
127 gridConfig = source.Configs["UserAccountService"];
128 if (gridConfig != null)
129 {
130 serviceUrl = gridConfig.GetString("UserAccountServerURI");
131 if (!String.IsNullOrEmpty(serviceUrl))
132 {
133 m_userServerUrl = serviceUrl;
134 m_Enabled = true;
135 }
136 }
137 }
138 }
139  
140 if (String.IsNullOrEmpty(m_serverUrl))
141 m_log.Info("[SIMIAN INVENTORY CONNECTOR]: No InventoryServerURI specified, disabling connector");
142 else if (String.IsNullOrEmpty(m_userServerUrl))
143 m_log.Info("[SIMIAN INVENTORY CONNECTOR]: No UserAccountServerURI specified, disabling connector");
144 }
145  
146 /// <summary>
147 /// Create the entire inventory for a given user
148 /// </summary>
149 /// <param name="user"></param>
150 /// <returns></returns>
151 public bool CreateUserInventory(UUID userID)
152 {
153 NameValueCollection requestArgs = new NameValueCollection
154 {
155 { "RequestMethod", "AddInventory" },
156 { "OwnerID", userID.ToString() }
157 };
158  
159 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
160 bool success = response["Success"].AsBoolean();
161  
162 if (!success)
163 m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Inventory creation for " + userID + " failed: " + response["Message"].AsString());
164  
165 return success;
166 }
167  
168 /// <summary>
169 /// Gets the skeleton of the inventory -- folders only
170 /// </summary>
171 /// <param name="userID"></param>
172 /// <returns></returns>
173 public List<InventoryFolderBase> GetInventorySkeleton(UUID userID)
174 {
175 NameValueCollection requestArgs = new NameValueCollection
176 {
177 { "RequestMethod", "GetInventoryNode" },
178 { "ItemID", userID.ToString() },
179 { "OwnerID", userID.ToString() },
180 { "IncludeFolders", "1" },
181 { "IncludeItems", "0" },
182 { "ChildrenOnly", "0" }
183 };
184  
185 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
186 if (response["Success"].AsBoolean() && response["Items"] is OSDArray)
187 {
188 OSDArray items = (OSDArray)response["Items"];
189 return GetFoldersFromResponse(items, userID, true);
190 }
191 else
192 {
193 m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Failed to retrieve inventory skeleton for " + userID + ": " +
194 response["Message"].AsString());
195 return new List<InventoryFolderBase>(0);
196 }
197 }
198  
199 /// <summary>
200 /// Synchronous inventory fetch.
201 /// </summary>
202 /// <param name="userID"></param>
203 /// <returns></returns>
204 [Obsolete]
205 public InventoryCollection GetUserInventory(UUID userID)
206 {
207 m_log.Error("[SIMIAN INVENTORY CONNECTOR]: Obsolete GetUserInventory called for " + userID);
208  
209 InventoryCollection inventory = new InventoryCollection();
210 inventory.UserID = userID;
211 inventory.Folders = new List<InventoryFolderBase>();
212 inventory.Items = new List<InventoryItemBase>();
213  
214 return inventory;
215 }
216  
217 /// <summary>
218 /// Request the inventory for a user. This is an asynchronous operation that will call the callback when the
219 /// inventory has been received
220 /// </summary>
221 /// <param name="userID"></param>
222 /// <param name="callback"></param>
223 [Obsolete]
224 public void GetUserInventory(UUID userID, InventoryReceiptCallback callback)
225 {
226 m_log.Error("[SIMIAN INVENTORY CONNECTOR]: Obsolete GetUserInventory called for " + userID);
227 callback(new List<InventoryFolderImpl>(0), new List<InventoryItemBase>(0));
228 }
229  
230 /// <summary>
231 /// Retrieve the root inventory folder for the given user.
232 /// </summary>
233 /// <param name="userID"></param>
234 /// <returns>null if no root folder was found</returns>
235 public InventoryFolderBase GetRootFolder(UUID userID)
236 {
237 NameValueCollection requestArgs = new NameValueCollection
238 {
239 { "RequestMethod", "GetInventoryNode" },
240 { "ItemID", userID.ToString() },
241 { "OwnerID", userID.ToString() },
242 { "IncludeFolders", "1" },
243 { "IncludeItems", "0" },
244 { "ChildrenOnly", "1" }
245 };
246  
247 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
248 if (response["Success"].AsBoolean() && response["Items"] is OSDArray)
249 {
250 OSDArray items = (OSDArray)response["Items"];
251 List<InventoryFolderBase> folders = GetFoldersFromResponse(items, userID, true);
252  
253 if (folders.Count > 0)
254 return folders[0];
255 }
256  
257 return null;
258 }
259  
260 /// <summary>
261 /// Gets the user folder for the given folder-type
262 /// </summary>
263 /// <param name="userID"></param>
264 /// <param name="type"></param>
265 /// <returns></returns>
266 public InventoryFolderBase GetFolderForType(UUID userID, AssetType type)
267 {
268 string contentType = SLUtil.SLAssetTypeToContentType((int)type);
269  
270 NameValueCollection requestArgs = new NameValueCollection
271 {
272 { "RequestMethod", "GetFolderForType" },
273 { "ContentType", contentType },
274 { "OwnerID", userID.ToString() }
275 };
276  
277 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
278 if (response["Success"].AsBoolean() && response["Folder"] is OSDMap)
279 {
280 OSDMap folder = (OSDMap)response["Folder"];
281  
282 return new InventoryFolderBase(
283 folder["ID"].AsUUID(),
284 folder["Name"].AsString(),
285 folder["OwnerID"].AsUUID(),
286 (short)SLUtil.ContentTypeToSLAssetType(folder["ContentType"].AsString()),
287 folder["ParentID"].AsUUID(),
288 (ushort)folder["Version"].AsInteger()
289 );
290 }
291 else
292 {
293 m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Default folder not found for content type " + contentType + ": " + response["Message"].AsString());
294 return GetRootFolder(userID);
295 }
296 }
297  
298 /// <summary>
299 /// Get an item, given by its UUID
300 /// </summary>
301 /// <param name="item"></param>
302 /// <returns></returns>
303 public InventoryItemBase GetItem(InventoryItemBase item)
304 {
305 NameValueCollection requestArgs = new NameValueCollection
306 {
307 { "RequestMethod", "GetInventoryNode" },
308 { "ItemID", item.ID.ToString() },
309 { "OwnerID", item.Owner.ToString() },
310 { "IncludeFolders", "1" },
311 { "IncludeItems", "1" },
312 { "ChildrenOnly", "1" }
313 };
314  
315 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
316 if (response["Success"].AsBoolean() && response["Items"] is OSDArray)
317 {
318 List<InventoryItemBase> items = GetItemsFromResponse((OSDArray)response["Items"]);
319 if (items.Count > 0)
320 {
321 // The requested item should be the first in this list, but loop through
322 // and sanity check just in case
323 for (int i = 0; i < items.Count; i++)
324 {
325 if (items[i].ID == item.ID)
326 return items[i];
327 }
328 }
329 }
330  
331 m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Item " + item.ID + " owned by " + item.Owner + " not found");
332 return null;
333 }
334  
335 /// <summary>
336 /// Get a folder, given by its UUID
337 /// </summary>
338 /// <param name="folder"></param>
339 /// <returns></returns>
340 public InventoryFolderBase GetFolder(InventoryFolderBase folder)
341 {
342 NameValueCollection requestArgs = new NameValueCollection
343 {
344 { "RequestMethod", "GetInventoryNode" },
345 { "ItemID", folder.ID.ToString() },
346 { "OwnerID", folder.Owner.ToString() },
347 { "IncludeFolders", "1" },
348 { "IncludeItems", "0" },
349 { "ChildrenOnly", "1" }
350 };
351  
352 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
353 if (response["Success"].AsBoolean() && response["Items"] is OSDArray)
354 {
355 OSDArray items = (OSDArray)response["Items"];
356 List<InventoryFolderBase> folders = GetFoldersFromResponse(items, folder.ID, true);
357  
358 if (folders.Count > 0)
359 return folders[0];
360 }
361  
362 return null;
363 }
364  
365 /// <summary>
366 /// Gets everything (folders and items) inside a folder
367 /// </summary>
368 /// <param name="userID"></param>
369 /// <param name="folderID"></param>
370 /// <returns></returns>
371 public InventoryCollection GetFolderContent(UUID userID, UUID folderID)
372 {
373 InventoryCollection inventory = new InventoryCollection();
374 inventory.UserID = userID;
375  
376 NameValueCollection requestArgs = new NameValueCollection
377 {
378 { "RequestMethod", "GetInventoryNode" },
379 { "ItemID", folderID.ToString() },
380 { "OwnerID", userID.ToString() },
381 { "IncludeFolders", "1" },
382 { "IncludeItems", "1" },
383 { "ChildrenOnly", "1" }
384 };
385  
386 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
387 if (response["Success"].AsBoolean() && response["Items"] is OSDArray)
388 {
389 OSDArray items = (OSDArray)response["Items"];
390  
391 inventory.Folders = GetFoldersFromResponse(items, folderID, false);
392 inventory.Items = GetItemsFromResponse(items);
393 }
394 else
395 {
396 m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Error fetching folder " + folderID + " content for " + userID + ": " +
397 response["Message"].AsString());
398 inventory.Folders = new List<InventoryFolderBase>(0);
399 inventory.Items = new List<InventoryItemBase>(0);
400 }
401  
402 return inventory;
403 }
404  
405 /// <summary>
406 /// Gets the items inside a folder
407 /// </summary>
408 /// <param name="userID"></param>
409 /// <param name="folderID"></param>
410 /// <returns></returns>
411 public List<InventoryItemBase> GetFolderItems(UUID userID, UUID folderID)
412 {
413 InventoryCollection inventory = new InventoryCollection();
414 inventory.UserID = userID;
415  
416 NameValueCollection requestArgs = new NameValueCollection
417 {
418 { "RequestMethod", "GetInventoryNode" },
419 { "ItemID", folderID.ToString() },
420 { "OwnerID", userID.ToString() },
421 { "IncludeFolders", "0" },
422 { "IncludeItems", "1" },
423 { "ChildrenOnly", "1" }
424 };
425  
426 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
427 if (response["Success"].AsBoolean() && response["Items"] is OSDArray)
428 {
429 OSDArray items = (OSDArray)response["Items"];
430 return GetItemsFromResponse(items);
431 }
432 else
433 {
434 m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Error fetching folder " + folderID + " for " + userID + ": " +
435 response["Message"].AsString());
436 return new List<InventoryItemBase>(0);
437 }
438 }
439  
440 /// <summary>
441 /// Add a new folder to the user's inventory
442 /// </summary>
443 /// <param name="folder"></param>
444 /// <returns>true if the folder was successfully added</returns>
445 public bool AddFolder(InventoryFolderBase folder)
446 {
447 NameValueCollection requestArgs = new NameValueCollection
448 {
449 { "RequestMethod", "AddInventoryFolder" },
450 { "FolderID", folder.ID.ToString() },
451 { "ParentID", folder.ParentID.ToString() },
452 { "OwnerID", folder.Owner.ToString() },
453 { "Name", folder.Name },
454 { "ContentType", SLUtil.SLAssetTypeToContentType(folder.Type) }
455 };
456  
457 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
458 bool success = response["Success"].AsBoolean();
459  
460 if (!success)
461 {
462 m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Error creating folder " + folder.Name + " for " + folder.Owner + ": " +
463 response["Message"].AsString());
464 }
465  
466 return success;
467 }
468  
469 /// <summary>
470 /// Update a folder in the user's inventory
471 /// </summary>
472 /// <param name="folder"></param>
473 /// <returns>true if the folder was successfully updated</returns>
474 public bool UpdateFolder(InventoryFolderBase folder)
475 {
476 return AddFolder(folder);
477 }
478  
479 /// <summary>
480 /// Move an inventory folder to a new location
481 /// </summary>
482 /// <param name="folder">A folder containing the details of the new location</param>
483 /// <returns>true if the folder was successfully moved</returns>
484 public bool MoveFolder(InventoryFolderBase folder)
485 {
486 return AddFolder(folder);
487 }
488  
489 /// <summary>
490 /// Delete an item from the user's inventory
491 /// </summary>
492 /// <param name="item"></param>
493 /// <returns>true if the item was successfully deleted</returns>
494 //bool DeleteItem(InventoryItemBase item);
495 public bool DeleteFolders(UUID userID, List<UUID> folderIDs)
496 {
497 return DeleteItems(userID, folderIDs);
498 }
499  
500 /// <summary>
501 /// Delete an item from the user's inventory
502 /// </summary>
503 /// <param name="item"></param>
504 /// <returns>true if the item was successfully deleted</returns>
505 public bool DeleteItems(UUID userID, List<UUID> itemIDs)
506 {
507 // TODO: RemoveInventoryNode should be replaced with RemoveInventoryNodes
508 bool allSuccess = true;
509  
510 for (int i = 0; i < itemIDs.Count; i++)
511 {
512 UUID itemID = itemIDs[i];
513  
514 NameValueCollection requestArgs = new NameValueCollection
515 {
516 { "RequestMethod", "RemoveInventoryNode" },
517 { "OwnerID", userID.ToString() },
518 { "ItemID", itemID.ToString() }
519 };
520  
521 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
522 bool success = response["Success"].AsBoolean();
523  
524 if (!success)
525 {
526 m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Error removing item " + itemID + " for " + userID + ": " +
527 response["Message"].AsString());
528 allSuccess = false;
529 }
530 }
531  
532 return allSuccess;
533 }
534  
535 /// <summary>
536 /// Purge an inventory folder of all its items and subfolders.
537 /// </summary>
538 /// <param name="folder"></param>
539 /// <returns>true if the folder was successfully purged</returns>
540 public bool PurgeFolder(InventoryFolderBase folder)
541 {
542 NameValueCollection requestArgs = new NameValueCollection
543 {
544 { "RequestMethod", "PurgeInventoryFolder" },
545 { "OwnerID", folder.Owner.ToString() },
546 { "FolderID", folder.ID.ToString() }
547 };
548  
549 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
550 bool success = response["Success"].AsBoolean();
551  
552 if (!success)
553 {
554 m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Error purging folder " + folder.ID + " for " + folder.Owner + ": " +
555 response["Message"].AsString());
556 }
557  
558 return success;
559 }
560  
561 /// <summary>
562 /// Add a new item to the user's inventory
563 /// </summary>
564 /// <param name="item"></param>
565 /// <returns>true if the item was successfully added</returns>
566 public bool AddItem(InventoryItemBase item)
567 {
568 // A folder of UUID.Zero means we need to find the most appropriate home for this item
569 if (item.Folder == UUID.Zero)
570 {
571 InventoryFolderBase folder = GetFolderForType(item.Owner, (AssetType)item.AssetType);
572 if (folder != null && folder.ID != UUID.Zero)
573 item.Folder = folder.ID;
574 else
575 item.Folder = item.Owner; // Root folder
576 }
577  
578 if ((AssetType)item.AssetType == AssetType.Gesture)
579 UpdateGesture(item.Owner, item.ID, item.Flags == 1);
580  
581 if (item.BasePermissions == 0)
582 m_log.WarnFormat("[SIMIAN INVENTORY CONNECTOR]: Adding inventory item {0} ({1}) with no base permissions", item.Name, item.ID);
583  
584 OSDMap permissions = new OSDMap
585 {
586 { "BaseMask", OSD.FromInteger(item.BasePermissions) },
587 { "EveryoneMask", OSD.FromInteger(item.EveryOnePermissions) },
588 { "GroupMask", OSD.FromInteger(item.GroupPermissions) },
589 { "NextOwnerMask", OSD.FromInteger(item.NextPermissions) },
590 { "OwnerMask", OSD.FromInteger(item.CurrentPermissions) }
591 };
592  
593 OSDMap extraData = new OSDMap()
594 {
595 { "Flags", OSD.FromInteger(item.Flags) },
596 { "GroupID", OSD.FromUUID(item.GroupID) },
597 { "GroupOwned", OSD.FromBoolean(item.GroupOwned) },
598 { "SalePrice", OSD.FromInteger(item.SalePrice) },
599 { "SaleType", OSD.FromInteger(item.SaleType) },
600 { "Permissions", permissions }
601 };
602  
603 // Add different asset type only if it differs from inventory type
604 // (needed for links)
605 string invContentType = SLUtil.SLInvTypeToContentType(item.InvType);
606 string assetContentType = SLUtil.SLAssetTypeToContentType(item.AssetType);
607  
608 if (invContentType != assetContentType)
609 extraData["LinkedItemType"] = OSD.FromString(assetContentType);
610  
611 NameValueCollection requestArgs = new NameValueCollection
612 {
613 { "RequestMethod", "AddInventoryItem" },
614 { "ItemID", item.ID.ToString() },
615 { "AssetID", item.AssetID.ToString() },
616 { "ParentID", item.Folder.ToString() },
617 { "OwnerID", item.Owner.ToString() },
618 { "Name", item.Name },
619 { "Description", item.Description },
620 { "CreatorID", item.CreatorId },
621 { "CreatorData", item.CreatorData },
622 { "ContentType", invContentType },
623 { "ExtraData", OSDParser.SerializeJsonString(extraData) }
624 };
625  
626 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
627 bool success = response["Success"].AsBoolean();
628  
629 if (!success)
630 {
631 m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Error creating item " + item.Name + " for " + item.Owner + ": " +
632 response["Message"].AsString());
633 }
634  
635 return success;
636 }
637  
638 /// <summary>
639 /// Update an item in the user's inventory
640 /// </summary>
641 /// <param name="item"></param>
642 /// <returns>true if the item was successfully updated</returns>
643 public bool UpdateItem(InventoryItemBase item)
644 {
645 if (item.AssetID != UUID.Zero)
646 {
647 return AddItem(item);
648 }
649 else
650 {
651 // This is actually a folder update
652 InventoryFolderBase folder = new InventoryFolderBase(item.ID, item.Name, item.Owner, (short)item.AssetType, item.Folder, 0);
653 return UpdateFolder(folder);
654 }
655 }
656  
657 public bool MoveItems(UUID ownerID, List<InventoryItemBase> items)
658 {
659 bool success = true;
660  
661 while (items.Count > 0)
662 {
663 List<InventoryItemBase> currentItems = new List<InventoryItemBase>();
664 UUID destFolderID = items[0].Folder;
665  
666 // Find all of the items being moved to the current destination folder
667 for (int i = 0; i < items.Count; i++)
668 {
669 InventoryItemBase item = items[i];
670 if (item.Folder == destFolderID)
671 currentItems.Add(item);
672 }
673  
674 // Do the inventory move for the current items
675 success &= MoveItems(ownerID, items, destFolderID);
676  
677 // Remove the processed items from the list
678 for (int i = 0; i < currentItems.Count; i++)
679 items.Remove(currentItems[i]);
680 }
681  
682 return success;
683 }
684  
685 /// <summary>
686 /// Does the given user have an inventory structure?
687 /// </summary>
688 /// <param name="userID"></param>
689 /// <returns></returns>
690 public bool HasInventoryForUser(UUID userID)
691 {
692 return GetRootFolder(userID) != null;
693 }
694  
695 /// <summary>
696 /// Get the active gestures of the agent.
697 /// </summary>
698 /// <param name="userID"></param>
699 /// <returns></returns>
700 public List<InventoryItemBase> GetActiveGestures(UUID userID)
701 {
702 OSDArray items = FetchGestures(userID);
703  
704 string[] itemIDs = new string[items.Count];
705 for (int i = 0; i < items.Count; i++)
706 itemIDs[i] = items[i].AsUUID().ToString();
707  
708 // NameValueCollection requestArgs = new NameValueCollection
709 // {
710 // { "RequestMethod", "GetInventoryNodes" },
711 // { "OwnerID", userID.ToString() },
712 // { "Items", String.Join(",", itemIDs) }
713 // };
714  
715 // FIXME: Implement this in SimianGrid
716 return new List<InventoryItemBase>(0);
717 }
718  
719 /// <summary>
720 /// Get the union of permissions of all inventory items
721 /// that hold the given assetID.
722 /// </summary>
723 /// <param name="userID"></param>
724 /// <param name="assetID"></param>
725 /// <returns>The permissions or 0 if no such asset is found in
726 /// the user's inventory</returns>
727 public int GetAssetPermissions(UUID userID, UUID assetID)
728 {
729 // NameValueCollection requestArgs = new NameValueCollection
730 // {
731 // { "RequestMethod", "GetInventoryNodes" },
732 // { "OwnerID", userID.ToString() },
733 // { "AssetID", assetID.ToString() }
734 // };
735  
736 // FIXME: Implement this in SimianGrid
737 return (int)PermissionMask.All;
738 }
739  
740 private List<InventoryFolderBase> GetFoldersFromResponse(OSDArray items, UUID baseFolder, bool includeBaseFolder)
741 {
742 List<InventoryFolderBase> invFolders = new List<InventoryFolderBase>(items.Count);
743  
744 for (int i = 0; i < items.Count; i++)
745 {
746 OSDMap item = items[i] as OSDMap;
747  
748 if (item != null && item["Type"].AsString() == "Folder")
749 {
750 UUID folderID = item["ID"].AsUUID();
751  
752 if (folderID == baseFolder && !includeBaseFolder)
753 continue;
754  
755 invFolders.Add(new InventoryFolderBase(
756 folderID,
757 item["Name"].AsString(),
758 item["OwnerID"].AsUUID(),
759 (short)SLUtil.ContentTypeToSLAssetType(item["ContentType"].AsString()),
760 item["ParentID"].AsUUID(),
761 (ushort)item["Version"].AsInteger()
762 ));
763 }
764 }
765  
766 // m_log.Debug("[SIMIAN INVENTORY CONNECTOR]: Parsed " + invFolders.Count + " folders from SimianGrid response");
767 return invFolders;
768 }
769  
770 private List<InventoryItemBase> GetItemsFromResponse(OSDArray items)
771 {
772 List<InventoryItemBase> invItems = new List<InventoryItemBase>(items.Count);
773  
774 for (int i = 0; i < items.Count; i++)
775 {
776 OSDMap item = items[i] as OSDMap;
777  
778 if (item != null && item["Type"].AsString() == "Item")
779 {
780 InventoryItemBase invItem = new InventoryItemBase();
781  
782 invItem.AssetID = item["AssetID"].AsUUID();
783 invItem.AssetType = SLUtil.ContentTypeToSLAssetType(item["ContentType"].AsString());
784 invItem.CreationDate = item["CreationDate"].AsInteger();
785 invItem.CreatorId = item["CreatorID"].AsString();
786 invItem.CreatorData = item["CreatorData"].AsString();
787 invItem.Description = item["Description"].AsString();
788 invItem.Folder = item["ParentID"].AsUUID();
789 invItem.ID = item["ID"].AsUUID();
790 invItem.InvType = SLUtil.ContentTypeToSLInvType(item["ContentType"].AsString());
791 invItem.Name = item["Name"].AsString();
792 invItem.Owner = item["OwnerID"].AsUUID();
793  
794 OSDMap extraData = item["ExtraData"] as OSDMap;
795 if (extraData != null && extraData.Count > 0)
796 {
797 invItem.Flags = extraData["Flags"].AsUInteger();
798 invItem.GroupID = extraData["GroupID"].AsUUID();
799 invItem.GroupOwned = extraData["GroupOwned"].AsBoolean();
800 invItem.SalePrice = extraData["SalePrice"].AsInteger();
801 invItem.SaleType = (byte)extraData["SaleType"].AsInteger();
802  
803 OSDMap perms = extraData["Permissions"] as OSDMap;
804 if (perms != null)
805 {
806 invItem.BasePermissions = perms["BaseMask"].AsUInteger();
807 invItem.CurrentPermissions = perms["OwnerMask"].AsUInteger();
808 invItem.EveryOnePermissions = perms["EveryoneMask"].AsUInteger();
809 invItem.GroupPermissions = perms["GroupMask"].AsUInteger();
810 invItem.NextPermissions = perms["NextOwnerMask"].AsUInteger();
811 }
812  
813 if (extraData.ContainsKey("LinkedItemType"))
814 invItem.AssetType = SLUtil.ContentTypeToSLAssetType(extraData["LinkedItemType"].AsString());
815 }
816  
817 if (invItem.BasePermissions == 0)
818 {
819 m_log.InfoFormat("[SIMIAN INVENTORY CONNECTOR]: Forcing item permissions to full for item {0} ({1})",
820 invItem.Name, invItem.ID);
821 invItem.BasePermissions = (uint)PermissionMask.All;
822 invItem.CurrentPermissions = (uint)PermissionMask.All;
823 invItem.EveryOnePermissions = (uint)PermissionMask.All;
824 invItem.GroupPermissions = (uint)PermissionMask.All;
825 invItem.NextPermissions = (uint)PermissionMask.All;
826 }
827  
828 invItems.Add(invItem);
829 }
830 }
831  
832 // m_log.Debug("[SIMIAN INVENTORY CONNECTOR]: Parsed " + invItems.Count + " items from SimianGrid response");
833 return invItems;
834 }
835  
836 private bool MoveItems(UUID ownerID, List<InventoryItemBase> items, UUID destFolderID)
837 {
838 string[] itemIDs = new string[items.Count];
839 for (int i = 0; i < items.Count; i++)
840 itemIDs[i] = items[i].ID.ToString();
841  
842 NameValueCollection requestArgs = new NameValueCollection
843 {
844 { "RequestMethod", "MoveInventoryNodes" },
845 { "OwnerID", ownerID.ToString() },
846 { "FolderID", destFolderID.ToString() },
847 { "Items", String.Join(",", itemIDs) }
848 };
849  
850 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
851 bool success = response["Success"].AsBoolean();
852  
853 if (!success)
854 {
855 m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Failed to move " + items.Count + " items to " +
856 destFolderID + ": " + response["Message"].AsString());
857 }
858  
859 return success;
860 }
861  
862 private void UpdateGesture(UUID userID, UUID itemID, bool enabled)
863 {
864 OSDArray gestures = FetchGestures(userID);
865 OSDArray newGestures = new OSDArray();
866  
867 for (int i = 0; i < gestures.Count; i++)
868 {
869 UUID gesture = gestures[i].AsUUID();
870 if (gesture != itemID)
871 newGestures.Add(OSD.FromUUID(gesture));
872 }
873  
874 if (enabled)
875 newGestures.Add(OSD.FromUUID(itemID));
876  
877 SaveGestures(userID, newGestures);
878 }
879  
880 private OSDArray FetchGestures(UUID userID)
881 {
882 NameValueCollection requestArgs = new NameValueCollection
883 {
884 { "RequestMethod", "GetUser" },
885 { "UserID", userID.ToString() }
886 };
887  
888 OSDMap response = SimianGrid.PostToService(m_userServerUrl, requestArgs);
889 if (response["Success"].AsBoolean())
890 {
891 OSDMap user = response["User"] as OSDMap;
892 if (user != null && response.ContainsKey("Gestures"))
893 {
894 OSD gestures = OSDParser.DeserializeJson(response["Gestures"].AsString());
895 if (gestures != null && gestures is OSDArray)
896 return (OSDArray)gestures;
897 else
898 m_log.Error("[SIMIAN INVENTORY CONNECTOR]: Unrecognized active gestures data for " + userID);
899 }
900 }
901 else
902 {
903 m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Failed to fetch active gestures for " + userID + ": " +
904 response["Message"].AsString());
905 }
906  
907 return new OSDArray();
908 }
909  
910 private void SaveGestures(UUID userID, OSDArray gestures)
911 {
912 NameValueCollection requestArgs = new NameValueCollection
913 {
914 { "RequestMethod", "AddUserData" },
915 { "UserID", userID.ToString() },
916 { "Gestures", OSDParser.SerializeJsonString(gestures) }
917 };
918  
919 OSDMap response = SimianGrid.PostToService(m_userServerUrl, requestArgs);
920 if (!response["Success"].AsBoolean())
921 {
922 m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Failed to save active gestures for " + userID + ": " +
923 response["Message"].AsString());
924 }
925 }
926 }
927 }