InventoryAccessModule.cs 56 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340
  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. using System;
  28. using System.Collections.Generic;
  29. using System.Net;
  30. using System.Xml;
  31. using System.Reflection;
  32. using System.Text;
  33. using System.Threading;
  34. using OpenSim.Framework;
  35. using OpenSim.Framework.Capabilities;
  36. using OpenSim.Framework.Client;
  37. using OpenSim.Region.Framework.Interfaces;
  38. using OpenSim.Region.Framework.Scenes;
  39. using OpenSim.Region.Framework.Scenes.Serialization;
  40. using OpenSim.Services.Interfaces;
  41. using GridRegion = OpenSim.Services.Interfaces.GridRegion;
  42. using OpenMetaverse;
  43. using log4net;
  44. using Nini.Config;
  45. using Mono.Addins;
  46. using PermissionMask = OpenSim.Framework.PermissionMask;
  47. namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
  48. {
  49. [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "BasicInventoryAccessModule")]
  50. public class BasicInventoryAccessModule : INonSharedRegionModule, IInventoryAccessModule
  51. {
  52. private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  53. protected bool m_Enabled = false;
  54. protected Scene m_Scene;
  55. protected IUserManagement m_UserManagement;
  56. protected IUserManagement UserManagementModule
  57. {
  58. get
  59. {
  60. if (m_UserManagement == null)
  61. m_UserManagement = m_Scene.RequestModuleInterface<IUserManagement>();
  62. return m_UserManagement;
  63. }
  64. }
  65. public bool CoalesceMultipleObjectsToInventory { get; set; }
  66. #region INonSharedRegionModule
  67. public Type ReplaceableInterface
  68. {
  69. get { return null; }
  70. }
  71. public virtual string Name
  72. {
  73. get { return "BasicInventoryAccessModule"; }
  74. }
  75. public virtual void Initialise(IConfigSource source)
  76. {
  77. IConfig moduleConfig = source.Configs["Modules"];
  78. if (moduleConfig != null)
  79. {
  80. string name = moduleConfig.GetString("InventoryAccessModule", "");
  81. if (name == Name)
  82. {
  83. m_Enabled = true;
  84. InitialiseCommon(source);
  85. m_log.InfoFormat("[INVENTORY ACCESS MODULE]: {0} enabled.", Name);
  86. }
  87. }
  88. }
  89. /// <summary>
  90. /// Common module config for both this and descendant classes.
  91. /// </summary>
  92. /// <param name="source"></param>
  93. protected virtual void InitialiseCommon(IConfigSource source)
  94. {
  95. IConfig inventoryConfig = source.Configs["Inventory"];
  96. if (inventoryConfig != null)
  97. CoalesceMultipleObjectsToInventory
  98. = inventoryConfig.GetBoolean("CoalesceMultipleObjectsToInventory", true);
  99. else
  100. CoalesceMultipleObjectsToInventory = true;
  101. }
  102. public virtual void PostInitialise()
  103. {
  104. }
  105. public virtual void AddRegion(Scene scene)
  106. {
  107. if (!m_Enabled)
  108. return;
  109. m_Scene = scene;
  110. scene.RegisterModuleInterface<IInventoryAccessModule>(this);
  111. scene.EventManager.OnNewClient += OnNewClient;
  112. }
  113. protected virtual void OnNewClient(IClientAPI client)
  114. {
  115. client.OnCreateNewInventoryItem += CreateNewInventoryItem;
  116. }
  117. public virtual void Close()
  118. {
  119. if (!m_Enabled)
  120. return;
  121. }
  122. public virtual void RemoveRegion(Scene scene)
  123. {
  124. if (!m_Enabled)
  125. return;
  126. m_Scene = null;
  127. }
  128. public virtual void RegionLoaded(Scene scene)
  129. {
  130. if (!m_Enabled)
  131. return;
  132. }
  133. #endregion
  134. #region Inventory Access
  135. /// <summary>
  136. /// Create a new inventory item. Called when the client creates a new item directly within their
  137. /// inventory (e.g. by selecting a context inventory menu option).
  138. /// </summary>
  139. /// <param name="remoteClient"></param>
  140. /// <param name="transactionID"></param>
  141. /// <param name="folderID"></param>
  142. /// <param name="callbackID"></param>
  143. /// <param name="description"></param>
  144. /// <param name="name"></param>
  145. /// <param name="invType"></param>
  146. /// <param name="type"></param>
  147. /// <param name="wearableType"></param>
  148. /// <param name="nextOwnerMask"></param>
  149. public void CreateNewInventoryItem(IClientAPI remoteClient, UUID transactionID, UUID folderID,
  150. uint callbackID, string description, string name, sbyte invType,
  151. sbyte assetType, byte wearableType,
  152. uint nextOwnerMask, int creationDate)
  153. {
  154. m_log.DebugFormat("[INVENTORY ACCESS MODULE]: Received request to create inventory item {0} in folder {1}, transactionID {2}", name,
  155. folderID, transactionID);
  156. if (!m_Scene.Permissions.CanCreateUserInventory(invType, remoteClient.AgentId))
  157. return;
  158. InventoryFolderBase folder = m_Scene.InventoryService.GetFolder(remoteClient.AgentId, folderID);
  159. if (folder == null && Enum.IsDefined(typeof(FolderType), (sbyte)invType))
  160. {
  161. folder = m_Scene.InventoryService.GetFolderForType(remoteClient.AgentId, (FolderType)invType);
  162. if (folder != null)
  163. m_log.DebugFormat("[INVENTORY ACCESS MODULE]: Requested folder not found but found folder for type {0}", invType);
  164. }
  165. if (folder == null || folder.Owner != remoteClient.AgentId)
  166. return;
  167. if (transactionID != UUID.Zero)
  168. {
  169. IAgentAssetTransactions agentTransactions = m_Scene.AgentTransactionsModule;
  170. if (agentTransactions != null)
  171. {
  172. if (agentTransactions.HandleItemCreationFromTransaction(
  173. remoteClient, transactionID, folderID, callbackID, description,
  174. name, invType, assetType, wearableType, nextOwnerMask))
  175. return;
  176. }
  177. }
  178. ScenePresence presence;
  179. if (m_Scene.TryGetScenePresence(remoteClient.AgentId, out presence))
  180. {
  181. byte[] data = null;
  182. uint everyonemask = 0;
  183. uint groupmask = 0;
  184. if (invType == (sbyte)InventoryType.Landmark && presence != null)
  185. {
  186. string suffix = string.Empty, prefix = string.Empty;
  187. string strdata = GenerateLandmark(presence, out prefix, out suffix);
  188. data = Encoding.ASCII.GetBytes(strdata);
  189. name = prefix + name;
  190. description += suffix;
  191. groupmask = (uint)PermissionMask.AllAndExport;
  192. everyonemask = (uint)(PermissionMask.AllAndExport & ~PermissionMask.Modify);
  193. }
  194. AssetBase asset = m_Scene.CreateAsset(name, description, assetType, data, remoteClient.AgentId);
  195. m_Scene.AssetService.Store(asset);
  196. m_Scene.CreateNewInventoryItem(
  197. remoteClient, remoteClient.AgentId.ToString(), string.Empty, folderID,
  198. name, description, 0, callbackID, asset.FullID, asset.Type, invType,
  199. (uint)PermissionMask.AllAndExport, // Base
  200. (uint)PermissionMask.AllAndExport, // Current
  201. everyonemask,
  202. nextOwnerMask, groupmask, creationDate, false); // Data from viewer
  203. }
  204. else
  205. {
  206. m_log.ErrorFormat(
  207. "[INVENTORY ACCESS MODULE]: ScenePresence for agent uuid {0} unexpectedly not found in CreateNewInventoryItem",
  208. remoteClient.AgentId);
  209. }
  210. }
  211. protected virtual string GenerateLandmark(ScenePresence presence, out string prefix, out string suffix)
  212. {
  213. prefix = string.Empty;
  214. suffix = string.Empty;
  215. Vector3 pos = presence.AbsolutePosition;
  216. return String.Format("Landmark version 2\nregion_id {0}\nlocal_pos {1} {2} {3}\nregion_handle {4}\n",
  217. presence.Scene.RegionInfo.RegionID,
  218. pos.X, pos.Y, pos.Z,
  219. presence.RegionHandle);
  220. }
  221. /// <summary>
  222. /// Capability originating call to update the asset of an item in an agent's inventory
  223. /// </summary>
  224. /// <param name="remoteClient"></param>
  225. /// <param name="itemID"></param>
  226. /// <param name="data"></param>
  227. /// <returns></returns>
  228. public virtual UUID CapsUpdateInventoryItemAsset(IClientAPI remoteClient, UUID itemID, byte[] data)
  229. {
  230. InventoryItemBase item = m_Scene.InventoryService.GetItem(remoteClient.AgentId, itemID);
  231. if (item == null)
  232. {
  233. m_log.ErrorFormat(
  234. "[INVENTORY ACCESS MODULE]: Could not find item {0} for caps inventory update", itemID);
  235. return UUID.Zero;
  236. }
  237. if (item.Owner != remoteClient.AgentId)
  238. return UUID.Zero;
  239. if ((InventoryType)item.InvType == InventoryType.Notecard)
  240. {
  241. if (!m_Scene.Permissions.CanEditNotecard(itemID, UUID.Zero, remoteClient.AgentId))
  242. {
  243. remoteClient.SendAgentAlertMessage("Insufficient permissions to edit notecard", false);
  244. return UUID.Zero;
  245. }
  246. remoteClient.SendAlertMessage("Notecard saved");
  247. }
  248. else if ((InventoryType)item.InvType == InventoryType.LSL)
  249. {
  250. if (!m_Scene.Permissions.CanEditScript(itemID, UUID.Zero, remoteClient.AgentId))
  251. {
  252. remoteClient.SendAgentAlertMessage("Insufficient permissions to edit script", false);
  253. return UUID.Zero;
  254. }
  255. remoteClient.SendAlertMessage("Script saved");
  256. }
  257. else if ((CustomInventoryType)item.InvType == CustomInventoryType.AnimationSet)
  258. {
  259. AnimationSet animSet = new AnimationSet(data);
  260. uint res = animSet.Validate(x => {
  261. const int required = (int)(PermissionMask.Transfer | PermissionMask.Copy);
  262. int perms = m_Scene.InventoryService.GetAssetPermissions(remoteClient.AgentId, x);
  263. // enforce previus perm rule
  264. if ((perms & required) != required)
  265. return 0;
  266. return (uint) perms;
  267. });
  268. if(res == 0)
  269. {
  270. remoteClient.SendAgentAlertMessage("Not enought permissions on asset(s) referenced by animation set '{0}', update failed", false);
  271. return UUID.Zero;
  272. }
  273. }
  274. AssetBase asset =
  275. CreateAsset(item.Name, item.Description, (sbyte)item.AssetType, data, remoteClient.AgentId.ToString());
  276. item.AssetID = asset.FullID;
  277. m_Scene.AssetService.Store(asset);
  278. m_Scene.InventoryService.UpdateItem(item);
  279. // remoteClient.SendInventoryItemCreateUpdate(item);
  280. return (asset.FullID);
  281. }
  282. public virtual bool UpdateInventoryItemAsset(UUID ownerID, InventoryItemBase item, AssetBase asset)
  283. {
  284. if (item != null && item.Owner == ownerID && asset != null)
  285. {
  286. // m_log.DebugFormat(
  287. // "[INVENTORY ACCESS MODULE]: Updating item {0} {1} with new asset {2}",
  288. // item.Name, item.ID, asset.ID);
  289. m_Scene.AssetService.Store(asset);
  290. m_Scene.InventoryService.UpdateItem(item);
  291. return true;
  292. }
  293. else
  294. {
  295. m_log.ErrorFormat("[INVENTORY ACCESS MODULE]: Given invalid item for inventory update: {0}",
  296. (item == null || asset == null? "null item or asset" : "wrong owner"));
  297. return false;
  298. }
  299. }
  300. public virtual List<InventoryItemBase> CopyToInventory(
  301. DeRezAction action, UUID folderID,
  302. List<SceneObjectGroup> objectGroups, IClientAPI remoteClient, bool asAttachment)
  303. {
  304. List<InventoryItemBase> copiedItems = new List<InventoryItemBase>();
  305. Dictionary<UUID, List<SceneObjectGroup>> bundlesToCopy = new Dictionary<UUID, List<SceneObjectGroup>>();
  306. if (CoalesceMultipleObjectsToInventory)
  307. {
  308. // The following code groups the SOG's by owner. No objects
  309. // belonging to different people can be coalesced, for obvious
  310. // reasons.
  311. foreach (SceneObjectGroup g in objectGroups)
  312. {
  313. if (!bundlesToCopy.ContainsKey(g.OwnerID))
  314. bundlesToCopy[g.OwnerID] = new List<SceneObjectGroup>();
  315. bundlesToCopy[g.OwnerID].Add(g);
  316. }
  317. }
  318. else
  319. {
  320. // If we don't want to coalesce then put every object in its own bundle.
  321. foreach (SceneObjectGroup g in objectGroups)
  322. {
  323. List<SceneObjectGroup> bundle = new List<SceneObjectGroup>();
  324. bundle.Add(g);
  325. bundlesToCopy[g.UUID] = bundle;
  326. }
  327. }
  328. // m_log.DebugFormat(
  329. // "[INVENTORY ACCESS MODULE]: Copying {0} object bundles to folder {1} action {2} for {3}",
  330. // bundlesToCopy.Count, folderID, action, remoteClient.Name);
  331. // Each iteration is really a separate asset being created,
  332. // with distinct destinations as well.
  333. foreach (List<SceneObjectGroup> bundle in bundlesToCopy.Values)
  334. copiedItems.Add(CopyBundleToInventory(action, folderID, bundle, remoteClient, asAttachment));
  335. return copiedItems;
  336. }
  337. /// <summary>
  338. /// Copy a bundle of objects to inventory. If there is only one object, then this will create an object
  339. /// item. If there are multiple objects then these will be saved as a single coalesced item.
  340. /// </summary>
  341. /// <param name="action"></param>
  342. /// <param name="folderID"></param>
  343. /// <param name="objlist"></param>
  344. /// <param name="remoteClient"></param>
  345. /// <param name="asAttachment">Should be true if the bundle is being copied as an attachment. This prevents
  346. /// attempted serialization of any script state which would abort any operating scripts.</param>
  347. /// <returns>The inventory item created by the copy</returns>
  348. protected InventoryItemBase CopyBundleToInventory(
  349. DeRezAction action, UUID folderID, List<SceneObjectGroup> objlist, IClientAPI remoteClient,
  350. bool asAttachment)
  351. {
  352. CoalescedSceneObjects coa = new CoalescedSceneObjects(UUID.Zero);
  353. Dictionary<UUID, Vector3> originalPositions = new Dictionary<UUID, Vector3>();
  354. Dictionary<UUID, Quaternion> originalRotations = new Dictionary<UUID, Quaternion>();
  355. // this possible is not needed if keyframes are saved
  356. // Dictionary<UUID, KeyframeMotion> originalKeyframes = new Dictionary<UUID, KeyframeMotion>();
  357. foreach (SceneObjectGroup objectGroup in objlist)
  358. {
  359. if (objectGroup.RootPart.KeyframeMotion != null)
  360. {
  361. objectGroup.RootPart.KeyframeMotion.Suspend();
  362. }
  363. objectGroup.RootPart.SetForce(Vector3.Zero);
  364. objectGroup.RootPart.SetAngularImpulse(Vector3.Zero, false);
  365. // originalKeyframes[objectGroup.UUID] = objectGroup.RootPart.KeyframeMotion;
  366. // objectGroup.RootPart.KeyframeMotion = null;
  367. Vector3 inventoryStoredPosition = objectGroup.AbsolutePosition;
  368. originalPositions[objectGroup.UUID] = inventoryStoredPosition;
  369. Quaternion inventoryStoredRotation = objectGroup.GroupRotation;
  370. originalRotations[objectGroup.UUID] = inventoryStoredRotation;
  371. // Restore attachment data after trip through the sim
  372. if (objectGroup.AttachmentPoint > 0)
  373. {
  374. inventoryStoredPosition = objectGroup.RootPart.AttachedPos;
  375. inventoryStoredRotation = objectGroup.RootPart.AttachRotation;
  376. if (objectGroup.RootPart.Shape.PCode != (byte) PCode.Tree &&
  377. objectGroup.RootPart.Shape.PCode != (byte) PCode.NewTree)
  378. objectGroup.RootPart.Shape.LastAttachPoint = (byte)objectGroup.AttachmentPoint;
  379. }
  380. objectGroup.AbsolutePosition = inventoryStoredPosition;
  381. objectGroup.RootPart.RotationOffset = inventoryStoredRotation;
  382. // Make sure all bits but the ones we want are clear
  383. // on take.
  384. // This will be applied to the current perms, so
  385. // it will do what we want.
  386. objectGroup.RootPart.NextOwnerMask &=
  387. ((uint)PermissionMask.Copy |
  388. (uint)PermissionMask.Transfer |
  389. (uint)PermissionMask.Modify |
  390. (uint)PermissionMask.Export);
  391. objectGroup.RootPart.NextOwnerMask |=
  392. (uint)PermissionMask.Move;
  393. coa.Add(objectGroup);
  394. }
  395. string itemXml;
  396. // If we're being called from a script, then trying to serialize that same script's state will not complete
  397. // in any reasonable time period. Therefore, we'll avoid it. The worst that can happen is that if
  398. // the client/server crashes rather than logging out normally, the attachment's scripts will resume
  399. // without state on relog. Arguably, this is what we want anyway.
  400. if (objlist.Count > 1)
  401. itemXml = CoalescedSceneObjectsSerializer.ToXml(coa, !asAttachment);
  402. else
  403. itemXml = SceneObjectSerializer.ToOriginalXmlFormat(objlist[0], !asAttachment);
  404. // Restore the position of each group now that it has been stored to inventory.
  405. foreach (SceneObjectGroup objectGroup in objlist)
  406. {
  407. objectGroup.AbsolutePosition = originalPositions[objectGroup.UUID];
  408. objectGroup.RootPart.RotationOffset = originalRotations[objectGroup.UUID];
  409. // objectGroup.RootPart.KeyframeMotion = originalKeyframes[objectGroup.UUID];
  410. if (objectGroup.RootPart.KeyframeMotion != null)
  411. objectGroup.RootPart.KeyframeMotion.Resume();
  412. }
  413. InventoryItemBase item = CreateItemForObject(action, remoteClient, objlist[0], folderID);
  414. // m_log.DebugFormat(
  415. // "[INVENTORY ACCESS MODULE]: Created item is {0}",
  416. // item != null ? item.ID.ToString() : "NULL");
  417. if (item == null)
  418. return null;
  419. item.CreatorId = objlist[0].RootPart.CreatorID.ToString();
  420. item.CreatorData = objlist[0].RootPart.CreatorData;
  421. if (objlist.Count > 1)
  422. {
  423. item.Flags = (uint)InventoryItemFlags.ObjectHasMultipleItems;
  424. // If the objects have different creators then don't specify a creator at all
  425. foreach (SceneObjectGroup objectGroup in objlist)
  426. {
  427. if ((objectGroup.RootPart.CreatorID.ToString() != item.CreatorId)
  428. || (objectGroup.RootPart.CreatorData.ToString() != item.CreatorData))
  429. {
  430. item.CreatorId = UUID.Zero.ToString();
  431. item.CreatorData = string.Empty;
  432. break;
  433. }
  434. }
  435. }
  436. else
  437. {
  438. item.SaleType = objlist[0].RootPart.ObjectSaleType;
  439. item.SalePrice = objlist[0].RootPart.SalePrice;
  440. }
  441. string name = objlist[0].RootPart.Name;
  442. string desc = objlist[0].RootPart.Description;
  443. AssetBase asset = CreateAsset(
  444. name, desc,
  445. (sbyte)AssetType.Object,
  446. Utils.StringToBytes(itemXml),
  447. objlist[0].OwnerID.ToString());
  448. m_Scene.AssetService.Store(asset);
  449. item.Description = desc;
  450. item.Name = name;
  451. item.AssetType = (int)AssetType.Object;
  452. item.AssetID = asset.FullID;
  453. if (action == DeRezAction.SaveToExistingUserInventoryItem)
  454. {
  455. m_Scene.InventoryService.UpdateItem(item);
  456. }
  457. else
  458. {
  459. bool isowner = remoteClient != null && item.Owner == remoteClient.AgentId;
  460. if(action == DeRezAction.Return)
  461. AddPermissions(item, objlist[0], objlist, null);
  462. else if(action == DeRezAction.Delete && !isowner)
  463. AddPermissions(item, objlist[0], objlist, null);
  464. else
  465. AddPermissions(item, objlist[0], objlist, remoteClient);
  466. m_Scene.AddInventoryItem(item);
  467. if (isowner)
  468. {
  469. remoteClient.SendInventoryItemCreateUpdate(item, 0);
  470. }
  471. else
  472. {
  473. ScenePresence notifyUser = m_Scene.GetScenePresence(item.Owner);
  474. if (notifyUser != null)
  475. {
  476. notifyUser.ControllingClient.SendInventoryItemCreateUpdate(item, 0);
  477. }
  478. }
  479. }
  480. // This is a hook to do some per-asset post-processing for subclasses that need that
  481. if (remoteClient != null && action != DeRezAction.Delete)
  482. ExportAsset(remoteClient.AgentId, asset.FullID);
  483. return item;
  484. }
  485. protected virtual void ExportAsset(UUID agentID, UUID assetID)
  486. {
  487. // nothing to do here
  488. }
  489. /// <summary>
  490. /// Add relevant permissions for an object to the item.
  491. /// </summary>
  492. /// <param name="item"></param>
  493. /// <param name="so"></param>
  494. /// <param name="objsForEffectivePermissions"></param>
  495. /// <param name="remoteClient"></param>
  496. /// <returns></returns>
  497. protected InventoryItemBase AddPermissions(
  498. InventoryItemBase item, SceneObjectGroup so, List<SceneObjectGroup> objsForEffectivePermissions,
  499. IClientAPI remoteClient)
  500. {
  501. uint effectivePerms = (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify | PermissionMask.Move | PermissionMask.Export | PermissionMask.FoldedMask);
  502. foreach (SceneObjectGroup grp in objsForEffectivePermissions)
  503. {
  504. effectivePerms &= grp.CurrentAndFoldedNextPermissions();
  505. }
  506. if (remoteClient != null && (remoteClient.AgentId != so.RootPart.OwnerID) && m_Scene.Permissions.PropagatePermissions())
  507. {
  508. // apply parts inventory items next owner
  509. PermissionsUtil.ApplyNoModFoldedPermissions(effectivePerms, ref effectivePerms);
  510. // change to next owner
  511. uint basePerms = effectivePerms & so.RootPart.NextOwnerMask;
  512. // fix and update folded
  513. basePerms = PermissionsUtil.FixAndFoldPermissions(basePerms);
  514. item.BasePermissions = basePerms;
  515. item.CurrentPermissions = basePerms;
  516. item.NextPermissions = basePerms & so.RootPart.NextOwnerMask;
  517. item.EveryOnePermissions = basePerms & so.RootPart.EveryoneMask;
  518. item.GroupPermissions = basePerms & so.RootPart.GroupMask;
  519. // apply next owner perms on rez
  520. item.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm;
  521. }
  522. else
  523. {
  524. item.BasePermissions = effectivePerms;
  525. item.CurrentPermissions = effectivePerms;
  526. item.NextPermissions = so.RootPart.NextOwnerMask & effectivePerms;
  527. item.EveryOnePermissions = so.RootPart.EveryoneMask & effectivePerms;
  528. item.GroupPermissions = so.RootPart.GroupMask & effectivePerms;
  529. item.CurrentPermissions &=
  530. ((uint)PermissionMask.Copy |
  531. (uint)PermissionMask.Transfer |
  532. (uint)PermissionMask.Modify |
  533. (uint)PermissionMask.Move |
  534. (uint)PermissionMask.Export |
  535. (uint)PermissionMask.FoldedMask); // Preserve folded permissions ??
  536. }
  537. return item;
  538. }
  539. /// <summary>
  540. /// Create an item using details for the given scene object.
  541. /// </summary>
  542. /// <param name="action"></param>
  543. /// <param name="remoteClient"></param>
  544. /// <param name="so"></param>
  545. /// <param name="folderID"></param>
  546. /// <returns></returns>
  547. protected InventoryItemBase CreateItemForObject(
  548. DeRezAction action, IClientAPI remoteClient, SceneObjectGroup so, UUID folderID)
  549. {
  550. // m_log.DebugFormat(
  551. // "[BASIC INVENTORY ACCESS MODULE]: Creating item for object {0} {1} for folder {2}, action {3}",
  552. // so.Name, so.UUID, folderID, action);
  553. //
  554. // Get the user info of the item destination
  555. //
  556. UUID userID = UUID.Zero;
  557. if (action == DeRezAction.Take || action == DeRezAction.TakeCopy ||
  558. action == DeRezAction.SaveToExistingUserInventoryItem)
  559. {
  560. // Take or take copy require a taker
  561. // Saving changes requires a local user
  562. //
  563. if (remoteClient == null)
  564. return null;
  565. userID = remoteClient.AgentId;
  566. // m_log.DebugFormat(
  567. // "[INVENTORY ACCESS MODULE]: Target of {0} in CreateItemForObject() is {1} {2}",
  568. // action, remoteClient.Name, userID);
  569. }
  570. else if (so.RootPart.OwnerID == so.RootPart.GroupID)
  571. {
  572. // Group owned objects go to the last owner before the object was transferred.
  573. userID = so.RootPart.LastOwnerID;
  574. }
  575. else
  576. {
  577. // Other returns / deletes go to the object owner
  578. //
  579. userID = so.RootPart.OwnerID;
  580. // m_log.DebugFormat(
  581. // "[INVENTORY ACCESS MODULE]: Target of {0} in CreateItemForObject() is object owner {1}",
  582. // action, userID);
  583. }
  584. if (userID == UUID.Zero) // Can't proceed
  585. {
  586. return null;
  587. }
  588. InventoryItemBase item = null;
  589. if (DeRezAction.SaveToExistingUserInventoryItem == action)
  590. {
  591. item = m_Scene.InventoryService.GetItem(userID, so.RootPart.FromUserInventoryItemID);
  592. //item = userInfo.RootFolder.FindItem(
  593. // objectGroup.RootPart.FromUserInventoryItemID);
  594. if (item == null)
  595. {
  596. m_log.DebugFormat(
  597. "[INVENTORY ACCESS MODULE]: Object {0} {1} scheduled for save to inventory has already been deleted.",
  598. so.Name, so.UUID);
  599. return null;
  600. }
  601. return item;
  602. }
  603. // Folder magic
  604. //
  605. // If we're returning someone's item, it goes back to the
  606. // owner's Lost And Found folder.
  607. // Delete is treated like return in this case
  608. // Deleting your own items makes them go to trash
  609. //
  610. InventoryFolderBase folder = null;
  611. if (action == DeRezAction.Delete)
  612. {
  613. // Deleting someone else's item
  614. //
  615. if (remoteClient == null ||
  616. so.OwnerID != remoteClient.AgentId)
  617. {
  618. folder = m_Scene.InventoryService.GetFolderForType(userID, FolderType.LostAndFound);
  619. }
  620. else
  621. {
  622. folder = m_Scene.InventoryService.GetFolderForType(userID, FolderType.Trash);
  623. }
  624. }
  625. else if (action == DeRezAction.Return)
  626. {
  627. // Dump to lost + found unconditionally
  628. //
  629. folder = m_Scene.InventoryService.GetFolderForType(userID, FolderType.LostAndFound);
  630. }
  631. if (folderID == UUID.Zero && folder == null)
  632. {
  633. if (action == DeRezAction.Delete)
  634. {
  635. // Deletes go to trash by default
  636. //
  637. folder = m_Scene.InventoryService.GetFolderForType(userID, FolderType.Trash);
  638. }
  639. else
  640. {
  641. if (remoteClient == null || so.RootPart.OwnerID != remoteClient.AgentId)
  642. {
  643. // Taking copy of another person's item. Take to
  644. // Objects folder.
  645. folder = m_Scene.InventoryService.GetFolderForType(userID, FolderType.Object);
  646. so.FromFolderID = UUID.Zero;
  647. }
  648. else
  649. {
  650. // Catch all. Use lost & found
  651. //
  652. folder = m_Scene.InventoryService.GetFolderForType(userID, FolderType.LostAndFound);
  653. }
  654. }
  655. }
  656. if (action == DeRezAction.TakeCopy)
  657. folder = m_Scene.InventoryService.GetFolderForType(userID, FolderType.Object);
  658. else if (action == DeRezAction.Take)
  659. {
  660. // Override and put into where it came from, if it came
  661. // from anywhere in inventory and the owner is taking it back.
  662. if (so.FromFolderID != UUID.Zero && so.RootPart.OwnerID == remoteClient.AgentId)
  663. {
  664. folder = m_Scene.InventoryService.GetFolder(userID, so.FromFolderID);
  665. if(folder == null || folder.Type == (int)FolderType.Trash || folder.Type == (int)FolderType.LostAndFound)
  666. {
  667. folder = m_Scene.InventoryService.GetFolderForType(userID, FolderType.Object);
  668. }
  669. else
  670. {
  671. InventoryFolderBase parent = folder;
  672. while(true)
  673. {
  674. parent = m_Scene.InventoryService.GetFolder(userID, parent.ParentID);
  675. if (parent != null && parent.ParentID == UUID.Zero)
  676. break;
  677. if (parent == null || parent.Type == (int)FolderType.Trash || parent.Type == (int)FolderType.LostAndFound)
  678. {
  679. folder = m_Scene.InventoryService.GetFolderForType(userID, FolderType.Object);
  680. break;
  681. }
  682. }
  683. }
  684. }
  685. }
  686. if (folder == null) // None of the above
  687. {
  688. folder = new InventoryFolderBase(folderID);
  689. if (folder == null) // Nowhere to put it
  690. {
  691. return null;
  692. }
  693. }
  694. item = new InventoryItemBase();
  695. item.ID = UUID.Random();
  696. item.InvType = (int)InventoryType.Object;
  697. item.Folder = folder.ID;
  698. item.Owner = userID;
  699. item.CreationDate = Util.UnixTimeSinceEpoch();
  700. return item;
  701. }
  702. // compatibility do not use
  703. public virtual SceneObjectGroup RezObject(
  704. IClientAPI remoteClient, UUID itemID, Vector3 RayEnd, Vector3 RayStart,
  705. UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection,
  706. bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment)
  707. {
  708. return RezObject(remoteClient, itemID, UUID.Zero, RayEnd, RayStart,
  709. RayTargetID, BypassRayCast, RayEndIsIntersection,
  710. RezSelected, RemoveItem, fromTaskID, attachment);
  711. }
  712. public virtual SceneObjectGroup RezObject(
  713. IClientAPI remoteClient, UUID itemID, UUID rezGroupID, Vector3 RayEnd, Vector3 RayStart,
  714. UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection,
  715. bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment)
  716. {
  717. // m_log.DebugFormat("[INVENTORY ACCESS MODULE]: RezObject for {0}, item {1}", remoteClient.Name, itemID);
  718. InventoryItemBase item = m_Scene.InventoryService.GetItem(remoteClient.AgentId, itemID);
  719. if (item == null)
  720. {
  721. return null;
  722. }
  723. item.Owner = remoteClient.AgentId;
  724. return RezObject(
  725. remoteClient, item, rezGroupID, item.AssetID,
  726. RayEnd, RayStart, RayTargetID, BypassRayCast, RayEndIsIntersection,
  727. RezSelected, RemoveItem, fromTaskID, attachment);
  728. }
  729. // compatility
  730. public virtual SceneObjectGroup RezObject(
  731. IClientAPI remoteClient, InventoryItemBase item, UUID assetID, Vector3 RayEnd, Vector3 RayStart,
  732. UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection,
  733. bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment)
  734. {
  735. return RezObject(remoteClient, item, UUID.Zero, assetID,
  736. RayEnd, RayStart, RayTargetID,
  737. BypassRayCast, RayEndIsIntersection,
  738. RezSelected, RemoveItem, fromTaskID, attachment);
  739. }
  740. public virtual SceneObjectGroup RezObject(
  741. IClientAPI remoteClient, InventoryItemBase item, UUID groupID, UUID assetID,
  742. Vector3 RayEnd, Vector3 RayStart, UUID RayTargetID,
  743. byte BypassRayCast, bool RayEndIsIntersection,
  744. bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment)
  745. {
  746. AssetBase rezAsset = m_Scene.AssetService.Get(assetID.ToString());
  747. if (rezAsset == null)
  748. {
  749. if (item != null)
  750. {
  751. m_log.WarnFormat(
  752. "[InventoryAccessModule]: Could not find asset {0} for item {1} {2} for {3} in RezObject()",
  753. assetID, item.Name, item.ID, remoteClient.Name);
  754. remoteClient.SendAgentAlertMessage(string.Format("Unable to rez: could not find asset {0} for item {1}.", assetID, item.Name), false);
  755. }
  756. else
  757. {
  758. m_log.WarnFormat(
  759. "[INVENTORY ACCESS MODULE]: Could not find asset {0} for {1} in RezObject()",
  760. assetID, remoteClient.Name);
  761. remoteClient.SendAgentAlertMessage(string.Format("Unable to rez: could not find asset {0}.", assetID), false);
  762. }
  763. return null;
  764. }
  765. if(rezAsset.Data == null || rezAsset.Data.Length == 0)
  766. {
  767. m_log.WarnFormat(
  768. "[INVENTORY ACCESS MODULE]: missing data in asset {0} to RezObject()",
  769. assetID, remoteClient.Name);
  770. remoteClient.SendAgentAlertMessage(string.Format("Unable to rez: missing data in asset {0} ", assetID), false);
  771. return null;
  772. }
  773. SceneObjectGroup group = null;
  774. List<SceneObjectGroup> objlist;
  775. List<Vector3> veclist;
  776. Vector3 bbox;
  777. float offsetHeight;
  778. byte bRayEndIsIntersection = (byte)(RayEndIsIntersection ? 1 : 0);
  779. Vector3 pos;
  780. bool single
  781. = m_Scene.GetObjectsToRez(
  782. rezAsset.Data, attachment, out objlist, out veclist, out bbox, out offsetHeight);
  783. if (single)
  784. {
  785. pos = m_Scene.GetNewRezLocation(
  786. RayStart, RayEnd, RayTargetID, Quaternion.Identity,
  787. BypassRayCast, bRayEndIsIntersection, true, bbox, false);
  788. pos.Z += offsetHeight;
  789. }
  790. else
  791. {
  792. pos = m_Scene.GetNewRezLocation(RayStart, RayEnd,
  793. RayTargetID, Quaternion.Identity,
  794. BypassRayCast, bRayEndIsIntersection, true,
  795. bbox, false);
  796. pos -= bbox / 2;
  797. }
  798. int primcount = 0;
  799. foreach (SceneObjectGroup g in objlist)
  800. primcount += g.PrimCount;
  801. if (!m_Scene.Permissions.CanRezObject(
  802. primcount, remoteClient.AgentId, pos)
  803. && !attachment)
  804. {
  805. // The client operates in no fail mode. It will
  806. // have already removed the item from the folder
  807. // if it's no copy.
  808. // Put it back if it's not an attachment
  809. //
  810. if (item != null)
  811. {
  812. if (((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) && (!attachment))
  813. remoteClient.SendBulkUpdateInventory(item);
  814. }
  815. return null;
  816. }
  817. if (item != null && !DoPreRezWhenFromItem(remoteClient, item, objlist, pos, veclist, attachment))
  818. return null;
  819. for (int i = 0; i < objlist.Count; i++)
  820. {
  821. group = objlist[i];
  822. SceneObjectPart rootPart = group.RootPart;
  823. // m_log.DebugFormat(
  824. // "[INVENTORY ACCESS MODULE]: Preparing to rez {0} {1} {2} ownermask={3:X} nextownermask={4:X} groupmask={5:X} everyonemask={6:X} for {7}",
  825. // group.Name, group.LocalId, group.UUID,
  826. // group.RootPart.OwnerMask, group.RootPart.NextOwnerMask, group.RootPart.GroupMask, group.RootPart.EveryoneMask,
  827. // remoteClient.Name);
  828. // Vector3 storedPosition = group.AbsolutePosition;
  829. if (group.UUID == UUID.Zero)
  830. {
  831. m_log.Debug("[INVENTORY ACCESS MODULE]: Object has UUID.Zero! Position 3");
  832. }
  833. // if this was previously an attachment and is now being rezzed,
  834. // save the old attachment info.
  835. if (group.IsAttachment == false && group.RootPart.Shape.State != 0)
  836. {
  837. group.RootPart.AttachedPos = group.AbsolutePosition;
  838. group.RootPart.Shape.LastAttachPoint = (byte)group.AttachmentPoint;
  839. }
  840. if (item == null)
  841. {
  842. // Change ownership. Normally this is done in DoPreRezWhenFromItem(), but in this case we must do it here.
  843. foreach (SceneObjectPart part in group.Parts)
  844. {
  845. // Make the rezzer the owner, as this is not necessarily set correctly in the serialized asset.
  846. part.LastOwnerID = part.OwnerID;
  847. part.OwnerID = remoteClient.AgentId;
  848. part.RezzerID = remoteClient.AgentId;
  849. }
  850. }
  851. group.ResetIDs();
  852. if (!attachment)
  853. {
  854. // If it's rezzed in world, select it. Much easier to
  855. // find small items.
  856. //
  857. foreach (SceneObjectPart part in group.Parts)
  858. {
  859. part.CreateSelected = true;
  860. }
  861. if (rootPart.Shape.PCode == (byte)PCode.Prim)
  862. group.ClearPartAttachmentData();
  863. }
  864. else
  865. {
  866. group.IsAttachment = true;
  867. }
  868. group.SetGroup(groupID, remoteClient);
  869. // If we're rezzing an attachment then don't ask
  870. // AddNewSceneObject() to update the client since
  871. // we'll be doing that later on. Scheduling more than
  872. // one full update during the attachment
  873. // process causes some clients to fail to display the
  874. // attachment properly.
  875. if (!attachment)
  876. {
  877. group.AbsolutePosition = pos + veclist[i];
  878. m_Scene.AddNewSceneObject(group, true, false);
  879. // Fire on_rez
  880. group.CreateScriptInstances(0, true, m_Scene.DefaultScriptEngine, 1);
  881. rootPart.ParentGroup.ResumeScripts();
  882. group.ScheduleGroupForFullAnimUpdate();
  883. }
  884. else
  885. m_Scene.AddNewSceneObject(group, true, false);
  886. // m_log.DebugFormat(
  887. // "[INVENTORY ACCESS MODULE]: Rezzed {0} {1} {2} ownermask={3:X} nextownermask={4:X} groupmask={5:X} everyonemask={6:X} for {7}",
  888. // group.Name, group.LocalId, group.UUID,
  889. // group.RootPart.OwnerMask, group.RootPart.NextOwnerMask, group.RootPart.GroupMask, group.RootPart.EveryoneMask,
  890. // remoteClient.Name);
  891. }
  892. // group.SetGroup(remoteClient.ActiveGroupId, remoteClient);
  893. if (item != null)
  894. DoPostRezWhenFromItem(item, attachment);
  895. return group;
  896. }
  897. /// <summary>
  898. /// Do pre-rez processing when the object comes from an item.
  899. /// </summary>
  900. /// <param name="remoteClient"></param>
  901. /// <param name="item"></param>
  902. /// <param name="objlist"></param>
  903. /// <param name="pos"></param>
  904. /// <param name="veclist">
  905. /// List of vector position adjustments for a coalesced objects. For ordinary objects
  906. /// this list will contain just Vector3.Zero. The order of adjustments must match the order of objlist
  907. /// </param>
  908. /// <param name="isAttachment"></param>
  909. /// <returns>true if we can processed with rezzing, false if we need to abort</returns>
  910. private bool DoPreRezWhenFromItem(
  911. IClientAPI remoteClient, InventoryItemBase item, List<SceneObjectGroup> objlist,
  912. Vector3 pos, List<Vector3> veclist, bool isAttachment)
  913. {
  914. UUID fromUserInventoryItemId = UUID.Zero;
  915. // If we have permission to copy then link the rezzed object back to the user inventory
  916. // item that it came from. This allows us to enable 'save object to inventory'
  917. if (!m_Scene.Permissions.BypassPermissions())
  918. {
  919. if ((item.CurrentPermissions & (uint)PermissionMask.Copy)
  920. == (uint)PermissionMask.Copy && (item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0)
  921. {
  922. fromUserInventoryItemId = item.ID;
  923. }
  924. }
  925. else
  926. {
  927. if ((item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0)
  928. {
  929. // Brave new fullperm world
  930. fromUserInventoryItemId = item.ID;
  931. }
  932. }
  933. for (int i = 0; i < objlist.Count; i++)
  934. {
  935. SceneObjectGroup g = objlist[i];
  936. if (!m_Scene.Permissions.CanRezObject(
  937. g.PrimCount, remoteClient.AgentId, pos + veclist[i])
  938. && !isAttachment)
  939. {
  940. // The client operates in no fail mode. It will
  941. // have already removed the item from the folder
  942. // if it's no copy.
  943. // Put it back if it's not an attachment
  944. //
  945. if (((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) && (!isAttachment))
  946. remoteClient.SendBulkUpdateInventory(item);
  947. ILandObject land = m_Scene.LandChannel.GetLandObject(pos.X, pos.Y);
  948. remoteClient.SendAlertMessage(string.Format(
  949. "Can't rez object '{0}' at <{1:F3}, {2:F3}, {3:F3}> on parcel '{4}' in region {5}.",
  950. item.Name, pos.X, pos.Y, pos.Z, land != null ? land.LandData.Name : "Unknown", m_Scene.Name));
  951. return false;
  952. }
  953. }
  954. for (int i = 0; i < objlist.Count; i++)
  955. {
  956. SceneObjectGroup so = objlist[i];
  957. SceneObjectPart rootPart = so.RootPart;
  958. // Since renaming the item in the inventory does not
  959. // affect the name stored in the serialization, transfer
  960. // the correct name from the inventory to the
  961. // object itself before we rez.
  962. //
  963. // Only do these for the first object if we are rezzing a coalescence.
  964. // nahh dont mess with coalescence objects,
  965. // the name in inventory can be change for inventory purpuses only
  966. if (objlist.Count == 1)
  967. {
  968. rootPart.Name = item.Name;
  969. rootPart.Description = item.Description;
  970. }
  971. if ((item.Flags & (uint)InventoryItemFlags.ObjectSlamSale) != 0)
  972. {
  973. rootPart.ObjectSaleType = item.SaleType;
  974. rootPart.SalePrice = item.SalePrice;
  975. }
  976. so.FromFolderID = item.Folder;
  977. // m_log.DebugFormat(
  978. // "[INVENTORY ACCESS MODULE]: rootPart.OwnedID {0}, item.Owner {1}, item.CurrentPermissions {2:X}",
  979. // rootPart.OwnerID, item.Owner, item.CurrentPermissions);
  980. if ((rootPart.OwnerID != item.Owner) ||
  981. (item.CurrentPermissions & (uint)PermissionMask.Slam) != 0 ||
  982. (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0)
  983. {
  984. //Need to kill the for sale here
  985. rootPart.ObjectSaleType = 0;
  986. rootPart.SalePrice = 10;
  987. if (m_Scene.Permissions.PropagatePermissions())
  988. {
  989. foreach (SceneObjectPart part in so.Parts)
  990. {
  991. part.GroupMask = 0; // DO NOT propagate here
  992. if( part.OwnerID != part.GroupID)
  993. part.LastOwnerID = part.OwnerID;
  994. part.OwnerID = item.Owner;
  995. part.RezzerID = item.Owner;
  996. part.Inventory.ChangeInventoryOwner(item.Owner);
  997. // Reconstruct the original item's base permissions. They
  998. // can be found in the lower (folded) bits.
  999. if ((item.BasePermissions & (uint)PermissionMask.FoldedMask) != 0)
  1000. {
  1001. // We have permissions stored there so use them
  1002. part.NextOwnerMask = ((item.BasePermissions & (uint)PermissionMask.FoldedMask) << (int)PermissionMask.FoldingShift);
  1003. part.NextOwnerMask |= (uint)PermissionMask.Move;
  1004. }
  1005. else
  1006. {
  1007. // This is a legacy object and we can't avoid the issues that
  1008. // caused perms loss or escalation before, treat it the legacy
  1009. // way.
  1010. part.NextOwnerMask = item.NextPermissions;
  1011. }
  1012. }
  1013. so.ApplyNextOwnerPermissions();
  1014. // In case the user has changed flags on a received item
  1015. // we have to apply those changes after the slam. Else we
  1016. // get a net loss of permissions.
  1017. // On legacy objects, this opts for a loss of permissions rather
  1018. // than the previous handling that allowed escalation.
  1019. foreach (SceneObjectPart part in so.Parts)
  1020. {
  1021. if ((item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0)
  1022. {
  1023. part.GroupMask = item.GroupPermissions & part.BaseMask;
  1024. part.EveryoneMask = item.EveryOnePermissions & part.BaseMask;
  1025. part.NextOwnerMask = item.NextPermissions & part.BaseMask;
  1026. }
  1027. }
  1028. }
  1029. }
  1030. else
  1031. {
  1032. foreach (SceneObjectPart part in so.Parts)
  1033. {
  1034. part.FromUserInventoryItemID = fromUserInventoryItemId;
  1035. if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0)
  1036. part.EveryoneMask = item.EveryOnePermissions;
  1037. if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
  1038. part.NextOwnerMask = item.NextPermissions;
  1039. if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
  1040. part.GroupMask = item.GroupPermissions;
  1041. }
  1042. }
  1043. rootPart.TrimPermissions();
  1044. so.InvalidateDeepEffectivePerms();
  1045. if (isAttachment)
  1046. so.FromItemID = item.ID;
  1047. }
  1048. return true;
  1049. }
  1050. /// <summary>
  1051. /// Do post-rez processing when the object comes from an item.
  1052. /// </summary>
  1053. /// <param name="item"></param>
  1054. /// <param name="isAttachment"></param>
  1055. private void DoPostRezWhenFromItem(InventoryItemBase item, bool isAttachment)
  1056. {
  1057. if (!m_Scene.Permissions.BypassPermissions())
  1058. {
  1059. if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
  1060. {
  1061. // If this is done on attachments, no
  1062. // copy ones will be lost, so avoid it
  1063. //
  1064. if (!isAttachment)
  1065. {
  1066. List<UUID> uuids = new List<UUID>();
  1067. uuids.Add(item.ID);
  1068. m_Scene.InventoryService.DeleteItems(item.Owner, uuids);
  1069. }
  1070. }
  1071. }
  1072. }
  1073. protected void AddUserData(SceneObjectGroup sog)
  1074. {
  1075. UserManagementModule.AddUser(sog.RootPart.CreatorID, sog.RootPart.CreatorData);
  1076. foreach (SceneObjectPart sop in sog.Parts)
  1077. UserManagementModule.AddUser(sop.CreatorID, sop.CreatorData);
  1078. }
  1079. public virtual void TransferInventoryAssets(InventoryItemBase item, UUID sender, UUID receiver)
  1080. {
  1081. }
  1082. public virtual bool CanGetAgentInventoryItem(IClientAPI remoteClient, UUID itemID, UUID requestID)
  1083. {
  1084. InventoryItemBase assetRequestItem = GetItem(remoteClient.AgentId, itemID);
  1085. if (assetRequestItem == null)
  1086. {
  1087. ILibraryService lib = m_Scene.RequestModuleInterface<ILibraryService>();
  1088. if (lib != null)
  1089. assetRequestItem = lib.LibraryRootFolder.FindItem(itemID);
  1090. if (assetRequestItem == null)
  1091. return false;
  1092. }
  1093. // At this point, we need to apply perms
  1094. // only to notecards and scripts. All
  1095. // other asset types are always available
  1096. //
  1097. if (assetRequestItem.AssetType == (int)AssetType.LSLText)
  1098. {
  1099. if (!m_Scene.Permissions.CanViewScript(itemID, UUID.Zero, remoteClient.AgentId))
  1100. {
  1101. remoteClient.SendAgentAlertMessage("Insufficient permissions to view script", false);
  1102. return false;
  1103. }
  1104. }
  1105. else if (assetRequestItem.AssetType == (int)AssetType.Notecard)
  1106. {
  1107. if (!m_Scene.Permissions.CanViewNotecard(itemID, UUID.Zero, remoteClient.AgentId))
  1108. {
  1109. remoteClient.SendAgentAlertMessage("Insufficient permissions to view notecard", false);
  1110. return false;
  1111. }
  1112. }
  1113. if (assetRequestItem.AssetID != requestID)
  1114. {
  1115. m_log.WarnFormat(
  1116. "[INVENTORY ACCESS MODULE]: {0} requested asset {1} from item {2} but this does not match item's asset {3}",
  1117. Name, requestID, itemID, assetRequestItem.AssetID);
  1118. return false;
  1119. }
  1120. return true;
  1121. }
  1122. public virtual bool IsForeignUser(UUID userID, out string assetServerURL)
  1123. {
  1124. assetServerURL = string.Empty;
  1125. return false;
  1126. }
  1127. #endregion
  1128. #region Misc
  1129. /// <summary>
  1130. /// Create a new asset data structure.
  1131. /// </summary>
  1132. /// <param name="name"></param>
  1133. /// <param name="description"></param>
  1134. /// <param name="invType"></param>
  1135. /// <param name="assetType"></param>
  1136. /// <param name="data"></param>
  1137. /// <returns></returns>
  1138. private AssetBase CreateAsset(string name, string description, sbyte assetType, byte[] data, string creatorID)
  1139. {
  1140. AssetBase asset = new AssetBase(UUID.Random(), name, assetType, creatorID);
  1141. asset.Description = description;
  1142. asset.Data = (data == null) ? new byte[1] : data;
  1143. return asset;
  1144. }
  1145. protected virtual InventoryItemBase GetItem(UUID agentID, UUID itemID)
  1146. {
  1147. IInventoryService invService = m_Scene.RequestModuleInterface<IInventoryService>();
  1148. InventoryItemBase item = invService.GetItem(agentID, itemID);
  1149. if (item != null && item.CreatorData != null && item.CreatorData != string.Empty)
  1150. UserManagementModule.AddUser(item.CreatorIdAsUuid, item.CreatorData);
  1151. return item;
  1152. }
  1153. #endregion
  1154. }
  1155. }