SceneObjectPartInventory.cs 59 KB

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