Merge branch 'master' of /home/opensim/var/repo/opensim

integration
BlueWall 2012-04-06 19:24:14 -04:00
commit 4f4ca1625f
18 changed files with 787 additions and 289 deletions

View File

@ -162,7 +162,7 @@ namespace OpenSim.Capabilities.Handlers
invFetch.owner_id, invFetch.folder_id, invFetch.owner_id, invFetch.owner_id, invFetch.folder_id, invFetch.owner_id,
invFetch.fetch_folders, invFetch.fetch_items, invFetch.sort_order, out version); invFetch.fetch_folders, invFetch.fetch_items, invFetch.sort_order, out version);
if (inv.Folders != null) if (inv != null && inv.Folders != null)
{ {
foreach (InventoryFolderBase invFolder in inv.Folders) foreach (InventoryFolderBase invFolder in inv.Folders)
{ {
@ -170,7 +170,7 @@ namespace OpenSim.Capabilities.Handlers
} }
} }
if (inv.Items != null) if (inv != null && inv.Items != null)
{ {
foreach (InventoryItemBase invItem in inv.Items) foreach (InventoryItemBase invItem in inv.Items)
{ {

View File

@ -662,11 +662,11 @@ namespace OpenSim.Framework.Servers.HttpServer
} }
catch (IOException e) catch (IOException e)
{ {
m_log.ErrorFormat("[BASE HTTP SERVER]: HandleRequest() threw ", e); m_log.ErrorFormat("[BASE HTTP SERVER]: HandleRequest() threw {0}", e);
} }
catch (Exception e) catch (Exception e)
{ {
m_log.ErrorFormat("[BASE HTTP SERVER]: HandleRequest() threw " + e.ToString()); m_log.ErrorFormat("[BASE HTTP SERVER]: HandleRequest() threw {0}", e.StackTrace);
SendHTML500(response); SendHTML500(response);
} }
finally finally

View File

@ -1913,7 +1913,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
folderBlock.FolderID = folder.ID; folderBlock.FolderID = folder.ID;
folderBlock.ParentID = folder.ParentID; folderBlock.ParentID = folder.ParentID;
folderBlock.Type = -1; //folderBlock.Type = -1;
folderBlock.Type = (sbyte)folder.Type;
folderBlock.Name = Util.StringToBytes256(folder.Name); folderBlock.Name = Util.StringToBytes256(folder.Name);
return folderBlock; return folderBlock;

View File

@ -114,7 +114,17 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: ViaHGLogin"); m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: ViaHGLogin");
if (m_RestrictInventoryAccessAbroad) if (m_RestrictInventoryAccessAbroad)
{ {
RestoreRootFolderContents(client); IUserManagement uMan = m_Scenes[0].RequestModuleInterface<IUserManagement>();
if (uMan.IsLocalGridUser(client.AgentId))
{
m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: User is local");
RestoreRootFolderContents(client);
}
else
{
m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: User is foreign");
RestoreSuitcaseFolderContents(client);
}
} }
} }
} }
@ -210,7 +220,20 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
logout = success; // flag for later logout from this grid; this is an HG TP logout = success; // flag for later logout from this grid; this is an HG TP
if (success && m_RestrictInventoryAccessAbroad) if (success && m_RestrictInventoryAccessAbroad)
RemoveRootFolderContents(sp.ControllingClient); {
IUserManagement uMan = m_aScene.RequestModuleInterface<IUserManagement>();
if (uMan != null && uMan.IsLocalGridUser(sp.UUID))
{
// local grid user
m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: User is local");
RemoveRootFolderContents(sp.ControllingClient);
}
else
{
m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: User is foreign");
RemoveSuitcaseFolderContents(sp.ControllingClient);
}
}
return success; return success;
} }
@ -401,25 +424,40 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
InventoryFolderBase root = m_Scenes[0].InventoryService.GetRootFolder(client.AgentId); InventoryFolderBase root = m_Scenes[0].InventoryService.GetRootFolder(client.AgentId);
if (root != null) if (root != null)
{ {
m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Removing root inventory for user {0}", client.AgentId); m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Removing root inventory for user {0}", client.Name);
InventoryCollection content = m_Scenes[0].InventoryService.GetFolderContent(client.AgentId, root.ID); InventoryCollection content = m_Scenes[0].InventoryService.GetFolderContent(client.AgentId, root.ID);
UUID[] ids = new UUID[content.Folders.Count]; List<UUID> fids = new List<UUID>();
int i = 0; List<UUID> iids = new List<UUID>();
List<InventoryFolderBase> keep = new List<InventoryFolderBase>();
foreach (InventoryFolderBase f in content.Folders) foreach (InventoryFolderBase f in content.Folders)
ids[i++] = f.ID; {
inv.SendRemoveInventoryFolders(ids); if (f.Name != "My Suitcase")
ids = new UUID[content.Items.Count]; {
i = 0; f.Name = f.Name + " (Unavailable)";
keep.Add(f);
}
}
// items directly under the root folder
foreach (InventoryItemBase it in content.Items) foreach (InventoryItemBase it in content.Items)
ids[i++] = it.ID; it.Name = it.Name + " (Unavailable)"; ;
inv.SendRemoveInventoryItems(ids);
// Send the new names
inv.SendBulkUpdateInventory(keep.ToArray(), content.Items.ToArray());
} }
} }
} }
} }
private void RemoveSuitcaseFolderContents(IClientAPI client)
{
}
private void RestoreRootFolderContents(IClientAPI client) private void RestoreRootFolderContents(IClientAPI client)
{ {
m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Restoring root folder");
if (client is IClientCore) if (client is IClientCore)
{ {
IClientCore core = (IClientCore)client; IClientCore core = (IClientCore)client;
@ -428,21 +466,17 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
if (core.TryGet<IClientInventory>(out inv)) if (core.TryGet<IClientInventory>(out inv))
{ {
InventoryFolderBase root = m_Scenes[0].InventoryService.GetRootFolder(client.AgentId); InventoryFolderBase root = m_Scenes[0].InventoryService.GetRootFolder(client.AgentId);
client.SendBulkUpdateInventory(root); InventoryCollection content = m_Scenes[0].InventoryService.GetFolderContent(client.AgentId, root.ID);
//if (root != null)
//{
// m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Restoring root inventory for user {0}", client.AgentId);
// InventoryCollection content = m_Scenes[0].InventoryService.GetFolderContent(client.AgentId, root.ID);
// m_log.DebugFormat("[XXX]: Folder name {0}, id {1}, parent {2}", root.Name, root.ID, root.ParentID);
// foreach (InventoryItemBase i in content.Items)
// m_log.DebugFormat("[XXX]: Name={0}, folderID={1}", i.Name, i.Folder);
// inv.SendBulkUpdateInventory(content.Folders.ToArray(), content.Items.ToArray()); inv.SendBulkUpdateInventory(content.Folders.ToArray(), content.Items.ToArray());
//}
} }
} }
} }
private void RestoreSuitcaseFolderContents(IClientAPI client)
{
}
private GridRegion MakeRegion(AgentCircuitData aCircuit) private GridRegion MakeRegion(AgentCircuitData aCircuit)
{ {
GridRegion region = new GridRegion(); GridRegion region = new GridRegion();

View File

@ -297,14 +297,35 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
return m_LocalGridInventoryService.CreateUserInventory(userID); return m_LocalGridInventoryService.CreateUserInventory(userID);
} }
public List<InventoryFolderBase> GetInventorySkeleton(UUID userId) public List<InventoryFolderBase> GetInventorySkeleton(UUID userID)
{ {
return m_LocalGridInventoryService.GetInventorySkeleton(userId); string invURL = GetInventoryServiceURL(userID);
if (invURL == null) // not there, forward to local inventory connector to resolve
return m_LocalGridInventoryService.GetInventorySkeleton(userID);
IInventoryService connector = GetConnector(invURL);
return connector.GetInventorySkeleton(userID);
} }
public InventoryCollection GetUserInventory(UUID userID) public InventoryCollection GetUserInventory(UUID userID)
{ {
return null; string invURL = GetInventoryServiceURL(userID);
m_log.DebugFormat("[HG INVENTORY CONNECTOR]: GetUserInventory for {0} {1}", userID, invURL);
if (invURL == null) // not there, forward to local inventory connector to resolve
return m_LocalGridInventoryService.GetUserInventory(userID);
InventoryCollection c = m_Cache.GetUserInventory(userID);
if (c != null)
return c;
IInventoryService connector = GetConnector(invURL);
c = connector.GetUserInventory(userID);
m_Cache.Cache(userID, c);
return c;
} }
public void GetUserInventory(UUID userID, InventoryReceiptCallback callback) public void GetUserInventory(UUID userID, InventoryReceiptCallback callback)
@ -362,8 +383,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
if (invURL == null) // not there, forward to local inventory connector to resolve if (invURL == null) // not there, forward to local inventory connector to resolve
return m_LocalGridInventoryService.GetFolderContent(userID, folderID); return m_LocalGridInventoryService.GetFolderContent(userID, folderID);
IInventoryService connector = GetConnector(invURL); InventoryCollection c = m_Cache.GetFolderContent(userID, folderID);
if (c != null)
{
m_log.Debug("[HG INVENTORY CONNECTOR]: GetFolderContent found content in cache " + folderID);
return c;
}
IInventoryService connector = GetConnector(invURL);
return connector.GetFolderContent(userID, folderID); return connector.GetFolderContent(userID, folderID);
} }
@ -377,8 +404,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
if (invURL == null) // not there, forward to local inventory connector to resolve if (invURL == null) // not there, forward to local inventory connector to resolve
return m_LocalGridInventoryService.GetFolderItems(userID, folderID); return m_LocalGridInventoryService.GetFolderItems(userID, folderID);
IInventoryService connector = GetConnector(invURL); List<InventoryItemBase> items = m_Cache.GetFolderItems(userID, folderID);
if (items != null)
{
m_log.Debug("[HG INVENTORY CONNECTOR]: GetFolderItems found items in cache " + folderID);
return items;
}
IInventoryService connector = GetConnector(invURL);
return connector.GetFolderItems(userID, folderID); return connector.GetFolderItems(userID, folderID);
} }

View File

@ -12,6 +12,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
private static ExpiringCache<UUID, InventoryFolderBase> m_RootFolders = new ExpiringCache<UUID, InventoryFolderBase>(); private static ExpiringCache<UUID, InventoryFolderBase> m_RootFolders = new ExpiringCache<UUID, InventoryFolderBase>();
private static ExpiringCache<UUID, Dictionary<AssetType, InventoryFolderBase>> m_FolderTypes = new ExpiringCache<UUID, Dictionary<AssetType, InventoryFolderBase>>(); private static ExpiringCache<UUID, Dictionary<AssetType, InventoryFolderBase>> m_FolderTypes = new ExpiringCache<UUID, Dictionary<AssetType, InventoryFolderBase>>();
private static ExpiringCache<UUID, InventoryCollection> m_Inventories = new ExpiringCache<UUID, InventoryCollection>();
public void Cache(UUID userID, InventoryFolderBase root) public void Cache(UUID userID, InventoryFolderBase root)
{ {
@ -55,5 +56,55 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
return null; return null;
} }
public void Cache(UUID userID, InventoryCollection inv)
{
lock (m_Inventories)
m_Inventories.AddOrUpdate(userID, inv, 120);
}
public InventoryCollection GetUserInventory(UUID userID)
{
InventoryCollection inv = null;
if (m_Inventories.TryGetValue(userID, out inv))
return inv;
return null;
}
public InventoryCollection GetFolderContent(UUID userID, UUID folderID)
{
InventoryCollection inv = null;
InventoryCollection c;
if (m_Inventories.TryGetValue(userID, out inv))
{
c = new InventoryCollection();
c.UserID = userID;
c.Folders = inv.Folders.FindAll(delegate(InventoryFolderBase f)
{
return f.ParentID == folderID;
});
c.Items = inv.Items.FindAll(delegate(InventoryItemBase i)
{
return i.Folder == folderID;
});
return c;
}
return null;
}
public List<InventoryItemBase> GetFolderItems(UUID userID, UUID folderID)
{
InventoryCollection inv = null;
if (m_Inventories.TryGetValue(userID, out inv))
{
List<InventoryItemBase> items = inv.Items.FindAll(delegate(InventoryItemBase i)
{
return i.Folder == folderID;
});
return items;
}
return null;
}
} }
} }

View File

@ -172,7 +172,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
public InventoryCollection GetUserInventory(UUID userID) public InventoryCollection GetUserInventory(UUID userID)
{ {
return null; return m_RemoteConnector.GetUserInventory(userID);
} }
public void GetUserInventory(UUID userID, InventoryReceiptCallback callback) public void GetUserInventory(UUID userID, InventoryReceiptCallback callback)
@ -193,16 +193,17 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
{ {
InventoryCollection invCol = m_RemoteConnector.GetFolderContent(userID, folderID); InventoryCollection invCol = m_RemoteConnector.GetFolderContent(userID, folderID);
if (UserManager != null) if (invCol != null && UserManager != null)
{ {
// Protect ourselves against the caller subsequently modifying the items list // Protect ourselves against the caller subsequently modifying the items list
List<InventoryItemBase> items = new List<InventoryItemBase>(invCol.Items); List<InventoryItemBase> items = new List<InventoryItemBase>(invCol.Items);
Util.FireAndForget(delegate if (items != null && items.Count > 0)
{ Util.FireAndForget(delegate
foreach (InventoryItemBase item in items) {
UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData); foreach (InventoryItemBase item in items)
}); UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData);
});
} }
return invCol; return invCol;

View File

@ -36,6 +36,7 @@ using OpenMetaverse.Packets;
using log4net; using log4net;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Region.Framework; using OpenSim.Region.Framework;
using OpenSim.Framework.Client;
using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes.Serialization; using OpenSim.Region.Framework.Scenes.Serialization;
@ -117,31 +118,42 @@ namespace OpenSim.Region.Framework.Scenes
/// <param name="item"></param> /// <param name="item"></param>
public bool AddInventoryItem(InventoryItemBase item) public bool AddInventoryItem(InventoryItemBase item)
{ {
if (UUID.Zero == item.Folder) if (item.Folder != UUID.Zero && InventoryService.AddItem(item))
{ {
InventoryFolderBase f = InventoryService.GetFolderForType(item.Owner, (AssetType)item.AssetType); int userlevel = 0;
if (Permissions.IsGod(item.Owner))
{
userlevel = 1;
}
EventManager.TriggerOnNewInventoryItemUploadComplete(item.Owner, item.AssetID, item.Name, userlevel);
return true;
}
// OK so either the viewer didn't send a folderID or AddItem failed
UUID originalFolder = item.Folder;
InventoryFolderBase f = InventoryService.GetFolderForType(item.Owner, (AssetType)item.AssetType);
if (f != null)
{
m_log.DebugFormat(
"[AGENT INVENTORY]: Found folder {0} type {1} for item {2}",
f.Name, (AssetType)f.Type, item.Name);
item.Folder = f.ID;
}
else
{
f = InventoryService.GetRootFolder(item.Owner);
if (f != null) if (f != null)
{ {
// m_log.DebugFormat(
// "[LOCAL INVENTORY SERVICES CONNECTOR]: Found folder {0} type {1} for item {2}",
// f.Name, (AssetType)f.Type, item.Name);
item.Folder = f.ID; item.Folder = f.ID;
} }
else else
{ {
f = InventoryService.GetRootFolder(item.Owner); m_log.WarnFormat(
if (f != null) "[AGENT INVENTORY]: Could not find root folder for {0} when trying to add item {1} with no parent folder specified",
{ item.Owner, item.Name);
item.Folder = f.ID; return false;
}
else
{
m_log.WarnFormat(
"[AGENT INVENTORY]: Could not find root folder for {0} when trying to add item {1} with no parent folder specified",
item.Owner, item.Name);
return false;
}
} }
} }
@ -154,6 +166,12 @@ namespace OpenSim.Region.Framework.Scenes
} }
EventManager.TriggerOnNewInventoryItemUploadComplete(item.Owner, item.AssetID, item.Name, userlevel); EventManager.TriggerOnNewInventoryItemUploadComplete(item.Owner, item.AssetID, item.Name, userlevel);
if (originalFolder != UUID.Zero)
{
// Tell the viewer that the item didn't go there
ChangePlacement(item, f);
}
return true; return true;
} }
else else
@ -166,6 +184,31 @@ namespace OpenSim.Region.Framework.Scenes
} }
} }
private void ChangePlacement(InventoryItemBase item, InventoryFolderBase f)
{
ScenePresence sp = GetScenePresence(item.Owner);
if (sp != null)
{
if (sp.ControllingClient is IClientCore)
{
IClientCore core = (IClientCore)sp.ControllingClient;
IClientInventory inv;
if (core.TryGet<IClientInventory>(out inv))
{
InventoryFolderBase parent = new InventoryFolderBase(f.ParentID, f.Owner);
parent = InventoryService.GetFolder(parent);
inv.SendRemoveInventoryItems(new UUID[] { item.ID });
inv.SendBulkUpdateInventory(new InventoryFolderBase[0], new InventoryItemBase[] { item });
string message = "The item was placed in folder " + f.Name;
if (parent != null)
message += " under " + parent.Name;
sp.ControllingClient.SendAgentAlertMessage(message, false);
}
}
}
}
/// <summary> /// <summary>
/// Add the given inventory item to a user's inventory. /// Add the given inventory item to a user's inventory.
/// </summary> /// </summary>

View File

@ -2164,12 +2164,6 @@ namespace OpenSim.Region.Framework.Scenes
} }
} }
// if (rootPart.PhysActor != null)
// {
// PhysicsScene.RemovePrim(rootPart.PhysActor);
// rootPart.PhysActor = null;
// }
if (UnlinkSceneObject(group, false)) if (UnlinkSceneObject(group, false))
{ {
EventManager.TriggerObjectBeingRemovedFromScene(group); EventManager.TriggerObjectBeingRemovedFromScene(group);

View File

@ -125,12 +125,14 @@ namespace OpenSim.Region.Framework.Scenes
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
/// <value> /// <value>
/// Is this sop a root part? /// Is this a root part?
/// </value> /// </value>
/// <remarks>
/// This will return true even if the whole object is attached to an avatar.
/// </remarks>
public bool IsRoot public bool IsRoot
{ {
get { return ParentGroup.RootPart == this; } get { return ParentGroup.RootPart == this; }
} }
#region Fields #region Fields
@ -159,15 +161,7 @@ namespace OpenSim.Region.Framework.Scenes
/// If another thread is simultaneously turning physics off on this part then this refernece could become /// If another thread is simultaneously turning physics off on this part then this refernece could become
/// null at any time. /// null at any time.
/// </remarks> /// </remarks>
public PhysicsActor PhysActor public PhysicsActor PhysActor { get; set; }
{
get { return m_physActor; }
set
{
// m_log.DebugFormat("[SOP]: PhysActor set to {0} for {1} {2}", value, Name, UUID);
m_physActor = value;
}
}
//Xantor 20080528 Sound stuff: //Xantor 20080528 Sound stuff:
// Note: This isn't persisted in the database right now, as the fields for that aren't just there yet. // Note: This isn't persisted in the database right now, as the fields for that aren't just there yet.
@ -266,7 +260,6 @@ namespace OpenSim.Region.Framework.Scenes
private bool m_passTouches; private bool m_passTouches;
private PhysicsActor m_physActor;
protected Vector3 m_acceleration; protected Vector3 m_acceleration;
protected Vector3 m_angularVelocity; protected Vector3 m_angularVelocity;
@ -1112,6 +1105,14 @@ namespace OpenSim.Region.Framework.Scenes
} }
} }
/// <summary>
/// The parent ID of this part.
/// </summary>
/// <remarks>
/// If this is a root part which is not attached to an avatar then the value will be 0.
/// If this is a root part which is attached to an avatar then the value is the local id of that avatar.
/// If this is a child part then the value is the local ID of the root part.
/// </remarks>
public uint ParentID public uint ParentID
{ {
get { return _parentID; } get { return _parentID; }
@ -1488,40 +1489,17 @@ namespace OpenSim.Region.Framework.Scenes
if (VolumeDetectActive) if (VolumeDetectActive)
isPhantom = false; isPhantom = false;
// Added clarification.. since A rigid body is an object that you can kick around, etc.
bool RigidBody = isPhysical && !isPhantom;
// The only time the physics scene shouldn't know about the prim is if it's phantom or an attachment, which is phantom by definition // The only time the physics scene shouldn't know about the prim is if it's phantom or an attachment, which is phantom by definition
// or flexible // or flexible
if (!isPhantom && !ParentGroup.IsAttachment && !(Shape.PathCurve == (byte)Extrusion.Flexible)) if (!isPhantom && !ParentGroup.IsAttachment && !(Shape.PathCurve == (byte)Extrusion.Flexible))
{ {
try // Added clarification.. since A rigid body is an object that you can kick around, etc.
{ bool rigidBody = isPhysical && !isPhantom;
PhysActor = ParentGroup.Scene.PhysicsScene.AddPrimShape(
string.Format("{0}/{1}", Name, UUID),
Shape,
AbsolutePosition,
Scale,
RotationOffset,
RigidBody,
m_localId);
}
catch
{
m_log.ErrorFormat("[SCENE]: caught exception meshing object {0}. Object set to phantom.", m_uuid);
PhysActor = null;
}
// Basic Physics can also return null as well as an exception catch. PhysicsActor pa = AddToPhysics(rigidBody);
PhysicsActor pa = PhysActor;
if (pa != null) if (pa != null)
{
pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info
pa.SetMaterial(Material);
DoPhysicsPropertyUpdate(RigidBody, true);
pa.SetVolumeDetect(VolumeDetectActive ? 1 : 0); pa.SetVolumeDetect(VolumeDetectActive ? 1 : 0);
}
} }
} }
} }
@ -4322,41 +4300,36 @@ namespace OpenSim.Region.Framework.Scenes
if (ParentGroup.Scene == null) if (ParentGroup.Scene == null)
return; return;
if (ParentGroup.Scene.CollidablePrims && PhysActor == null) if (ParentGroup.Scene.CollidablePrims && pa == null)
{ {
// It's not phantom anymore. So make sure the physics engine get's knowledge of it pa = AddToPhysics(UsePhysics);
PhysActor = ParentGroup.Scene.PhysicsScene.AddPrimShape(
string.Format("{0}/{1}", Name, UUID),
Shape,
AbsolutePosition,
Scale,
RotationOffset,
UsePhysics,
m_localId);
PhysActor.SetMaterial(Material); if (pa != null)
DoPhysicsPropertyUpdate(UsePhysics, true);
if (!ParentGroup.IsDeleted)
{ {
if (LocalId == ParentGroup.RootPart.LocalId) pa.SetMaterial(Material);
DoPhysicsPropertyUpdate(UsePhysics, true);
if (!ParentGroup.IsDeleted)
{ {
ParentGroup.CheckSculptAndLoad(); if (LocalId == ParentGroup.RootPart.LocalId)
{
ParentGroup.CheckSculptAndLoad();
}
} }
}
if ( if (
((AggregateScriptEvents & scriptEvents.collision) != 0) || ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
((AggregateScriptEvents & scriptEvents.collision_end) != 0) || ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
((AggregateScriptEvents & scriptEvents.collision_start) != 0) || ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) || ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
((AggregateScriptEvents & scriptEvents.land_collision) != 0) || ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) || ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
(CollisionSound != UUID.Zero) (CollisionSound != UUID.Zero)
) )
{ {
PhysActor.OnCollisionUpdate += PhysicsCollision; pa.OnCollisionUpdate += PhysicsCollision;
PhysActor.SubscribeEvents(1000); pa.SubscribeEvents(1000);
}
} }
} }
else // it already has a physical representation else // it already has a physical representation
@ -4418,7 +4391,52 @@ namespace OpenSim.Region.Framework.Scenes
} }
/// <summary> /// <summary>
/// This removes the part from physics /// Adds this part to the physics scene.
/// </summary>
/// <remarks>This method also sets the PhysActor property.</remarks>
/// <param name="rigidBody">Add this prim with a rigid body.</param>
/// <returns>
/// The physics actor. null if there was a failure.
/// </returns>
private PhysicsActor AddToPhysics(bool rigidBody)
{
PhysicsActor pa;
try
{
pa = ParentGroup.Scene.PhysicsScene.AddPrimShape(
string.Format("{0}/{1}", Name, UUID),
Shape,
AbsolutePosition,
Scale,
RotationOffset,
rigidBody,
m_localId);
}
catch
{
m_log.ErrorFormat("[SCENE]: caught exception meshing object {0}. Object set to phantom.", m_uuid);
pa = null;
}
// FIXME: Ideally we wouldn't set the property here to reduce situations where threads changing physical
// properties can stop on each other. However, DoPhysicsPropertyUpdate() currently relies on PhysActor
// being set.
PhysActor = pa;
// Basic Physics can also return null as well as an exception catch.
if (pa != null)
{
pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info
pa.SetMaterial(Material);
DoPhysicsPropertyUpdate(rigidBody, true);
}
return pa;
}
/// <summary>
/// This removes the part from the physics scene.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// This isn't the same as turning off physical, since even without being physical the prim has a physics /// This isn't the same as turning off physical, since even without being physical the prim has a physics

View File

@ -3514,6 +3514,22 @@ namespace OpenSim.Region.Framework.Scenes
}); });
} }
/// <summary>
/// Gets the mass.
/// </summary>
/// <returns>
/// The mass.
/// </returns>
public float GetMass()
{
PhysicsActor pa = PhysicsActor;
if (pa != null)
return pa.Mass;
else
return 0;
}
internal void PushForce(Vector3 impulse) internal void PushForce(Vector3 impulse)
{ {
if (PhysicsActor != null) if (PhysicsActor != null)

View File

@ -2022,27 +2022,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
protected LSL_Vector GetPartLocalPos(SceneObjectPart part) protected LSL_Vector GetPartLocalPos(SceneObjectPart part)
{ {
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
if (part.ParentID == 0)
Vector3 pos;
if (!part.IsRoot)
{ {
return new LSL_Vector(part.AbsolutePosition.X, pos = part.OffsetPosition;
part.AbsolutePosition.Y,
part.AbsolutePosition.Z);
} }
else else
{ {
if (m_host.IsRoot) if (part.ParentGroup.IsAttachment)
{ {
return new LSL_Vector(m_host.AttachedPos.X, pos = part.AttachedPos;
m_host.AttachedPos.Y,
m_host.AttachedPos.Z);
} }
else else
{ {
return new LSL_Vector(part.OffsetPosition.X, pos = part.AbsolutePosition;
part.OffsetPosition.Y,
part.OffsetPosition.Z);
} }
} }
// m_log.DebugFormat("[LSL API]: Returning {0} in GetPartLocalPos()", pos);
return new LSL_Vector(pos.X, pos.Y, pos.Z);
} }
public void llSetRot(LSL_Rotation rot) public void llSetRot(LSL_Rotation rot)
@ -2907,7 +2908,31 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public LSL_Float llGetMass() public LSL_Float llGetMass()
{ {
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
return m_host.GetMass();
if (m_host.ParentGroup.IsAttachment)
{
ScenePresence attachedAvatar = World.GetScenePresence(m_host.ParentGroup.AttachedAvatar);
if (attachedAvatar != null)
{
return attachedAvatar.GetMass();
}
else
{
return 0;
}
}
else
{
if (m_host.IsRoot)
{
return m_host.ParentGroup.GetMass();
}
else
{
return m_host.GetMass();
}
}
} }
public void llCollisionFilter(string name, string id, int accept) public void llCollisionFilter(string name, string id, int accept)
@ -7146,6 +7171,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
switch (code) switch (code)
{ {
case (int)ScriptBaseClass.PRIM_POSITION: case (int)ScriptBaseClass.PRIM_POSITION:
case (int)ScriptBaseClass.PRIM_POS_LOCAL:
if (remain < 1) if (remain < 1)
return; return;
@ -10330,6 +10356,35 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case ScriptBaseClass.OBJECT_CREATOR: case ScriptBaseClass.OBJECT_CREATOR:
ret.Add(new LSL_String(UUID.Zero.ToString())); ret.Add(new LSL_String(UUID.Zero.ToString()));
break; break;
// For the following 8 see the Object version below
case ScriptBaseClass.OBJECT_RUNNING_SCRIPT_COUNT:
ret.Add(new LSL_Integer(0));
break;
case ScriptBaseClass.OBJECT_TOTAL_SCRIPT_COUNT:
ret.Add(new LSL_Integer(0));
break;
case ScriptBaseClass.OBJECT_SCRIPT_MEMORY:
ret.Add(new LSL_Integer(0));
break;
case ScriptBaseClass.OBJECT_SCRIPT_TIME:
ret.Add(new LSL_Float(0));
break;
case ScriptBaseClass.OBJECT_PRIM_EQUIVALENCE:
ret.Add(new LSL_Integer(0));
break;
case ScriptBaseClass.OBJECT_SERVER_COST:
ret.Add(new LSL_Float(0));
break;
case ScriptBaseClass.OBJECT_STREAMING_COST:
ret.Add(new LSL_Float(0));
break;
case ScriptBaseClass.OBJECT_PHYSICS_COST:
ret.Add(new LSL_Float(0));
break;
default:
// Invalid or unhandled constant.
ret.Add(new LSL_Integer(ScriptBaseClass.OBJECT_UNKNOWN_DETAIL));
break;
} }
} }
@ -10367,6 +10422,49 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case ScriptBaseClass.OBJECT_CREATOR: case ScriptBaseClass.OBJECT_CREATOR:
ret.Add(new LSL_String(obj.CreatorID.ToString())); ret.Add(new LSL_String(obj.CreatorID.ToString()));
break; break;
// The following 8 I have intentionaly coded to return zero. They are part of
// "Land Impact" calculations. These calculations are probably not applicable
// to OpenSim, required figures (cpu/memory usage) are not currently tracked
// I have intentionally left these all at zero rather than return possibly
// missleading numbers
case ScriptBaseClass.OBJECT_RUNNING_SCRIPT_COUNT:
// in SL this currently includes crashed scripts
ret.Add(new LSL_Integer(0));
break;
case ScriptBaseClass.OBJECT_TOTAL_SCRIPT_COUNT:
ret.Add(new LSL_Integer(0));
break;
case ScriptBaseClass.OBJECT_SCRIPT_MEMORY:
// The value returned in SL for mono scripts is 65536 * number of active scripts
ret.Add(new LSL_Integer(0));
break;
case ScriptBaseClass.OBJECT_SCRIPT_TIME:
// Average cpu time per simulator frame expended on all scripts in the objetc
ret.Add(new LSL_Float(0));
break;
case ScriptBaseClass.OBJECT_PRIM_EQUIVALENCE:
// according to the SL wiki A prim or linkset will have prim
// equivalent of the number of prims in a linkset if it does not
// contain a mesh anywhere in the link set or is not a normal prim
// The value returned in SL for normal prims is prim count
ret.Add(new LSL_Integer(0));
break;
case ScriptBaseClass.OBJECT_SERVER_COST:
// The value returned in SL for normal prims is prim count
ret.Add(new LSL_Float(0));
break;
case ScriptBaseClass.OBJECT_STREAMING_COST:
// The value returned in SL for normal prims is prim count * 0.06
ret.Add(new LSL_Float(0));
break;
case ScriptBaseClass.OBJECT_PHYSICS_COST:
// The value returned in SL for normal prims is prim count
ret.Add(new LSL_Float(0));
break;
default:
// Invalid or unhandled constant.
ret.Add(new LSL_Integer(ScriptBaseClass.OBJECT_UNKNOWN_DETAIL));
break;
} }
} }

View File

@ -479,6 +479,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
public const int DEBUG_CHANNEL = 0x7FFFFFFF; public const int DEBUG_CHANNEL = 0x7FFFFFFF;
public const int PUBLIC_CHANNEL = 0x00000000; public const int PUBLIC_CHANNEL = 0x00000000;
// Constants for llGetObjectDetails
public const int OBJECT_UNKNOWN_DETAIL = -1;
public const int OBJECT_NAME = 1; public const int OBJECT_NAME = 1;
public const int OBJECT_DESC = 2; public const int OBJECT_DESC = 2;
public const int OBJECT_POS = 3; public const int OBJECT_POS = 3;
@ -487,6 +489,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
public const int OBJECT_OWNER = 6; public const int OBJECT_OWNER = 6;
public const int OBJECT_GROUP = 7; public const int OBJECT_GROUP = 7;
public const int OBJECT_CREATOR = 8; public const int OBJECT_CREATOR = 8;
public const int OBJECT_RUNNING_SCRIPT_COUNT = 9;
public const int OBJECT_TOTAL_SCRIPT_COUNT = 10;
public const int OBJECT_SCRIPT_MEMORY = 11;
public const int OBJECT_SCRIPT_TIME = 12;
public const int OBJECT_PRIM_EQUIVALENCE = 13;
public const int OBJECT_SERVER_COST = 14;
public const int OBJECT_STREAMING_COST = 15;
public const int OBJECT_PHYSICS_COST = 16;
// Can not be public const? // Can not be public const?
public static readonly vector ZERO_VECTOR = new vector(0.0, 0.0, 0.0); public static readonly vector ZERO_VECTOR = new vector(0.0, 0.0, 0.0);

View File

@ -114,6 +114,8 @@ namespace OpenSim.Server.Handlers.Asset
return HandleCreateUserInventory(request); return HandleCreateUserInventory(request);
case "GETINVENTORYSKELETON": case "GETINVENTORYSKELETON":
return HandleGetInventorySkeleton(request); return HandleGetInventorySkeleton(request);
case "GETUSERINVENTORY":
return HandleGetUserInventory(request);
case "GETROOTFOLDER": case "GETROOTFOLDER":
return HandleGetRootFolder(request); return HandleGetRootFolder(request);
case "GETFOLDERFORTYPE": case "GETFOLDERFORTYPE":
@ -153,7 +155,7 @@ namespace OpenSim.Server.Handlers.Asset
} }
catch (Exception e) catch (Exception e)
{ {
m_log.DebugFormat("[XINVENTORY HANDLER]: Exception {0}", e); m_log.DebugFormat("[XINVENTORY HANDLER]: Exception {0}", e.StackTrace);
} }
return FailureResult(); return FailureResult();
@ -248,6 +250,45 @@ namespace OpenSim.Server.Handlers.Asset
return encoding.GetBytes(xmlString); return encoding.GetBytes(xmlString);
} }
byte[] HandleGetUserInventory(Dictionary<string, object> request)
{
Dictionary<string, object> result = new Dictionary<string, object>();
UUID principal = UUID.Zero;
UUID.TryParse(request["PRINCIPAL"].ToString(), out principal);
InventoryCollection icoll = m_InventoryService.GetUserInventory(principal);
if (icoll != null)
{
Dictionary<string, object> folders = new Dictionary<string, object>();
int i = 0;
if (icoll.Folders != null)
{
foreach (InventoryFolderBase f in icoll.Folders)
{
folders["folder_" + i.ToString()] = EncodeFolder(f);
i++;
}
result["FOLDERS"] = folders;
}
if (icoll.Items != null)
{
i = 0;
Dictionary<string, object> items = new Dictionary<string, object>();
foreach (InventoryItemBase it in icoll.Items)
{
items["item_" + i.ToString()] = EncodeItem(it);
i++;
}
result["ITEMS"] = items;
}
}
string xmlString = ServerUtils.BuildXmlResponse(result);
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
UTF8Encoding encoding = new UTF8Encoding();
return encoding.GetBytes(xmlString);
}
byte[] HandleGetRootFolder(Dictionary<string,object> request) byte[] HandleGetRootFolder(Dictionary<string,object> request)
{ {
Dictionary<string,object> result = new Dictionary<string,object>(); Dictionary<string,object> result = new Dictionary<string,object>();
@ -294,21 +335,26 @@ namespace OpenSim.Server.Handlers.Asset
{ {
Dictionary<string, object> folders = new Dictionary<string, object>(); Dictionary<string, object> folders = new Dictionary<string, object>();
int i = 0; int i = 0;
foreach (InventoryFolderBase f in icoll.Folders) if (icoll.Folders != null)
{ {
folders["folder_" + i.ToString()] = EncodeFolder(f); foreach (InventoryFolderBase f in icoll.Folders)
i++; {
folders["folder_" + i.ToString()] = EncodeFolder(f);
i++;
}
result["FOLDERS"] = folders;
} }
result["FOLDERS"] = folders; if (icoll.Items != null)
i = 0;
Dictionary<string, object> items = new Dictionary<string, object>();
foreach (InventoryItemBase it in icoll.Items)
{ {
items["item_" + i.ToString()] = EncodeItem(it); i = 0;
i++; Dictionary<string, object> items = new Dictionary<string, object>();
foreach (InventoryItemBase it in icoll.Items)
{
items["item_" + i.ToString()] = EncodeItem(it);
i++;
}
result["ITEMS"] = items;
} }
result["ITEMS"] = items;
} }
string xmlString = ServerUtils.BuildXmlResponse(result); string xmlString = ServerUtils.BuildXmlResponse(result);

View File

@ -111,19 +111,21 @@ namespace OpenSim.Services.Connectors
if (ret.Count == 0) if (ret.Count == 0)
return null; return null;
List<InventoryFolderBase> folders = new List<InventoryFolderBase>(); Dictionary<string, object> folders = (Dictionary<string, object>)ret["FOLDERS"];
List<InventoryFolderBase> fldrs = new List<InventoryFolderBase>();
try try
{ {
foreach (Object o in ret.Values) foreach (Object o in folders.Values)
folders.Add(BuildFolder((Dictionary<string, object>)o)); fldrs.Add(BuildFolder((Dictionary<string, object>)o));
} }
catch (Exception e) catch (Exception e)
{ {
m_log.DebugFormat("[XINVENTORY CONNECTOR STUB]: Exception unwrapping folder list: {0}", e.Message); m_log.DebugFormat("[XINVENTORY CONNECTOR STUB]: Exception unwrapping folder list: {0}", e.Message);
} }
return folders; return fldrs;
} }
public InventoryFolderBase GetRootFolder(UUID principalID) public InventoryFolderBase GetRootFolder(UUID principalID)
@ -492,12 +494,41 @@ namespace OpenSim.Services.Connectors
return int.Parse(ret["RESULT"].ToString()); return int.Parse(ret["RESULT"].ToString());
} }
// These are either obsolete or unused
//
public InventoryCollection GetUserInventory(UUID principalID) public InventoryCollection GetUserInventory(UUID principalID)
{ {
return null; InventoryCollection inventory = new InventoryCollection();
inventory.Folders = new List<InventoryFolderBase>();
inventory.Items = new List<InventoryItemBase>();
inventory.UserID = principalID;
try
{
Dictionary<string, object> ret = MakeRequest("GETUSERINVENTORY",
new Dictionary<string, object> {
{ "PRINCIPAL", principalID.ToString() }
});
if (ret == null)
return null;
if (ret.Count == 0)
return null;
Dictionary<string, object> folders =
(Dictionary<string, object>)ret["FOLDERS"];
Dictionary<string, object> items =
(Dictionary<string, object>)ret["ITEMS"];
foreach (Object o in folders.Values) // getting the values directly, we don't care about the keys folder_i
inventory.Folders.Add(BuildFolder((Dictionary<string, object>)o));
foreach (Object o in items.Values) // getting the values directly, we don't care about the keys item_i
inventory.Items.Add(BuildItem((Dictionary<string, object>)o));
}
catch (Exception e)
{
m_log.DebugFormat("[XINVENTORY CONNECTOR STUB]: Exception in GetUserInventory: {0}", e.Message);
}
return inventory;
} }
public void GetUserInventory(UUID principalID, InventoryReceiptCallback callback) public void GetUserInventory(UUID principalID, InventoryReceiptCallback callback)

View File

@ -105,6 +105,12 @@ namespace OpenSim.Services.HypergridService
return new List<InventoryFolderBase>(); return new List<InventoryFolderBase>();
} }
public override InventoryCollection GetUserInventory(UUID userID)
{
// NOGO for this inventory service
return null;
}
public override InventoryFolderBase GetRootFolder(UUID principalID) public override InventoryFolderBase GetRootFolder(UUID principalID)
{ {
//m_log.DebugFormat("[HG INVENTORY SERVICE]: GetRootFolder for {0}", principalID); //m_log.DebugFormat("[HG INVENTORY SERVICE]: GetRootFolder for {0}", principalID);

View File

@ -59,7 +59,7 @@ namespace OpenSim.Services.HypergridService
private UserAccountCache m_Cache; private UserAccountCache m_Cache;
private ExpiringCache<UUID, List<XInventoryFolder>> m_SuitcaseTrees = new ExpiringCache<UUID,List<XInventoryFolder>>(); private ExpiringCache<UUID, List<XInventoryFolder>> m_SuitcaseTrees = new ExpiringCache<UUID, List<XInventoryFolder>>();
public HGSuitcaseInventoryService(IConfigSource config, string configName) public HGSuitcaseInventoryService(IConfigSource config, string configName)
: base(config, configName) : base(config, configName)
@ -104,11 +104,72 @@ namespace OpenSim.Services.HypergridService
return false; return false;
} }
public override List<InventoryFolderBase> GetInventorySkeleton(UUID principalID) public override List<InventoryFolderBase> GetInventorySkeleton(UUID principalID)
{ {
// NOGO for this inventory service XInventoryFolder suitcase = GetSuitcaseXFolder(principalID);
return new List<InventoryFolderBase>(); XInventoryFolder root = GetRootXFolder(principalID);
List<XInventoryFolder> tree = GetFolderTree(suitcase.folderID);
if (tree == null || (tree != null && tree.Count == 0))
return null;
List<InventoryFolderBase> folders = new List<InventoryFolderBase>();
foreach (XInventoryFolder x in tree)
{
folders.Add(ConvertToOpenSim(x));
}
SetAsRootFolder(suitcase, root);
folders.Add(ConvertToOpenSim(suitcase));
return folders;
}
public override InventoryCollection GetUserInventory(UUID userID)
{
m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Get Suitcase inventory for user {0}", userID);
InventoryCollection userInventory = new InventoryCollection();
userInventory.UserID = userID;
userInventory.Folders = new List<InventoryFolderBase>();
userInventory.Items = new List<InventoryItemBase>();
XInventoryFolder suitcase = GetSuitcaseXFolder(userID);
XInventoryFolder root = GetRootXFolder(userID);
List<XInventoryFolder> tree = GetFolderTree(suitcase.folderID);
if (tree == null || (tree != null && tree.Count == 0))
{
SetAsRootFolder(suitcase, root);
userInventory.Folders.Add(ConvertToOpenSim(suitcase));
return userInventory;
}
List<InventoryItemBase> items;
foreach (XInventoryFolder f in tree)
{
// Add the items of this subfolder
items = GetFolderItems(userID, f.folderID);
if (items != null && items.Count > 0)
{
userInventory.Items.AddRange(items);
}
// Add the folder itself
userInventory.Folders.Add(ConvertToOpenSim(f));
}
items = GetFolderItems(userID, suitcase.folderID);
if (items != null && items.Count > 0)
{
userInventory.Items.AddRange(items);
}
SetAsRootFolder(suitcase, root);
userInventory.Folders.Add(ConvertToOpenSim(suitcase));
m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: GetUserInventory for user {0} returning {1} folders and {2} items",
userID, userInventory.Folders.Count, userInventory.Items.Count);
return userInventory;
} }
public override InventoryFolderBase GetRootFolder(UUID principalID) public override InventoryFolderBase GetRootFolder(UUID principalID)
@ -131,51 +192,92 @@ namespace OpenSim.Services.HypergridService
{ {
m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: User {0} does not have a Suitcase folder. Creating it...", principalID); m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: User {0} does not have a Suitcase folder. Creating it...", principalID);
// make one, and let's add it to the user's inventory as a direct child of the root folder // make one, and let's add it to the user's inventory as a direct child of the root folder
// In the DB we tag it as type 100, but we use -1 (Unknown) outside
suitcase = CreateFolder(principalID, root.folderID, 100, "My Suitcase"); suitcase = CreateFolder(principalID, root.folderID, 100, "My Suitcase");
if (suitcase == null) if (suitcase == null)
m_log.ErrorFormat("[HG SUITCASE INVENTORY SERVICE]: Unable to create suitcase folder"); m_log.ErrorFormat("[HG SUITCASE INVENTORY SERVICE]: Unable to create suitcase folder");
m_Database.StoreFolder(suitcase); m_Database.StoreFolder(suitcase);
// Create System folders
CreateSystemFolders(principalID, suitcase.folderID);
} }
// Now let's change the folder ID to match that of the real root folder SetAsRootFolder(suitcase, root);
SetAsRootFolder(suitcase, root.folderID);
return ConvertToOpenSim(suitcase); return ConvertToOpenSim(suitcase);
} }
protected void CreateSystemFolders(UUID principalID, UUID rootID)
{
m_log.Debug("[HG SUITCASE INVENTORY SERVICE]: Creating System folders under Suitcase...");
XInventoryFolder[] sysFolders = GetSystemFolders(principalID, rootID);
if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Animation) return true; return false; }))
CreateFolder(principalID, rootID, (int)AssetType.Animation, "Animations");
if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Bodypart) return true; return false; }))
CreateFolder(principalID, rootID, (int)AssetType.Bodypart, "Body Parts");
if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.CallingCard) return true; return false; }))
CreateFolder(principalID, rootID, (int)AssetType.CallingCard, "Calling Cards");
if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Clothing) return true; return false; }))
CreateFolder(principalID, rootID, (int)AssetType.Clothing, "Clothing");
if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Gesture) return true; return false; }))
CreateFolder(principalID, rootID, (int)AssetType.Gesture, "Gestures");
if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Landmark) return true; return false; }))
CreateFolder(principalID, rootID, (int)AssetType.Landmark, "Landmarks");
if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.LostAndFoundFolder) return true; return false; }))
CreateFolder(principalID, rootID, (int)AssetType.LostAndFoundFolder, "Lost And Found");
if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Notecard) return true; return false; }))
CreateFolder(principalID, rootID, (int)AssetType.Notecard, "Notecards");
if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Object) return true; return false; }))
CreateFolder(principalID, rootID, (int)AssetType.Object, "Objects");
if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.SnapshotFolder) return true; return false; }))
CreateFolder(principalID, rootID, (int)AssetType.SnapshotFolder, "Photo Album");
if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.LSLText) return true; return false; }))
CreateFolder(principalID, rootID, (int)AssetType.LSLText, "Scripts");
if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Sound) return true; return false; }))
CreateFolder(principalID, rootID, (int)AssetType.Sound, "Sounds");
if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Texture) return true; return false; }))
CreateFolder(principalID, rootID, (int)AssetType.Texture, "Textures");
if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.TrashFolder) return true; return false; }))
CreateFolder(principalID, rootID, (int)AssetType.TrashFolder, "Trash");
if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.FavoriteFolder) return true; return false; }))
CreateFolder(principalID, rootID, (int)AssetType.FavoriteFolder, "Favorites");
if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.CurrentOutfitFolder) return true; return false; }))
CreateFolder(principalID, rootID, (int)AssetType.CurrentOutfitFolder, "Current Outfit");
}
public override InventoryFolderBase GetFolderForType(UUID principalID, AssetType type) public override InventoryFolderBase GetFolderForType(UUID principalID, AssetType type)
{ {
//m_log.DebugFormat("[HG INVENTORY SERVICE]: GetFolderForType for {0} {0}", principalID, type); //m_log.DebugFormat("[HG INVENTORY SERVICE]: GetFolderForType for {0} {0}", principalID, type);
return GetRootFolder(principalID); XInventoryFolder suitcase = GetSuitcaseXFolder(principalID);
XInventoryFolder[] folders = m_Database.GetFolders(
new string[] { "agentID", "type", "parentFolderID" },
new string[] { principalID.ToString(), ((int)type).ToString(), suitcase.folderID.ToString() });
if (folders.Length == 0)
{
m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: Found no folder for type {0} for user {1}", type, principalID);
return null;
}
m_log.DebugFormat(
"[HG SUITCASE INVENTORY SERVICE]: Found folder {0} {1} for type {2} for user {3}",
folders[0].folderName, folders[0].folderID, type, principalID);
return ConvertToOpenSim(folders[0]);
} }
public override InventoryCollection GetFolderContent(UUID principalID, UUID folderID) public override InventoryCollection GetFolderContent(UUID principalID, UUID folderID)
{ {
InventoryCollection coll = null; InventoryCollection coll = null;
XInventoryFolder suitcase = GetSuitcaseXFolder(principalID); XInventoryFolder suitcase = GetSuitcaseXFolder(principalID);
XInventoryFolder root = GetRootXFolder(principalID);
if (!IsWithinSuitcaseTree(folderID, root, suitcase)) if (!IsWithinSuitcaseTree(folderID, suitcase))
return new InventoryCollection(); return new InventoryCollection();
if (folderID == root.folderID) // someone's asking for the root folder, we'll give them the suitcase coll = base.GetFolderContent(principalID, folderID);
{
if (suitcase != null)
{
coll = base.GetFolderContent(principalID, suitcase.folderID);
foreach (InventoryFolderBase f in coll.Folders)
f.ParentID = root.folderID;
foreach (InventoryItemBase i in coll.Items)
i.Folder = root.folderID;
m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: GetFolderContent for root folder returned content for suitcase folder");
}
}
else
{
coll = base.GetFolderContent(principalID, folderID);
m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: GetFolderContent for non-root folder {0}", folderID);
}
if (coll == null) if (coll == null)
{ {
m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: Something wrong with user {0}'s suitcase folder", principalID); m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: Something wrong with user {0}'s suitcase folder", principalID);
@ -188,10 +290,9 @@ namespace OpenSim.Services.HypergridService
{ {
// Let's do a bit of sanity checking, more than the base service does // Let's do a bit of sanity checking, more than the base service does
// make sure the given folder exists under the suitcase tree of this user // make sure the given folder exists under the suitcase tree of this user
XInventoryFolder root = GetRootXFolder(principalID);
XInventoryFolder suitcase = GetSuitcaseXFolder(principalID); XInventoryFolder suitcase = GetSuitcaseXFolder(principalID);
if (!IsWithinSuitcaseTree(folderID, root, suitcase)) if (!IsWithinSuitcaseTree(folderID, suitcase))
return new List<InventoryItemBase>(); return new List<InventoryItemBase>();
return base.GetFolderItems(principalID, folderID); return base.GetFolderItems(principalID, folderID);
@ -199,52 +300,40 @@ namespace OpenSim.Services.HypergridService
public override bool AddFolder(InventoryFolderBase folder) public override bool AddFolder(InventoryFolderBase folder)
{ {
m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: AddFolder {0} {1}", folder.Name, folder.ParentID);
// Let's do a bit of sanity checking, more than the base service does // Let's do a bit of sanity checking, more than the base service does
// make sure the given folder's parent folder exists under the suitcase tree of this user // make sure the given folder's parent folder exists under the suitcase tree of this user
XInventoryFolder root = GetRootXFolder(folder.Owner);
XInventoryFolder suitcase = GetSuitcaseXFolder(folder.Owner); XInventoryFolder suitcase = GetSuitcaseXFolder(folder.Owner);
if (!IsWithinSuitcaseTree(folder.ParentID, root, suitcase)) if (!IsWithinSuitcaseTree(folder.ParentID, suitcase))
return false; return false;
// OK, it's legit // OK, it's legit
// Check if it's under the Root folder directly
if (folder.ParentID == root.folderID)
{
// someone's trying to add a subfolder of the root folder, we'll add it to the suitcase instead
m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: AddFolder for root folder for user {0}. Adding in suitcase instead", folder.Owner);
folder.ParentID = suitcase.folderID;
}
return base.AddFolder(folder); return base.AddFolder(folder);
} }
public bool UpdateFolder(InventoryFolderBase folder) public override bool UpdateFolder(InventoryFolderBase folder)
{ {
XInventoryFolder root = GetRootXFolder(folder.Owner);
XInventoryFolder suitcase = GetSuitcaseXFolder(folder.Owner); XInventoryFolder suitcase = GetSuitcaseXFolder(folder.Owner);
if (!IsWithinSuitcaseTree(folder.ID, root, suitcase)) m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Update folder {0}, version {1}", folder.ID, folder.Version);
if (!IsWithinSuitcaseTree(folder.ID, suitcase))
{
m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: folder {0} not within Suitcase tree", folder.Name);
return false; return false;
}
// For all others
return base.UpdateFolder(folder); return base.UpdateFolder(folder);
} }
public override bool MoveFolder(InventoryFolderBase folder) public override bool MoveFolder(InventoryFolderBase folder)
{ {
XInventoryFolder root = GetRootXFolder(folder.Owner);
XInventoryFolder suitcase = GetSuitcaseXFolder(folder.Owner); XInventoryFolder suitcase = GetSuitcaseXFolder(folder.Owner);
if (!IsWithinSuitcaseTree(folder.ID, root, suitcase) || !IsWithinSuitcaseTree(folder.ParentID, root, suitcase)) if (!IsWithinSuitcaseTree(folder.ID, suitcase) || !IsWithinSuitcaseTree(folder.ParentID, suitcase))
return false; return false;
if (folder.ParentID == root.folderID)
{
// someone's trying to add a subfolder of the root folder, we'll add it to the suitcase instead
m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: MoveFolder to root folder for user {0}. Moving it to suitcase instead", folder.Owner);
folder.ParentID = suitcase.folderID;
}
return base.MoveFolder(folder); return base.MoveFolder(folder);
} }
@ -264,31 +353,21 @@ namespace OpenSim.Services.HypergridService
{ {
// Let's do a bit of sanity checking, more than the base service does // Let's do a bit of sanity checking, more than the base service does
// make sure the given folder's parent folder exists under the suitcase tree of this user // make sure the given folder's parent folder exists under the suitcase tree of this user
XInventoryFolder root = GetRootXFolder(item.Owner);
XInventoryFolder suitcase = GetSuitcaseXFolder(item.Owner); XInventoryFolder suitcase = GetSuitcaseXFolder(item.Owner);
if (!IsWithinSuitcaseTree(item.Folder, root, suitcase)) if (!IsWithinSuitcaseTree(item.Folder, suitcase))
return false; return false;
// OK, it's legit // OK, it's legit
// Check if it's under the Root folder directly
if (item.Folder == root.folderID)
{
// someone's trying to add a subfolder of the root folder, we'll add it to the suitcase instead
m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: AddItem for root folder for user {0}. Adding in suitcase instead", item.Owner);
item.Folder = suitcase.folderID;
}
return base.AddItem(item); return base.AddItem(item);
} }
public override bool UpdateItem(InventoryItemBase item) public override bool UpdateItem(InventoryItemBase item)
{ {
XInventoryFolder root = GetRootXFolder(item.Owner);
XInventoryFolder suitcase = GetSuitcaseXFolder(item.Owner); XInventoryFolder suitcase = GetSuitcaseXFolder(item.Owner);
if (!IsWithinSuitcaseTree(item.Folder, root, suitcase)) if (!IsWithinSuitcaseTree(item.Folder, suitcase))
return false; return false;
return base.UpdateItem(item); return base.UpdateItem(item);
@ -298,68 +377,64 @@ namespace OpenSim.Services.HypergridService
{ {
// Principal is b0rked. *sigh* // Principal is b0rked. *sigh*
XInventoryFolder root = GetRootXFolder(items[0].Owner);
XInventoryFolder suitcase = GetSuitcaseXFolder(items[0].Owner); XInventoryFolder suitcase = GetSuitcaseXFolder(items[0].Owner);
if (!IsWithinSuitcaseTree(items[0].Folder, root, suitcase)) if (!IsWithinSuitcaseTree(items[0].Folder, suitcase))
return false; return false;
foreach (InventoryItemBase it in items)
if (it.Folder == root.folderID)
{
// someone's trying to add a subfolder of the root folder, we'll add it to the suitcase instead
m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: MoveItem to root folder for user {0}. Moving it to suitcase instead", it.Owner);
it.Folder = suitcase.folderID;
}
return base.MoveItems(principalID, items); return base.MoveItems(principalID, items);
} }
// Let these pass. Use inherited methods.
public override bool DeleteItems(UUID principalID, List<UUID> itemIDs) public override bool DeleteItems(UUID principalID, List<UUID> itemIDs)
{ {
return false; return false;
} }
public override InventoryItemBase GetItem(InventoryItemBase item) public new InventoryItemBase GetItem(InventoryItemBase item)
{ {
InventoryItemBase it = base.GetItem(item); InventoryItemBase it = base.GetItem(item);
XInventoryFolder root = GetRootXFolder(it.Owner); if (it == null)
XInventoryFolder suitcase = GetSuitcaseXFolder(it.Owner);
if (it != null)
{ {
if (!IsWithinSuitcaseTree(it.Folder, root, suitcase)) m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Unable to retrieve item {0} ({1}) in folder {2}",
return null; item.Name, item.ID, item.Folder);
return null;
if (it.Folder == suitcase.folderID)
it.Folder = root.folderID;
// UserAccount user = m_Cache.GetUser(it.CreatorId);
// // Adjust the creator data
// if (user != null && it != null && (it.CreatorData == null || it.CreatorData == string.Empty))
// it.CreatorData = m_HomeURL + ";" + user.FirstName + " " + user.LastName;
//}
} }
XInventoryFolder suitcase = GetSuitcaseXFolder(it.Owner);
if (suitcase == null)
{
m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Root or Suitcase are null for user {0}",
it.Owner);
return null;
}
if (!IsWithinSuitcaseTree(it.Folder, suitcase))
{
m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Item {0} (folder {1}) is not within Suitcase",
it.Name, it.Folder);
return null;
}
// UserAccount user = m_Cache.GetUser(it.CreatorId);
// // Adjust the creator data
// if (user != null && it != null && (it.CreatorData == null || it.CreatorData == string.Empty))
// it.CreatorData = m_HomeURL + ";" + user.FirstName + " " + user.LastName;
//}
return it; return it;
} }
public override InventoryFolderBase GetFolder(InventoryFolderBase folder) public new InventoryFolderBase GetFolder(InventoryFolderBase folder)
{ {
InventoryFolderBase f = base.GetFolder(folder); InventoryFolderBase f = base.GetFolder(folder);
XInventoryFolder root = GetRootXFolder(f.Owner);
XInventoryFolder suitcase = GetSuitcaseXFolder(f.Owner);
if (f != null) if (f != null)
{ {
if (!IsWithinSuitcaseTree(f.ID, root, suitcase)) XInventoryFolder suitcase = GetSuitcaseXFolder(f.Owner);
return null;
if (f.ParentID == suitcase.folderID) if (!IsWithinSuitcaseTree(f.ID, suitcase))
f.ParentID = root.folderID; return null;
} }
return f; return f;
@ -409,20 +484,19 @@ namespace OpenSim.Services.HypergridService
return null; return null;
} }
private void SetAsRootFolder(XInventoryFolder suitcase, UUID rootID) private void SetAsRootFolder(XInventoryFolder suitcase, XInventoryFolder root)
{ {
suitcase.folderID = rootID; suitcase.type = (short)AssetType.Folder;
suitcase.parentFolderID = UUID.Zero;
} }
private List<XInventoryFolder> GetFolderTree(UUID root) private List<XInventoryFolder> GetFolderTree(UUID folder)
{ {
List<XInventoryFolder> t = null; List<XInventoryFolder> t = null;
if (m_SuitcaseTrees.TryGetValue(root, out t)) if (m_SuitcaseTrees.TryGetValue(folder, out t))
return t; return t;
t = GetFolderTreeRecursive(root); t = GetFolderTreeRecursive(folder);
m_SuitcaseTrees.AddOrUpdate(root, t, 120); m_SuitcaseTrees.AddOrUpdate(folder, t, 120);
return t; return t;
} }
@ -447,10 +521,17 @@ namespace OpenSim.Services.HypergridService
} }
private bool IsWithinSuitcaseTree(UUID folderID, XInventoryFolder root, XInventoryFolder suitcase) /// <summary>
/// Return true if the folderID is a subfolder of the Suitcase or the suitcase folder itself
/// </summary>
/// <param name="folderID"></param>
/// <param name="root"></param>
/// <param name="suitcase"></param>
/// <returns></returns>
private bool IsWithinSuitcaseTree(UUID folderID, XInventoryFolder suitcase)
{ {
List<XInventoryFolder> tree = new List<XInventoryFolder>(); List<XInventoryFolder> tree = new List<XInventoryFolder>();
tree.Add(root); // Warp! the tree is the real root folder plus the children of the suitcase folder tree.Add(suitcase); // Warp! the tree is the real root folder plus the children of the suitcase folder
tree.AddRange(GetFolderTree(suitcase.folderID)); tree.AddRange(GetFolderTree(suitcase.folderID));
XInventoryFolder f = tree.Find(delegate(XInventoryFolder fl) XInventoryFolder f = tree.Find(delegate(XInventoryFolder fl)
{ {
@ -463,4 +544,5 @@ namespace OpenSim.Services.HypergridService
} }
#endregion #endregion
} }
} }

View File

@ -40,9 +40,9 @@ namespace OpenSim.Services.InventoryService
{ {
public class XInventoryService : ServiceBase, IInventoryService public class XInventoryService : ServiceBase, IInventoryService
{ {
// private static readonly ILog m_log = private static readonly ILog m_log =
// LogManager.GetLogger( LogManager.GetLogger(
// MethodBase.GetCurrentMethod().DeclaringType); MethodBase.GetCurrentMethod().DeclaringType);
protected IXInventoryData m_Database; protected IXInventoryData m_Database;
protected bool m_AllowDelete = true; protected bool m_AllowDelete = true;
@ -113,7 +113,7 @@ namespace OpenSim.Services.InventoryService
result = true; result = true;
} }
XInventoryFolder[] sysFolders = GetSystemFolders(principalID); XInventoryFolder[] sysFolders = GetSystemFolders(principalID, rootFolder.ID);
if (!Array.Exists(sysFolders, delegate (XInventoryFolder f) { if (f.type == (int)AssetType.Animation) return true; return false; })) if (!Array.Exists(sysFolders, delegate (XInventoryFolder f) { if (f.type == (int)AssetType.Animation) return true; return false; }))
CreateFolder(principalID, rootFolder.ID, (int)AssetType.Animation, "Animations"); CreateFolder(principalID, rootFolder.ID, (int)AssetType.Animation, "Animations");
@ -163,13 +163,13 @@ namespace OpenSim.Services.InventoryService
return newFolder; return newFolder;
} }
protected virtual XInventoryFolder[] GetSystemFolders(UUID principalID) protected virtual XInventoryFolder[] GetSystemFolders(UUID principalID, UUID rootID)
{ {
// m_log.DebugFormat("[XINVENTORY SERVICE]: Getting system folders for {0}", principalID); // m_log.DebugFormat("[XINVENTORY SERVICE]: Getting system folders for {0}", principalID);
XInventoryFolder[] allFolders = m_Database.GetFolders( XInventoryFolder[] allFolders = m_Database.GetFolders(
new string[] { "agentID" }, new string[] { "agentID", "parentFolderID" },
new string[] { principalID.ToString() }); new string[] { principalID.ToString(), rootID.ToString() });
XInventoryFolder[] sysFolders = Array.FindAll( XInventoryFolder[] sysFolders = Array.FindAll(
allFolders, allFolders,
@ -301,16 +301,26 @@ namespace OpenSim.Services.InventoryService
public virtual bool AddFolder(InventoryFolderBase folder) public virtual bool AddFolder(InventoryFolderBase folder)
{ {
//m_log.DebugFormat("[XINVENTORY]: Add folder {0} type {1} in parent {2}", folder.Name, folder.Type, folder.ParentID);
InventoryFolderBase check = GetFolder(folder); InventoryFolderBase check = GetFolder(folder);
if (check != null) if (check != null)
return false; return false;
XInventoryFolder xFolder = ConvertFromOpenSim(folder); if (folder.Type == (short)AssetType.Folder || folder.Type == (short)AssetType.Unknown ||
return m_Database.StoreFolder(xFolder); GetFolderForType(folder.Owner, (AssetType)(folder.Type)) == null)
{
XInventoryFolder xFolder = ConvertFromOpenSim(folder);
return m_Database.StoreFolder(xFolder);
}
else
m_log.DebugFormat("[XINVENTORY]: Folder {0} of type {1} already exists", folder.Name, folder.Type);
return false;
} }
public virtual bool UpdateFolder(InventoryFolderBase folder) public virtual bool UpdateFolder(InventoryFolderBase folder)
{ {
//m_log.DebugFormat("[XINVENTORY]: Update folder {0} {1} ({2})", folder.Name, folder.Type, folder.ID);
XInventoryFolder xFolder = ConvertFromOpenSim(folder); XInventoryFolder xFolder = ConvertFromOpenSim(folder);
InventoryFolderBase check = GetFolder(folder); InventoryFolderBase check = GetFolder(folder);
if (check == null) if (check == null)
@ -319,9 +329,13 @@ namespace OpenSim.Services.InventoryService
if (check.Type != -1 || xFolder.type != -1) if (check.Type != -1 || xFolder.type != -1)
{ {
if (xFolder.version < check.Version) if (xFolder.version < check.Version)
{
//m_log.DebugFormat("[XINVENTORY]: {0} < {1} can't do", xFolder.version, check.Version);
return false; return false;
}
check.Version = (ushort)xFolder.version; check.Version = (ushort)xFolder.version;
xFolder = ConvertFromOpenSim(check); xFolder = ConvertFromOpenSim(check);
//m_log.DebugFormat("[XINVENTORY]: Storing {0} {1} {2}", xFolder.folderName, xFolder.version, xFolder.type);
return m_Database.StoreFolder(xFolder); return m_Database.StoreFolder(xFolder);
} }
@ -499,13 +513,30 @@ namespace OpenSim.Services.InventoryService
return m_Database.GetAssetPermissions(principalID, assetID); return m_Database.GetAssetPermissions(principalID, assetID);
} }
// CM never needed those. Left unimplemented. public virtual InventoryCollection GetUserInventory(UUID userID)
// Obsolete in core
//
public InventoryCollection GetUserInventory(UUID userID)
{ {
return null; InventoryCollection userInventory = new InventoryCollection();
userInventory.UserID = userID;
userInventory.Folders = new List<InventoryFolderBase>();
userInventory.Items = new List<InventoryItemBase>();
List<InventoryFolderBase> skel = GetInventorySkeleton(userID);
if (skel != null)
{
foreach (InventoryFolderBase f in skel)
{
InventoryCollection c = GetFolderContent(userID, f.ID);
if (c != null && c.Items != null && c.Items.Count > 0)
userInventory.Items.AddRange(c.Items);
if (c != null && c.Folders != null && c.Folders.Count > 0)
userInventory.Folders.AddRange(c.Folders);
}
}
m_log.DebugFormat("[XINVENTORY SERVICE]: GetUserInventory for user {0} returning {1} folders and {2} items",
userID, userInventory.Folders.Count, userInventory.Items.Count);
return userInventory;
} }
public void GetUserInventory(UUID userID, InventoryReceiptCallback callback) public void GetUserInventory(UUID userID, InventoryReceiptCallback callback)
{ {
} }
@ -525,6 +556,9 @@ namespace OpenSim.Services.InventoryService
newFolder.ParentID = folder.parentFolderID; newFolder.ParentID = folder.parentFolderID;
newFolder.Type = (short)folder.type; newFolder.Type = (short)folder.type;
// Viewer can't understand anything that's not in it's LLFolderType enum
if (newFolder.Type == 100)
newFolder.Type = -1;
newFolder.Version = (ushort)folder.version; newFolder.Version = (ushort)folder.version;
newFolder.Name = folder.folderName; newFolder.Name = folder.folderName;
newFolder.Owner = folder.agentID; newFolder.Owner = folder.agentID;