SceneObjectPartInventory.cs 59 KB

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