clockwerk-opensim – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 vero 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  
28 using System;
29 using System.Collections.Generic;
30 using System.Collections;
31 using System.Reflection;
32 using System.Text;
33 using System.Threading;
34 using System.Timers;
35 using System.Xml;
36 using OpenMetaverse;
37 using OpenMetaverse.Packets;
38 using log4net;
39 using OpenSim.Framework;
40 using OpenSim.Region.Framework;
41 using OpenSim.Framework.Client;
42 using OpenSim.Region.Framework.Interfaces;
43 using OpenSim.Region.Framework.Scenes.Serialization;
44 using PermissionMask = OpenSim.Framework.PermissionMask;
45  
46 namespace OpenSim.Region.Framework.Scenes
47 {
48 public partial class Scene
49 {
50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51 private static readonly string LogHeader = "[SCENE INVENTORY]";
52  
53 /// <summary>
54 /// Allows asynchronous derezzing of objects from the scene into a client's inventory.
55 /// </summary>
56 protected AsyncSceneObjectGroupDeleter m_asyncSceneObjectDeleter;
57  
58 /// <summary>
59 /// Allows inventory details to be sent to clients asynchronously
60 /// </summary>
61 protected AsyncInventorySender m_asyncInventorySender;
62  
63 /// <summary>
64 /// Creates all the scripts in the scene which should be started.
65 /// </summary>
66 /// <returns>
67 /// Number of scripts that were valid for starting. This does not guarantee that all these scripts
68 /// were actually started, but just that the start could be attempt (e.g. the asset data for the script could be found)
69 /// </returns>
70 public int CreateScriptInstances()
71 {
72 m_log.InfoFormat("[SCENE]: Initializing script instances in {0}", RegionInfo.RegionName);
73  
74 int scriptsValidForStarting = 0;
75  
76 EntityBase[] entities = Entities.GetEntities();
77 foreach (EntityBase group in entities)
78 {
79 if (group is SceneObjectGroup)
80 {
81 scriptsValidForStarting
82 += ((SceneObjectGroup) group).CreateScriptInstances(0, false, DefaultScriptEngine, 0);
83 ((SceneObjectGroup) group).ResumeScripts();
84 }
85 }
86  
87 m_log.InfoFormat(
88 "[SCENE]: Initialized {0} script instances in {1}",
89 scriptsValidForStarting, RegionInfo.RegionName);
90  
91 return scriptsValidForStarting;
92 }
93  
94 /// <summary>
95 /// Lets the script engines start processing scripts.
96 /// </summary>
97 public void StartScripts()
98 {
99 // m_log.InfoFormat("[SCENE]: Starting scripts in {0}, please wait.", RegionInfo.RegionName);
100  
101 IScriptModule[] engines = RequestModuleInterfaces<IScriptModule>();
102  
103 foreach (IScriptModule engine in engines)
104 engine.StartProcessing();
105 }
106  
107 public void AddUploadedInventoryItem(UUID agentID, InventoryItemBase item)
108 {
109 IMoneyModule money = RequestModuleInterface<IMoneyModule>();
110 if (money != null)
111 {
112 money.ApplyUploadCharge(agentID, money.UploadCharge, "Asset upload");
113 }
114  
115 AddInventoryItem(item);
116 }
117  
118 public bool AddInventoryItemReturned(UUID AgentId, InventoryItemBase item)
119 {
120 if (AddInventoryItem(item))
121 return true;
122 else
123 {
124 m_log.WarnFormat(
125 "[AGENT INVENTORY]: Unable to add item {1} to agent {2} inventory", item.Name, AgentId);
126  
127 return false;
128 }
129 }
130  
131 public bool AddInventoryItem(InventoryItemBase item)
132 {
133 return AddInventoryItem(item, true);
134 }
135  
136 /// <summary>
137 /// Add the given inventory item to a user's inventory.
138 /// </summary>
139 /// <param name="item"></param>
140 public bool AddInventoryItem(InventoryItemBase item, bool trigger)
141 {
142 if (item.Folder != UUID.Zero && InventoryService.AddItem(item))
143 {
144 int userlevel = 0;
145 if (Permissions.IsGod(item.Owner))
146 {
147 userlevel = 1;
148 }
149 if (trigger)
150 EventManager.TriggerOnNewInventoryItemUploadComplete(item.Owner, (AssetType)item.AssetType, item.AssetID, item.Name, userlevel);
151  
152 return true;
153 }
154  
155 // OK so either the viewer didn't send a folderID or AddItem failed
156 UUID originalFolder = item.Folder;
157 InventoryFolderBase f = InventoryService.GetFolderForType(item.Owner, (AssetType)item.AssetType);
158 if (f != null)
159 {
160 m_log.DebugFormat(
161 "[AGENT INVENTORY]: Found folder {0} type {1} for item {2}",
162 f.Name, (AssetType)f.Type, item.Name);
163  
164 item.Folder = f.ID;
165 }
166 else
167 {
168 f = InventoryService.GetRootFolder(item.Owner);
169 if (f != null)
170 {
171 item.Folder = f.ID;
172 }
173 else
174 {
175 m_log.WarnFormat(
176 "[AGENT INVENTORY]: Could not find root folder for {0} when trying to add item {1} with no parent folder specified",
177 item.Owner, item.Name);
178 return false;
179 }
180 }
181  
182 if (InventoryService.AddItem(item))
183 {
184 int userlevel = 0;
185 if (Permissions.IsGod(item.Owner))
186 {
187 userlevel = 1;
188 }
189 if (trigger)
190 EventManager.TriggerOnNewInventoryItemUploadComplete(item.Owner, (AssetType)item.AssetType, item.AssetID, item.Name, userlevel);
191  
192 if (originalFolder != UUID.Zero)
193 {
194 // Tell the viewer that the item didn't go there
195 ChangePlacement(item, f);
196 }
197  
198 return true;
199 }
200 else
201 {
202 m_log.WarnFormat(
203 "[AGENT INVENTORY]: Agent {0} could not add item {1} {2}",
204 item.Owner, item.Name, item.ID);
205  
206 return false;
207 }
208 }
209  
210 private void ChangePlacement(InventoryItemBase item, InventoryFolderBase f)
211 {
212 ScenePresence sp = GetScenePresence(item.Owner);
213 if (sp != null)
214 {
215 if (sp.ControllingClient is IClientCore)
216 {
217 IClientCore core = (IClientCore)sp.ControllingClient;
218 IClientInventory inv;
219  
220 if (core.TryGet<IClientInventory>(out inv))
221 {
222 InventoryFolderBase parent = new InventoryFolderBase(f.ParentID, f.Owner);
223 parent = InventoryService.GetFolder(parent);
224 inv.SendRemoveInventoryItems(new UUID[] { item.ID });
225 inv.SendBulkUpdateInventory(new InventoryFolderBase[0], new InventoryItemBase[] { item });
226 string message = "The item was placed in folder " + f.Name;
227 if (parent != null)
228 message += " under " + parent.Name;
229 sp.ControllingClient.SendAgentAlertMessage(message, false);
230 }
231 }
232 }
233 }
234  
235 /// <summary>
236 /// Add the given inventory item to a user's inventory.
237 /// </summary>
238 /// <param name="AgentID">
239 /// A <see cref="UUID"/>
240 /// </param>
241 /// <param name="item">
242 /// A <see cref="InventoryItemBase"/>
243 /// </param>
244 [Obsolete("Use AddInventoryItem(InventoryItemBase item) instead. This was deprecated in OpenSim 0.7.1")]
245 public void AddInventoryItem(UUID AgentID, InventoryItemBase item)
246 {
247 AddInventoryItem(item);
248 }
249  
250 /// <summary>
251 /// Add an inventory item to an avatar's inventory.
252 /// </summary>
253 /// <param name="remoteClient">The remote client controlling the avatar</param>
254 /// <param name="item">The item. This structure contains all the item metadata, including the folder
255 /// in which the item is to be placed.</param>
256 public void AddInventoryItem(IClientAPI remoteClient, InventoryItemBase item)
257 {
258 AddInventoryItem(item);
259 remoteClient.SendInventoryItemCreateUpdate(item, 0);
260 }
261  
262 /// <summary>
263 /// <see>CapsUpdatedInventoryItemAsset(IClientAPI, UUID, byte[])</see>
264 /// </summary>
265 public UUID CapsUpdateInventoryItemAsset(UUID avatarId, UUID itemID, byte[] data)
266 {
267 ScenePresence avatar;
268  
269 if (TryGetScenePresence(avatarId, out avatar))
270 {
271 IInventoryAccessModule invAccess = RequestModuleInterface<IInventoryAccessModule>();
272 if (invAccess != null)
273 return invAccess.CapsUpdateInventoryItemAsset(avatar.ControllingClient, itemID, data);
274 }
275 else
276 {
277 m_log.ErrorFormat(
278 "[AGENT INVENTORY]: " +
279 "Avatar {0} cannot be found to update its inventory item asset",
280 avatarId);
281 }
282  
283 return UUID.Zero;
284 }
285  
286 /// <summary>
287 /// Capability originating call to update the asset of a script in a prim's (task's) inventory
288 /// </summary>
289 /// <param name="remoteClient"></param>
290 /// <param name="itemID"></param>
291 /// <param name="primID">The prim which contains the item to update</param>
292 /// <param name="isScriptRunning">Indicates whether the script to update is currently running</param>
293 /// <param name="data"></param>
294 public ArrayList CapsUpdateTaskInventoryScriptAsset(IClientAPI remoteClient, UUID itemId,
295 UUID primId, bool isScriptRunning, byte[] data)
296 {
297 if (!Permissions.CanEditScript(itemId, primId, remoteClient.AgentId))
298 {
299 remoteClient.SendAgentAlertMessage("Insufficient permissions to edit script", false);
300 return new ArrayList();
301 }
302  
303 // Retrieve group
304 SceneObjectPart part = GetSceneObjectPart(primId);
305 if (part == null)
306 return new ArrayList();
307  
308 SceneObjectGroup group = part.ParentGroup;
309  
310 // Retrieve item
311 TaskInventoryItem item = group.GetInventoryItem(part.LocalId, itemId);
312  
313 if (null == item)
314 {
315 m_log.ErrorFormat(
316 "[PRIM INVENTORY]: Tried to retrieve item ID {0} from prim {1}, {2} for caps script update "
317 + " but the item does not exist in this inventory",
318 itemId, part.Name, part.UUID);
319  
320 return new ArrayList();
321 }
322  
323 AssetBase asset = CreateAsset(item.Name, item.Description, (sbyte)AssetType.LSLText, data, remoteClient.AgentId);
324 AssetService.Store(asset);
325  
326 // m_log.DebugFormat(
327 // "[PRIM INVENTORY]: Stored asset {0} when updating item {1} in prim {2} for {3}",
328 // asset.ID, item.Name, part.Name, remoteClient.Name);
329  
330 if (isScriptRunning)
331 {
332 part.Inventory.RemoveScriptInstance(item.ItemID, false);
333 }
334  
335 // Update item with new asset
336 item.AssetID = asset.FullID;
337 if (group.UpdateInventoryItem(item))
338 remoteClient.SendAlertMessage("Script saved");
339  
340 part.SendPropertiesToClient(remoteClient);
341  
342 // Trigger rerunning of script (use TriggerRezScript event, see RezScript)
343 ArrayList errors = new ArrayList();
344  
345 if (isScriptRunning)
346 {
347 // Needs to determine which engine was running it and use that
348 //
349 part.Inventory.CreateScriptInstance(item.ItemID, 0, false, DefaultScriptEngine, 0);
350 errors = part.Inventory.GetScriptErrors(item.ItemID);
351 }
352 else
353 {
354 remoteClient.SendAlertMessage("Script saved");
355 }
356  
357 // Tell anyone managing scripts that a script has been reloaded/changed
358 EventManager.TriggerUpdateScript(remoteClient.AgentId, itemId, primId, isScriptRunning, item.AssetID);
359  
360 part.ParentGroup.ResumeScripts();
361 return errors;
362 }
363  
364 /// <summary>
365 /// <see>CapsUpdateTaskInventoryScriptAsset(IClientAPI, UUID, UUID, bool, byte[])</see>
366 /// </summary>
367 public ArrayList CapsUpdateTaskInventoryScriptAsset(UUID avatarId, UUID itemId,
368 UUID primId, bool isScriptRunning, byte[] data)
369 {
370 ScenePresence avatar;
371  
372 if (TryGetScenePresence(avatarId, out avatar))
373 {
374 return CapsUpdateTaskInventoryScriptAsset(
375 avatar.ControllingClient, itemId, primId, isScriptRunning, data);
376 }
377 else
378 {
379 m_log.ErrorFormat(
380 "[PRIM INVENTORY]: " +
381 "Avatar {0} cannot be found to update its prim item asset",
382 avatarId);
383 return new ArrayList();
384 }
385 }
386  
387 /// <summary>
388 /// Update an item which is either already in the client's inventory or is within
389 /// a transaction
390 /// </summary>
391 /// <param name="remoteClient"></param>
392 /// <param name="transactionID">The transaction ID. If this is UUID.Zero we will
393 /// assume that we are not in a transaction</param>
394 /// <param name="itemID">The ID of the updated item</param>
395 /// <param name="name">The name of the updated item</param>
396 /// <param name="description">The description of the updated item</param>
397 /// <param name="nextOwnerMask">The permissions of the updated item</param>
398 /* public void UpdateInventoryItemAsset(IClientAPI remoteClient, UUID transactionID,
399 UUID itemID, string name, string description,
400 uint nextOwnerMask)*/
401 public void UpdateInventoryItemAsset(IClientAPI remoteClient, UUID transactionID,
402 UUID itemID, InventoryItemBase itemUpd)
403 {
404 // m_log.DebugFormat(
405 // "[USER INVENTORY]: Updating asset for item {0} {1}, transaction ID {2} for {3}",
406 // itemID, itemUpd.Name, transactionID, remoteClient.Name);
407  
408 // This one will let people set next perms on items in agent
409 // inventory. Rut-Roh. Whatever. Make this secure. Yeah.
410 //
411 // Passing something to another avatar or a an object will already
412 InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId);
413 item = InventoryService.GetItem(item);
414  
415 if (item != null)
416 {
417 if (item.Owner != remoteClient.AgentId)
418 return;
419  
420 item.Name = itemUpd.Name;
421 item.Description = itemUpd.Description;
422  
423 // m_log.DebugFormat(
424 // "[USER INVENTORY]: itemUpd {0} {1} {2} {3}, item {4} {5} {6} {7}",
425 // itemUpd.NextPermissions, itemUpd.GroupPermissions, itemUpd.EveryOnePermissions, item.Flags,
426 // item.NextPermissions, item.GroupPermissions, item.EveryOnePermissions, item.CurrentPermissions);
427  
428 bool sendUpdate = false;
429  
430 if (itemUpd.NextPermissions != 0) // Use this to determine validity. Can never be 0 if valid
431 {
432 // Create a set of base permissions that will not include export if the user
433 // is not allowed to change the export flag.
434 bool denyExportChange = false;
435  
436 // m_log.DebugFormat("[XXX]: B: {0} O: {1} E: {2}", itemUpd.BasePermissions, itemUpd.CurrentPermissions, itemUpd.EveryOnePermissions);
437  
438 // If the user is not the creator or doesn't have "E" in both "B" and "O", deny setting export
439 if ((item.BasePermissions & (uint)(PermissionMask.All | PermissionMask.Export)) != (uint)(PermissionMask.All | PermissionMask.Export) || (item.CurrentPermissions & (uint)PermissionMask.Export) == 0 || item.CreatorIdAsUuid != item.Owner)
440 denyExportChange = true;
441  
442 // m_log.DebugFormat("[XXX]: Deny Export Update {0}", denyExportChange);
443  
444 // If it is already set, force it set and also force full perm
445 // else prevent setting it. It can and should never be set unless
446 // set in base, so the condition above is valid
447 if (denyExportChange)
448 {
449 // If we are not allowed to change it, then force it to the
450 // original item's setting and if it was on, also force full perm
451 if ((item.EveryOnePermissions & (uint)PermissionMask.Export) != 0)
452 {
453 itemUpd.NextPermissions = (uint)(PermissionMask.All);
454 itemUpd.EveryOnePermissions |= (uint)PermissionMask.Export;
455 }
456 else
457 {
458 itemUpd.EveryOnePermissions &= ~(uint)PermissionMask.Export;
459 }
460 }
461 else
462 {
463 // If the new state is exportable, force full perm
464 if ((itemUpd.EveryOnePermissions & (uint)PermissionMask.Export) != 0)
465 {
466 // m_log.DebugFormat("[XXX]: Force full perm");
467 itemUpd.NextPermissions = (uint)(PermissionMask.All);
468 }
469 }
470  
471 if (item.NextPermissions != (itemUpd.NextPermissions & item.BasePermissions))
472 item.Flags |= (uint)InventoryItemFlags.ObjectOverwriteNextOwner;
473 item.NextPermissions = itemUpd.NextPermissions & item.BasePermissions;
474  
475 if (item.EveryOnePermissions != (itemUpd.EveryOnePermissions & item.BasePermissions))
476 item.Flags |= (uint)InventoryItemFlags.ObjectOverwriteEveryone;
477 item.EveryOnePermissions = itemUpd.EveryOnePermissions & item.BasePermissions;
478  
479 if (item.GroupPermissions != (itemUpd.GroupPermissions & item.BasePermissions))
480 item.Flags |= (uint)InventoryItemFlags.ObjectOverwriteGroup;
481 item.GroupPermissions = itemUpd.GroupPermissions & item.BasePermissions;
482  
483 item.GroupID = itemUpd.GroupID;
484 item.GroupOwned = itemUpd.GroupOwned;
485 item.CreationDate = itemUpd.CreationDate;
486 // The client sends zero if its newly created?
487  
488 if (itemUpd.CreationDate == 0)
489 item.CreationDate = Util.UnixTimeSinceEpoch();
490 else
491 item.CreationDate = itemUpd.CreationDate;
492  
493 // TODO: Check if folder changed and move item
494 //item.NextPermissions = itemUpd.Folder;
495 item.InvType = itemUpd.InvType;
496  
497 if (item.SalePrice != itemUpd.SalePrice ||
498 item.SaleType != itemUpd.SaleType)
499 item.Flags |= (uint)InventoryItemFlags.ObjectSlamSale;
500 item.SalePrice = itemUpd.SalePrice;
501 item.SaleType = itemUpd.SaleType;
502  
503 if (item.InvType == (int)InventoryType.Wearable && (item.Flags & 0xf) == 0 && (itemUpd.Flags & 0xf) != 0)
504 {
505 item.Flags = (uint)(item.Flags & 0xfffffff0) | (itemUpd.Flags & 0xf);
506 sendUpdate = true;
507 }
508  
509 InventoryService.UpdateItem(item);
510 }
511  
512 if (UUID.Zero != transactionID)
513 {
514 if (AgentTransactionsModule != null)
515 {
516 AgentTransactionsModule.HandleItemUpdateFromTransaction(remoteClient, transactionID, item);
517 }
518 }
519 else
520 {
521 // This MAY be problematic, if it is, another solution
522 // needs to be found. If inventory item flags are updated
523 // the viewer's notion of the item needs to be refreshed.
524 //
525 // In other situations we cannot send out a bulk update here, since this will cause editing of clothing to start
526 // failing frequently. Possibly this is a race with a separate transaction that uploads the asset.
527 if (sendUpdate)
528 remoteClient.SendBulkUpdateInventory(item);
529 }
530 }
531 else
532 {
533 m_log.ErrorFormat(
534 "[AGENTINVENTORY]: Item id {0} not found for an inventory item update for {1}.",
535 itemID, remoteClient.Name);
536 }
537 }
538  
539 /// <summary>
540 /// Give an inventory item from one user to another
541 /// </summary>
542 /// <param name="recipientClient"></param>
543 /// <param name="senderId">ID of the sender of the item</param>
544 /// <param name="itemId"></param>
545 public virtual void GiveInventoryItem(IClientAPI recipientClient, UUID senderId, UUID itemId, out string message)
546 {
547 InventoryItemBase itemCopy = GiveInventoryItem(recipientClient.AgentId, senderId, itemId, out message);
548  
549 if (itemCopy != null)
550 recipientClient.SendBulkUpdateInventory(itemCopy);
551 }
552  
553 /// <summary>
554 /// Give an inventory item from one user to another
555 /// </summary>
556 /// <param name="recipient"></param>
557 /// <param name="senderId">ID of the sender of the item</param>
558 /// <param name="itemId"></param>
559 /// <returns>The inventory item copy given, null if the give was unsuccessful</returns>
560 public virtual InventoryItemBase GiveInventoryItem(UUID recipient, UUID senderId, UUID itemId, out string message)
561 {
562 return GiveInventoryItem(recipient, senderId, itemId, UUID.Zero, out message);
563 }
564  
565 /// <summary>
566 /// Give an inventory item from one user to another
567 /// </summary>
568 /// <param name="recipient"></param>
569 /// <param name="senderId">ID of the sender of the item</param>
570 /// <param name="itemId"></param>
571 /// <param name="recipientFolderId">
572 /// The id of the folder in which the copy item should go. If UUID.Zero then the item is placed in the most
573 /// appropriate default folder.
574 /// </param>
575 /// <returns>
576 /// The inventory item copy given, null if the give was unsuccessful
577 /// </returns>
578 public virtual InventoryItemBase GiveInventoryItem(
579 UUID recipient, UUID senderId, UUID itemId, UUID recipientFolderId, out string message)
580 {
581 //Console.WriteLine("Scene.Inventory.cs: GiveInventoryItem");
582  
583 if (!Permissions.CanTransferUserInventory(itemId, senderId, recipient))
584 {
585 message = "Not allowed to transfer this item.";
586 return null;
587 }
588  
589 InventoryItemBase item = new InventoryItemBase(itemId, senderId);
590 item = InventoryService.GetItem(item);
591  
592 if (item == null)
593 {
594 m_log.WarnFormat(
595 "[AGENT INVENTORY]: Failed to find item {0} sent by {1} to {2}", itemId, senderId, recipient);
596 message = string.Format("Item not found: {0}.", itemId);
597 return null;
598 }
599  
600 if (item.Owner != senderId)
601 {
602 m_log.WarnFormat(
603 "[AGENT INVENTORY]: Attempt to send item {0} {1} to {2} failed because sender {3} did not match item owner {4}",
604 item.Name, item.ID, recipient, senderId, item.Owner);
605 message = "Sender did not match item owner.";
606 return null;
607 }
608  
609 IUserManagement uman = RequestModuleInterface<IUserManagement>();
610 if (uman != null)
611 uman.AddUser(item.CreatorIdAsUuid, item.CreatorData);
612  
613 if (!Permissions.BypassPermissions())
614 {
615 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
616 {
617 message = "Item doesn't have the Transfer permission.";
618 return null;
619 }
620 }
621  
622 // Insert a copy of the item into the recipient
623 InventoryItemBase itemCopy = new InventoryItemBase();
624 itemCopy.Owner = recipient;
625 itemCopy.CreatorId = item.CreatorId;
626 itemCopy.CreatorData = item.CreatorData;
627 itemCopy.ID = UUID.Random();
628 itemCopy.AssetID = item.AssetID;
629 itemCopy.Description = item.Description;
630 itemCopy.Name = item.Name;
631 itemCopy.AssetType = item.AssetType;
632 itemCopy.InvType = item.InvType;
633 itemCopy.Folder = recipientFolderId;
634  
635 if (Permissions.PropagatePermissions() && recipient != senderId)
636 {
637 // Trying to do this right this time. This is evil. If
638 // you believe in Good, go elsewhere. Vampires and other
639 // evil creatores only beyond this point. You have been
640 // warned.
641  
642 // We're going to mask a lot of things by the next perms
643 // Tweak the next perms to be nicer to our data
644 //
645 // In this mask, all the bits we do NOT want to mess
646 // with are set. These are:
647 //
648 // Transfer
649 // Copy
650 // Modufy
651 uint permsMask = ~ ((uint)PermissionMask.Copy |
652 (uint)PermissionMask.Transfer |
653 (uint)PermissionMask.Modify);
654  
655 // Now, reduce the next perms to the mask bits
656 // relevant to the operation
657 uint nextPerms = permsMask | (item.NextPermissions &
658 ((uint)PermissionMask.Copy |
659 (uint)PermissionMask.Transfer |
660 (uint)PermissionMask.Modify));
661  
662 // nextPerms now has all bits set, except for the actual
663 // next permission bits.
664  
665 // This checks for no mod, no copy, no trans.
666 // This indicates an error or messed up item. Do it like
667 // SL and assume trans
668 if (nextPerms == permsMask)
669 nextPerms |= (uint)PermissionMask.Transfer;
670  
671 // Inventory owner perms are the logical AND of the
672 // folded perms and the root prim perms, however, if
673 // the root prim is mod, the inventory perms will be
674 // mod. This happens on "take" and is of little concern
675 // here, save for preventing escalation
676  
677 // This hack ensures that items previously permalocked
678 // get unlocked when they're passed or rezzed
679 uint basePerms = item.BasePermissions |
680 (uint)PermissionMask.Move;
681 uint ownerPerms = item.CurrentPermissions;
682  
683 // If this is an object, root prim perms may be more
684 // permissive than folded perms. Use folded perms as
685 // a mask
686 if (item.InvType == (int)InventoryType.Object)
687 {
688 bool isRootMod = (item.CurrentPermissions &
689 (uint)PermissionMask.Modify) != 0 ?
690 true : false;
691  
692 // Mask the owner perms to the folded perms
693 PermissionsUtil.ApplyFoldedPermissions(item.CurrentPermissions, ref ownerPerms);
694 PermissionsUtil.ApplyFoldedPermissions(item.CurrentPermissions, ref basePerms);
695  
696 // If the root was mod, let the mask reflect that
697 // We also need to adjust the base here, because
698 // we should be able to edit in-inventory perms
699 // for the root prim, if it's mod.
700 if (isRootMod)
701 {
702 ownerPerms |= (uint)PermissionMask.Modify;
703 basePerms |= (uint)PermissionMask.Modify;
704 }
705 }
706  
707 // These will be applied to the root prim at next rez.
708 // The slam bit (bit 3) and folded permission (bits 0-2)
709 // are preserved due to the above mangling
710 ownerPerms &= nextPerms;
711  
712 // Mask the base permissions. This is a conservative
713 // approach altering only the three main perms
714 basePerms &= nextPerms;
715  
716 // Assign to the actual item. Make sure the slam bit is
717 // set, if it wasn't set before.
718 itemCopy.BasePermissions = basePerms;
719 itemCopy.CurrentPermissions = ownerPerms;
720 itemCopy.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm;
721  
722 itemCopy.NextPermissions = item.NextPermissions;
723  
724 // This preserves "everyone can move"
725 itemCopy.EveryOnePermissions = item.EveryOnePermissions &
726 nextPerms;
727  
728 // Intentionally killing "share with group" here, as
729 // the recipient will not have the group this is
730 // set to
731 itemCopy.GroupPermissions = 0;
732 }
733 else
734 {
735 itemCopy.CurrentPermissions = item.CurrentPermissions;
736 itemCopy.NextPermissions = item.NextPermissions;
737 itemCopy.EveryOnePermissions = item.EveryOnePermissions & item.NextPermissions;
738 itemCopy.GroupPermissions = item.GroupPermissions & item.NextPermissions;
739 itemCopy.BasePermissions = item.BasePermissions;
740 }
741  
742 if (itemCopy.Folder == UUID.Zero)
743 {
744 InventoryFolderBase folder = InventoryService.GetFolderForType(recipient, (AssetType)itemCopy.AssetType);
745  
746 if (folder != null)
747 {
748 itemCopy.Folder = folder.ID;
749 }
750 else
751 {
752 InventoryFolderBase root = InventoryService.GetRootFolder(recipient);
753  
754 if (root != null)
755 {
756 itemCopy.Folder = root.ID;
757 }
758 else
759 {
760 message = "Can't find a folder to add the item to.";
761 return null;
762 }
763 }
764 }
765  
766 itemCopy.GroupID = UUID.Zero;
767 itemCopy.GroupOwned = false;
768 itemCopy.Flags = item.Flags;
769 itemCopy.SalePrice = item.SalePrice;
770 itemCopy.SaleType = item.SaleType;
771  
772 IInventoryAccessModule invAccess = RequestModuleInterface<IInventoryAccessModule>();
773 if (invAccess != null)
774 invAccess.TransferInventoryAssets(itemCopy, senderId, recipient);
775 AddInventoryItem(itemCopy, false);
776  
777 if (!Permissions.BypassPermissions())
778 {
779 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
780 {
781 List<UUID> items = new List<UUID>();
782 items.Add(itemId);
783 InventoryService.DeleteItems(senderId, items);
784 }
785 }
786  
787 message = null;
788 return itemCopy;
789 }
790  
791 /// <summary>
792 /// Give an entire inventory folder from one user to another. The entire contents (including all descendent
793 /// folders) is given.
794 /// </summary>
795 /// <param name="recipientId"></param>
796 /// <param name="senderId">ID of the sender of the item</param>
797 /// <param name="folderId"></param>
798 /// <param name="recipientParentFolderId">
799 /// The id of the receipient folder in which the send folder should be placed. If UUID.Zero then the
800 /// recipient folder is the root folder
801 /// </param>
802 /// <returns>
803 /// The inventory folder copy given, null if the copy was unsuccessful
804 /// </returns>
805 public virtual InventoryFolderBase GiveInventoryFolder(IClientAPI client,
806 UUID recipientId, UUID senderId, UUID folderId, UUID recipientParentFolderId)
807 {
808 //// Retrieve the folder from the sender
809 InventoryFolderBase folder = InventoryService.GetFolder(new InventoryFolderBase(folderId));
810 if (null == folder)
811 {
812 m_log.ErrorFormat(
813 "[AGENT INVENTORY]: Could not find inventory folder {0} to give", folderId);
814  
815 return null;
816 }
817  
818 if (recipientParentFolderId == UUID.Zero)
819 {
820 InventoryFolderBase recipientRootFolder = InventoryService.GetRootFolder(recipientId);
821 if (recipientRootFolder != null)
822 recipientParentFolderId = recipientRootFolder.ID;
823 else
824 {
825 m_log.WarnFormat("[AGENT INVENTORY]: Unable to find root folder for receiving agent");
826 return null;
827 }
828 }
829  
830 UUID newFolderId = UUID.Random();
831 InventoryFolderBase newFolder
832 = new InventoryFolderBase(
833 newFolderId, folder.Name, recipientId, folder.Type, recipientParentFolderId, folder.Version);
834 InventoryService.AddFolder(newFolder);
835  
836 // Give all the subfolders
837 InventoryCollection contents = InventoryService.GetFolderContent(senderId, folderId);
838 foreach (InventoryFolderBase childFolder in contents.Folders)
839 {
840 GiveInventoryFolder(client, recipientId, senderId, childFolder.ID, newFolder.ID);
841 }
842  
843 // Give all the items
844 foreach (InventoryItemBase item in contents.Items)
845 {
846 string message;
847 if (GiveInventoryItem(recipientId, senderId, item.ID, newFolder.ID, out message) == null)
848 {
849 if (client != null)
850 client.SendAgentAlertMessage(message, false);
851 }
852 }
853  
854 return newFolder;
855 }
856  
857 public void CopyInventoryItem(IClientAPI remoteClient, uint callbackID, UUID oldAgentID, UUID oldItemID,
858 UUID newFolderID, string newName)
859 {
860 m_log.DebugFormat(
861 "[AGENT INVENTORY]: CopyInventoryItem received by {0} with oldAgentID {1}, oldItemID {2}, new FolderID {3}, newName {4}",
862 remoteClient.AgentId, oldAgentID, oldItemID, newFolderID, newName);
863  
864 InventoryItemBase item = null;
865 if (LibraryService != null && LibraryService.LibraryRootFolder != null)
866 item = LibraryService.LibraryRootFolder.FindItem(oldItemID);
867  
868 if (item == null)
869 {
870 item = new InventoryItemBase(oldItemID, remoteClient.AgentId);
871 item = InventoryService.GetItem(item);
872  
873 if (item == null)
874 {
875 m_log.Error("[AGENT INVENTORY]: Failed to find item " + oldItemID.ToString());
876 return;
877 }
878  
879 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
880 return;
881 }
882  
883 if (newName == String.Empty)
884 newName = item.Name;
885  
886 if (remoteClient.AgentId == oldAgentID
887 || (LibraryService != null
888 && LibraryService.LibraryRootFolder != null
889 && oldAgentID == LibraryService.LibraryRootFolder.Owner))
890 {
891 CreateNewInventoryItem(
892 remoteClient, item.CreatorId, item.CreatorData, newFolderID,
893 newName, item.Description, item.Flags, callbackID, item.AssetID, (sbyte)item.AssetType, (sbyte)item.InvType,
894 item.BasePermissions, item.CurrentPermissions, item.EveryOnePermissions,
895 item.NextPermissions, item.GroupPermissions, Util.UnixTimeSinceEpoch(), false);
896 }
897 else
898 {
899 // If item is transfer or permissions are off or calling agent is allowed to copy item owner's inventory item.
900 if (((item.CurrentPermissions & (uint)PermissionMask.Transfer) != 0)
901 && (m_permissions.BypassPermissions()
902 || m_permissions.CanCopyUserInventory(remoteClient.AgentId, oldItemID)))
903 {
904 CreateNewInventoryItem(
905 remoteClient, item.CreatorId, item.CreatorData, newFolderID, newName, item.Description, item.Flags, callbackID,
906 item.AssetID, (sbyte)item.AssetType, (sbyte) item.InvType,
907 item.NextPermissions, item.NextPermissions, item.EveryOnePermissions & item.NextPermissions,
908 item.NextPermissions, item.GroupPermissions, Util.UnixTimeSinceEpoch(), false);
909 }
910 }
911 }
912  
913 /// <summary>
914 /// Create a new asset data structure.
915 /// </summary>
916 public AssetBase CreateAsset(string name, string description, sbyte assetType, byte[] data, UUID creatorID)
917 {
918 AssetBase asset = new AssetBase(UUID.Random(), name, assetType, creatorID.ToString());
919 asset.Description = description;
920 asset.Data = (data == null) ? new byte[1] : data;
921  
922 return asset;
923 }
924  
925 /// <summary>
926 /// Move an item within the agent's inventory.
927 /// </summary>
928 /// <param name="remoteClient"></param>
929 /// <param name="folderID"></param>
930 /// <param name="itemID"></param>
931 /// <param name="length"></param>
932 /// <param name="newName"></param>
933 public void MoveInventoryItem(IClientAPI remoteClient, List<InventoryItemBase> items)
934 {
935 m_log.DebugFormat(
936 "[AGENT INVENTORY]: Moving {0} items for user {1}", items.Count, remoteClient.AgentId);
937  
938 if (!InventoryService.MoveItems(remoteClient.AgentId, items))
939 m_log.Warn("[AGENT INVENTORY]: Failed to move items for user " + remoteClient.AgentId);
940 }
941  
942 /// <summary>
943 /// Create a new inventory item.
944 /// </summary>
945 /// <param name="remoteClient">Client creating this inventory item.</param>
946 /// <param name="creatorID"></param>
947 /// <param name="creatorData"></param>
948 /// <param name="folderID">UUID of folder in which this item should be placed.</param>
949 /// <param name="name">Item name.</para>
950 /// <param name="description">Item description.</param>
951 /// <param name="flags">Item flags</param>
952 /// <param name="callbackID">Generated by the client.</para>
953 /// <param name="asset">Asset to which this item refers.</param>
954 /// <param name="invType">Type of inventory item.</param>
955 /// <param name="nextOwnerMask">Next owner pemrissions mask.</param>
956 /// <param name="creationDate">Unix timestamp at which this item was created.</param>
957 public void CreateNewInventoryItem(
958 IClientAPI remoteClient, string creatorID, string creatorData, UUID folderID,
959 string name, string description, uint flags, uint callbackID,
960 UUID assetID, sbyte assetType, sbyte invType, uint nextOwnerMask, int creationDate)
961 {
962 CreateNewInventoryItem(
963 remoteClient, creatorID, creatorData, folderID, name, description, flags, callbackID, assetID, assetType, invType,
964 (uint)PermissionMask.All | (uint)PermissionMask.Export, (uint)PermissionMask.All | (uint)PermissionMask.Export, 0, nextOwnerMask, 0,
965 creationDate, true);
966 }
967  
968 /// <summary>
969 /// Create a new Inventory Item
970 /// </summary>
971 /// <param name="remoteClient">Client creating this inventory item.</param>
972 /// <param name="creatorID"></param>
973 /// <param name="creatorData"></param>
974 /// <param name="folderID">UUID of folder in which this item should be placed.</param>
975 /// <param name="name">Item name.</para>
976 /// <param name="description">Item description.</param>
977 /// <param name="flags">Item flags</param>
978 /// <param name="callbackID">Generated by the client.</para>
979 /// <param name="asset">Asset to which this item refers.</param>
980 /// <param name="invType">Type of inventory item.</param>
981 /// <param name="baseMask">Base permissions mask.</param>
982 /// <param name="currentMask">Current permissions mask.</param>
983 /// <param name="everyoneMask">Everyone permissions mask.</param>
984 /// <param name="nextOwnerMask">Next owner pemrissions mask.</param>
985 /// <param name="groupMask">Group permissions mask.</param>
986 /// <param name="creationDate">Unix timestamp at which this item was created.</param>
987 private void CreateNewInventoryItem(
988 IClientAPI remoteClient, string creatorID, string creatorData, UUID folderID,
989 string name, string description, uint flags, uint callbackID, UUID assetID, sbyte assetType, sbyte invType,
990 uint baseMask, uint currentMask, uint everyoneMask, uint nextOwnerMask, uint groupMask, int creationDate,
991 bool assetUpload)
992 {
993 InventoryItemBase item = new InventoryItemBase();
994 item.Owner = remoteClient.AgentId;
995 item.CreatorId = creatorID;
996 item.CreatorData = creatorData;
997 item.ID = UUID.Random();
998 item.AssetID = assetID;
999 item.Name = name;
1000 item.Description = description;
1001 item.Flags = flags;
1002 item.AssetType = assetType;
1003 item.InvType = invType;
1004 item.Folder = folderID;
1005 item.CurrentPermissions = currentMask;
1006 item.NextPermissions = nextOwnerMask;
1007 item.EveryOnePermissions = everyoneMask;
1008 item.GroupPermissions = groupMask;
1009 item.BasePermissions = baseMask;
1010 item.CreationDate = creationDate;
1011  
1012 if (AddInventoryItem(item, assetUpload))
1013 {
1014 remoteClient.SendInventoryItemCreateUpdate(item, callbackID);
1015 }
1016 else
1017 {
1018 m_dialogModule.SendAlertToUser(remoteClient, "Failed to create item");
1019 m_log.WarnFormat(
1020 "Failed to add item for {0} in CreateNewInventoryItem!",
1021 remoteClient.Name);
1022 }
1023 }
1024  
1025 /// <summary>
1026 /// Link an inventory item to an existing item.
1027 /// </summary>
1028 /// <remarks>
1029 /// The linkee item id is placed in the asset id slot. This appears to be what the viewer expects when
1030 /// it receives inventory information.
1031 /// </remarks>
1032 /// <param name="remoteClient"></param>
1033 /// <param name="transActionID"></param>
1034 /// <param name="folderID"></param>
1035 /// <param name="callbackID"></param>
1036 /// <param name="description"></param>
1037 /// <param name="name"></param>
1038 /// <param name="invType"></param>
1039 /// <param name="type">/param>
1040 /// <param name="olditemID"></param>
1041 private void HandleLinkInventoryItem(IClientAPI remoteClient, UUID transActionID, UUID folderID,
1042 uint callbackID, string description, string name,
1043 sbyte invType, sbyte type, UUID olditemID)
1044 {
1045 // m_log.DebugFormat(
1046 // "[AGENT INVENTORY]: Received request from {0} to create inventory item link {1} in folder {2} pointing to {3}, assetType {4}, inventoryType {5}",
1047 // remoteClient.Name, name, folderID, olditemID, (AssetType)type, (InventoryType)invType);
1048  
1049 if (!Permissions.CanCreateUserInventory(invType, remoteClient.AgentId))
1050 return;
1051  
1052 ScenePresence presence;
1053 if (TryGetScenePresence(remoteClient.AgentId, out presence))
1054 {
1055 // Disabled the check for duplicate links.
1056 //
1057 // When outfits are being adjusted, the viewer rapidly sends delete link messages followed by
1058 // create links. However, since these are handled asynchronously, the deletes do not complete before
1059 // the creates are handled. Therefore, we cannot enforce a duplicate link check.
1060 // InventoryItemBase existingLink = null;
1061 // List<InventoryItemBase> existingItems = InventoryService.GetFolderItems(remoteClient.AgentId, folderID);
1062 // foreach (InventoryItemBase item in existingItems)
1063 // if (item.AssetID == olditemID)
1064 // existingLink = item;
1065 //
1066 // if (existingLink != null)
1067 // {
1068 // m_log.WarnFormat(
1069 // "[AGENT INVENTORY]: Ignoring request from {0} to create item link {1} in folder {2} pointing to {3} since a link named {4} with id {5} already exists",
1070 // remoteClient.Name, name, folderID, olditemID, existingLink.Name, existingLink.ID);
1071 //
1072 // return;
1073 // }
1074  
1075 CreateNewInventoryItem(
1076 remoteClient, remoteClient.AgentId.ToString(), string.Empty, folderID,
1077 name, description, 0, callbackID, olditemID, type, invType,
1078 (uint)PermissionMask.All | (uint)PermissionMask.Export, (uint)PermissionMask.All | (uint)PermissionMask.Export, (uint)PermissionMask.All,
1079 (uint)PermissionMask.All | (uint)PermissionMask.Export, (uint)PermissionMask.All | (uint)PermissionMask.Export, Util.UnixTimeSinceEpoch(),
1080 false);
1081 }
1082 else
1083 {
1084 m_log.ErrorFormat(
1085 "ScenePresence for agent uuid {0} unexpectedly not found in HandleLinkInventoryItem",
1086 remoteClient.AgentId);
1087 }
1088 }
1089  
1090 /// <summary>
1091 /// Remove an inventory item for the client's inventory
1092 /// </summary>
1093 /// <param name="remoteClient"></param>
1094 /// <param name="itemID"></param>
1095 private void RemoveInventoryItem(IClientAPI remoteClient, List<UUID> itemIDs)
1096 {
1097 // m_log.DebugFormat(
1098 // "[AGENT INVENTORY]: Removing inventory items {0} for {1}",
1099 // string.Join(",", itemIDs.ConvertAll<string>(uuid => uuid.ToString()).ToArray()),
1100 // remoteClient.Name);
1101  
1102 InventoryService.DeleteItems(remoteClient.AgentId, itemIDs);
1103 }
1104  
1105 /// <summary>
1106 /// Removes an inventory folder. This packet is sent when the user
1107 /// right-clicks a folder that's already in trash and chooses "purge"
1108 /// </summary>
1109 /// <param name="remoteClient"></param>
1110 /// <param name="folderID"></param>
1111 private void RemoveInventoryFolder(IClientAPI remoteClient, List<UUID> folderIDs)
1112 {
1113 m_log.DebugFormat("[SCENE INVENTORY]: RemoveInventoryFolders count {0}", folderIDs.Count);
1114 InventoryService.DeleteFolders(remoteClient.AgentId, folderIDs);
1115 }
1116  
1117 /// <summary>
1118 /// Send the details of a prim's inventory to the client.
1119 /// </summary>
1120 /// <param name="remoteClient"></param>
1121 /// <param name="primLocalID"></param>
1122 public void RequestTaskInventory(IClientAPI remoteClient, uint primLocalID)
1123 {
1124 SceneObjectPart part = GetSceneObjectPart(primLocalID);
1125 if (part == null)
1126 return;
1127  
1128 if (XferManager != null)
1129 part.Inventory.RequestInventoryFile(remoteClient, XferManager);
1130 }
1131  
1132 /// <summary>
1133 /// Remove an item from a prim (task) inventory
1134 /// </summary>
1135 /// <param name="remoteClient">Unused at the moment but retained since the avatar ID might
1136 /// be necessary for a permissions check at some stage.</param>
1137 /// <param name="itemID"></param>
1138 /// <param name="localID"></param>
1139 public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID)
1140 {
1141 SceneObjectPart part = GetSceneObjectPart(localID);
1142 SceneObjectGroup group = null;
1143 if (part != null)
1144 {
1145 group = part.ParentGroup;
1146 }
1147 if (part != null && group != null)
1148 {
1149 if (!Permissions.CanEditObjectInventory(part.UUID, remoteClient.AgentId))
1150 return;
1151  
1152 TaskInventoryItem item = group.GetInventoryItem(localID, itemID);
1153 if (item == null)
1154 return;
1155  
1156 InventoryFolderBase destFolder = InventoryService.GetFolderForType(remoteClient.AgentId, AssetType.TrashFolder);
1157  
1158 // Move the item to trash. If this is a copyable item, only
1159 // a copy will be moved and we will still need to delete
1160 // the item from the prim. If it was no copy, it will be
1161 // deleted by this method.
1162 string message;
1163 InventoryItemBase item2 = MoveTaskInventoryItem(remoteClient, destFolder.ID, part, itemID, out message);
1164  
1165 if (item2 == null)
1166 {
1167 m_log.WarnFormat("[SCENE INVENTORY]: RemoveTaskInventory of item {0} failed: {1}", itemID, message);
1168 remoteClient.SendAgentAlertMessage(message, false);
1169 return;
1170 }
1171  
1172 if (group.GetInventoryItem(localID, itemID) != null)
1173 {
1174 if (item.Type == 10)
1175 {
1176 part.RemoveScriptEvents(itemID);
1177 EventManager.TriggerRemoveScript(localID, itemID);
1178 }
1179  
1180 group.RemoveInventoryItem(localID, itemID);
1181 }
1182  
1183 part.SendPropertiesToClient(remoteClient);
1184 }
1185 }
1186  
1187  
1188 /// <summary>
1189 /// Creates (in memory only) a user inventory item that will contain a copy of a task inventory item.
1190 /// </summary>
1191 private InventoryItemBase CreateAgentInventoryItemFromTask(UUID destAgent, SceneObjectPart part, UUID itemId, out string message)
1192 {
1193 TaskInventoryItem taskItem = part.Inventory.GetInventoryItem(itemId);
1194  
1195 if (null == taskItem)
1196 {
1197 m_log.ErrorFormat(
1198 "[PRIM INVENTORY]: Tried to retrieve item ID {0} from prim {1}, {2} for creating an avatar"
1199 + " inventory item from a prim's inventory item "
1200 + " but the required item does not exist in the prim's inventory",
1201 itemId, part.Name, part.UUID);
1202 message = "Item not found: " + itemId;
1203 return null;
1204 }
1205  
1206 if ((destAgent != taskItem.OwnerID) && ((taskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0))
1207 {
1208 message = "Item doesn't have the Transfer permission.";
1209 return null;
1210 }
1211  
1212 InventoryItemBase agentItem = new InventoryItemBase();
1213  
1214 agentItem.ID = UUID.Random();
1215 agentItem.CreatorId = taskItem.CreatorID.ToString();
1216 agentItem.CreatorData = taskItem.CreatorData;
1217 agentItem.Owner = destAgent;
1218 agentItem.AssetID = taskItem.AssetID;
1219 agentItem.Description = taskItem.Description;
1220 agentItem.Name = taskItem.Name;
1221 agentItem.AssetType = taskItem.Type;
1222 agentItem.InvType = taskItem.InvType;
1223 agentItem.Flags = taskItem.Flags;
1224  
1225 if ((part.OwnerID != destAgent) && Permissions.PropagatePermissions())
1226 {
1227 agentItem.BasePermissions = taskItem.BasePermissions & (taskItem.NextPermissions | (uint)PermissionMask.Move);
1228 if (taskItem.InvType == (int)InventoryType.Object)
1229 {
1230 uint perms = taskItem.CurrentPermissions;
1231 PermissionsUtil.ApplyFoldedPermissions(taskItem.CurrentPermissions, ref perms);
1232 agentItem.BasePermissions = perms | (uint)PermissionMask.Move;
1233 agentItem.CurrentPermissions = agentItem.BasePermissions;
1234 }
1235 else
1236 {
1237 agentItem.CurrentPermissions = agentItem.BasePermissions & taskItem.CurrentPermissions;
1238 }
1239  
1240 agentItem.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm;
1241 agentItem.NextPermissions = taskItem.NextPermissions;
1242 agentItem.EveryOnePermissions = taskItem.EveryonePermissions & (taskItem.NextPermissions | (uint)PermissionMask.Move);
1243 agentItem.GroupPermissions = taskItem.GroupPermissions & taskItem.NextPermissions;
1244 }
1245 else
1246 {
1247 agentItem.BasePermissions = taskItem.BasePermissions;
1248 agentItem.CurrentPermissions = taskItem.CurrentPermissions;
1249 agentItem.NextPermissions = taskItem.NextPermissions;
1250 agentItem.EveryOnePermissions = taskItem.EveryonePermissions;
1251 agentItem.GroupPermissions = taskItem.GroupPermissions;
1252 }
1253  
1254 message = null;
1255 return agentItem;
1256 }
1257  
1258 /// <summary>
1259 /// If the task item is not-copyable then remove it from the prim.
1260 /// </summary>
1261 private void RemoveNonCopyTaskItemFromPrim(SceneObjectPart part, UUID itemId)
1262 {
1263 TaskInventoryItem taskItem = part.Inventory.GetInventoryItem(itemId);
1264 if (taskItem == null)
1265 return;
1266  
1267 if (!Permissions.BypassPermissions())
1268 {
1269 if ((taskItem.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1270 {
1271 if (taskItem.Type == (int)AssetType.LSLText)
1272 {
1273 part.RemoveScriptEvents(itemId);
1274 EventManager.TriggerRemoveScript(part.LocalId, itemId);
1275 }
1276  
1277 part.Inventory.RemoveInventoryItem(itemId);
1278 }
1279 }
1280 }
1281  
1282 /// <summary>
1283 /// Move the given item in the given prim to a folder in the client's inventory
1284 /// </summary>
1285 /// <param name="remoteClient"></param>
1286 /// <param name="folderID"></param>
1287 /// <param name="part"></param>
1288 /// <param name="itemID"></param>
1289 public InventoryItemBase MoveTaskInventoryItem(IClientAPI remoteClient, UUID folderId, SceneObjectPart part, UUID itemId, out string message)
1290 {
1291 m_log.DebugFormat(
1292 "[PRIM INVENTORY]: Adding item {0} from {1} to folder {2} for {3}",
1293 itemId, part.Name, folderId, remoteClient.Name);
1294  
1295 InventoryItemBase agentItem = CreateAgentInventoryItemFromTask(remoteClient.AgentId, part, itemId, out message);
1296 if (agentItem == null)
1297 return null;
1298  
1299 agentItem.Folder = folderId;
1300 AddInventoryItem(remoteClient, agentItem);
1301  
1302 RemoveNonCopyTaskItemFromPrim(part, itemId);
1303  
1304 message = null;
1305 return agentItem;
1306 }
1307  
1308 /// <summary>
1309 /// <see>ClientMoveTaskInventoryItem</see>
1310 /// </summary>
1311 /// <param name="remoteClient"></param>
1312 /// <param name="folderID"></param>
1313 /// <param name="primLocalID"></param>
1314 /// <param name="itemID"></param>
1315 public void ClientMoveTaskInventoryItem(IClientAPI remoteClient, UUID folderId, uint primLocalId, UUID itemId)
1316 {
1317 SceneObjectPart part = GetSceneObjectPart(primLocalId);
1318  
1319 if (null == part)
1320 {
1321 m_log.WarnFormat(
1322 "[PRIM INVENTORY]: " +
1323 "Move of inventory item {0} from prim with local id {1} failed because the prim could not be found",
1324 itemId, primLocalId);
1325  
1326 return;
1327 }
1328  
1329 TaskInventoryItem taskItem = part.Inventory.GetInventoryItem(itemId);
1330  
1331 if (null == taskItem)
1332 {
1333 m_log.WarnFormat("[PRIM INVENTORY]: Move of inventory item {0} from prim with local id {1} failed"
1334 + " because the inventory item could not be found",
1335 itemId, primLocalId);
1336  
1337 return;
1338 }
1339  
1340 if ((taskItem.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1341 {
1342 // If the item to be moved is no copy, we need to be able to
1343 // edit the prim.
1344 if (!Permissions.CanEditObjectInventory(part.UUID, remoteClient.AgentId))
1345 return;
1346 }
1347 else
1348 {
1349 // If the item is copiable, then we just need to have perms
1350 // on it. The delete check is a pure rights check
1351 if (!Permissions.CanDeleteObject(part.UUID, remoteClient.AgentId))
1352 return;
1353 }
1354  
1355 string message;
1356 InventoryItemBase item = MoveTaskInventoryItem(remoteClient, folderId, part, itemId, out message);
1357  
1358 if (item == null)
1359 remoteClient.SendAgentAlertMessage(message, false);
1360 }
1361  
1362 /// <summary>
1363 /// <see>MoveTaskInventoryItem</see>
1364 /// </summary>
1365 /// <param name="remoteClient"></param>
1366 /// <param name="folderID">
1367 /// The user inventory folder to move (or copy) the item to. If null, then the most
1368 /// suitable system folder is used (e.g. the Objects folder for objects). If there is no suitable folder, then
1369 /// the item is placed in the user's root inventory folder
1370 /// </param>
1371 /// <param name="part"></param>
1372 /// <param name="itemID"></param>
1373 public InventoryItemBase MoveTaskInventoryItem(UUID avatarId, UUID folderId, SceneObjectPart part, UUID itemId, out string message)
1374 {
1375 ScenePresence avatar;
1376  
1377 if (TryGetScenePresence(avatarId, out avatar))
1378 {
1379 return MoveTaskInventoryItem(avatar.ControllingClient, folderId, part, itemId, out message);
1380 }
1381 else
1382 {
1383 InventoryItemBase agentItem = CreateAgentInventoryItemFromTask(avatarId, part, itemId, out message);
1384  
1385 if (agentItem == null)
1386 return null;
1387  
1388 agentItem.Folder = folderId;
1389  
1390 AddInventoryItem(agentItem);
1391  
1392 RemoveNonCopyTaskItemFromPrim(part, itemId);
1393  
1394 return agentItem;
1395 }
1396 }
1397  
1398 /// <summary>
1399 /// Copy a task (prim) inventory item to another task (prim)
1400 /// </summary>
1401 /// <param name="destId">ID of destination part</param>
1402 /// <param name="part">Source part</param>
1403 /// <param name="itemId">Source item id to transfer</param>
1404 public void MoveTaskInventoryItem(UUID destId, SceneObjectPart part, UUID itemId)
1405 {
1406 TaskInventoryItem srcTaskItem = part.Inventory.GetInventoryItem(itemId);
1407  
1408 if (srcTaskItem == null)
1409 {
1410 m_log.ErrorFormat(
1411 "[PRIM INVENTORY]: Tried to retrieve item ID {0} from prim {1}, {2} for moving"
1412 + " but the item does not exist in this inventory",
1413 itemId, part.Name, part.UUID);
1414  
1415 return;
1416 }
1417  
1418 SceneObjectPart destPart = GetSceneObjectPart(destId);
1419  
1420 if (destPart == null)
1421 {
1422 m_log.ErrorFormat(
1423 "[PRIM INVENTORY]: " +
1424 "Could not find prim for ID {0}",
1425 destId);
1426 return;
1427 }
1428  
1429 if (part.OwnerID != destPart.OwnerID)
1430 {
1431 // Source must have transfer permissions
1432 if ((srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1433 return;
1434  
1435 // Object cannot copy items to an object owned by a different owner
1436 // unless llAllowInventoryDrop has been called on the destination
1437 if ((destPart.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0)
1438 return;
1439 }
1440  
1441 // must have both move and modify permission to put an item in an object
1442 if ((part.OwnerMask & ((uint)PermissionMask.Move | (uint)PermissionMask.Modify)) == 0)
1443 return;
1444  
1445 TaskInventoryItem destTaskItem = new TaskInventoryItem();
1446  
1447 destTaskItem.ItemID = UUID.Random();
1448 destTaskItem.CreatorID = srcTaskItem.CreatorID;
1449 destTaskItem.CreatorData = srcTaskItem.CreatorData;
1450 destTaskItem.AssetID = srcTaskItem.AssetID;
1451 destTaskItem.GroupID = destPart.GroupID;
1452 destTaskItem.OwnerID = destPart.OwnerID;
1453 destTaskItem.ParentID = destPart.UUID;
1454 destTaskItem.ParentPartID = destPart.UUID;
1455  
1456 destTaskItem.BasePermissions = srcTaskItem.BasePermissions;
1457 destTaskItem.EveryonePermissions = srcTaskItem.EveryonePermissions;
1458 destTaskItem.GroupPermissions = srcTaskItem.GroupPermissions;
1459 destTaskItem.CurrentPermissions = srcTaskItem.CurrentPermissions;
1460 destTaskItem.NextPermissions = srcTaskItem.NextPermissions;
1461 destTaskItem.Flags = srcTaskItem.Flags;
1462  
1463 if (destPart.OwnerID != part.OwnerID)
1464 {
1465 if (Permissions.PropagatePermissions())
1466 {
1467 destTaskItem.CurrentPermissions = srcTaskItem.CurrentPermissions &
1468 (srcTaskItem.NextPermissions | (uint)PermissionMask.Move);
1469 destTaskItem.GroupPermissions = srcTaskItem.GroupPermissions &
1470 (srcTaskItem.NextPermissions | (uint)PermissionMask.Move);
1471 destTaskItem.EveryonePermissions = srcTaskItem.EveryonePermissions &
1472 (srcTaskItem.NextPermissions | (uint)PermissionMask.Move);
1473 destTaskItem.BasePermissions = srcTaskItem.BasePermissions &
1474 (srcTaskItem.NextPermissions | (uint)PermissionMask.Move);
1475 destTaskItem.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm;
1476 }
1477 }
1478  
1479 destTaskItem.Description = srcTaskItem.Description;
1480 destTaskItem.Name = srcTaskItem.Name;
1481 destTaskItem.InvType = srcTaskItem.InvType;
1482 destTaskItem.Type = srcTaskItem.Type;
1483  
1484 destPart.Inventory.AddInventoryItem(destTaskItem, part.OwnerID != destPart.OwnerID);
1485  
1486 if ((srcTaskItem.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1487 part.Inventory.RemoveInventoryItem(itemId);
1488  
1489 ScenePresence avatar;
1490  
1491 if (TryGetScenePresence(srcTaskItem.OwnerID, out avatar))
1492 {
1493 destPart.SendPropertiesToClient(avatar.ControllingClient);
1494 }
1495 }
1496  
1497 public UUID MoveTaskInventoryItems(UUID destID, string category, SceneObjectPart host, List<UUID> items)
1498 {
1499 ScenePresence avatar;
1500 IClientAPI remoteClient = null;
1501 if (TryGetScenePresence(destID, out avatar))
1502 remoteClient = avatar.ControllingClient;
1503  
1504 InventoryFolderBase rootFolder = InventoryService.GetRootFolder(destID);
1505  
1506 UUID newFolderID = UUID.Random();
1507  
1508 InventoryFolderBase newFolder = new InventoryFolderBase(newFolderID, category, destID, -1, rootFolder.ID, rootFolder.Version);
1509 InventoryService.AddFolder(newFolder);
1510  
1511 foreach (UUID itemID in items)
1512 {
1513 string message;
1514 InventoryItemBase agentItem = CreateAgentInventoryItemFromTask(destID, host, itemID, out message);
1515  
1516 if (agentItem != null)
1517 {
1518 agentItem.Folder = newFolderID;
1519  
1520 AddInventoryItem(agentItem);
1521  
1522 RemoveNonCopyTaskItemFromPrim(host, itemID);
1523 }
1524 else
1525 {
1526 if (remoteClient != null)
1527 remoteClient.SendAgentAlertMessage(message, false);
1528 }
1529 }
1530  
1531 if (remoteClient != null)
1532 {
1533 SendInventoryUpdate(remoteClient, rootFolder, true, false);
1534 SendInventoryUpdate(remoteClient, newFolder, false, true);
1535 }
1536  
1537 return newFolderID;
1538 }
1539  
1540 public void SendInventoryUpdate(IClientAPI client, InventoryFolderBase folder, bool fetchFolders, bool fetchItems)
1541 {
1542 if (folder == null)
1543 return;
1544  
1545 // TODO: This code for looking in the folder for the library should be folded somewhere else
1546 // so that this class doesn't have to know the details (and so that multiple libraries, etc.
1547 // can be handled transparently).
1548 InventoryFolderImpl fold = null;
1549 if (LibraryService != null && LibraryService.LibraryRootFolder != null)
1550 {
1551 if ((fold = LibraryService.LibraryRootFolder.FindFolder(folder.ID)) != null)
1552 {
1553 client.SendInventoryFolderDetails(
1554 fold.Owner, folder.ID, fold.RequestListOfItems(),
1555 fold.RequestListOfFolders(), fold.Version, fetchFolders, fetchItems);
1556 return;
1557 }
1558 }
1559  
1560 // Fetch the folder contents
1561 InventoryCollection contents = InventoryService.GetFolderContent(client.AgentId, folder.ID);
1562  
1563 // Fetch the folder itself to get its current version
1564 InventoryFolderBase containingFolder = new InventoryFolderBase(folder.ID, client.AgentId);
1565 containingFolder = InventoryService.GetFolder(containingFolder);
1566  
1567 // m_log.DebugFormat("[AGENT INVENTORY]: Sending inventory folder contents ({0} nodes) for \"{1}\" to {2} {3}",
1568 // contents.Folders.Count + contents.Items.Count, containingFolder.Name, client.FirstName, client.LastName);
1569  
1570 if (containingFolder != null)
1571 {
1572 // If the folder requested contains links, then we need to send those folders first, otherwise the links
1573 // will be broken in the viewer.
1574 HashSet<UUID> linkedItemFolderIdsToSend = new HashSet<UUID>();
1575 foreach (InventoryItemBase item in contents.Items)
1576 {
1577 if (item.AssetType == (int)AssetType.Link)
1578 {
1579 InventoryItemBase linkedItem = InventoryService.GetItem(new InventoryItemBase(item.AssetID));
1580  
1581 // Take care of genuinely broken links where the target doesn't exist
1582 // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
1583 // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
1584 // rather than having to keep track of every folder requested in the recursion.
1585 if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link)
1586 {
1587 // We don't need to send the folder if source and destination of the link are in the same
1588 // folder.
1589 if (linkedItem.Folder != containingFolder.ID)
1590 linkedItemFolderIdsToSend.Add(linkedItem.Folder);
1591 }
1592 }
1593 }
1594  
1595 foreach (UUID linkedItemFolderId in linkedItemFolderIdsToSend)
1596 SendInventoryUpdate(client, new InventoryFolderBase(linkedItemFolderId), false, true);
1597  
1598 client.SendInventoryFolderDetails(
1599 client.AgentId, folder.ID, contents.Items, contents.Folders,
1600 containingFolder.Version, fetchFolders, fetchItems);
1601 }
1602 }
1603  
1604 /// <summary>
1605 /// Update an item in a prim (task) inventory.
1606 /// This method does not handle scripts, <see>RezScript(IClientAPI, UUID, unit)</see>
1607 /// </summary>
1608 /// <param name="remoteClient"></param>
1609 /// <param name="transactionID"></param>
1610 /// <param name="itemInfo"></param>
1611 /// <param name="primLocalID"></param>
1612 public void UpdateTaskInventory(IClientAPI remoteClient, UUID transactionID, TaskInventoryItem itemInfo,
1613 uint primLocalID)
1614 {
1615 UUID itemID = itemInfo.ItemID;
1616  
1617 // Find the prim we're dealing with
1618 SceneObjectPart part = GetSceneObjectPart(primLocalID);
1619  
1620 if (part != null)
1621 {
1622 TaskInventoryItem currentItem = part.Inventory.GetInventoryItem(itemID);
1623 bool allowInventoryDrop = (part.GetEffectiveObjectFlags()
1624 & (uint)PrimFlags.AllowInventoryDrop) != 0;
1625  
1626 // Explicity allow anyone to add to the inventory if the
1627 // AllowInventoryDrop flag has been set. Don't however let
1628 // them update an item unless they pass the external checks
1629 //
1630 if (!Permissions.CanEditObjectInventory(part.UUID, remoteClient.AgentId)
1631 && (currentItem != null || !allowInventoryDrop))
1632 return;
1633  
1634 if (currentItem == null)
1635 {
1636 UUID copyID = UUID.Random();
1637 if (itemID != UUID.Zero)
1638 {
1639 InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId);
1640 item = InventoryService.GetItem(item);
1641  
1642 // Try library
1643 if (null == item && LibraryService != null && LibraryService.LibraryRootFolder != null)
1644 {
1645 item = LibraryService.LibraryRootFolder.FindItem(itemID);
1646 }
1647  
1648 // If we've found the item in the user's inventory or in the library
1649 if (item != null)
1650 {
1651 part.ParentGroup.AddInventoryItem(remoteClient.AgentId, primLocalID, item, copyID);
1652 m_log.InfoFormat(
1653 "[PRIM INVENTORY]: Update with item {0} requested of prim {1} for {2}",
1654 item.Name, primLocalID, remoteClient.Name);
1655 part.SendPropertiesToClient(remoteClient);
1656 if (!Permissions.BypassPermissions())
1657 {
1658 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1659 {
1660 List<UUID> uuids = new List<UUID>();
1661 uuids.Add(itemID);
1662 RemoveInventoryItem(remoteClient, uuids);
1663 }
1664 }
1665 }
1666 else
1667 {
1668 m_log.ErrorFormat(
1669 "[PRIM INVENTORY]: Could not find inventory item {0} to update for {1}!",
1670 itemID, remoteClient.Name);
1671 }
1672 }
1673 }
1674 else // Updating existing item with new perms etc
1675 {
1676 // m_log.DebugFormat(
1677 // "[PRIM INVENTORY]: Updating item {0} in {1} for UpdateTaskInventory()",
1678 // currentItem.Name, part.Name);
1679  
1680 // Only look for an uploaded updated asset if we are passed a transaction ID. This is only the
1681 // case for updates uploded through UDP. Updates uploaded via a capability (e.g. a script update)
1682 // will not pass in a transaction ID in the update message.
1683 if (transactionID != UUID.Zero && AgentTransactionsModule != null)
1684 {
1685 AgentTransactionsModule.HandleTaskItemUpdateFromTransaction(
1686 remoteClient, part, transactionID, currentItem);
1687  
1688 if ((InventoryType)itemInfo.InvType == InventoryType.Notecard)
1689 remoteClient.SendAlertMessage("Notecard saved");
1690 else if ((InventoryType)itemInfo.InvType == InventoryType.LSL)
1691 remoteClient.SendAlertMessage("Script saved");
1692 else
1693 remoteClient.SendAlertMessage("Item saved");
1694 }
1695  
1696 // Base ALWAYS has move
1697 currentItem.BasePermissions |= (uint)PermissionMask.Move;
1698  
1699 itemInfo.Flags = currentItem.Flags;
1700  
1701 // Check if we're allowed to mess with permissions
1702 if (!Permissions.IsGod(remoteClient.AgentId)) // Not a god
1703 {
1704 if (remoteClient.AgentId != part.OwnerID) // Not owner
1705 {
1706 // Friends and group members can't change any perms
1707 itemInfo.BasePermissions = currentItem.BasePermissions;
1708 itemInfo.EveryonePermissions = currentItem.EveryonePermissions;
1709 itemInfo.GroupPermissions = currentItem.GroupPermissions;
1710 itemInfo.NextPermissions = currentItem.NextPermissions;
1711 itemInfo.CurrentPermissions = currentItem.CurrentPermissions;
1712 }
1713 else
1714 {
1715 // Owner can't change base, and can change other
1716 // only up to base
1717 itemInfo.BasePermissions = currentItem.BasePermissions;
1718 if (itemInfo.EveryonePermissions != currentItem.EveryonePermissions)
1719 itemInfo.Flags |= (uint)InventoryItemFlags.ObjectOverwriteEveryone;
1720 if (itemInfo.GroupPermissions != currentItem.GroupPermissions)
1721 itemInfo.Flags |= (uint)InventoryItemFlags.ObjectOverwriteGroup;
1722 if (itemInfo.CurrentPermissions != currentItem.CurrentPermissions)
1723 itemInfo.Flags |= (uint)InventoryItemFlags.ObjectOverwriteOwner;
1724 if (itemInfo.NextPermissions != currentItem.NextPermissions)
1725 itemInfo.Flags |= (uint)InventoryItemFlags.ObjectOverwriteNextOwner;
1726 itemInfo.EveryonePermissions &= currentItem.BasePermissions;
1727 itemInfo.GroupPermissions &= currentItem.BasePermissions;
1728 itemInfo.CurrentPermissions &= currentItem.BasePermissions;
1729 itemInfo.NextPermissions &= currentItem.BasePermissions;
1730 }
1731  
1732 }
1733 else
1734 {
1735 if (itemInfo.BasePermissions != currentItem.BasePermissions)
1736 itemInfo.Flags |= (uint)InventoryItemFlags.ObjectOverwriteBase;
1737 if (itemInfo.EveryonePermissions != currentItem.EveryonePermissions)
1738 itemInfo.Flags |= (uint)InventoryItemFlags.ObjectOverwriteEveryone;
1739 if (itemInfo.GroupPermissions != currentItem.GroupPermissions)
1740 itemInfo.Flags |= (uint)InventoryItemFlags.ObjectOverwriteGroup;
1741 if (itemInfo.CurrentPermissions != currentItem.CurrentPermissions)
1742 itemInfo.Flags |= (uint)InventoryItemFlags.ObjectOverwriteOwner;
1743 if (itemInfo.NextPermissions != currentItem.NextPermissions)
1744 itemInfo.Flags |= (uint)InventoryItemFlags.ObjectOverwriteNextOwner;
1745 }
1746  
1747 // Next ALWAYS has move
1748 itemInfo.NextPermissions |= (uint)PermissionMask.Move;
1749  
1750 if (part.Inventory.UpdateInventoryItem(itemInfo))
1751 {
1752 part.SendPropertiesToClient(remoteClient);
1753 }
1754 }
1755 }
1756 else
1757 {
1758 m_log.WarnFormat(
1759 "[PRIM INVENTORY]: " +
1760 "Update with item {0} requested of prim {1} for {2} but this prim does not exist",
1761 itemID, primLocalID, remoteClient.Name);
1762 }
1763 }
1764  
1765 /// <summary>
1766 /// Rez a script into a prim's inventory, either ex nihilo or from an existing avatar inventory
1767 /// </summary>
1768 /// <param name="remoteClient"></param>
1769 /// <param name="itemBase"> </param>
1770 /// <param name="transactionID"></param>
1771 /// <param name="localID"></param>
1772 public void RezScript(IClientAPI remoteClient, InventoryItemBase itemBase, UUID transactionID, uint localID)
1773 {
1774 SceneObjectPart partWhereRezzed;
1775  
1776 if (itemBase.ID != UUID.Zero)
1777 partWhereRezzed = RezScriptFromAgentInventory(remoteClient.AgentId, itemBase.ID, localID);
1778 else
1779 partWhereRezzed = RezNewScript(remoteClient.AgentId, itemBase);
1780  
1781 if (partWhereRezzed != null)
1782 partWhereRezzed.SendPropertiesToClient(remoteClient);
1783 }
1784  
1785 /// <summary>
1786 /// Rez a script into a prim from an agent inventory.
1787 /// </summary>
1788 /// <param name="agentID"></param>
1789 /// <param name="fromItemID"></param>
1790 /// <param name="localID"></param>
1791 /// <returns>The part where the script was rezzed if successful. False otherwise.</returns>
1792 public SceneObjectPart RezScriptFromAgentInventory(UUID agentID, UUID fromItemID, uint localID)
1793 {
1794 UUID copyID = UUID.Random();
1795 InventoryItemBase item = new InventoryItemBase(fromItemID, agentID);
1796 item = InventoryService.GetItem(item);
1797  
1798 // Try library
1799 // XXX clumsy, possibly should be one call
1800 if (null == item && LibraryService != null && LibraryService.LibraryRootFolder != null)
1801 {
1802 item = LibraryService.LibraryRootFolder.FindItem(fromItemID);
1803 }
1804  
1805 if (item != null)
1806 {
1807 SceneObjectPart part = GetSceneObjectPart(localID);
1808 if (part != null)
1809 {
1810 if (!Permissions.CanEditObjectInventory(part.UUID, agentID))
1811 return null;
1812  
1813 part.ParentGroup.AddInventoryItem(agentID, localID, item, copyID);
1814 // TODO: switch to posting on_rez here when scripts
1815 // have state in inventory
1816 part.Inventory.CreateScriptInstance(copyID, 0, false, DefaultScriptEngine, 0);
1817  
1818 // tell anyone watching that there is a new script in town
1819 EventManager.TriggerNewScript(agentID, part, copyID);
1820  
1821 // m_log.InfoFormat("[PRIMINVENTORY]: " +
1822 // "Rezzed script {0} into prim local ID {1} for user {2}",
1823 // item.inventoryName, localID, remoteClient.Name);
1824  
1825 part.ParentGroup.ResumeScripts();
1826  
1827 return part;
1828 }
1829 else
1830 {
1831 m_log.ErrorFormat(
1832 "[PRIM INVENTORY]: " +
1833 "Could not rez script {0} into prim local ID {1} for user {2}"
1834 + " because the prim could not be found in the region!",
1835 item.Name, localID, agentID);
1836 }
1837 }
1838 else
1839 {
1840 m_log.ErrorFormat(
1841 "[PRIM INVENTORY]: Could not find script inventory item {0} to rez for {1}!",
1842 fromItemID, agentID);
1843 }
1844  
1845 return null;
1846 }
1847  
1848 /// <summary>
1849 /// Rez a new script from nothing.
1850 /// </summary>
1851 /// <param name="remoteClient"></param>
1852 /// <param name="itemBase"></param>
1853 /// <returns>The part where the script was rezzed if successful. False otherwise.</returns>
1854 public SceneObjectPart RezNewScript(UUID agentID, InventoryItemBase itemBase)
1855 {
1856 return RezNewScript(
1857 agentID,
1858 itemBase,
1859 "default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n}");
1860 }
1861  
1862 /// <summary>
1863 /// Rez a new script from nothing with given script text.
1864 /// </summary>
1865 /// <param name="remoteClient"></param>
1866 /// <param name="itemBase">Template item.</param>
1867 /// <param name="scriptText"></param>
1868 /// <returns>The part where the script was rezzed if successful. False otherwise.</returns>
1869 public SceneObjectPart RezNewScript(UUID agentID, InventoryItemBase itemBase, string scriptText)
1870 {
1871 // The part ID is the folder ID!
1872 SceneObjectPart part = GetSceneObjectPart(itemBase.Folder);
1873 if (part == null)
1874 {
1875 // m_log.DebugFormat(
1876 // "[SCENE INVENTORY]: Could not find part with id {0} for {1} to rez new script",
1877 // itemBase.Folder, agentID);
1878  
1879 return null;
1880 }
1881  
1882 if (!Permissions.CanCreateObjectInventory(itemBase.InvType, part.UUID, agentID))
1883 {
1884 // m_log.DebugFormat(
1885 // "[SCENE INVENTORY]: No permission to create new script in {0} for {1}", part.Name, agentID);
1886  
1887 return null;
1888 }
1889  
1890 AssetBase asset
1891 = CreateAsset(
1892 itemBase.Name,
1893 itemBase.Description,
1894 (sbyte)itemBase.AssetType,
1895 Encoding.ASCII.GetBytes(scriptText),
1896 agentID);
1897  
1898 AssetService.Store(asset);
1899  
1900 TaskInventoryItem taskItem = new TaskInventoryItem();
1901  
1902 taskItem.ResetIDs(itemBase.Folder);
1903 taskItem.ParentID = itemBase.Folder;
1904 taskItem.CreationDate = (uint)itemBase.CreationDate;
1905 taskItem.Name = itemBase.Name;
1906 taskItem.Description = itemBase.Description;
1907 taskItem.Type = itemBase.AssetType;
1908 taskItem.InvType = itemBase.InvType;
1909 taskItem.OwnerID = itemBase.Owner;
1910 taskItem.CreatorID = itemBase.CreatorIdAsUuid;
1911 taskItem.BasePermissions = itemBase.BasePermissions;
1912 taskItem.CurrentPermissions = itemBase.CurrentPermissions;
1913 taskItem.EveryonePermissions = itemBase.EveryOnePermissions;
1914 taskItem.GroupPermissions = itemBase.GroupPermissions;
1915 taskItem.NextPermissions = itemBase.NextPermissions;
1916 taskItem.GroupID = itemBase.GroupID;
1917 taskItem.GroupPermissions = 0;
1918 taskItem.Flags = itemBase.Flags;
1919 taskItem.PermsGranter = UUID.Zero;
1920 taskItem.PermsMask = 0;
1921 taskItem.AssetID = asset.FullID;
1922  
1923 part.Inventory.AddInventoryItem(taskItem, false);
1924 part.Inventory.CreateScriptInstance(taskItem, 0, false, DefaultScriptEngine, 0);
1925  
1926 // tell anyone managing scripts that a new script exists
1927 EventManager.TriggerNewScript(agentID, part, taskItem.ItemID);
1928  
1929 part.ParentGroup.ResumeScripts();
1930  
1931 return part;
1932 }
1933  
1934 /// <summary>
1935 /// Rez a script into a prim's inventory from another prim
1936 /// </summary>
1937 /// <param name="remoteClient"></param>
1938 /// <param name="itemID"> </param>
1939 /// <param name="localID"></param>
1940 public void RezScriptFromPrim(UUID srcId, SceneObjectPart srcPart, UUID destId, int pin, int running, int start_param)
1941 {
1942 TaskInventoryItem srcTaskItem = srcPart.Inventory.GetInventoryItem(srcId);
1943  
1944 if (srcTaskItem == null)
1945 {
1946 m_log.ErrorFormat(
1947 "[PRIM INVENTORY]: Tried to retrieve item ID {0} from prim {1}, {2} for rezzing a script but the "
1948 + " item does not exist in this inventory",
1949 srcId, srcPart.Name, srcPart.UUID);
1950  
1951 return;
1952 }
1953  
1954 SceneObjectPart destPart = GetSceneObjectPart(destId);
1955  
1956 if (destPart == null)
1957 {
1958 m_log.ErrorFormat(
1959 "[PRIM INVENTORY]: " +
1960 "Could not find script for ID {0}",
1961 destId);
1962 return;
1963 }
1964  
1965 // Must own the object, and have modify rights
1966 if (srcPart.OwnerID != destPart.OwnerID)
1967 {
1968 // Group permissions
1969 if ((destPart.GroupID == UUID.Zero) || (destPart.GroupID != srcPart.GroupID) ||
1970 ((destPart.GroupMask & (uint)PermissionMask.Modify) == 0))
1971 return;
1972 } else {
1973 if ((destPart.OwnerMask & (uint)PermissionMask.Modify) == 0)
1974 return;
1975 }
1976  
1977 if (destPart.ScriptAccessPin != pin)
1978 {
1979 m_log.WarnFormat(
1980 "[PRIM INVENTORY]: " +
1981 "Script in object {0} : {1}, attempted to load script {2} : {3} into object {4} : {5} with invalid pin {6}",
1982 srcPart.Name, srcId, srcTaskItem.Name, srcTaskItem.ItemID, destPart.Name, destId, pin);
1983 // the LSL Wiki says we are supposed to shout on the DEBUG_CHANNEL -
1984 // "Object: Task Object trying to illegally load script onto task Other_Object!"
1985 // How do we shout from in here?
1986 return;
1987 }
1988  
1989 TaskInventoryItem destTaskItem = new TaskInventoryItem();
1990  
1991 destTaskItem.ItemID = UUID.Random();
1992 destTaskItem.CreatorID = srcTaskItem.CreatorID;
1993 destTaskItem.CreatorData = srcTaskItem.CreatorData;
1994 destTaskItem.AssetID = srcTaskItem.AssetID;
1995 destTaskItem.GroupID = destPart.GroupID;
1996 destTaskItem.OwnerID = destPart.OwnerID;
1997 destTaskItem.ParentID = destPart.UUID;
1998 destTaskItem.ParentPartID = destPart.UUID;
1999  
2000 destTaskItem.BasePermissions = srcTaskItem.BasePermissions;
2001 destTaskItem.EveryonePermissions = srcTaskItem.EveryonePermissions;
2002 destTaskItem.GroupPermissions = srcTaskItem.GroupPermissions;
2003 destTaskItem.CurrentPermissions = srcTaskItem.CurrentPermissions;
2004 destTaskItem.NextPermissions = srcTaskItem.NextPermissions;
2005 destTaskItem.Flags = srcTaskItem.Flags;
2006  
2007 if (destPart.OwnerID != srcPart.OwnerID)
2008 {
2009 if (Permissions.PropagatePermissions())
2010 {
2011 destTaskItem.CurrentPermissions = srcTaskItem.CurrentPermissions &
2012 srcTaskItem.NextPermissions;
2013 destTaskItem.GroupPermissions = srcTaskItem.GroupPermissions &
2014 srcTaskItem.NextPermissions;
2015 destTaskItem.EveryonePermissions = srcTaskItem.EveryonePermissions &
2016 srcTaskItem.NextPermissions;
2017 destTaskItem.BasePermissions = srcTaskItem.BasePermissions &
2018 srcTaskItem.NextPermissions;
2019 destTaskItem.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm;
2020 }
2021 }
2022  
2023 destTaskItem.Description = srcTaskItem.Description;
2024 destTaskItem.Name = srcTaskItem.Name;
2025 destTaskItem.InvType = srcTaskItem.InvType;
2026 destTaskItem.Type = srcTaskItem.Type;
2027  
2028 destPart.Inventory.AddInventoryItemExclusive(destTaskItem, false);
2029  
2030 if (running > 0)
2031 {
2032 destPart.Inventory.CreateScriptInstance(destTaskItem, start_param, false, DefaultScriptEngine, 0);
2033 }
2034  
2035 destPart.ParentGroup.ResumeScripts();
2036  
2037 ScenePresence avatar;
2038  
2039 if (TryGetScenePresence(srcTaskItem.OwnerID, out avatar))
2040 {
2041 destPart.SendPropertiesToClient(avatar.ControllingClient);
2042 }
2043 }
2044  
2045 /// <summary>
2046 /// Derez one or more objects from the scene.
2047 /// </summary>
2048 /// <remarks>
2049 /// Won't actually remove the scene object in the case where the object is being copied to a user inventory.
2050 /// </remarks>
2051 /// <param name='remoteClient'>Client requesting derez</param>
2052 /// <param name='localIDs'>Local ids of root parts of objects to delete.</param>
2053 /// <param name='groupID'>Not currently used. Here because the client passes this to us.</param>
2054 /// <param name='action'>DeRezAction</param>
2055 /// <param name='destinationID'>User folder ID to place derezzed object</param>
2056 public virtual void DeRezObjects(
2057 IClientAPI remoteClient, List<uint> localIDs, UUID groupID, DeRezAction action, UUID destinationID)
2058 {
2059 // First, see of we can perform the requested action and
2060 // build a list of eligible objects
2061 List<uint> deleteIDs = new List<uint>();
2062 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>();
2063  
2064 // Start with true for both, then remove the flags if objects
2065 // that we can't derez are part of the selection
2066 bool permissionToTake = true;
2067 bool permissionToTakeCopy = true;
2068 bool permissionToDelete = true;
2069  
2070 foreach (uint localID in localIDs)
2071 {
2072 // Invalid id
2073 SceneObjectPart part = GetSceneObjectPart(localID);
2074 if (part == null)
2075 continue;
2076  
2077 // Already deleted by someone else
2078 if (part.ParentGroup.IsDeleted)
2079 continue;
2080  
2081 // Can't delete child prims
2082 if (part != part.ParentGroup.RootPart)
2083 continue;
2084  
2085 SceneObjectGroup grp = part.ParentGroup;
2086  
2087 deleteIDs.Add(localID);
2088 deleteGroups.Add(grp);
2089  
2090 // If child prims have invalid perms, fix them
2091 grp.AdjustChildPrimPermissions(false);
2092  
2093 if (remoteClient == null)
2094 {
2095 // Autoreturn has a null client. Nothing else does. So
2096 // allow only returns
2097 if (action != DeRezAction.Return)
2098 {
2099 m_log.WarnFormat(
2100 "[AGENT INVENTORY]: Ignoring attempt to {0} {1} {2} without a client",
2101 action, grp.Name, grp.UUID);
2102 return;
2103 }
2104  
2105 permissionToTakeCopy = false;
2106 }
2107 else
2108 {
2109 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId))
2110 permissionToTakeCopy = false;
2111  
2112 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId))
2113 permissionToTake = false;
2114  
2115 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId))
2116 permissionToDelete = false;
2117 }
2118 }
2119  
2120 // Handle god perms
2121 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId))
2122 {
2123 permissionToTake = true;
2124 permissionToTakeCopy = true;
2125 permissionToDelete = true;
2126 }
2127  
2128 // If we're re-saving, we don't even want to delete
2129 if (action == DeRezAction.SaveToExistingUserInventoryItem)
2130 permissionToDelete = false;
2131  
2132 // if we want to take a copy, we also don't want to delete
2133 // Note: after this point, the permissionToTakeCopy flag
2134 // becomes irrelevant. It already includes the permissionToTake
2135 // permission and after excluding no copy items here, we can
2136 // just use that.
2137 if (action == DeRezAction.TakeCopy)
2138 {
2139 // If we don't have permission, stop right here
2140 if (!permissionToTakeCopy)
2141 {
2142 remoteClient.SendAlertMessage("You don't have permission to take the object");
2143 return;
2144 }
2145  
2146 permissionToTake = true;
2147 // Don't delete
2148 permissionToDelete = false;
2149 }
2150  
2151 if (action == DeRezAction.Return)
2152 {
2153 if (remoteClient != null)
2154 {
2155 if (Permissions.CanReturnObjects(
2156 null,
2157 remoteClient.AgentId,
2158 deleteGroups))
2159 {
2160 permissionToTake = true;
2161 permissionToDelete = true;
2162  
2163 foreach (SceneObjectGroup g in deleteGroups)
2164 {
2165 AddReturn(g.OwnerID == g.GroupID ? g.LastOwnerID : g.OwnerID, g.Name, g.AbsolutePosition, "parcel owner return");
2166 }
2167 }
2168 }
2169 else // Auto return passes through here with null agent
2170 {
2171 permissionToTake = true;
2172 permissionToDelete = true;
2173 }
2174 }
2175  
2176 if (permissionToTake && (action != DeRezAction.Delete || this.m_useTrashOnDelete))
2177 {
2178 m_asyncSceneObjectDeleter.DeleteToInventory(
2179 action, destinationID, deleteGroups, remoteClient,
2180 permissionToDelete);
2181 }
2182 else if (permissionToDelete)
2183 {
2184 foreach (SceneObjectGroup g in deleteGroups)
2185 DeleteSceneObject(g, false);
2186 }
2187 }
2188  
2189 /// <summary>
2190 /// Returns the list of Scene Objects in an asset.
2191 /// </summary>
2192 /// <remarks>
2193 /// Returns one object if the asset is a regular object, and multiple objects for a coalesced object.
2194 /// </remarks>
2195 /// <param name="assetData">Asset data</param>
2196 /// <param name="isAttachment">True if the object is an attachment.</param>
2197 /// <param name="objlist">The objects included in the asset</param>
2198 /// <param name="veclist">Relative positions of the objects</param>
2199 /// <param name="bbox">Bounding box of all the objects</param>
2200 /// <param name="offsetHeight">Offset in the Z axis from the centre of the bounding box
2201 /// to the centre of the root prim (relevant only when returning a single object)</param>
2202 /// <returns>
2203 /// true if returning a single object or deserialization fails, false if returning the coalesced
2204 /// list of objects
2205 /// </returns>
2206 public bool GetObjectsToRez(
2207 byte[] assetData, bool isAttachment, out List<SceneObjectGroup> objlist, out List<Vector3> veclist,
2208 out Vector3 bbox, out float offsetHeight)
2209 {
2210 objlist = new List<SceneObjectGroup>();
2211 veclist = new List<Vector3>();
2212  
2213 string xmlData = Utils.BytesToString(assetData);
2214  
2215 try
2216 {
2217 using (XmlTextReader wrappedReader = new XmlTextReader(xmlData, XmlNodeType.Element, null))
2218 {
2219 using (XmlReader reader = XmlReader.Create(wrappedReader, new XmlReaderSettings() { IgnoreWhitespace = true, ConformanceLevel = ConformanceLevel.Fragment }))
2220 {
2221 reader.Read();
2222 bool isSingleObject = reader.Name != "CoalescedObject";
2223  
2224 if (isSingleObject || isAttachment)
2225 {
2226 SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(reader);
2227 objlist.Add(g);
2228 veclist.Add(Vector3.Zero);
2229 bbox = g.GetAxisAlignedBoundingBox(out offsetHeight);
2230 return true;
2231 }
2232 else
2233 {
2234 XmlDocument doc = new XmlDocument();
2235 doc.LoadXml(xmlData);
2236 XmlElement e = (XmlElement)doc.SelectSingleNode("/CoalescedObject");
2237 XmlElement coll = (XmlElement)e;
2238 float bx = Convert.ToSingle(coll.GetAttribute("x"));
2239 float by = Convert.ToSingle(coll.GetAttribute("y"));
2240 float bz = Convert.ToSingle(coll.GetAttribute("z"));
2241 bbox = new Vector3(bx, by, bz);
2242 offsetHeight = 0;
2243  
2244 XmlNodeList groups = e.SelectNodes("SceneObjectGroup");
2245 foreach (XmlNode n in groups)
2246 {
2247 SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(n.OuterXml);
2248 objlist.Add(g);
2249  
2250 XmlElement el = (XmlElement)n;
2251 string rawX = el.GetAttribute("offsetx");
2252 string rawY = el.GetAttribute("offsety");
2253 string rawZ = el.GetAttribute("offsetz");
2254  
2255 float x = Convert.ToSingle(rawX);
2256 float y = Convert.ToSingle(rawY);
2257 float z = Convert.ToSingle(rawZ);
2258 veclist.Add(new Vector3(x, y, z));
2259 }
2260  
2261 return false;
2262 }
2263 }
2264 }
2265 }
2266 catch (Exception e)
2267 {
2268 m_log.Error(
2269 "[AGENT INVENTORY]: Deserialization of xml failed when looking for CoalescedObject tag. Exception ",
2270 e);
2271  
2272 bbox = Vector3.Zero;
2273 offsetHeight = 0;
2274 }
2275  
2276 return true;
2277 }
2278  
2279 /// <summary>
2280 /// Event Handler Rez an object into a scene
2281 /// Calls the non-void event handler
2282 /// </summary>
2283 /// <param name="remoteClient"></param>
2284 /// <param name="itemID"></param>
2285 /// <param name="RayEnd"></param>
2286 /// <param name="RayStart"></param>
2287 /// <param name="RayTargetID"></param>
2288 /// <param name="BypassRayCast"></param>
2289 /// <param name="RayEndIsIntersection"></param>
2290 /// <param name="EveryoneMask"></param>
2291 /// <param name="GroupMask"></param>
2292 /// <param name="RezSelected"></param>
2293 /// <param name="RemoveItem"></param>
2294 /// <param name="fromTaskID"></param>
2295 public virtual void RezObject(IClientAPI remoteClient, UUID itemID, Vector3 RayEnd, Vector3 RayStart,
2296 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection,
2297 bool RezSelected, bool RemoveItem, UUID fromTaskID)
2298 {
2299 // m_log.DebugFormat(
2300 // "[PRIM INVENTORY]: RezObject from {0} for item {1} from task id {2}",
2301 // remoteClient.Name, itemID, fromTaskID);
2302  
2303 if (fromTaskID == UUID.Zero)
2304 {
2305 IInventoryAccessModule invAccess = RequestModuleInterface<IInventoryAccessModule>();
2306 if (invAccess != null)
2307 invAccess.RezObject(
2308 remoteClient, itemID, RayEnd, RayStart, RayTargetID, BypassRayCast, RayEndIsIntersection,
2309 RezSelected, RemoveItem, fromTaskID, false);
2310 }
2311 else
2312 {
2313 SceneObjectPart part = GetSceneObjectPart(fromTaskID);
2314 if (part == null)
2315 {
2316 m_log.ErrorFormat(
2317 "[TASK INVENTORY]: {0} tried to rez item id {1} from object id {2} but there is no such scene object",
2318 remoteClient.Name, itemID, fromTaskID);
2319  
2320 return;
2321 }
2322  
2323 TaskInventoryItem item = part.Inventory.GetInventoryItem(itemID);
2324 if (item == null)
2325 {
2326 m_log.ErrorFormat(
2327 "[TASK INVENTORY]: {0} tried to rez item id {1} from object id {2} but there is no such item",
2328 remoteClient.Name, itemID, fromTaskID);
2329  
2330 return;
2331 }
2332  
2333 byte bRayEndIsIntersection = (byte)(RayEndIsIntersection ? 1 : 0);
2334 Vector3 scale = new Vector3(0.5f, 0.5f, 0.5f);
2335 Vector3 pos
2336 = GetNewRezLocation(
2337 RayStart, RayEnd, RayTargetID, Quaternion.Identity,
2338 BypassRayCast, bRayEndIsIntersection, true, scale, false);
2339  
2340 RezObject(part, item, pos, null, Vector3.Zero, 0);
2341 }
2342 }
2343  
2344 /// <summary>
2345 /// Rez an object into the scene from a prim's inventory.
2346 /// </summary>
2347 /// <param name="sourcePart"></param>
2348 /// <param name="item"></param>
2349 /// <param name="pos">The position of the rezzed object.</param>
2350 /// <param name="rot">The rotation of the rezzed object. If null, then the rotation stored with the object
2351 /// will be used if it exists.</param>
2352 /// <param name="vel">The velocity of the rezzed object.</param>
2353 /// <param name="param"></param>
2354 /// <returns>The SceneObjectGroup(s) rezzed, or null if rez was unsuccessful</returns>
2355 public virtual List<SceneObjectGroup> RezObject(
2356 SceneObjectPart sourcePart, TaskInventoryItem item, Vector3 pos, Quaternion? rot, Vector3 vel, int param)
2357 {
2358 if (null == item)
2359 return null;
2360  
2361 List<SceneObjectGroup> objlist;
2362 List<Vector3> veclist;
2363  
2364 bool success = sourcePart.Inventory.GetRezReadySceneObjects(item, out objlist, out veclist);
2365 if (!success)
2366 return null;
2367  
2368 int totalPrims = 0;
2369 foreach (SceneObjectGroup group in objlist)
2370 totalPrims += group.PrimCount;
2371  
2372 if (!Permissions.CanRezObject(totalPrims, item.OwnerID, pos))
2373 return null;
2374  
2375 if (!Permissions.BypassPermissions())
2376 {
2377 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
2378 sourcePart.Inventory.RemoveInventoryItem(item.ItemID);
2379 }
2380  
2381 for (int i = 0; i < objlist.Count; i++)
2382 {
2383 SceneObjectGroup group = objlist[i];
2384 Vector3 curpos = pos + veclist[i];
2385  
2386 if (group.IsAttachment == false && group.RootPart.Shape.State != 0)
2387 {
2388 group.RootPart.AttachedPos = group.AbsolutePosition;
2389 group.RootPart.Shape.LastAttachPoint = (byte)group.AttachmentPoint;
2390 }
2391  
2392 group.FromPartID = sourcePart.UUID;
2393 AddNewSceneObject(group, true, curpos, rot, vel);
2394  
2395 // We can only call this after adding the scene object, since the scene object references the scene
2396 // to find out if scripts should be activated at all.
2397 group.CreateScriptInstances(param, true, DefaultScriptEngine, 3);
2398  
2399 group.ScheduleGroupForFullUpdate();
2400 }
2401  
2402 return objlist;
2403 }
2404  
2405 public virtual bool returnObjects(SceneObjectGroup[] returnobjects,
2406 UUID AgentId)
2407 {
2408 List<uint> localIDs = new List<uint>();
2409  
2410 foreach (SceneObjectGroup grp in returnobjects)
2411 {
2412 AddReturn(grp.OwnerID, grp.Name, grp.AbsolutePosition,
2413 "parcel owner return");
2414 localIDs.Add(grp.RootPart.LocalId);
2415 }
2416 DeRezObjects(null, localIDs, UUID.Zero, DeRezAction.Return,
2417 UUID.Zero);
2418  
2419 return true;
2420 }
2421  
2422 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running)
2423 {
2424 SceneObjectPart part = GetSceneObjectPart(objectID);
2425 if (part == null)
2426 return;
2427  
2428 if (running)
2429 EventManager.TriggerStartScript(part.LocalId, itemID);
2430 else
2431 EventManager.TriggerStopScript(part.LocalId, itemID);
2432 }
2433  
2434 public void GetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID)
2435 {
2436 EventManager.TriggerGetScriptRunning(controllingClient, objectID, itemID);
2437 }
2438  
2439 void ObjectOwner(IClientAPI remoteClient, UUID ownerID, UUID groupID, List<uint> localIDs)
2440 {
2441 if (!Permissions.IsGod(remoteClient.AgentId))
2442 {
2443 if (ownerID != UUID.Zero)
2444 return;
2445  
2446 if (!Permissions.CanDeedObject(remoteClient.AgentId, groupID))
2447 return;
2448 }
2449  
2450 List<SceneObjectGroup> groups = new List<SceneObjectGroup>();
2451  
2452 foreach (uint localID in localIDs)
2453 {
2454 SceneObjectPart part = GetSceneObjectPart(localID);
2455 if (part == null)
2456 continue;
2457  
2458 if (!groups.Contains(part.ParentGroup))
2459 groups.Add(part.ParentGroup);
2460 }
2461  
2462 foreach (SceneObjectGroup sog in groups)
2463 {
2464 if (ownerID != UUID.Zero)
2465 {
2466 sog.SetOwnerId(ownerID);
2467 sog.SetGroup(groupID, remoteClient);
2468 sog.ScheduleGroupForFullUpdate();
2469  
2470 SceneObjectPart[] partList = sog.Parts;
2471  
2472 foreach (SceneObjectPart child in partList)
2473 {
2474 child.Inventory.ChangeInventoryOwner(ownerID);
2475 child.TriggerScriptChangedEvent(Changed.OWNER);
2476 }
2477 }
2478 else
2479 {
2480 if (!Permissions.CanEditObject(sog.UUID, remoteClient.AgentId))
2481 continue;
2482  
2483 if (sog.GroupID != groupID)
2484 continue;
2485  
2486 SceneObjectPart[] partList = sog.Parts;
2487  
2488 foreach (SceneObjectPart child in partList)
2489 {
2490 child.LastOwnerID = child.OwnerID;
2491 child.Inventory.ChangeInventoryOwner(groupID);
2492 child.TriggerScriptChangedEvent(Changed.OWNER);
2493 }
2494  
2495 sog.SetOwnerId(groupID);
2496 sog.ApplyNextOwnerPermissions();
2497 }
2498 }
2499  
2500 foreach (uint localID in localIDs)
2501 {
2502 SceneObjectPart part = GetSceneObjectPart(localID);
2503 if (part == null)
2504 continue;
2505 part.SendPropertiesToClient(remoteClient);
2506 }
2507 }
2508  
2509 public void DelinkObjects(List<uint> primIds, IClientAPI client)
2510 {
2511 List<SceneObjectPart> parts = new List<SceneObjectPart>();
2512  
2513 foreach (uint localID in primIds)
2514 {
2515 SceneObjectPart part = GetSceneObjectPart(localID);
2516  
2517 if (part == null)
2518 continue;
2519  
2520 if (Permissions.CanDelinkObject(client.AgentId, part.ParentGroup.RootPart.UUID))
2521 parts.Add(part);
2522 }
2523  
2524 m_sceneGraph.DelinkObjects(parts);
2525 }
2526  
2527 /// <summary>
2528 /// Link the scene objects containing the indicated parts to a root object.
2529 /// </summary>
2530 /// <param name="client"></param>
2531 /// <param name="parentPrimId">A root prim id of the object which will be the root prim of the resulting linkset.</param>
2532 /// <param name="childPrimIds">A list of child prims for the objects that should be linked in.</param>
2533 public void LinkObjects(IClientAPI client, uint parentPrimId, List<uint> childPrimIds)
2534 {
2535 LinkObjects(client.AgentId, parentPrimId, childPrimIds);
2536 }
2537  
2538 /// <summary>
2539 /// Link the scene objects containing the indicated parts to a root object.
2540 /// </summary>
2541 /// <param name="agentId">The ID of the user linking.</param>
2542 /// <param name="parentPrimId">A root prim id of the object which will be the root prim of the resulting linkset.</param>
2543 /// <param name="childPrimIds">A list of child prims for the objects that should be linked in.</param>
2544 public void LinkObjects(UUID agentId, uint parentPrimId, List<uint> childPrimIds)
2545 {
2546 List<UUID> owners = new List<UUID>();
2547  
2548 List<SceneObjectPart> children = new List<SceneObjectPart>();
2549 SceneObjectPart root = GetSceneObjectPart(parentPrimId);
2550  
2551 if (root == null)
2552 {
2553 m_log.DebugFormat("[LINK]: Can't find linkset root prim {0}", parentPrimId);
2554 return;
2555 }
2556  
2557 if (!Permissions.CanLinkObject(agentId, root.ParentGroup.RootPart.UUID))
2558 {
2559 m_log.DebugFormat("[LINK]: Refusing link. No permissions on root prim");
2560 return;
2561 }
2562  
2563 foreach (uint localID in childPrimIds)
2564 {
2565 SceneObjectPart part = GetSceneObjectPart(localID);
2566  
2567 if (part == null)
2568 continue;
2569  
2570 if (!owners.Contains(part.OwnerID))
2571 owners.Add(part.OwnerID);
2572  
2573 if (Permissions.CanLinkObject(agentId, part.ParentGroup.RootPart.UUID))
2574 children.Add(part);
2575 }
2576  
2577 // Must be all one owner
2578 //
2579 if (owners.Count > 1)
2580 {
2581 m_log.DebugFormat("[LINK]: Refusing link. Too many owners");
2582 return;
2583 }
2584  
2585 if (children.Count == 0)
2586 {
2587 m_log.DebugFormat("[LINK]: Refusing link. No permissions to link any of the children");
2588 return;
2589 }
2590  
2591 m_sceneGraph.LinkObjects(root, children);
2592 }
2593  
2594 private string PermissionString(uint permissions)
2595 {
2596 PermissionMask perms = (PermissionMask)permissions &
2597 (PermissionMask.Move |
2598 PermissionMask.Copy |
2599 PermissionMask.Transfer |
2600 PermissionMask.Modify);
2601 return perms.ToString();
2602 }
2603 }
2604 }