SceneObjectPartInventory.cs 68 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839
  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.Text;
  29. using System.Xml;
  30. using System.IO;
  31. using System.Collections.Generic;
  32. using System.Collections;
  33. using System.Reflection;
  34. using System.Threading;
  35. using OpenMetaverse;
  36. using log4net;
  37. using OpenSim.Framework;
  38. using OpenSim.Region.Framework.Interfaces;
  39. using OpenSim.Region.Framework.Scenes.Scripting;
  40. using OpenSim.Region.Framework.Scenes.Serialization;
  41. using PermissionMask = OpenSim.Framework.PermissionMask;
  42. namespace OpenSim.Region.Framework.Scenes
  43. {
  44. public class SceneObjectPartInventory : IEntityInventory , IDisposable
  45. {
  46. private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  47. private byte[] m_inventoryFileData = Array.Empty<byte>();
  48. private byte[] m_inventoryFileNameBytes = Array.Empty<byte>();
  49. private string m_inventoryFileName = "";
  50. private uint m_inventoryFileNameSerial = 0;
  51. private bool m_inventoryPrivileged = false;
  52. private object m_inventoryFileLock = new object();
  53. private Dictionary<UUID, ArrayList> m_scriptErrors = new Dictionary<UUID, ArrayList>();
  54. /// <value>
  55. /// The part to which the inventory belongs.
  56. /// </value>
  57. private SceneObjectPart m_part;
  58. /// <summary>
  59. /// Serial count for inventory file , used to tell if inventory has changed
  60. /// no need for this to be part of Database backup
  61. /// </summary>
  62. protected uint m_inventorySerial = 0;
  63. /// <summary>
  64. /// Holds in memory prim inventory
  65. /// </summary>
  66. protected TaskInventoryDictionary m_items = new TaskInventoryDictionary();
  67. protected Dictionary<UUID, TaskInventoryItem> m_scripts = null;
  68. /// <summary>
  69. /// Tracks whether inventory has changed since the last persistent backup
  70. /// </summary>
  71. internal bool HasInventoryChanged;
  72. /// <value>
  73. /// Inventory serial number
  74. /// </value>
  75. protected internal uint Serial
  76. {
  77. get { return m_inventorySerial; }
  78. set { m_inventorySerial = value; }
  79. }
  80. /// <value>
  81. /// Raw inventory data
  82. /// </value>
  83. protected internal TaskInventoryDictionary Items
  84. {
  85. get
  86. {
  87. return m_items;
  88. }
  89. set
  90. {
  91. m_items = value;
  92. m_inventorySerial++;
  93. gatherScriptsAndQueryStates();
  94. }
  95. }
  96. public int Count
  97. {
  98. get
  99. {
  100. m_items.LockItemsForRead(true);
  101. int c = m_items.Count;
  102. m_items.LockItemsForRead(false);
  103. return c;
  104. }
  105. }
  106. /// <summary>
  107. /// Constructor
  108. /// </summary>
  109. /// <param name="part">
  110. /// A <see cref="SceneObjectPart"/>
  111. /// </param>
  112. public SceneObjectPartInventory(SceneObjectPart part)
  113. {
  114. m_part = part;
  115. }
  116. ~SceneObjectPartInventory()
  117. {
  118. Dispose(false);
  119. }
  120. private bool disposed = false;
  121. public void Dispose()
  122. {
  123. Dispose(true);
  124. GC.SuppressFinalize(this);
  125. }
  126. protected void Dispose(bool disposing)
  127. {
  128. // Check to see if Dispose has already been called.
  129. if (!disposed)
  130. {
  131. if (m_items != null)
  132. {
  133. m_items.Dispose();
  134. m_items = null;
  135. }
  136. disposed = true;
  137. }
  138. }
  139. /// <summary>
  140. /// Force the task inventory of this prim to persist at the next update sweep
  141. /// </summary>
  142. public void ForceInventoryPersistence()
  143. {
  144. HasInventoryChanged = true;
  145. }
  146. /// <summary>
  147. /// Reset UUIDs for all the items in the prim's inventory.
  148. /// </summary>
  149. /// <remarks>
  150. /// This involves either generating
  151. /// new ones or setting existing UUIDs to the correct parent UUIDs.
  152. ///
  153. /// If this method is called and there are inventory items, then we regard the inventory as having changed.
  154. /// </remarks>
  155. public void ResetInventoryIDs()
  156. {
  157. if (m_part == null)
  158. return;
  159. m_items.LockItemsForWrite(true);
  160. if (m_items.Count == 0)
  161. {
  162. m_items.LockItemsForWrite(false);
  163. return;
  164. }
  165. UUID partID = m_part.UUID;
  166. IList<TaskInventoryItem> items = new List<TaskInventoryItem>(m_items.Values);
  167. m_items.Clear();
  168. if(m_scripts == null)
  169. {
  170. for (int i = 0; i < items.Count; ++i)
  171. {
  172. TaskInventoryItem item = items[i];
  173. item.ResetIDs(partID);
  174. m_items.Add(item.ItemID, item);
  175. }
  176. }
  177. else
  178. {
  179. m_scripts.Clear();
  180. for (int i = 0; i < items.Count; ++i)
  181. {
  182. TaskInventoryItem item = items[i];
  183. item.ResetIDs(partID);
  184. m_items.Add(item.ItemID, item);
  185. if (item.InvType == (int)InventoryType.LSL)
  186. m_scripts.Add(item.ItemID, item);
  187. }
  188. }
  189. m_inventorySerial++;
  190. m_items.LockItemsForWrite(false);
  191. }
  192. public void ResetObjectID()
  193. {
  194. if (m_part == null)
  195. return;
  196. UUID partID = m_part.UUID;
  197. m_items.LockItemsForWrite(true);
  198. if (m_items.Count == 0)
  199. {
  200. m_items.LockItemsForWrite(false);
  201. return;
  202. }
  203. foreach(TaskInventoryItem item in m_items.Values)
  204. {
  205. item.ParentPartID = partID;
  206. item.ParentID = partID;
  207. }
  208. m_inventorySerial++;
  209. m_items.LockItemsForWrite(false);
  210. }
  211. /// <summary>
  212. /// Change every item in this inventory to a new owner.
  213. /// </summary>
  214. /// <param name="ownerId"></param>
  215. public void ChangeInventoryOwner(UUID ownerId)
  216. {
  217. if(m_part == null)
  218. return;
  219. m_items.LockItemsForWrite(true);
  220. if (m_items.Count == 0)
  221. {
  222. m_items.LockItemsForWrite(false);
  223. return;
  224. }
  225. foreach (TaskInventoryItem item in m_items.Values)
  226. {
  227. if (ownerId != item.OwnerID)
  228. item.LastOwnerID = item.OwnerID;
  229. item.OwnerID = ownerId;
  230. item.PermsMask = 0;
  231. item.PermsGranter = UUID.Zero;
  232. item.OwnerChanged = true;
  233. }
  234. HasInventoryChanged = true;
  235. m_part.ParentGroup.HasGroupChanged = true;
  236. m_inventorySerial++;
  237. m_items.LockItemsForWrite(false);
  238. }
  239. /// <summary>
  240. /// Change every item in this inventory to a new group.
  241. /// </summary>
  242. /// <param name="groupID"></param>
  243. public void ChangeInventoryGroup(UUID groupID)
  244. {
  245. if(m_part == null)
  246. return;
  247. m_items.LockItemsForWrite(true);
  248. if (m_items.Count == 0)
  249. {
  250. m_items.LockItemsForWrite(false);
  251. return;
  252. }
  253. m_inventorySerial++;
  254. // Don't let this set the HasGroupChanged flag for attachments
  255. // as this happens during rez and we don't want a new asset
  256. // for each attachment each time
  257. if (!m_part.ParentGroup.IsAttachment)
  258. {
  259. HasInventoryChanged = true;
  260. m_part.ParentGroup.HasGroupChanged = true;
  261. }
  262. foreach (TaskInventoryItem item in m_items.Values)
  263. item.GroupID = groupID;
  264. m_items.LockItemsForWrite(false);
  265. }
  266. private void gatherScriptsAndQueryStates()
  267. {
  268. m_items.LockItemsForWrite(true);
  269. m_scripts = new Dictionary<UUID, TaskInventoryItem>();
  270. foreach (TaskInventoryItem item in m_items.Values)
  271. {
  272. if (item.InvType == (int)InventoryType.LSL)
  273. m_scripts[item.ItemID] = item;
  274. }
  275. if (m_scripts.Count == 0)
  276. {
  277. m_items.LockItemsForWrite(false);
  278. m_scripts = null;
  279. return;
  280. }
  281. m_items.LockItemsForWrite(false);
  282. if (m_part.ParentGroup == null || m_part.ParentGroup.Scene == null)
  283. return;
  284. IScriptModule[] scriptEngines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
  285. if (scriptEngines.Length == 0) // No engine at all
  286. return;
  287. bool running;
  288. m_items.LockItemsForRead(true);
  289. foreach (TaskInventoryItem item in m_scripts.Values)
  290. {
  291. //running = false;
  292. foreach (IScriptModule e in scriptEngines)
  293. {
  294. if (e.HasScript(item.ItemID, out running))
  295. {
  296. item.ScriptRunning = running;
  297. break;
  298. }
  299. }
  300. //item.ScriptRunning = running;
  301. }
  302. m_items.LockItemsForRead(false);
  303. }
  304. public bool TryGetScriptInstanceRunning(UUID itemId, out bool running)
  305. {
  306. running = false;
  307. TaskInventoryItem item = GetInventoryItem(itemId);
  308. if (item == null)
  309. return false;
  310. return TryGetScriptInstanceRunning(m_part.ParentGroup.Scene, item, out running);
  311. }
  312. public static bool TryGetScriptInstanceRunning(Scene scene, TaskInventoryItem item, out bool running)
  313. {
  314. running = false;
  315. if (item.InvType != (int)InventoryType.LSL)
  316. return false;
  317. IScriptModule[] scriptEngines = scene.RequestModuleInterfaces<IScriptModule>();
  318. if (scriptEngines.Length == 0) // No engine at all
  319. return false;
  320. foreach (IScriptModule e in scriptEngines)
  321. {
  322. if (e.HasScript(item.ItemID, out running))
  323. return true;
  324. }
  325. return false;
  326. }
  327. public int CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource)
  328. {
  329. m_items.LockItemsForRead(true);
  330. if(m_scripts == null || m_scripts.Count == 0)
  331. {
  332. m_items.LockItemsForRead(false);
  333. return 0;
  334. }
  335. List<TaskInventoryItem> scripts = new List<TaskInventoryItem>(m_scripts.Values);
  336. m_items.LockItemsForRead(false);
  337. int scriptsValidForStarting = 0;
  338. for (int i = 0; i < scripts.Count; ++i)
  339. {
  340. if (CreateScriptInstance(scripts[i], startParam, postOnRez, engine, stateSource))
  341. scriptsValidForStarting++;
  342. }
  343. return scriptsValidForStarting;
  344. }
  345. public ArrayList GetScriptErrors(UUID itemID)
  346. {
  347. IScriptModule[] scriptEngines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
  348. ArrayList ret = new ArrayList();
  349. foreach (IScriptModule e in scriptEngines)
  350. {
  351. if (e != null)
  352. {
  353. ArrayList errors = e.GetScriptErrors(itemID);
  354. foreach (Object line in errors)
  355. ret.Add(line);
  356. }
  357. }
  358. return ret;
  359. }
  360. /// <summary>
  361. /// Stop and remove all the scripts in this prim.
  362. /// </summary>
  363. /// <param name="sceneObjectBeingDeleted">
  364. /// Should be true if these scripts are being removed because the scene
  365. /// object is being deleted. This will prevent spurious updates to the client.
  366. /// </param>
  367. public void RemoveScriptInstances(bool sceneObjectBeingDeleted)
  368. {
  369. m_items.LockItemsForRead(true);
  370. if (m_scripts == null || m_scripts.Count == 0)
  371. {
  372. m_items.LockItemsForRead(false);
  373. return;
  374. }
  375. List<TaskInventoryItem> scripts = new List<TaskInventoryItem>(m_scripts.Values);
  376. m_items.LockItemsForRead(false);
  377. foreach (TaskInventoryItem item in scripts)
  378. {
  379. RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted);
  380. m_part.RemoveScriptEvents(item.ItemID);
  381. }
  382. }
  383. /// <summary>
  384. /// Stop all the scripts in this prim.
  385. /// </summary>
  386. public void StopScriptInstances()
  387. {
  388. m_items.LockItemsForRead(true);
  389. if (m_scripts == null || m_scripts.Count == 0)
  390. {
  391. m_items.LockItemsForRead(false);
  392. return;
  393. }
  394. List<TaskInventoryItem> scripts = new List<TaskInventoryItem>(m_scripts.Values);
  395. m_items.LockItemsForRead(false);
  396. foreach (TaskInventoryItem item in scripts)
  397. StopScriptInstance(item);
  398. }
  399. /// <summary>
  400. /// Start a script which is in this prim's inventory.
  401. /// </summary>
  402. /// <param name="item"></param>
  403. /// <returns>true if the script instance was created, false otherwise</returns>
  404. public bool CreateScriptInstance(TaskInventoryItem item, int startParam, bool postOnRez, string engine, int stateSource)
  405. {
  406. //m_log.DebugFormat("[PRIM INVENTORY]: Starting script {0} {1} in prim {2} {3} in {4}",
  407. // item.Name, item.ItemID, m_part.Name, m_part.UUID, m_part.ParentGroup.Scene.RegionInfo.RegionName);
  408. if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item, m_part))
  409. {
  410. StoreScriptError(item.ItemID, "no permission");
  411. return false;
  412. }
  413. m_part.AddFlag(PrimFlags.Scripted);
  414. if (m_part.ParentGroup.Scene.RegionInfo.RegionSettings.DisableScripts)
  415. return false;
  416. UUID itemID = item.ItemID;
  417. m_items.LockItemsForRead(true);
  418. if (!m_items.TryGetValue(item.ItemID, out TaskInventoryItem it))
  419. {
  420. m_items.LockItemsForRead(false);
  421. StoreScriptError(itemID, String.Format("TaskItem ID {0} could not be found", item.ItemID));
  422. m_log.ErrorFormat(
  423. "[PRIM INVENTORY]: Couldn't start script {0}, {1} at {2} in {3} since taskitem ID {4} could not be found",
  424. item.Name, item.ItemID, m_part.AbsolutePosition,
  425. m_part.ParentGroup.Scene.RegionInfo.RegionName, item.ItemID);
  426. return false;
  427. }
  428. m_items.LockItemsForRead(false);
  429. if (stateSource == 2 && m_part.ParentGroup.Scene.m_trustBinaries)
  430. {
  431. // Prim crossing
  432. m_items.LockItemsForWrite(true);
  433. it.PermsMask = 0;
  434. it.PermsGranter = UUID.Zero;
  435. m_items.LockItemsForWrite(false);
  436. m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
  437. m_part.LocalId, itemID, String.Empty, startParam, postOnRez, engine, stateSource);
  438. StoreScriptErrors(itemID, null);
  439. m_part.ParentGroup.AddActiveScriptCount(1);
  440. m_part.ScheduleFullUpdate();
  441. return true;
  442. }
  443. AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString());
  444. if (asset == null)
  445. {
  446. StoreScriptError(itemID, String.Format("asset ID {0} could not be found", item.AssetID));
  447. m_log.ErrorFormat(
  448. "[PRIM INVENTORY]: Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found",
  449. item.Name, item.ItemID, m_part.AbsolutePosition,
  450. m_part.ParentGroup.Scene.RegionInfo.RegionName, item.AssetID);
  451. return false;
  452. }
  453. if (m_part.ParentGroup.m_savedScriptState != null)
  454. item.OldItemID = RestoreSavedScriptState(item.LoadedItemID, item.OldItemID, itemID);
  455. m_items.LockItemsForWrite(true);
  456. it.OldItemID = item.OldItemID;
  457. it.PermsMask = 0;
  458. it.PermsGranter = UUID.Zero;
  459. m_items.LockItemsForWrite(false);
  460. string script = Utils.BytesToString(asset.Data);
  461. m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
  462. m_part.LocalId, itemID, script, startParam, postOnRez, engine, stateSource);
  463. StoreScriptErrors(itemID, null);
  464. //if (item.ScriptRunning)
  465. m_part.ParentGroup.AddActiveScriptCount(1);
  466. return true;
  467. }
  468. private UUID RestoreSavedScriptState(UUID loadedID, UUID oldID, UUID newID)
  469. {
  470. //m_log.DebugFormat(
  471. // "[PRIM INVENTORY]: Restoring scripted state for item {0}, oldID {1}, loadedID {2}",
  472. // newID, oldID, loadedID);
  473. IScriptModule[] scriptEngines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
  474. if (scriptEngines.Length == 0) // No engine at all
  475. return oldID;
  476. UUID stateID = oldID;
  477. if (!m_part.ParentGroup.m_savedScriptState.ContainsKey(oldID))
  478. stateID = loadedID;
  479. if (m_part.ParentGroup.m_savedScriptState.ContainsKey(stateID))
  480. {
  481. XmlDocument doc = new XmlDocument();
  482. doc.LoadXml(m_part.ParentGroup.m_savedScriptState[stateID]);
  483. ////////// CRUFT WARNING ///////////////////////////////////
  484. //
  485. // Old objects will have <ScriptState><State> ...
  486. // This format is XEngine ONLY
  487. //
  488. // New objects have <State Engine="...." ...><ScriptState>...
  489. // This can be passed to any engine
  490. //
  491. XmlNode n = doc.SelectSingleNode("ScriptState");
  492. if (n != null) // Old format data
  493. {
  494. XmlDocument newDoc = new XmlDocument();
  495. XmlElement rootN = newDoc.CreateElement("", "State", "");
  496. XmlAttribute uuidA = newDoc.CreateAttribute("", "UUID", "");
  497. uuidA.Value = stateID.ToString();
  498. rootN.Attributes.Append(uuidA);
  499. XmlAttribute engineA = newDoc.CreateAttribute("", "Engine", "");
  500. engineA.Value = "XEngine";
  501. rootN.Attributes.Append(engineA);
  502. newDoc.AppendChild(rootN);
  503. XmlNode stateN = newDoc.ImportNode(n, true);
  504. rootN.AppendChild(stateN);
  505. // This created document has only the minimun data
  506. // necessary for XEngine to parse it successfully
  507. //m_log.DebugFormat("[PRIM INVENTORY]: Adding legacy state {0} in {1}", stateID, newID);
  508. m_part.ParentGroup.m_savedScriptState[stateID] = newDoc.OuterXml;
  509. }
  510. foreach (IScriptModule e in scriptEngines)
  511. {
  512. if (e != null)
  513. {
  514. if (e.SetXMLState(newID, m_part.ParentGroup.m_savedScriptState[stateID]))
  515. break;
  516. }
  517. }
  518. m_part.ParentGroup.m_savedScriptState.Remove(stateID);
  519. }
  520. return stateID;
  521. }
  522. /// <summary>
  523. /// Start a script which is in this prim's inventory.
  524. /// Some processing may occur in the background, but this routine returns asap.
  525. /// </summary>
  526. /// <param name="itemId">
  527. /// A <see cref="UUID"/>
  528. /// </param>
  529. public bool CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
  530. {
  531. lock (m_scriptErrors)
  532. {
  533. // Indicate to CreateScriptInstanceInternal() we don't want it to wait for completion
  534. m_scriptErrors.Remove(itemId);
  535. }
  536. CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
  537. return true;
  538. }
  539. private void CreateScriptInstanceInternal(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
  540. {
  541. m_items.LockItemsForRead(true);
  542. if (m_items.TryGetValue(itemId, out TaskInventoryItem it))
  543. {
  544. m_items.LockItemsForRead(false);
  545. CreateScriptInstance(it, startParam, postOnRez, engine, stateSource);
  546. }
  547. else
  548. {
  549. m_items.LockItemsForRead(false);
  550. string msg = String.Format("couldn't be found for prim {0}, {1} at {2} in {3}", m_part.Name, m_part.UUID,
  551. m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
  552. StoreScriptError(itemId, msg);
  553. m_log.ErrorFormat(
  554. "[PRIM INVENTORY]: " +
  555. "Couldn't start script with ID {0} since it {1}", itemId, msg);
  556. }
  557. }
  558. /// <summary>
  559. /// Start a script which is in this prim's inventory and return any compilation error messages.
  560. /// </summary>
  561. /// <param name="itemId">
  562. /// A <see cref="UUID"/>
  563. /// </param>
  564. public ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
  565. {
  566. ArrayList errors;
  567. // Indicate to CreateScriptInstanceInternal() we want it to
  568. // post any compilation/loading error messages
  569. lock (m_scriptErrors)
  570. {
  571. m_scriptErrors[itemId] = null;
  572. }
  573. // Perform compilation/loading
  574. CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
  575. // Wait for and retrieve any errors
  576. lock (m_scriptErrors)
  577. {
  578. while ((errors = m_scriptErrors[itemId]) == null)
  579. {
  580. if (!System.Threading.Monitor.Wait(m_scriptErrors, 15000))
  581. {
  582. m_log.ErrorFormat(
  583. "[PRIM INVENTORY]: " +
  584. "timedout waiting for script {0} errors", itemId);
  585. errors = m_scriptErrors[itemId];
  586. if (errors == null)
  587. {
  588. errors = new ArrayList(1);
  589. errors.Add("timedout waiting for errors");
  590. }
  591. break;
  592. }
  593. }
  594. m_scriptErrors.Remove(itemId);
  595. }
  596. return errors;
  597. }
  598. // Signal to CreateScriptInstanceEr() that compilation/loading is complete
  599. private void StoreScriptErrors(UUID itemId, ArrayList errors)
  600. {
  601. lock (m_scriptErrors)
  602. {
  603. // If compilation/loading initiated via CreateScriptInstance(),
  604. // it does not want the errors, so just get out
  605. if (!m_scriptErrors.ContainsKey(itemId))
  606. {
  607. return;
  608. }
  609. // Initiated via CreateScriptInstanceEr(), if we know what the
  610. // errors are, save them and wake CreateScriptInstanceEr().
  611. if (errors != null)
  612. {
  613. m_scriptErrors[itemId] = errors;
  614. System.Threading.Monitor.PulseAll(m_scriptErrors);
  615. return;
  616. }
  617. }
  618. // Initiated via CreateScriptInstanceEr() but we don't know what
  619. // the errors are yet, so retrieve them from the script engine.
  620. // This may involve some waiting internal to GetScriptErrors().
  621. errors = GetScriptErrors(itemId);
  622. // Get a default non-null value to indicate success.
  623. if (errors == null)
  624. {
  625. errors = new ArrayList();
  626. }
  627. // Post to CreateScriptInstanceEr() and wake it up
  628. lock (m_scriptErrors)
  629. {
  630. m_scriptErrors[itemId] = errors;
  631. System.Threading.Monitor.PulseAll(m_scriptErrors);
  632. }
  633. }
  634. // Like StoreScriptErrors(), but just posts a single string message
  635. private void StoreScriptError(UUID itemId, string message)
  636. {
  637. ArrayList errors = new ArrayList(1);
  638. errors.Add(message);
  639. StoreScriptErrors(itemId, errors);
  640. }
  641. /// <summary>
  642. /// Stop and remove a script which is in this prim's inventory.
  643. /// </summary>
  644. /// <param name="itemId"></param>
  645. /// <param name="sceneObjectBeingDeleted">
  646. /// Should be true if this script is being removed because the scene
  647. /// object is being deleted. This will prevent spurious updates to the client.
  648. /// </param>
  649. public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted)
  650. {
  651. if (m_items.ContainsKey(itemId))
  652. {
  653. if (!sceneObjectBeingDeleted)
  654. m_part.RemoveScriptEvents(itemId);
  655. m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemId);
  656. m_part.ParentGroup.AddActiveScriptCount(-1);
  657. }
  658. else
  659. {
  660. m_log.WarnFormat(
  661. "[PRIM INVENTORY]: " +
  662. "Couldn't stop script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}",
  663. itemId, m_part.Name, m_part.UUID,
  664. m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
  665. }
  666. }
  667. /// <summary>
  668. /// Stop a script which is in this prim's inventory.
  669. /// </summary>
  670. /// <param name="itemId"></param>
  671. /// <param name="sceneObjectBeingDeleted">
  672. /// Should be true if this script is being removed because the scene
  673. /// object is being deleted. This will prevent spurious updates to the client.
  674. /// </param>
  675. public void StopScriptInstance(UUID itemId)
  676. {
  677. m_items.LockItemsForRead(true);
  678. m_items.TryGetValue(itemId, out TaskInventoryItem scriptItem);
  679. m_items.LockItemsForRead(false);
  680. if (scriptItem != null)
  681. {
  682. StopScriptInstance(scriptItem);
  683. }
  684. else
  685. {
  686. m_log.WarnFormat(
  687. "[PRIM INVENTORY]: " +
  688. "Couldn't stop script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}",
  689. itemId, m_part.Name, m_part.UUID,
  690. m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
  691. }
  692. }
  693. /// <summary>
  694. /// Stop a script which is in this prim's inventory.
  695. /// </summary>
  696. /// <param name="itemId"></param>
  697. /// <param name="sceneObjectBeingDeleted">
  698. /// Should be true if this script is being removed because the scene
  699. /// object is being deleted. This will prevent spurious updates to the client.
  700. /// </param>
  701. public void StopScriptInstance(TaskInventoryItem item)
  702. {
  703. if (m_part.ParentGroup.Scene != null)
  704. m_part.ParentGroup.Scene.EventManager.TriggerStopScript(m_part.LocalId, item.ItemID);
  705. // At the moment, even stopped scripts are counted as active, which is probably wrong.
  706. // m_part.ParentGroup.AddActiveScriptCount(-1);
  707. }
  708. public void SendReleaseScriptsControl()
  709. {
  710. m_items.LockItemsForRead(true);
  711. if (m_scripts == null || m_scripts.Count == 0)
  712. {
  713. m_items.LockItemsForRead(false);
  714. return;
  715. }
  716. List<UUID> grants = new List<UUID>();
  717. List<UUID> items = new List<UUID>();
  718. foreach (TaskInventoryItem item in m_scripts.Values)
  719. {
  720. if (((item.PermsMask & 4) == 0))
  721. continue;
  722. grants.Add(item.PermsGranter);
  723. items.Add(item.ItemID);
  724. }
  725. m_items.LockItemsForRead(false);
  726. if (grants.Count > 0)
  727. {
  728. for (int i = 0; i < grants.Count; ++i)
  729. {
  730. ScenePresence presence = m_part.ParentGroup.Scene.GetScenePresence(grants[i]);
  731. if (presence != null && !presence.IsDeleted && presence.ParentPart != m_part) // last check mb needed for vehicle crossing ???
  732. presence.UnRegisterControlEventsToScript(m_part.LocalId, items[i]);
  733. }
  734. }
  735. }
  736. public void RemoveScriptsPermissions(int permissions)
  737. {
  738. m_items.LockItemsForWrite(true);
  739. if (m_scripts == null || m_scripts.Count == 0)
  740. {
  741. m_items.LockItemsForWrite(false);
  742. return;
  743. }
  744. bool removeControl = ((permissions & 4) != 0); //takecontrol
  745. List<UUID> grants = new List<UUID>();
  746. List<UUID> items = new List<UUID>();
  747. permissions = ~permissions;
  748. foreach (TaskInventoryItem item in m_scripts.Values)
  749. {
  750. int curmask = item.PermsMask;
  751. UUID curGrant = item.PermsGranter;
  752. if (removeControl && ((curmask & 4) != 0))
  753. {
  754. grants.Add(curGrant);
  755. items.Add(item.ItemID);
  756. }
  757. curmask &= permissions;
  758. item.PermsMask = curmask;
  759. if(curmask == 0)
  760. item.PermsGranter = UUID.Zero;
  761. }
  762. m_items.LockItemsForWrite(false);
  763. if(grants.Count > 0)
  764. {
  765. for(int i = 0; i< grants.Count;++i)
  766. {
  767. ScenePresence presence = m_part.ParentGroup.Scene.GetScenePresence(grants[i]);
  768. if (presence != null && !presence.IsDeleted)
  769. presence.UnRegisterControlEventsToScript(m_part.LocalId, items[i]);
  770. }
  771. }
  772. }
  773. public void RemoveScriptsPermissions(ScenePresence sp, int permissions)
  774. {
  775. m_items.LockItemsForWrite(true);
  776. if (m_scripts == null || m_scripts.Count == 0)
  777. {
  778. m_items.LockItemsForWrite(false);
  779. return;
  780. }
  781. bool removeControl = ((permissions & 4) != 0); //takecontrol
  782. UUID grant = sp.UUID;
  783. List<UUID> items = new List<UUID>();
  784. permissions = ~permissions;
  785. foreach (TaskInventoryItem item in m_scripts.Values)
  786. {
  787. if(grant != item.PermsGranter)
  788. continue;
  789. int curmask = item.PermsMask;
  790. if (removeControl && ((curmask & 4) != 0))
  791. items.Add(item.ItemID);
  792. curmask &= permissions;
  793. item.PermsMask = curmask;
  794. if(curmask == 0)
  795. item.PermsGranter = UUID.Zero;
  796. }
  797. m_items.LockItemsForWrite(false);
  798. if(items.Count > 0)
  799. {
  800. for(int i = 0; i < items.Count; ++i)
  801. {
  802. if (!sp.IsDeleted)
  803. sp.UnRegisterControlEventsToScript(m_part.LocalId, items[i]);
  804. }
  805. }
  806. }
  807. /// <summary>
  808. /// Check if the inventory holds an item with a given name.
  809. /// </summary>
  810. /// <param name="name"></param>
  811. /// <returns></returns>
  812. private bool InventoryContainsName(string name)
  813. {
  814. m_items.LockItemsForRead(true);
  815. foreach (TaskInventoryItem item in m_items.Values)
  816. {
  817. if (item.Name == name)
  818. {
  819. m_items.LockItemsForRead(false);
  820. return true;
  821. }
  822. }
  823. m_items.LockItemsForRead(false);
  824. return false;
  825. }
  826. /// <summary>
  827. /// For a given item name, return that name if it is available. Otherwise, return the next available
  828. /// similar name (which is currently the original name with the next available numeric suffix).
  829. /// </summary>
  830. /// <param name="name"></param>
  831. /// <returns></returns>
  832. private string FindAvailableInventoryName(string name)
  833. {
  834. if (!InventoryContainsName(name))
  835. return name;
  836. int suffix=1;
  837. while (suffix < 256)
  838. {
  839. string tryName=String.Format("{0} {1}", name, suffix);
  840. if (!InventoryContainsName(tryName))
  841. return tryName;
  842. suffix++;
  843. }
  844. return String.Empty;
  845. }
  846. /// <summary>
  847. /// Add an item to this prim's inventory. If an item with the same name already exists, then an alternative
  848. /// name is chosen.
  849. /// </summary>
  850. /// <param name="item"></param>
  851. public void AddInventoryItem(TaskInventoryItem item, bool allowedDrop)
  852. {
  853. AddInventoryItem(item.Name, item, allowedDrop);
  854. }
  855. /// <summary>
  856. /// Add an item to this prim's inventory. If an item with the same name already exists, it is replaced.
  857. /// </summary>
  858. /// <param name="item"></param>
  859. public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop)
  860. {
  861. m_items.LockItemsForRead(true);
  862. List<TaskInventoryItem> il = new List<TaskInventoryItem>(m_items.Values);
  863. m_items.LockItemsForRead(false);
  864. foreach (TaskInventoryItem i in il)
  865. {
  866. if (i.Name == item.Name)
  867. {
  868. if (i.InvType == (int)InventoryType.LSL)
  869. RemoveScriptInstance(i.ItemID, false);
  870. RemoveInventoryItem(i.ItemID);
  871. break;
  872. }
  873. }
  874. AddInventoryItem(item.Name, item, allowedDrop);
  875. }
  876. /// <summary>
  877. /// Add an item to this prim's inventory.
  878. /// </summary>
  879. /// <param name="name">The name that the new item should have.</param>
  880. /// <param name="item">
  881. /// The item itself. The name within this structure is ignored in favour of the name
  882. /// given in this method's arguments
  883. /// </param>
  884. /// <param name="allowedDrop">
  885. /// Item was only added to inventory because AllowedDrop is set
  886. /// </param>
  887. protected void AddInventoryItem(string name, TaskInventoryItem item, bool allowedDrop)
  888. {
  889. name = FindAvailableInventoryName(name);
  890. if (name.Length == 0)
  891. return;
  892. item.ParentID = m_part.UUID;
  893. item.ParentPartID = m_part.UUID;
  894. item.Name = name;
  895. item.GroupID = m_part.GroupID;
  896. m_items.LockItemsForWrite(true);
  897. m_items.Add(item.ItemID, item);
  898. if (item.InvType == (int)InventoryType.LSL)
  899. {
  900. if (m_scripts == null)
  901. m_scripts = new Dictionary<UUID, TaskInventoryItem>();
  902. m_scripts.Add(item.ItemID, item);
  903. }
  904. m_items.LockItemsForWrite(false);
  905. if (allowedDrop)
  906. m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP, item.ItemID);
  907. else
  908. m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
  909. m_part.AggregateInnerPerms();
  910. m_inventorySerial++;
  911. HasInventoryChanged = true;
  912. m_part.ParentGroup.HasGroupChanged = true;
  913. }
  914. /// <summary>
  915. /// Restore a whole collection of items to the prim's inventory at once.
  916. /// We assume that the items already have all their fields correctly filled out.
  917. /// The items are not flagged for persistence to the database, since they are being restored
  918. /// from persistence rather than being newly added.
  919. /// </summary>
  920. /// <param name="items"></param>
  921. public void RestoreInventoryItems(ICollection<TaskInventoryItem> items)
  922. {
  923. m_items.LockItemsForWrite(true);
  924. foreach (TaskInventoryItem item in items)
  925. {
  926. m_items.Add(item.ItemID, item);
  927. if (item.InvType == (int)InventoryType.LSL)
  928. {
  929. if (m_scripts == null)
  930. m_scripts = new Dictionary<UUID, TaskInventoryItem>();
  931. m_scripts.Add(item.ItemID, item);
  932. }
  933. }
  934. m_items.LockItemsForWrite(false);
  935. m_part.AggregateInnerPerms();
  936. m_inventorySerial++;
  937. }
  938. /// <summary>
  939. /// Returns an existing inventory item. Returns the original, so any changes will be live.
  940. /// </summary>
  941. /// <param name="itemID"></param>
  942. /// <returns>null if the item does not exist</returns>
  943. public TaskInventoryItem GetInventoryItem(UUID itemId)
  944. {
  945. TaskInventoryItem item;
  946. m_items.LockItemsForRead(true);
  947. m_items.TryGetValue(itemId, out item);
  948. m_items.LockItemsForRead(false);
  949. return item;
  950. }
  951. public TaskInventoryItem GetInventoryItem(string name)
  952. {
  953. m_items.LockItemsForRead(true);
  954. foreach (TaskInventoryItem item in m_items.Values)
  955. {
  956. if (item.Name == name)
  957. {
  958. m_items.LockItemsForRead(false);
  959. return item;
  960. }
  961. }
  962. m_items.LockItemsForRead(false);
  963. return null;
  964. }
  965. public TaskInventoryItem GetInventoryItem(string name, int type)
  966. {
  967. m_items.LockItemsForRead(true);
  968. foreach (TaskInventoryItem item in m_items.Values)
  969. {
  970. if (item.Type == type && item.Name == name)
  971. {
  972. m_items.LockItemsForRead(false);
  973. return item;
  974. }
  975. }
  976. m_items.LockItemsForRead(false);
  977. return null;
  978. }
  979. public List<TaskInventoryItem> GetInventoryItems(string name)
  980. {
  981. List<TaskInventoryItem> items = new List<TaskInventoryItem>();
  982. m_items.LockItemsForRead(true);
  983. foreach (TaskInventoryItem item in m_items.Values)
  984. {
  985. if (item.Name == name)
  986. items.Add(item);
  987. }
  988. m_items.LockItemsForRead(false);
  989. return items;
  990. }
  991. public bool GetRezReadySceneObjects(TaskInventoryItem item, out List<SceneObjectGroup> objlist, out List<Vector3> veclist, out Vector3 bbox, out float offsetHeight)
  992. {
  993. return GetRezReadySceneObjects(item, item.OwnerID, m_part.GroupID, out objlist, out veclist, out bbox, out offsetHeight);
  994. }
  995. public bool GetRezReadySceneObjects(TaskInventoryItem item, UUID NewOwner, UUID NewGroup, out List<SceneObjectGroup> objlist, out List<Vector3> veclist, out Vector3 bbox, out float offsetHeight)
  996. {
  997. AssetBase rezAsset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString());
  998. if (null == rezAsset)
  999. {
  1000. m_log.WarnFormat(
  1001. "[PRIM INVENTORY]: Could not find asset {0} for inventory item {1} in {2}",
  1002. item.AssetID, item.Name, m_part.Name);
  1003. objlist = null;
  1004. veclist = null;
  1005. bbox = Vector3.Zero;
  1006. offsetHeight = 0;
  1007. return false;
  1008. }
  1009. m_part.ParentGroup.Scene.GetObjectsToRez(rezAsset.Data, false, out objlist, out veclist, out bbox, out offsetHeight);
  1010. for (int i = 0; i < objlist.Count; i++)
  1011. {
  1012. SceneObjectGroup group = objlist[i];
  1013. /*
  1014. group.RootPart.AttachPoint = group.RootPart.Shape.State;
  1015. group.RootPart.AttachedPos = group.AbsolutePosition;
  1016. group.RootPart.AttachRotation = group.GroupRotation;
  1017. */
  1018. group.ResetIDs();
  1019. SceneObjectPart rootPart = group.GetPart(group.UUID);
  1020. // Since renaming the item in the inventory does not affect the name stored
  1021. // in the serialization, transfer the correct name from the inventory to the
  1022. // object itself before we rez.
  1023. // Only do these for the first object if we are rezzing a coalescence.
  1024. // nahh dont mess with coalescence objects,
  1025. // the name in inventory can be change for inventory purpuses only
  1026. if (objlist.Count == 1)
  1027. {
  1028. rootPart.Name = item.Name;
  1029. rootPart.Description = item.Description;
  1030. }
  1031. group.SetGroup(NewGroup, null);
  1032. SceneObjectPart[] partList = group.Parts;
  1033. bool slamThings = (item.CurrentPermissions & (uint)PermissionMask.Slam) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0;
  1034. if ((rootPart.OwnerID != NewOwner) || slamThings)
  1035. {
  1036. if (m_part.ParentGroup.Scene.Permissions.PropagatePermissions())
  1037. {
  1038. foreach (SceneObjectPart part in partList)
  1039. {
  1040. if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0)
  1041. part.EveryoneMask = item.EveryonePermissions;
  1042. if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
  1043. part.NextOwnerMask = item.NextPermissions;
  1044. if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
  1045. part.GroupMask = item.GroupPermissions;
  1046. }
  1047. group.ApplyNextOwnerPermissions();
  1048. }
  1049. }
  1050. foreach (SceneObjectPart part in partList)
  1051. {
  1052. if ((part.OwnerID.NotEqual(NewOwner)))
  1053. {
  1054. if(part.GroupID.NotEqual(part.OwnerID))
  1055. part.LastOwnerID = part.OwnerID;
  1056. part.OwnerID = NewOwner;
  1057. part.Inventory.ChangeInventoryOwner(NewOwner);
  1058. }
  1059. if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0)
  1060. part.EveryoneMask = item.EveryonePermissions;
  1061. if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
  1062. part.NextOwnerMask = item.NextPermissions;
  1063. if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
  1064. part.GroupMask = item.GroupPermissions;
  1065. }
  1066. rootPart.TrimPermissions();
  1067. group.InvalidateDeepEffectivePerms();
  1068. }
  1069. return true;
  1070. }
  1071. /// <summary>
  1072. /// Update an existing inventory item.
  1073. /// </summary>
  1074. /// <param name="item">The updated item. An item with the same id must already exist
  1075. /// in this prim's inventory.</param>
  1076. /// <returns>false if the item did not exist, true if the update occurred successfully</returns>
  1077. public bool UpdateInventoryItem(TaskInventoryItem item)
  1078. {
  1079. return UpdateInventoryItem(item, true, true);
  1080. }
  1081. public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents)
  1082. {
  1083. return UpdateInventoryItem(item, fireScriptEvents, true);
  1084. }
  1085. public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged)
  1086. {
  1087. m_items.LockItemsForWrite(true);
  1088. if (m_items.ContainsKey(item.ItemID))
  1089. {
  1090. //m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name);
  1091. item.ParentID = m_part.UUID;
  1092. item.ParentPartID = m_part.UUID;
  1093. // If group permissions have been set on, check that the groupID is up to date in case it has
  1094. // changed since permissions were last set.
  1095. if (item.GroupPermissions != (uint)PermissionMask.None)
  1096. item.GroupID = m_part.GroupID;
  1097. if(item.OwnerID.IsZero()) // viewer to internal enconding of group owned
  1098. item.OwnerID = item.GroupID;
  1099. if (item.AssetID.IsZero())
  1100. item.AssetID = m_items[item.ItemID].AssetID;
  1101. m_items[item.ItemID] = item;
  1102. if(item.InvType == (int)InventoryType.LSL)
  1103. {
  1104. if(m_scripts == null)
  1105. m_scripts = new Dictionary<UUID, TaskInventoryItem>();
  1106. m_scripts[item.ItemID] = item;
  1107. }
  1108. m_inventorySerial++;
  1109. if (fireScriptEvents)
  1110. m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
  1111. if (considerChanged)
  1112. {
  1113. m_part.ParentGroup.InvalidateDeepEffectivePerms();
  1114. HasInventoryChanged = true;
  1115. m_part.ParentGroup.HasGroupChanged = true;
  1116. }
  1117. m_items.LockItemsForWrite(false);
  1118. return true;
  1119. }
  1120. else
  1121. {
  1122. m_log.ErrorFormat(
  1123. "[PRIM INVENTORY]: " +
  1124. "Tried to retrieve item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory",
  1125. item.ItemID, m_part.Name, m_part.UUID,
  1126. m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
  1127. }
  1128. m_items.LockItemsForWrite(false);
  1129. return false;
  1130. }
  1131. /// <summary>
  1132. /// Remove an item from this prim's inventory
  1133. /// </summary>
  1134. /// <param name="itemID"></param>
  1135. /// <returns>Numeric asset type of the item removed. Returns -1 if the item did not exist
  1136. /// in this prim's inventory.</returns>
  1137. public int RemoveInventoryItem(UUID itemID)
  1138. {
  1139. m_items.LockItemsForRead(true);
  1140. if (m_items.ContainsKey(itemID))
  1141. {
  1142. int type = m_items[itemID].InvType;
  1143. m_items.LockItemsForRead(false);
  1144. if (type == (int)InventoryType.LSL) // Script
  1145. {
  1146. m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID);
  1147. }
  1148. m_items.LockItemsForWrite(true);
  1149. m_items.Remove(itemID);
  1150. if(m_scripts != null)
  1151. {
  1152. m_scripts.Remove(itemID);
  1153. if(m_scripts.Count == 0)
  1154. m_scripts = null;
  1155. }
  1156. if (m_scripts == null)
  1157. {
  1158. m_part.RemFlag(PrimFlags.Scripted);
  1159. }
  1160. m_inventorySerial++;
  1161. m_items.LockItemsForWrite(false);
  1162. m_part.ParentGroup.InvalidateDeepEffectivePerms();
  1163. HasInventoryChanged = true;
  1164. m_part.ParentGroup.HasGroupChanged = true;
  1165. m_part.ScheduleFullUpdate();
  1166. m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
  1167. return type;
  1168. }
  1169. else
  1170. {
  1171. m_items.LockItemsForRead(false);
  1172. m_log.ErrorFormat(
  1173. "[PRIM INVENTORY]: " +
  1174. "Tried to remove item ID {0} from prim {1}, {2} but the item does not exist in this inventory",
  1175. itemID, m_part.Name, m_part.UUID);
  1176. }
  1177. return -1;
  1178. }
  1179. /// <summary>
  1180. /// Serialize all the metadata for the items in this prim's inventory ready for sending to the client
  1181. /// </summary>
  1182. /// <param name="xferManager"></param>
  1183. public void RequestInventoryFile(IClientAPI client, IXfer xferManager)
  1184. {
  1185. lock (m_inventoryFileLock)
  1186. {
  1187. bool changed = false;
  1188. m_items.LockItemsForRead(true);
  1189. if (m_inventorySerial == 0) // No inventory
  1190. {
  1191. m_items.LockItemsForRead(false);
  1192. client.SendTaskInventory(m_part.UUID, 0, Array.Empty<byte>());
  1193. return;
  1194. }
  1195. if (m_items.Count == 0) // No inventory
  1196. {
  1197. m_items.LockItemsForRead(false);
  1198. client.SendTaskInventory(m_part.UUID, 0, Array.Empty<byte>());
  1199. return;
  1200. }
  1201. if (m_inventoryFileNameSerial != m_inventorySerial)
  1202. {
  1203. m_inventoryFileNameSerial = m_inventorySerial;
  1204. changed = true;
  1205. }
  1206. m_items.LockItemsForRead(false);
  1207. if (m_inventoryFileData.Length < 2)
  1208. changed = true;
  1209. bool includeAssets = false;
  1210. if (m_part.ParentGroup.Scene.Permissions.CanEditObjectInventory(m_part.UUID, client.AgentId))
  1211. includeAssets = true;
  1212. if (m_inventoryPrivileged != includeAssets)
  1213. changed = true;
  1214. if (!changed)
  1215. {
  1216. xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData);
  1217. client.SendTaskInventory(m_part.UUID, (short)m_inventoryFileNameSerial,
  1218. m_inventoryFileNameBytes);
  1219. return;
  1220. }
  1221. m_inventoryPrivileged = includeAssets;
  1222. InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero);
  1223. m_items.LockItemsForRead(true);
  1224. foreach (TaskInventoryItem item in m_items.Values)
  1225. {
  1226. UUID ownerID = item.OwnerID;
  1227. UUID groupID = item.GroupID;
  1228. uint everyoneMask = item.EveryonePermissions;
  1229. uint baseMask = item.BasePermissions;
  1230. uint ownerMask = item.CurrentPermissions;
  1231. uint groupMask = item.GroupPermissions;
  1232. invString.AddItemStart();
  1233. invString.AddNameValueLine("item_id", item.ItemID.ToString());
  1234. invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
  1235. invString.AddPermissionsStart();
  1236. invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask));
  1237. invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask));
  1238. invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask));
  1239. invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
  1240. invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
  1241. invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
  1242. invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString());
  1243. invString.AddNameValueLine("group_id",groupID.ToString());
  1244. if(!groupID.IsZero() && ownerID.Equals(groupID))
  1245. {
  1246. invString.AddNameValueLine("owner_id", UUID.ZeroString);
  1247. invString.AddNameValueLine("group_owned","1");
  1248. }
  1249. else
  1250. {
  1251. invString.AddNameValueLine("owner_id", ownerID.ToString());
  1252. invString.AddNameValueLine("group_owned","0");
  1253. }
  1254. invString.AddSectionEnd();
  1255. if (includeAssets)
  1256. invString.AddNameValueLine("asset_id", item.AssetID.ToString());
  1257. else
  1258. invString.AddNameValueLine("asset_id", UUID.Zero.ToString());
  1259. invString.AddNameValueLine("type", Utils.AssetTypeToString((AssetType)item.Type));
  1260. invString.AddNameValueLine("inv_type", Utils.InventoryTypeToString((InventoryType)item.InvType));
  1261. invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
  1262. invString.AddSaleStart();
  1263. invString.AddNameValueLine("sale_type", "not");
  1264. invString.AddNameValueLine("sale_price", "0");
  1265. invString.AddSectionEnd();
  1266. invString.AddNameValueLine("name", item.Name + "|");
  1267. invString.AddNameValueLine("desc", item.Description + "|");
  1268. invString.AddNameValueLine("creation_date", item.CreationDate.ToString());
  1269. invString.AddSectionEnd();
  1270. }
  1271. m_items.LockItemsForRead(false);
  1272. m_inventoryFileData = Utils.StringToBytes(invString.GetString());
  1273. if (m_inventoryFileData.Length > 2)
  1274. {
  1275. m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp";
  1276. m_inventoryFileNameBytes = Util.StringToBytes256(m_inventoryFileName);
  1277. xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData);
  1278. client.SendTaskInventory(m_part.UUID, (short)m_inventoryFileNameSerial,m_inventoryFileNameBytes);
  1279. return;
  1280. }
  1281. client.SendTaskInventory(m_part.UUID, 0, Array.Empty<byte>());
  1282. }
  1283. }
  1284. /// <summary>
  1285. /// Process inventory backup
  1286. /// </summary>
  1287. /// <param name="datastore"></param>
  1288. public void ProcessInventoryBackup(ISimulationDataService datastore)
  1289. {
  1290. // Removed this because linking will cause an immediate delete of the new
  1291. // child prim from the database and the subsequent storing of the prim sees
  1292. // the inventory of it as unchanged and doesn't store it at all. The overhead
  1293. // of storing prim inventory needlessly is much less than the aggravation
  1294. // of prim inventory loss.
  1295. // if (HasInventoryChanged)
  1296. // {
  1297. m_items.LockItemsForRead(true);
  1298. ICollection<TaskInventoryItem> itemsvalues = m_items.Values;
  1299. HasInventoryChanged = false;
  1300. m_items.LockItemsForRead(false);
  1301. try
  1302. {
  1303. datastore.StorePrimInventory(m_part.UUID, itemsvalues);
  1304. }
  1305. catch {}
  1306. // }
  1307. }
  1308. public class InventoryStringBuilder
  1309. {
  1310. private StringBuilder BuildString = new StringBuilder(1024);
  1311. public InventoryStringBuilder(UUID folderID, UUID parentID)
  1312. {
  1313. BuildString.Append("\tinv_object\t0\n\t{\n");
  1314. AddNameValueLine("obj_id", folderID.ToString());
  1315. AddNameValueLine("parent_id", parentID.ToString());
  1316. AddNameValueLine("type", "category");
  1317. AddNameValueLine("name", "Contents|\n\t}");
  1318. }
  1319. public void AddItemStart()
  1320. {
  1321. BuildString.Append("\tinv_item\t0\n\t{\n");
  1322. }
  1323. public void AddPermissionsStart()
  1324. {
  1325. BuildString.Append("\tpermissions 0\n\t{\n");
  1326. }
  1327. public void AddSaleStart()
  1328. {
  1329. BuildString.Append("\tsale_info\t0\n\t{\n");
  1330. }
  1331. protected void AddSectionStart()
  1332. {
  1333. BuildString.Append("\t{\n");
  1334. }
  1335. public void AddSectionEnd()
  1336. {
  1337. BuildString.Append("\t}\n");
  1338. }
  1339. public void AddLine(string addLine)
  1340. {
  1341. BuildString.Append(addLine);
  1342. }
  1343. public void AddNameValueLine(string name, string value)
  1344. {
  1345. BuildString.Append("\t\t");
  1346. BuildString.Append(name);
  1347. BuildString.Append("\t");
  1348. BuildString.Append(value);
  1349. BuildString.Append("\n");
  1350. }
  1351. public String GetString()
  1352. {
  1353. return BuildString.ToString();
  1354. }
  1355. public void Close()
  1356. {
  1357. }
  1358. }
  1359. public void AggregateInnerPerms(ref uint owner, ref uint group, ref uint everyone)
  1360. {
  1361. foreach (TaskInventoryItem item in m_items.Values)
  1362. {
  1363. if(item.InvType == (sbyte)InventoryType.Landmark)
  1364. continue;
  1365. owner &= item.CurrentPermissions;
  1366. group &= item.GroupPermissions;
  1367. everyone &= item.EveryonePermissions;
  1368. }
  1369. }
  1370. public uint MaskEffectivePermissions()
  1371. {
  1372. // used to propagate permissions restrictions outwards
  1373. // Modify does not propagate outwards.
  1374. uint mask=0x7fffffff;
  1375. foreach (TaskInventoryItem item in m_items.Values)
  1376. {
  1377. if(item.InvType == (sbyte)InventoryType.Landmark)
  1378. continue;
  1379. // apply current to normal permission bits
  1380. uint newperms = item.CurrentPermissions;
  1381. if ((newperms & (uint)PermissionMask.Copy) == 0)
  1382. mask &= ~(uint)PermissionMask.Copy;
  1383. if ((newperms & (uint)PermissionMask.Transfer) == 0)
  1384. mask &= ~(uint)PermissionMask.Transfer;
  1385. if ((newperms & (uint)PermissionMask.Export) == 0)
  1386. mask &= ~((uint)PermissionMask.Export);
  1387. // apply next owner restricted by current to folded bits
  1388. newperms &= item.NextPermissions;
  1389. if ((newperms & (uint)PermissionMask.Copy) == 0)
  1390. mask &= ~((uint)PermissionMask.FoldedCopy);
  1391. if ((newperms & (uint)PermissionMask.Transfer) == 0)
  1392. mask &= ~((uint)PermissionMask.FoldedTransfer);
  1393. if ((newperms & (uint)PermissionMask.Export) == 0)
  1394. mask &= ~((uint)PermissionMask.FoldedExport);
  1395. }
  1396. return mask;
  1397. }
  1398. public void ApplyNextOwnerPermissions()
  1399. {
  1400. foreach (TaskInventoryItem item in m_items.Values)
  1401. {
  1402. item.CurrentPermissions &= item.NextPermissions;
  1403. item.BasePermissions &= item.NextPermissions;
  1404. item.EveryonePermissions &= item.NextPermissions;
  1405. item.OwnerChanged = true;
  1406. item.PermsMask = 0;
  1407. item.PermsGranter = UUID.Zero;
  1408. }
  1409. }
  1410. public void ApplyGodPermissions(uint perms)
  1411. {
  1412. foreach (TaskInventoryItem item in m_items.Values)
  1413. {
  1414. item.CurrentPermissions = perms;
  1415. item.BasePermissions = perms;
  1416. }
  1417. m_inventorySerial++;
  1418. HasInventoryChanged = true;
  1419. }
  1420. /// <summary>
  1421. /// Returns true if this part inventory contains any scripts. False otherwise.
  1422. /// </summary>
  1423. /// <returns></returns>
  1424. public bool ContainsScripts()
  1425. {
  1426. m_items.LockItemsForRead(true);
  1427. bool res = (m_scripts != null && m_scripts.Count >0);
  1428. m_items.LockItemsForRead(false);
  1429. return res;
  1430. }
  1431. /// <summary>
  1432. /// Returns the count of scripts in this parts inventory.
  1433. /// </summary>
  1434. /// <returns></returns>
  1435. public int ScriptCount()
  1436. {
  1437. int count = 0;
  1438. m_items.LockItemsForRead(true);
  1439. if(m_scripts != null)
  1440. count = m_scripts.Count;
  1441. m_items.LockItemsForRead(false);
  1442. return count;
  1443. }
  1444. /// <summary>
  1445. /// Returns the count of running scripts in this parts inventory.
  1446. /// </summary>
  1447. /// <returns></returns>
  1448. public int RunningScriptCount()
  1449. {
  1450. IScriptModule[] scriptEngines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
  1451. if (scriptEngines.Length == 0)
  1452. return 0;
  1453. int count = 0;
  1454. m_items.LockItemsForRead(true);
  1455. if (m_scripts == null || m_scripts.Count == 0)
  1456. {
  1457. m_items.LockItemsForRead(false);
  1458. return 0;
  1459. }
  1460. List<TaskInventoryItem> scripts = new List<TaskInventoryItem>(m_scripts.Values);
  1461. m_items.LockItemsForRead(false);
  1462. foreach (TaskInventoryItem item in scripts)
  1463. {
  1464. foreach (IScriptModule engine in scriptEngines)
  1465. {
  1466. if (engine != null)
  1467. {
  1468. if (engine.HasScript(item.ItemID, out bool running))
  1469. {
  1470. if(running)
  1471. count++;
  1472. break;
  1473. }
  1474. }
  1475. }
  1476. }
  1477. return count;
  1478. }
  1479. public List<UUID> GetInventoryList()
  1480. {
  1481. m_items.LockItemsForRead(true);
  1482. List<UUID> ret = new List<UUID>(m_items.Count);
  1483. foreach (TaskInventoryItem item in m_items.Values)
  1484. ret.Add(item.ItemID);
  1485. m_items.LockItemsForRead(false);
  1486. return ret;
  1487. }
  1488. public List<TaskInventoryItem> GetInventoryItems()
  1489. {
  1490. m_items.LockItemsForRead(true);
  1491. List<TaskInventoryItem> ret = new List<TaskInventoryItem>(m_items.Values);
  1492. m_items.LockItemsForRead(false);
  1493. return ret;
  1494. }
  1495. public List<TaskInventoryItem> GetInventoryItems(InventoryType type)
  1496. {
  1497. m_items.LockItemsForRead(true);
  1498. List<TaskInventoryItem> ret = new List<TaskInventoryItem>(m_items.Count);
  1499. foreach (TaskInventoryItem item in m_items.Values)
  1500. if (item.InvType == (int)type)
  1501. ret.Add(item);
  1502. m_items.LockItemsForRead(false);
  1503. return ret;
  1504. }
  1505. public Dictionary<UUID, string> GetScriptStates()
  1506. {
  1507. return GetScriptStates(false);
  1508. }
  1509. public Dictionary<UUID, string> GetScriptStates(bool oldIDs)
  1510. {
  1511. Dictionary<UUID, string> ret = new Dictionary<UUID, string>();
  1512. if (m_part.ParentGroup.Scene == null) // Group not in a scene
  1513. return ret;
  1514. IScriptModule[] scriptEngines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
  1515. if (scriptEngines.Length == 0) // No engine at all
  1516. return ret;
  1517. m_items.LockItemsForRead(true);
  1518. if (m_scripts == null || m_scripts.Count == 0)
  1519. {
  1520. m_items.LockItemsForRead(false);
  1521. return ret;
  1522. }
  1523. List<TaskInventoryItem> scripts = new List<TaskInventoryItem>(m_scripts.Values);
  1524. m_items.LockItemsForRead(false);
  1525. foreach (TaskInventoryItem item in scripts)
  1526. {
  1527. foreach (IScriptModule e in scriptEngines)
  1528. {
  1529. if (e != null)
  1530. {
  1531. //m_log.DebugFormat(
  1532. // "[PRIM INVENTORY]: Getting script state from engine {0} for {1} in part {2} in group {3} in {4}",
  1533. // e.Name, item.Name, m_part.Name, m_part.ParentGroup.Name, m_part.ParentGroup.Scene.Name);
  1534. string n = e.GetXMLState(item.ItemID);
  1535. if (n != String.Empty)
  1536. {
  1537. if (oldIDs)
  1538. {
  1539. if (!ret.ContainsKey(item.OldItemID))
  1540. ret[item.OldItemID] = n;
  1541. }
  1542. else
  1543. {
  1544. if (!ret.ContainsKey(item.ItemID))
  1545. ret[item.ItemID] = n;
  1546. }
  1547. break;
  1548. }
  1549. }
  1550. }
  1551. }
  1552. return ret;
  1553. }
  1554. public void ResumeScripts()
  1555. {
  1556. IScriptModule[] scriptEngines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
  1557. if (scriptEngines.Length == 0)
  1558. return;
  1559. m_items.LockItemsForRead(true);
  1560. if (m_scripts == null || m_scripts.Count == 0)
  1561. {
  1562. m_items.LockItemsForRead(false);
  1563. return;
  1564. }
  1565. List<TaskInventoryItem> scripts = new List<TaskInventoryItem>(m_scripts.Values);
  1566. m_items.LockItemsForRead(false);
  1567. foreach (TaskInventoryItem item in scripts)
  1568. {
  1569. foreach (IScriptModule engine in scriptEngines)
  1570. {
  1571. if (engine != null)
  1572. {
  1573. //m_log.DebugFormat(
  1574. // "[PRIM INVENTORY]: Resuming script {0} {1} for {2}, OwnerChanged {3}",
  1575. // item.Name, item.ItemID, item.OwnerID, item.OwnerChanged);
  1576. if(!engine.ResumeScript(item.ItemID))
  1577. continue;
  1578. if (item.OwnerChanged)
  1579. engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER });
  1580. item.OwnerChanged = false;
  1581. }
  1582. }
  1583. }
  1584. }
  1585. }
  1586. }