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