SceneObjectPartInventory.cs 67 KB

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