opensim-development – Blame information for rev 1

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