diff --git a/OpenSim/Grid/InventoryServer/Main.cs b/OpenSim/Grid/InventoryServer/Main.cs index 75603831b5..537661efb4 100644 --- a/OpenSim/Grid/InventoryServer/Main.cs +++ b/OpenSim/Grid/InventoryServer/Main.cs @@ -135,6 +135,10 @@ namespace OpenSim.Grid.InventoryServer new RestDeserialiseSecureHandler( "POST", "/NewFolder/", m_inventoryService.AddFolder, m_inventoryService.CheckAuthSession)); + m_httpServer.AddStreamHandler( + new RestDeserialiseTrustedHandler( + "POST", "/CreateFolder/", m_inventoryService.AddFolder, m_inventoryService.CheckTrustSource)); + m_httpServer.AddStreamHandler( new RestDeserialiseSecureHandler( "POST", "/NewItem/", m_inventoryService.AddItem, m_inventoryService.CheckAuthSession)); diff --git a/OpenSim/Grid/UserServer.Modules/AvatarCreationModule.cs b/OpenSim/Grid/UserServer.Modules/AvatarCreationModule.cs new file mode 100644 index 0000000000..5e6bc859f9 --- /dev/null +++ b/OpenSim/Grid/UserServer.Modules/AvatarCreationModule.cs @@ -0,0 +1,499 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Reflection; +using System.Threading; +using log4net; +using Nwc.XmlRpc; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Framework.Communications; +using OpenSim.Framework.Servers; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Grid.Framework; + + +namespace OpenSim.Grid.UserServer.Modules +{ + public class AvatarCreationModule + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private UserDataBaseService m_userDataBaseService; + // private BaseHttpServer m_httpServer; + private UserConfig m_config; + + private string m_inventoryServerUrl; + private IInterServiceInventoryServices m_inventoryService; + + public AvatarCreationModule(UserDataBaseService userDataBaseService, UserConfig config, IInterServiceInventoryServices inventoryService) + { + m_config = config; + m_userDataBaseService = userDataBaseService; + m_inventoryService = inventoryService; + m_inventoryServerUrl = config.InventoryUrl.OriginalString; + } + + public void Initialise(IGridServiceCore core) + { + CommandConsole console; + if (core.TryGet(out console)) + { + console.Commands.AddCommand("userserver", false, "clone avatar", + "clone avatar ", + "Clone the template avatar inventory into a target avatar", RunCommand); + } + } + + public void PostInitialise() + { + + } + + public void RegisterHandlers(BaseHttpServer httpServer) + { + } + + public void RunCommand(string module, string[] cmd) + { + if ((cmd.Length == 6) && (cmd[0] == "clone") && (cmd[1] == "avatar")) + { + try + { + string tFirst = cmd[2]; + string tLast = cmd[3]; + + string nFirst = cmd[4]; + string nLast = cmd[5]; + + UserProfileData templateAvatar = m_userDataBaseService.GetUserProfile(tFirst, tLast); + UserProfileData newAvatar = m_userDataBaseService.GetUserProfile(nFirst, nLast); + + if (templateAvatar == null) + { + m_log.ErrorFormat("[AvatarAppearance] Clone Avatar: Could not find template avatar {0} , {1}", tFirst, tLast); + return; + } + + if (newAvatar == null) + { + m_log.ErrorFormat("[AvatarAppearance] Clone Avatar: Could not find target avatar {0} , {1}", nFirst, nLast); + return; + } + Guid avatar = newAvatar.ID.Guid; + Guid template = templateAvatar.ID.Guid; + CloneAvatar(avatar, template); + + } + catch (Exception e) + { + m_log.Error("Error: " + e.ToString()); + } + } + } + #region Avatar Appearance Creation + + public bool CloneAvatar(Guid avatarID, Guid templateID) + { + m_log.InfoFormat("[AvatarAppearance] Starting to create avatar's appearance for user {0}", avatarID.ToString()); + Guid bodyFolder = Guid.Empty; + Guid clothesFolder = Guid.Empty; + bool success = false; + + UUID avID = new UUID(avatarID); + List avatarInventory = m_inventoryService.GetInventorySkeleton(avID); + if ((avatarInventory == null) || (avatarInventory.Count == 0)) + { + m_log.InfoFormat("[AvatarAppearance] No inventory found for user {0} , so creating it", avID.ToString()); + m_inventoryService.CreateNewUserInventory(avID); + Thread.Sleep(5000); + avatarInventory = m_inventoryService.GetInventorySkeleton(avID); + } + + if ((avatarInventory != null) && (avatarInventory.Count > 0)) + { + UUID tempOwnID = new UUID(templateID); + AvatarAppearance appearance = m_userDataBaseService.GetUserAppearance(tempOwnID); + + List templateInventory = m_inventoryService.GetInventorySkeleton(tempOwnID); + if ((templateInventory != null) && (templateInventory.Count != 0)) + { + for (int i = 0; i < templateInventory.Count; i++) + { + if (templateInventory[i].ParentID == UUID.Zero) + { + success = CloneFolder(avatarInventory, avID, UUID.Zero, appearance, templateInventory[i], templateInventory); + break; + } + } + } + else + { + m_log.InfoFormat("[AvatarAppearance] Failed to find the template owner's {0} inventory", tempOwnID); + } + } + m_log.InfoFormat("[AvatarAppearance] finished cloning avatar with result: {0}", success); + return success; + } + + private void UpdateAvatarAppearance(UUID avatarID, int wearableType, UUID itemID, UUID assetID) + { + AvatarAppearance appearance = m_userDataBaseService.GetUserAppearance(avatarID); + if (appearance == null) + { + appearance = CreateDefaultAppearance(avatarID); + } + + appearance.Wearables[wearableType].AssetID = assetID; + appearance.Wearables[wearableType].ItemID = itemID; + + m_userDataBaseService.UpdateUserAppearance(avatarID, appearance); + + } + + private void UpdateAvatarAttachment(UUID avatarID, int attachmentPoint, UUID itemID, UUID assetID) + { + AvatarAppearance appearance = m_userDataBaseService.GetUserAppearance(avatarID); + if (appearance == null) + { + appearance = CreateDefaultAppearance(avatarID); + } + + appearance.SetAttachment(attachmentPoint, itemID, assetID); + + m_userDataBaseService.UpdateUserAppearance(avatarID, appearance); + + } + + private UUID FindFolderID(string name, List folders) + { + foreach (InventoryFolderBase folder in folders) + { + if (folder.Name == name) + { + return folder.ID; + } + } + return UUID.Zero; + } + + private InventoryFolderBase FindFolder(string name, List folders) + { + foreach (InventoryFolderBase folder in folders) + { + if (folder.Name == name) + { + return folder; + } + } + return null; + } + + private InventoryFolderBase FindFolder(string name, Guid parentFolderID, List folders) + { + foreach (InventoryFolderBase folder in folders) + { + if ((folder.Name == name) && (folder.ParentID.Guid == parentFolderID)) + { + return folder; + } + } + return null; + } + + private InventoryItemBase GetItem(string itemName, List items) + { + foreach (InventoryItemBase item in items) + { + if (item.Name.ToLower() == itemName.ToLower()) + { + return item; + } + } + return null; + } + + private List FindSubFolders(Guid parentFolderID, List folders) + { + List subFolders = new List(); + foreach (InventoryFolderBase folder in folders) + { + if (folder.ParentID.Guid == parentFolderID) + { + subFolders.Add(folder); + } + } + return subFolders; + } + + + private UUID CloneInventoryItem(UUID avatarID, UUID avatarFolder, InventoryItemBase item, bool modifyPerms) + { + if (avatarFolder != UUID.Zero) + { + InventoryItemBase clonedItem = new InventoryItemBase(); + clonedItem.Owner = avatarID; + clonedItem.AssetID = item.AssetID; + clonedItem.AssetType = item.AssetType; + clonedItem.BasePermissions = item.BasePermissions; + clonedItem.CreationDate = item.CreationDate; + clonedItem.CreatorId = item.CreatorId; + clonedItem.CreatorIdAsUuid = item.CreatorIdAsUuid; + clonedItem.CurrentPermissions = item.CurrentPermissions; + clonedItem.Description = item.Description; + clonedItem.EveryOnePermissions = item.EveryOnePermissions; + clonedItem.Flags = item.Flags; + clonedItem.Folder = avatarFolder; + clonedItem.GroupID = item.GroupID; + clonedItem.GroupOwned = item.GroupOwned; + clonedItem.GroupPermissions = item.GroupPermissions; + clonedItem.ID = UUID.Random(); + clonedItem.InvType = item.InvType; + clonedItem.Name = item.Name; + clonedItem.NextPermissions = item.NextPermissions; + clonedItem.SalePrice = item.SalePrice; + clonedItem.SaleType = item.SaleType; + + if (modifyPerms) + { + ModifyPermissions(clonedItem); + } + + SynchronousRestObjectRequester.MakeRequest( + "POST", m_inventoryServerUrl + "AddNewItem/", clonedItem); + + return clonedItem.ID; + } + + return UUID.Zero; + } + + private static void ModifyPermissions(InventoryItemBase clonedItem) + { + if ((clonedItem.CurrentPermissions & (uint)PermissionMask.Modify) == 0) + clonedItem.CurrentPermissions |= (uint)PermissionMask.Modify; + + if ((clonedItem.CurrentPermissions & (uint)PermissionMask.Copy) == 0) + clonedItem.CurrentPermissions |= (uint)PermissionMask.Copy; + + if ((clonedItem.CurrentPermissions & (uint)PermissionMask.Transfer) != 0) + clonedItem.CurrentPermissions &= ~(uint)PermissionMask.Transfer; + + if ((clonedItem.NextPermissions & (uint)PermissionMask.Modify) == 0) + clonedItem.NextPermissions |= (uint)PermissionMask.Modify; + + if ((clonedItem.NextPermissions & (uint)PermissionMask.Copy) == 0) + clonedItem.NextPermissions |= (uint)PermissionMask.Copy; + + if ((clonedItem.NextPermissions & (uint)PermissionMask.Transfer) != 0) + clonedItem.NextPermissions &= ~(uint)PermissionMask.Transfer; + } + + private AvatarAppearance CreateDefaultAppearance(UUID avatarId) + { + AvatarAppearance appearance = null; + AvatarWearable[] wearables; + byte[] visualParams; + GetDefaultAvatarAppearance(out wearables, out visualParams); + appearance = new AvatarAppearance(avatarId, wearables, visualParams); + + return appearance; + } + + private static void GetDefaultAvatarAppearance(out AvatarWearable[] wearables, out byte[] visualParams) + { + visualParams = GetDefaultVisualParams(); + wearables = AvatarWearable.DefaultWearables; + } + + private static byte[] GetDefaultVisualParams() + { + byte[] visualParams; + visualParams = new byte[218]; + for (int i = 0; i < 218; i++) + { + visualParams[i] = 100; + } + return visualParams; + } + #endregion + + + + private bool CloneFolder(List avatarInventory, UUID avID, UUID parentFolder, AvatarAppearance appearance, InventoryFolderBase templateFolder, List templateFolders) + { + bool success = false; + UUID templateFolderId = templateFolder.ID; + if (templateFolderId != UUID.Zero) + { + InventoryFolderBase toFolder = FindFolder(templateFolder.Name, parentFolder.Guid, avatarInventory); + if (toFolder == null) + { + //create new folder + toFolder = new InventoryFolderBase(); + toFolder.ID = UUID.Random(); + toFolder.Name = templateFolder.Name; + toFolder.Owner = avID; + toFolder.Type = templateFolder.Type; + toFolder.Version = 1; + toFolder.ParentID = parentFolder; + if (!SynchronousRestObjectRequester.MakeRequest( + "POST", m_inventoryServerUrl + "CreateFolder/", toFolder)) + { + m_log.InfoFormat("[AvatarApperance] Couldn't make new folder {0} in users inventory", toFolder.Name); + return false; + } + else + { + // m_log.InfoFormat("made new folder {0} in users inventory", toFolder.Name); + } + } + + List templateItems = SynchronousRestObjectRequester.MakeRequest>( + "POST", m_inventoryServerUrl + "GetItems/", templateFolderId.Guid); + if ((templateItems != null) && (templateItems.Count > 0)) + { + foreach (InventoryItemBase item in templateItems) + { + + UUID clonedItemId = CloneInventoryItem(avID, toFolder.ID, item, false); + if (clonedItemId != UUID.Zero) + { + int appearanceType = ItemIsPartOfAppearance(item, appearance); + if (appearanceType >= 0) + { + UpdateAvatarAppearance(avID, appearanceType, clonedItemId, item.AssetID); + } + + if (appearance != null) + { + int attachment = appearance.GetAttachpoint(item.ID); + if (attachment > 0) + { + UpdateAvatarAttachment(avID, attachment, clonedItemId, item.AssetID); + } + } + success = true; + } + } + } + + List subFolders = FindSubFolders(templateFolder.ID.Guid, templateFolders); + foreach (InventoryFolderBase subFolder in subFolders) + { + if (subFolder.Name.ToLower() != "trash") + { + success = CloneFolder(avatarInventory, avID, toFolder.ID, appearance, subFolder, templateFolders); + } + } + } + else + { + m_log.Info("[AvatarAppearance] Failed to find the template folder"); + } + return success; + } + + private int ItemIsPartOfAppearance(InventoryItemBase item, AvatarAppearance appearance) + { + if (appearance != null) + { + if (appearance.BodyItem == item.ID) + return (int)WearableType.Shape; + + if (appearance.EyesItem == item.ID) + return (int)WearableType.Eyes; + + if (appearance.GlovesItem == item.ID) + return (int)WearableType.Gloves; + + if (appearance.HairItem == item.ID) + return (int)WearableType.Hair; + + if (appearance.JacketItem == item.ID) + return (int)WearableType.Jacket; + + if (appearance.PantsItem == item.ID) + return (int)WearableType.Pants; + + if (appearance.ShirtItem == item.ID) + return (int)WearableType.Shirt; + + if (appearance.ShoesItem == item.ID) + return (int)WearableType.Shoes; + + if (appearance.SkinItem == item.ID) + return (int)WearableType.Skin; + + if (appearance.SkirtItem == item.ID) + return (int)WearableType.Skirt; + + if (appearance.SocksItem == item.ID) + return (int)WearableType.Socks; + + if (appearance.UnderPantsItem == item.ID) + return (int)WearableType.Underpants; + + if (appearance.UnderShirtItem == item.ID) + return (int)WearableType.Undershirt; + } + return -1; + } + + } + public enum PermissionMask + { + None = 0, + Transfer = 8192, + Modify = 16384, + Copy = 32768, + Move = 524288, + Damage = 1048576, + All = 2147483647, + } + + public enum WearableType + { + Shape = 0, + Skin = 1, + Hair = 2, + Eyes = 3, + Shirt = 4, + Pants = 5, + Shoes = 6, + Socks = 7, + Jacket = 8, + Gloves = 9, + Undershirt = 10, + Underpants = 11, + Skirt = 12, + } +} diff --git a/OpenSim/Grid/UserServer/Main.cs b/OpenSim/Grid/UserServer/Main.cs index 7bb8b12ea1..d9b3d3f820 100644 --- a/OpenSim/Grid/UserServer/Main.cs +++ b/OpenSim/Grid/UserServer/Main.cs @@ -71,6 +71,8 @@ namespace OpenSim.Grid.UserServer protected UserServerCommandModule m_consoleCommandModule; protected UserServerEventDispatchModule m_eventDispatcher; + protected AvatarCreationModule m_appearanceModule; + public static void Main(string[] args) { XmlConfigurator.Configure(); @@ -180,6 +182,9 @@ namespace OpenSim.Grid.UserServer protected virtual void StartOtherComponents(IInterServiceInventoryServices inventoryService) { + m_appearanceModule = new AvatarCreationModule(m_userDataBaseService, Cfg, inventoryService); + m_appearanceModule.Initialise(this); + StartupLoginService(inventoryService); // // Get the minimum defaultLevel to access to the grid @@ -216,6 +221,8 @@ namespace OpenSim.Grid.UserServer m_userManager.PostInitialise(); m_avatarAppearanceModule.PostInitialise(); m_friendsModule.PostInitialise(); + + m_avatarAppearanceModule.PostInitialise(); } protected virtual void RegisterHttpHandlers() @@ -230,6 +237,8 @@ namespace OpenSim.Grid.UserServer m_avatarAppearanceModule.RegisterHandlers(m_httpServer); m_messagesService.RegisterHandlers(m_httpServer); m_gridInfoService.RegisterHandlers(m_httpServer); + + m_avatarAppearanceModule.RegisterHandlers(m_httpServer); } public override void ShutdownSpecific()