clockwerk-opensim – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | vero | 1 | /* |
2 | * Copyright (c) Contributors, http://opensimulator.org/ |
||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. |
||
4 | * |
||
5 | * Redistribution and use in source and binary forms, with or without |
||
6 | * modification, are permitted provided that the following conditions are met: |
||
7 | * * Redistributions of source code must retain the above copyright |
||
8 | * notice, this list of conditions and the following disclaimer. |
||
9 | * * Redistributions in binary form must reproduce the above copyright |
||
10 | * notice, this list of conditions and the following disclaimer in the |
||
11 | * documentation and/or other materials provided with the distribution. |
||
12 | * * Neither the name of the OpenSimulator Project nor the |
||
13 | * names of its contributors may be used to endorse or promote products |
||
14 | * derived from this software without specific prior written permission. |
||
15 | * |
||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY |
||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY |
||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||
26 | */ |
||
27 | |||
28 | using System; |
||
29 | using System.Collections.Generic; |
||
30 | using System.Net; |
||
31 | using System.Xml; |
||
32 | using System.Reflection; |
||
33 | using System.Text; |
||
34 | using System.Threading; |
||
35 | |||
36 | using OpenSim.Framework; |
||
37 | using OpenSim.Framework.Capabilities; |
||
38 | using OpenSim.Framework.Client; |
||
39 | using OpenSim.Region.Framework.Interfaces; |
||
40 | using OpenSim.Region.Framework.Scenes; |
||
41 | using OpenSim.Region.Framework.Scenes.Serialization; |
||
42 | using OpenSim.Services.Interfaces; |
||
43 | |||
44 | using GridRegion = OpenSim.Services.Interfaces.GridRegion; |
||
45 | |||
46 | using OpenMetaverse; |
||
47 | using log4net; |
||
48 | using Nini.Config; |
||
49 | using Mono.Addins; |
||
50 | using PermissionMask = OpenSim.Framework.PermissionMask; |
||
51 | |||
52 | namespace OpenSim.Region.CoreModules.Framework.InventoryAccess |
||
53 | { |
||
54 | [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "BasicInventoryAccessModule")] |
||
55 | public class BasicInventoryAccessModule : INonSharedRegionModule, IInventoryAccessModule |
||
56 | { |
||
57 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
||
58 | |||
59 | protected bool m_Enabled = false; |
||
60 | protected Scene m_Scene; |
||
61 | protected IUserManagement m_UserManagement; |
||
62 | protected IUserManagement UserManagementModule |
||
63 | { |
||
64 | get |
||
65 | { |
||
66 | if (m_UserManagement == null) |
||
67 | m_UserManagement = m_Scene.RequestModuleInterface<IUserManagement>(); |
||
68 | return m_UserManagement; |
||
69 | } |
||
70 | } |
||
71 | |||
72 | public bool CoalesceMultipleObjectsToInventory { get; set; } |
||
73 | |||
74 | #region INonSharedRegionModule |
||
75 | |||
76 | public Type ReplaceableInterface |
||
77 | { |
||
78 | get { return null; } |
||
79 | } |
||
80 | |||
81 | public virtual string Name |
||
82 | { |
||
83 | get { return "BasicInventoryAccessModule"; } |
||
84 | } |
||
85 | |||
86 | public virtual void Initialise(IConfigSource source) |
||
87 | { |
||
88 | IConfig moduleConfig = source.Configs["Modules"]; |
||
89 | if (moduleConfig != null) |
||
90 | { |
||
91 | string name = moduleConfig.GetString("InventoryAccessModule", ""); |
||
92 | if (name == Name) |
||
93 | { |
||
94 | m_Enabled = true; |
||
95 | |||
96 | InitialiseCommon(source); |
||
97 | |||
98 | m_log.InfoFormat("[INVENTORY ACCESS MODULE]: {0} enabled.", Name); |
||
99 | } |
||
100 | } |
||
101 | } |
||
102 | |||
103 | /// <summary> |
||
104 | /// Common module config for both this and descendant classes. |
||
105 | /// </summary> |
||
106 | /// <param name="source"></param> |
||
107 | protected virtual void InitialiseCommon(IConfigSource source) |
||
108 | { |
||
109 | IConfig inventoryConfig = source.Configs["Inventory"]; |
||
110 | |||
111 | if (inventoryConfig != null) |
||
112 | CoalesceMultipleObjectsToInventory |
||
113 | = inventoryConfig.GetBoolean("CoalesceMultipleObjectsToInventory", true); |
||
114 | else |
||
115 | CoalesceMultipleObjectsToInventory = true; |
||
116 | } |
||
117 | |||
118 | public virtual void PostInitialise() |
||
119 | { |
||
120 | } |
||
121 | |||
122 | public virtual void AddRegion(Scene scene) |
||
123 | { |
||
124 | if (!m_Enabled) |
||
125 | return; |
||
126 | |||
127 | m_Scene = scene; |
||
128 | |||
129 | scene.RegisterModuleInterface<IInventoryAccessModule>(this); |
||
130 | scene.EventManager.OnNewClient += OnNewClient; |
||
131 | } |
||
132 | |||
133 | protected virtual void OnNewClient(IClientAPI client) |
||
134 | { |
||
135 | client.OnCreateNewInventoryItem += CreateNewInventoryItem; |
||
136 | } |
||
137 | |||
138 | public virtual void Close() |
||
139 | { |
||
140 | if (!m_Enabled) |
||
141 | return; |
||
142 | } |
||
143 | |||
144 | |||
145 | public virtual void RemoveRegion(Scene scene) |
||
146 | { |
||
147 | if (!m_Enabled) |
||
148 | return; |
||
149 | m_Scene = null; |
||
150 | } |
||
151 | |||
152 | public virtual void RegionLoaded(Scene scene) |
||
153 | { |
||
154 | if (!m_Enabled) |
||
155 | return; |
||
156 | } |
||
157 | |||
158 | #endregion |
||
159 | |||
160 | #region Inventory Access |
||
161 | |||
162 | /// <summary> |
||
163 | /// Create a new inventory item. Called when the client creates a new item directly within their |
||
164 | /// inventory (e.g. by selecting a context inventory menu option). |
||
165 | /// </summary> |
||
166 | /// <param name="remoteClient"></param> |
||
167 | /// <param name="transactionID"></param> |
||
168 | /// <param name="folderID"></param> |
||
169 | /// <param name="callbackID"></param> |
||
170 | /// <param name="description"></param> |
||
171 | /// <param name="name"></param> |
||
172 | /// <param name="invType"></param> |
||
173 | /// <param name="type"></param> |
||
174 | /// <param name="wearableType"></param> |
||
175 | /// <param name="nextOwnerMask"></param> |
||
176 | public void CreateNewInventoryItem(IClientAPI remoteClient, UUID transactionID, UUID folderID, |
||
177 | uint callbackID, string description, string name, sbyte invType, |
||
178 | sbyte assetType, |
||
179 | byte wearableType, uint nextOwnerMask, int creationDate) |
||
180 | { |
||
181 | m_log.DebugFormat("[INVENTORY ACCESS MODULE]: Received request to create inventory item {0} in folder {1}", name, folderID); |
||
182 | |||
183 | if (!m_Scene.Permissions.CanCreateUserInventory(invType, remoteClient.AgentId)) |
||
184 | return; |
||
185 | |||
186 | if (transactionID == UUID.Zero) |
||
187 | { |
||
188 | ScenePresence presence; |
||
189 | if (m_Scene.TryGetScenePresence(remoteClient.AgentId, out presence)) |
||
190 | { |
||
191 | byte[] data = null; |
||
192 | |||
193 | if (invType == (sbyte)InventoryType.Landmark && presence != null) |
||
194 | { |
||
195 | string suffix = string.Empty, prefix = string.Empty; |
||
196 | string strdata = GenerateLandmark(presence, out prefix, out suffix); |
||
197 | data = Encoding.ASCII.GetBytes(strdata); |
||
198 | name = prefix + name; |
||
199 | description += suffix; |
||
200 | } |
||
201 | |||
202 | AssetBase asset = m_Scene.CreateAsset(name, description, assetType, data, remoteClient.AgentId); |
||
203 | m_Scene.AssetService.Store(asset); |
||
204 | m_Scene.CreateNewInventoryItem( |
||
205 | remoteClient, remoteClient.AgentId.ToString(), string.Empty, folderID, |
||
206 | name, description, 0, callbackID, asset.FullID, asset.Type, invType, nextOwnerMask, creationDate); |
||
207 | } |
||
208 | else |
||
209 | { |
||
210 | m_log.ErrorFormat( |
||
211 | "[INVENTORY ACCESS MODULE]: ScenePresence for agent uuid {0} unexpectedly not found in CreateNewInventoryItem", |
||
212 | remoteClient.AgentId); |
||
213 | } |
||
214 | } |
||
215 | else |
||
216 | { |
||
217 | IAgentAssetTransactions agentTransactions = m_Scene.AgentTransactionsModule; |
||
218 | if (agentTransactions != null) |
||
219 | { |
||
220 | agentTransactions.HandleItemCreationFromTransaction( |
||
221 | remoteClient, transactionID, folderID, callbackID, description, |
||
222 | name, invType, assetType, wearableType, nextOwnerMask); |
||
223 | } |
||
224 | } |
||
225 | } |
||
226 | |||
227 | protected virtual string GenerateLandmark(ScenePresence presence, out string prefix, out string suffix) |
||
228 | { |
||
229 | prefix = string.Empty; |
||
230 | suffix = string.Empty; |
||
231 | Vector3 pos = presence.AbsolutePosition; |
||
232 | return String.Format("Landmark version 2\nregion_id {0}\nlocal_pos {1} {2} {3}\nregion_handle {4}\n", |
||
233 | presence.Scene.RegionInfo.RegionID, |
||
234 | pos.X, pos.Y, pos.Z, |
||
235 | presence.RegionHandle); |
||
236 | } |
||
237 | |||
238 | /// <summary> |
||
239 | /// Capability originating call to update the asset of an item in an agent's inventory |
||
240 | /// </summary> |
||
241 | /// <param name="remoteClient"></param> |
||
242 | /// <param name="itemID"></param> |
||
243 | /// <param name="data"></param> |
||
244 | /// <returns></returns> |
||
245 | public virtual UUID CapsUpdateInventoryItemAsset(IClientAPI remoteClient, UUID itemID, byte[] data) |
||
246 | { |
||
247 | InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); |
||
248 | item = m_Scene.InventoryService.GetItem(item); |
||
249 | |||
250 | if (item.Owner != remoteClient.AgentId) |
||
251 | return UUID.Zero; |
||
252 | |||
253 | if (item != null) |
||
254 | { |
||
255 | if ((InventoryType)item.InvType == InventoryType.Notecard) |
||
256 | { |
||
257 | if (!m_Scene.Permissions.CanEditNotecard(itemID, UUID.Zero, remoteClient.AgentId)) |
||
258 | { |
||
259 | remoteClient.SendAgentAlertMessage("Insufficient permissions to edit notecard", false); |
||
260 | return UUID.Zero; |
||
261 | } |
||
262 | |||
263 | remoteClient.SendAlertMessage("Notecard saved"); |
||
264 | } |
||
265 | else if ((InventoryType)item.InvType == InventoryType.LSL) |
||
266 | { |
||
267 | if (!m_Scene.Permissions.CanEditScript(itemID, UUID.Zero, remoteClient.AgentId)) |
||
268 | { |
||
269 | remoteClient.SendAgentAlertMessage("Insufficient permissions to edit script", false); |
||
270 | return UUID.Zero; |
||
271 | } |
||
272 | |||
273 | remoteClient.SendAlertMessage("Script saved"); |
||
274 | } |
||
275 | |||
276 | AssetBase asset = |
||
277 | CreateAsset(item.Name, item.Description, (sbyte)item.AssetType, data, remoteClient.AgentId.ToString()); |
||
278 | item.AssetID = asset.FullID; |
||
279 | m_Scene.AssetService.Store(asset); |
||
280 | |||
281 | m_Scene.InventoryService.UpdateItem(item); |
||
282 | |||
283 | // remoteClient.SendInventoryItemCreateUpdate(item); |
||
284 | return (asset.FullID); |
||
285 | } |
||
286 | else |
||
287 | { |
||
288 | m_log.ErrorFormat( |
||
289 | "[INVENTORY ACCESS MODULE]: Could not find item {0} for caps inventory update", |
||
290 | itemID); |
||
291 | } |
||
292 | |||
293 | return UUID.Zero; |
||
294 | } |
||
295 | |||
296 | public virtual bool UpdateInventoryItemAsset(UUID ownerID, InventoryItemBase item, AssetBase asset) |
||
297 | { |
||
298 | if (item != null && item.Owner == ownerID && asset != null) |
||
299 | { |
||
300 | item.AssetID = asset.FullID; |
||
301 | item.Description = asset.Description; |
||
302 | item.Name = asset.Name; |
||
303 | item.AssetType = asset.Type; |
||
304 | item.InvType = (int)InventoryType.Object; |
||
305 | |||
306 | m_Scene.AssetService.Store(asset); |
||
307 | m_Scene.InventoryService.UpdateItem(item); |
||
308 | |||
309 | return true; |
||
310 | } |
||
311 | else |
||
312 | { |
||
313 | m_log.ErrorFormat("[INVENTORY ACCESS MODULE]: Given invalid item for inventory update: {0}", |
||
314 | (item == null || asset == null? "null item or asset" : "wrong owner")); |
||
315 | return false; |
||
316 | } |
||
317 | |||
318 | } |
||
319 | |||
320 | public virtual List<InventoryItemBase> CopyToInventory( |
||
321 | DeRezAction action, UUID folderID, |
||
322 | List<SceneObjectGroup> objectGroups, IClientAPI remoteClient, bool asAttachment) |
||
323 | { |
||
324 | List<InventoryItemBase> copiedItems = new List<InventoryItemBase>(); |
||
325 | |||
326 | Dictionary<UUID, List<SceneObjectGroup>> bundlesToCopy = new Dictionary<UUID, List<SceneObjectGroup>>(); |
||
327 | |||
328 | if (CoalesceMultipleObjectsToInventory) |
||
329 | { |
||
330 | // The following code groups the SOG's by owner. No objects |
||
331 | // belonging to different people can be coalesced, for obvious |
||
332 | // reasons. |
||
333 | foreach (SceneObjectGroup g in objectGroups) |
||
334 | { |
||
335 | if (!bundlesToCopy.ContainsKey(g.OwnerID)) |
||
336 | bundlesToCopy[g.OwnerID] = new List<SceneObjectGroup>(); |
||
337 | |||
338 | bundlesToCopy[g.OwnerID].Add(g); |
||
339 | } |
||
340 | } |
||
341 | else |
||
342 | { |
||
343 | // If we don't want to coalesce then put every object in its own bundle. |
||
344 | foreach (SceneObjectGroup g in objectGroups) |
||
345 | { |
||
346 | List<SceneObjectGroup> bundle = new List<SceneObjectGroup>(); |
||
347 | bundle.Add(g); |
||
348 | bundlesToCopy[g.UUID] = bundle; |
||
349 | } |
||
350 | } |
||
351 | |||
352 | // m_log.DebugFormat( |
||
353 | // "[INVENTORY ACCESS MODULE]: Copying {0} object bundles to folder {1} action {2} for {3}", |
||
354 | // bundlesToCopy.Count, folderID, action, remoteClient.Name); |
||
355 | |||
356 | // Each iteration is really a separate asset being created, |
||
357 | // with distinct destinations as well. |
||
358 | foreach (List<SceneObjectGroup> bundle in bundlesToCopy.Values) |
||
359 | copiedItems.Add(CopyBundleToInventory(action, folderID, bundle, remoteClient, asAttachment)); |
||
360 | |||
361 | return copiedItems; |
||
362 | } |
||
363 | |||
364 | /// <summary> |
||
365 | /// Copy a bundle of objects to inventory. If there is only one object, then this will create an object |
||
366 | /// item. If there are multiple objects then these will be saved as a single coalesced item. |
||
367 | /// </summary> |
||
368 | /// <param name="action"></param> |
||
369 | /// <param name="folderID"></param> |
||
370 | /// <param name="objlist"></param> |
||
371 | /// <param name="remoteClient"></param> |
||
372 | /// <param name="asAttachment">Should be true if the bundle is being copied as an attachment. This prevents |
||
373 | /// attempted serialization of any script state which would abort any operating scripts.</param> |
||
374 | /// <returns>The inventory item created by the copy</returns> |
||
375 | protected InventoryItemBase CopyBundleToInventory( |
||
376 | DeRezAction action, UUID folderID, List<SceneObjectGroup> objlist, IClientAPI remoteClient, |
||
377 | bool asAttachment) |
||
378 | { |
||
379 | CoalescedSceneObjects coa = new CoalescedSceneObjects(UUID.Zero); |
||
380 | // Dictionary<UUID, Vector3> originalPositions = new Dictionary<UUID, Vector3>(); |
||
381 | |||
382 | Dictionary<SceneObjectGroup, KeyframeMotion> group2Keyframe = new Dictionary<SceneObjectGroup, KeyframeMotion>(); |
||
383 | |||
384 | foreach (SceneObjectGroup objectGroup in objlist) |
||
385 | { |
||
386 | if (objectGroup.RootPart.KeyframeMotion != null) |
||
387 | { |
||
388 | objectGroup.RootPart.KeyframeMotion.Pause(); |
||
389 | group2Keyframe.Add(objectGroup, objectGroup.RootPart.KeyframeMotion); |
||
390 | objectGroup.RootPart.KeyframeMotion = null; |
||
391 | } |
||
392 | |||
393 | // Vector3 inventoryStoredPosition = new Vector3 |
||
394 | // (((objectGroup.AbsolutePosition.X > (int)Constants.RegionSize) |
||
395 | // ? 250 |
||
396 | // : objectGroup.AbsolutePosition.X) |
||
397 | // , |
||
398 | // (objectGroup.AbsolutePosition.Y > (int)Constants.RegionSize) |
||
399 | // ? 250 |
||
400 | // : objectGroup.AbsolutePosition.Y, |
||
401 | // objectGroup.AbsolutePosition.Z); |
||
402 | // |
||
403 | // originalPositions[objectGroup.UUID] = objectGroup.AbsolutePosition; |
||
404 | // |
||
405 | // objectGroup.AbsolutePosition = inventoryStoredPosition; |
||
406 | |||
407 | // Make sure all bits but the ones we want are clear |
||
408 | // on take. |
||
409 | // This will be applied to the current perms, so |
||
410 | // it will do what we want. |
||
411 | objectGroup.RootPart.NextOwnerMask &= |
||
412 | ((uint)PermissionMask.Copy | |
||
413 | (uint)PermissionMask.Transfer | |
||
414 | (uint)PermissionMask.Modify | |
||
415 | (uint)PermissionMask.Export); |
||
416 | objectGroup.RootPart.NextOwnerMask |= |
||
417 | (uint)PermissionMask.Move; |
||
418 | |||
419 | coa.Add(objectGroup); |
||
420 | } |
||
421 | |||
422 | string itemXml; |
||
423 | |||
424 | // If we're being called from a script, then trying to serialize that same script's state will not complete |
||
425 | // in any reasonable time period. Therefore, we'll avoid it. The worst that can happen is that if |
||
426 | // the client/server crashes rather than logging out normally, the attachment's scripts will resume |
||
427 | // without state on relog. Arguably, this is what we want anyway. |
||
428 | if (objlist.Count > 1) |
||
429 | itemXml = CoalescedSceneObjectsSerializer.ToXml(coa, !asAttachment); |
||
430 | else |
||
431 | itemXml = SceneObjectSerializer.ToOriginalXmlFormat(objlist[0], !asAttachment); |
||
432 | |||
433 | // // Restore the position of each group now that it has been stored to inventory. |
||
434 | // foreach (SceneObjectGroup objectGroup in objlist) |
||
435 | // objectGroup.AbsolutePosition = originalPositions[objectGroup.UUID]; |
||
436 | |||
437 | InventoryItemBase item = CreateItemForObject(action, remoteClient, objlist[0], folderID); |
||
438 | |||
439 | // m_log.DebugFormat( |
||
440 | // "[INVENTORY ACCESS MODULE]: Created item is {0}", |
||
441 | // item != null ? item.ID.ToString() : "NULL"); |
||
442 | |||
443 | if (item == null) |
||
444 | return null; |
||
445 | |||
446 | item.CreatorId = objlist[0].RootPart.CreatorID.ToString(); |
||
447 | item.CreatorData = objlist[0].RootPart.CreatorData; |
||
448 | |||
449 | if (objlist.Count > 1) |
||
450 | { |
||
451 | item.Flags = (uint)InventoryItemFlags.ObjectHasMultipleItems; |
||
452 | |||
453 | // If the objects have different creators then don't specify a creator at all |
||
454 | foreach (SceneObjectGroup objectGroup in objlist) |
||
455 | { |
||
456 | if ((objectGroup.RootPart.CreatorID.ToString() != item.CreatorId) |
||
457 | || (objectGroup.RootPart.CreatorData.ToString() != item.CreatorData)) |
||
458 | { |
||
459 | item.CreatorId = UUID.Zero.ToString(); |
||
460 | item.CreatorData = string.Empty; |
||
461 | break; |
||
462 | } |
||
463 | } |
||
464 | } |
||
465 | else |
||
466 | { |
||
467 | item.SaleType = objlist[0].RootPart.ObjectSaleType; |
||
468 | item.SalePrice = objlist[0].RootPart.SalePrice; |
||
469 | } |
||
470 | |||
471 | AssetBase asset = CreateAsset( |
||
472 | objlist[0].GetPartName(objlist[0].RootPart.LocalId), |
||
473 | objlist[0].GetPartDescription(objlist[0].RootPart.LocalId), |
||
474 | (sbyte)AssetType.Object, |
||
475 | Utils.StringToBytes(itemXml), |
||
476 | objlist[0].OwnerID.ToString()); |
||
477 | m_Scene.AssetService.Store(asset); |
||
478 | |||
479 | item.AssetID = asset.FullID; |
||
480 | |||
481 | if (DeRezAction.SaveToExistingUserInventoryItem == action) |
||
482 | { |
||
483 | m_Scene.InventoryService.UpdateItem(item); |
||
484 | } |
||
485 | else |
||
486 | { |
||
487 | item.CreationDate = Util.UnixTimeSinceEpoch(); |
||
488 | item.Description = asset.Description; |
||
489 | item.Name = asset.Name; |
||
490 | item.AssetType = asset.Type; |
||
491 | |||
492 | AddPermissions(item, objlist[0], objlist, remoteClient); |
||
493 | |||
494 | m_Scene.AddInventoryItem(item); |
||
495 | |||
496 | if (remoteClient != null && item.Owner == remoteClient.AgentId) |
||
497 | { |
||
498 | remoteClient.SendInventoryItemCreateUpdate(item, 0); |
||
499 | } |
||
500 | else |
||
501 | { |
||
502 | ScenePresence notifyUser = m_Scene.GetScenePresence(item.Owner); |
||
503 | if (notifyUser != null) |
||
504 | { |
||
505 | notifyUser.ControllingClient.SendInventoryItemCreateUpdate(item, 0); |
||
506 | } |
||
507 | } |
||
508 | } |
||
509 | |||
510 | // Restore KeyframeMotion |
||
511 | foreach (SceneObjectGroup objectGroup in group2Keyframe.Keys) |
||
512 | { |
||
513 | objectGroup.RootPart.KeyframeMotion = group2Keyframe[objectGroup]; |
||
514 | objectGroup.RootPart.KeyframeMotion.Start(); |
||
515 | } |
||
516 | |||
517 | // This is a hook to do some per-asset post-processing for subclasses that need that |
||
518 | if (remoteClient != null) |
||
519 | ExportAsset(remoteClient.AgentId, asset.FullID); |
||
520 | |||
521 | return item; |
||
522 | } |
||
523 | |||
524 | protected virtual void ExportAsset(UUID agentID, UUID assetID) |
||
525 | { |
||
526 | // nothing to do here |
||
527 | } |
||
528 | |||
529 | /// <summary> |
||
530 | /// Add relevant permissions for an object to the item. |
||
531 | /// </summary> |
||
532 | /// <param name="item"></param> |
||
533 | /// <param name="so"></param> |
||
534 | /// <param name="objsForEffectivePermissions"></param> |
||
535 | /// <param name="remoteClient"></param> |
||
536 | /// <returns></returns> |
||
537 | protected InventoryItemBase AddPermissions( |
||
538 | InventoryItemBase item, SceneObjectGroup so, List<SceneObjectGroup> objsForEffectivePermissions, |
||
539 | IClientAPI remoteClient) |
||
540 | { |
||
541 | uint effectivePerms = (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify | PermissionMask.Move | PermissionMask.Export) | 7; |
||
542 | uint allObjectsNextOwnerPerms = 0x7fffffff; |
||
543 | uint allObjectsEveryOnePerms = 0x7fffffff; |
||
544 | uint allObjectsGroupPerms = 0x7fffffff; |
||
545 | |||
546 | foreach (SceneObjectGroup grp in objsForEffectivePermissions) |
||
547 | { |
||
548 | effectivePerms &= grp.GetEffectivePermissions(); |
||
549 | allObjectsNextOwnerPerms &= grp.RootPart.NextOwnerMask; |
||
550 | allObjectsEveryOnePerms &= grp.RootPart.EveryoneMask; |
||
551 | allObjectsGroupPerms &= grp.RootPart.GroupMask; |
||
552 | } |
||
553 | effectivePerms |= (uint)PermissionMask.Move; |
||
554 | |||
555 | //PermissionsUtil.LogPermissions(item.Name, "Before AddPermissions", item.BasePermissions, item.CurrentPermissions, item.NextPermissions); |
||
556 | |||
557 | if (remoteClient != null && (remoteClient.AgentId != so.RootPart.OwnerID) && m_Scene.Permissions.PropagatePermissions()) |
||
558 | { |
||
559 | // Changing ownership, so apply the "Next Owner" permissions to all of the |
||
560 | // inventory item's permissions. |
||
561 | |||
562 | uint perms = effectivePerms; |
||
563 | PermissionsUtil.ApplyFoldedPermissions(effectivePerms, ref perms); |
||
564 | |||
565 | item.BasePermissions = perms & allObjectsNextOwnerPerms; |
||
566 | item.CurrentPermissions = item.BasePermissions; |
||
567 | item.NextPermissions = perms & allObjectsNextOwnerPerms; |
||
568 | item.EveryOnePermissions = allObjectsEveryOnePerms & allObjectsNextOwnerPerms; |
||
569 | item.GroupPermissions = allObjectsGroupPerms & allObjectsNextOwnerPerms; |
||
570 | |||
571 | // apply next owner perms on rez |
||
572 | item.CurrentPermissions |= SceneObjectGroup.SLAM; |
||
573 | } |
||
574 | else |
||
575 | { |
||
576 | // Not changing ownership. |
||
577 | // In this case we apply the permissions in the object's items ONLY to the inventory |
||
578 | // item's "Next Owner" permissions, but NOT to its "Current", "Base", etc. permissions. |
||
579 | // E.g., if the object contains a No-Transfer item then the item's "Next Owner" |
||
580 | // permissions are also No-Transfer. |
||
581 | PermissionsUtil.ApplyFoldedPermissions(effectivePerms, ref allObjectsNextOwnerPerms); |
||
582 | |||
583 | item.BasePermissions = effectivePerms; |
||
584 | item.CurrentPermissions = effectivePerms; |
||
585 | item.NextPermissions = allObjectsNextOwnerPerms & effectivePerms; |
||
586 | item.EveryOnePermissions = allObjectsEveryOnePerms & effectivePerms; |
||
587 | item.GroupPermissions = allObjectsGroupPerms & effectivePerms; |
||
588 | |||
589 | item.CurrentPermissions &= |
||
590 | ((uint)PermissionMask.Copy | |
||
591 | (uint)PermissionMask.Transfer | |
||
592 | (uint)PermissionMask.Modify | |
||
593 | (uint)PermissionMask.Move | |
||
594 | (uint)PermissionMask.Export | |
||
595 | 7); // Preserve folded permissions |
||
596 | } |
||
597 | |||
598 | //PermissionsUtil.LogPermissions(item.Name, "After AddPermissions", item.BasePermissions, item.CurrentPermissions, item.NextPermissions); |
||
599 | |||
600 | return item; |
||
601 | } |
||
602 | |||
603 | /// <summary> |
||
604 | /// Create an item using details for the given scene object. |
||
605 | /// </summary> |
||
606 | /// <param name="action"></param> |
||
607 | /// <param name="remoteClient"></param> |
||
608 | /// <param name="so"></param> |
||
609 | /// <param name="folderID"></param> |
||
610 | /// <returns></returns> |
||
611 | protected InventoryItemBase CreateItemForObject( |
||
612 | DeRezAction action, IClientAPI remoteClient, SceneObjectGroup so, UUID folderID) |
||
613 | { |
||
614 | // Get the user info of the item destination |
||
615 | // |
||
616 | UUID userID = UUID.Zero; |
||
617 | |||
618 | if (action == DeRezAction.Take || action == DeRezAction.TakeCopy || |
||
619 | action == DeRezAction.SaveToExistingUserInventoryItem) |
||
620 | { |
||
621 | // Take or take copy require a taker |
||
622 | // Saving changes requires a local user |
||
623 | // |
||
624 | if (remoteClient == null) |
||
625 | return null; |
||
626 | |||
627 | userID = remoteClient.AgentId; |
||
628 | |||
629 | // m_log.DebugFormat( |
||
630 | // "[INVENTORY ACCESS MODULE]: Target of {0} in CreateItemForObject() is {1} {2}", |
||
631 | // action, remoteClient.Name, userID); |
||
632 | } |
||
633 | else if (so.RootPart.OwnerID == so.RootPart.GroupID) |
||
634 | { |
||
635 | // Group owned objects go to the last owner before the object was transferred. |
||
636 | userID = so.RootPart.LastOwnerID; |
||
637 | } |
||
638 | else |
||
639 | { |
||
640 | // Other returns / deletes go to the object owner |
||
641 | // |
||
642 | userID = so.RootPart.OwnerID; |
||
643 | |||
644 | // m_log.DebugFormat( |
||
645 | // "[INVENTORY ACCESS MODULE]: Target of {0} in CreateItemForObject() is object owner {1}", |
||
646 | // action, userID); |
||
647 | } |
||
648 | |||
649 | if (userID == UUID.Zero) // Can't proceed |
||
650 | { |
||
651 | return null; |
||
652 | } |
||
653 | |||
654 | // If we're returning someone's item, it goes back to the |
||
655 | // owner's Lost And Found folder. |
||
656 | // Delete is treated like return in this case |
||
657 | // Deleting your own items makes them go to trash |
||
658 | // |
||
659 | |||
660 | InventoryFolderBase folder = null; |
||
661 | InventoryItemBase item = null; |
||
662 | |||
663 | if (DeRezAction.SaveToExistingUserInventoryItem == action) |
||
664 | { |
||
665 | item = new InventoryItemBase(so.RootPart.FromUserInventoryItemID, userID); |
||
666 | item = m_Scene.InventoryService.GetItem(item); |
||
667 | |||
668 | //item = userInfo.RootFolder.FindItem( |
||
669 | // objectGroup.RootPart.FromUserInventoryItemID); |
||
670 | |||
671 | if (null == item) |
||
672 | { |
||
673 | m_log.DebugFormat( |
||
674 | "[INVENTORY ACCESS MODULE]: Object {0} {1} scheduled for save to inventory has already been deleted.", |
||
675 | so.Name, so.UUID); |
||
676 | |||
677 | return null; |
||
678 | } |
||
679 | } |
||
680 | else |
||
681 | { |
||
682 | // Folder magic |
||
683 | // |
||
684 | if (action == DeRezAction.Delete) |
||
685 | { |
||
686 | // Deleting someone else's item |
||
687 | // |
||
688 | if (remoteClient == null || |
||
689 | so.OwnerID != remoteClient.AgentId) |
||
690 | { |
||
691 | folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); |
||
692 | } |
||
693 | else |
||
694 | { |
||
695 | folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder); |
||
696 | } |
||
697 | } |
||
698 | else if (action == DeRezAction.Return) |
||
699 | { |
||
700 | // Dump to lost + found unconditionally |
||
701 | // |
||
702 | folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); |
||
703 | } |
||
704 | |||
705 | if (folderID == UUID.Zero && folder == null) |
||
706 | { |
||
707 | if (action == DeRezAction.Delete) |
||
708 | { |
||
709 | // Deletes go to trash by default |
||
710 | // |
||
711 | folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder); |
||
712 | } |
||
713 | else |
||
714 | { |
||
715 | if (remoteClient == null || so.RootPart.OwnerID != remoteClient.AgentId) |
||
716 | { |
||
717 | // Taking copy of another person's item. Take to |
||
718 | // Objects folder. |
||
719 | folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.Object); |
||
720 | so.FromFolderID = UUID.Zero; |
||
721 | } |
||
722 | else |
||
723 | { |
||
724 | // Catch all. Use lost & found |
||
725 | // |
||
726 | folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); |
||
727 | } |
||
728 | } |
||
729 | } |
||
730 | |||
731 | // Override and put into where it came from, if it came |
||
732 | // from anywhere in inventory and the owner is taking it back. |
||
733 | // |
||
734 | if (action == DeRezAction.Take || action == DeRezAction.TakeCopy) |
||
735 | { |
||
736 | if (so.FromFolderID != UUID.Zero && so.RootPart.OwnerID == remoteClient.AgentId) |
||
737 | { |
||
738 | InventoryFolderBase f = new InventoryFolderBase(so.FromFolderID, userID); |
||
739 | folder = m_Scene.InventoryService.GetFolder(f); |
||
740 | |||
741 | if(folder.Type == 14 || folder.Type == 16) |
||
742 | { |
||
743 | // folder.Type = 6; |
||
744 | folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.Object); |
||
745 | } |
||
746 | } |
||
747 | } |
||
748 | |||
749 | if (folder == null) // None of the above |
||
750 | { |
||
751 | folder = new InventoryFolderBase(folderID); |
||
752 | |||
753 | if (folder == null) // Nowhere to put it |
||
754 | { |
||
755 | return null; |
||
756 | } |
||
757 | } |
||
758 | |||
759 | item = new InventoryItemBase(); |
||
760 | item.ID = UUID.Random(); |
||
761 | item.InvType = (int)InventoryType.Object; |
||
762 | item.Folder = folder.ID; |
||
763 | item.Owner = userID; |
||
764 | } |
||
765 | |||
766 | return item; |
||
767 | } |
||
768 | |||
769 | public virtual SceneObjectGroup RezObject( |
||
770 | IClientAPI remoteClient, UUID itemID, Vector3 RayEnd, Vector3 RayStart, |
||
771 | UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, |
||
772 | bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment) |
||
773 | { |
||
774 | // m_log.DebugFormat("[INVENTORY ACCESS MODULE]: RezObject for {0}, item {1}", remoteClient.Name, itemID); |
||
775 | |||
776 | InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); |
||
777 | item = m_Scene.InventoryService.GetItem(item); |
||
778 | |||
779 | if (item == null) |
||
780 | { |
||
781 | m_log.WarnFormat( |
||
782 | "[INVENTORY ACCESS MODULE]: Could not find item {0} for {1} in RezObject()", |
||
783 | itemID, remoteClient.Name); |
||
784 | |||
785 | return null; |
||
786 | } |
||
787 | |||
788 | item.Owner = remoteClient.AgentId; |
||
789 | |||
790 | return RezObject( |
||
791 | remoteClient, item, item.AssetID, |
||
792 | RayEnd, RayStart, RayTargetID, BypassRayCast, RayEndIsIntersection, |
||
793 | RezSelected, RemoveItem, fromTaskID, attachment); |
||
794 | } |
||
795 | |||
796 | public virtual SceneObjectGroup RezObject( |
||
797 | IClientAPI remoteClient, InventoryItemBase item, UUID assetID, Vector3 RayEnd, Vector3 RayStart, |
||
798 | UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, |
||
799 | bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment) |
||
800 | { |
||
801 | AssetBase rezAsset = m_Scene.AssetService.Get(assetID.ToString()); |
||
802 | |||
803 | if (rezAsset == null) |
||
804 | { |
||
805 | if (item != null) |
||
806 | { |
||
807 | m_log.WarnFormat( |
||
808 | "[InventoryAccessModule]: Could not find asset {0} for item {1} {2} for {3} in RezObject()", |
||
809 | assetID, item.Name, item.ID, remoteClient.Name); |
||
810 | remoteClient.SendAgentAlertMessage(string.Format("Unable to rez: could not find asset {0} for item {1}.", assetID, item.Name), false); |
||
811 | } |
||
812 | else |
||
813 | { |
||
814 | m_log.WarnFormat( |
||
815 | "[INVENTORY ACCESS MODULE]: Could not find asset {0} for {1} in RezObject()", |
||
816 | assetID, remoteClient.Name); |
||
817 | remoteClient.SendAgentAlertMessage(string.Format("Unable to rez: could not find asset {0}.", assetID), false); |
||
818 | } |
||
819 | |||
820 | return null; |
||
821 | } |
||
822 | |||
823 | SceneObjectGroup group = null; |
||
824 | |||
825 | List<SceneObjectGroup> objlist; |
||
826 | List<Vector3> veclist; |
||
827 | Vector3 bbox; |
||
828 | float offsetHeight; |
||
829 | byte bRayEndIsIntersection = (byte)(RayEndIsIntersection ? 1 : 0); |
||
830 | Vector3 pos; |
||
831 | |||
832 | bool single |
||
833 | = m_Scene.GetObjectsToRez( |
||
834 | rezAsset.Data, attachment, out objlist, out veclist, out bbox, out offsetHeight); |
||
835 | |||
836 | if (single) |
||
837 | { |
||
838 | pos = m_Scene.GetNewRezLocation( |
||
839 | RayStart, RayEnd, RayTargetID, Quaternion.Identity, |
||
840 | BypassRayCast, bRayEndIsIntersection, true, bbox, false); |
||
841 | pos.Z += offsetHeight; |
||
842 | } |
||
843 | else |
||
844 | { |
||
845 | pos = m_Scene.GetNewRezLocation(RayStart, RayEnd, |
||
846 | RayTargetID, Quaternion.Identity, |
||
847 | BypassRayCast, bRayEndIsIntersection, true, |
||
848 | bbox, false); |
||
849 | pos -= bbox / 2; |
||
850 | } |
||
851 | |||
852 | if (item != null && !DoPreRezWhenFromItem(remoteClient, item, objlist, pos, veclist, attachment)) |
||
853 | return null; |
||
854 | |||
855 | for (int i = 0; i < objlist.Count; i++) |
||
856 | { |
||
857 | group = objlist[i]; |
||
858 | |||
859 | // m_log.DebugFormat( |
||
860 | // "[INVENTORY ACCESS MODULE]: Preparing to rez {0} {1} {2} ownermask={3:X} nextownermask={4:X} groupmask={5:X} everyonemask={6:X} for {7}", |
||
861 | // group.Name, group.LocalId, group.UUID, |
||
862 | // group.RootPart.OwnerMask, group.RootPart.NextOwnerMask, group.RootPart.GroupMask, group.RootPart.EveryoneMask, |
||
863 | // remoteClient.Name); |
||
864 | |||
865 | // Vector3 storedPosition = group.AbsolutePosition; |
||
866 | if (group.UUID == UUID.Zero) |
||
867 | { |
||
868 | m_log.Debug("[INVENTORY ACCESS MODULE]: Object has UUID.Zero! Position 3"); |
||
869 | } |
||
870 | |||
871 | // if this was previously an attachment and is now being rezzed, |
||
872 | // save the old attachment info. |
||
873 | if (group.IsAttachment == false && group.RootPart.Shape.State != 0) |
||
874 | { |
||
875 | group.RootPart.AttachedPos = group.AbsolutePosition; |
||
876 | group.RootPart.Shape.LastAttachPoint = (byte)group.AttachmentPoint; |
||
877 | } |
||
878 | |||
879 | if (item == null) |
||
880 | { |
||
881 | // Change ownership. Normally this is done in DoPreRezWhenFromItem(), but in this case we must do it here. |
||
882 | foreach (SceneObjectPart part in group.Parts) |
||
883 | { |
||
884 | // Make the rezzer the owner, as this is not necessarily set correctly in the serialized asset. |
||
885 | part.LastOwnerID = part.OwnerID; |
||
886 | part.OwnerID = remoteClient.AgentId; |
||
887 | } |
||
888 | } |
||
889 | |||
890 | if (!attachment) |
||
891 | { |
||
892 | // If it's rezzed in world, select it. Much easier to |
||
893 | // find small items. |
||
894 | // |
||
895 | foreach (SceneObjectPart part in group.Parts) |
||
896 | { |
||
897 | part.CreateSelected = true; |
||
898 | } |
||
899 | } |
||
900 | |||
901 | group.ResetIDs(); |
||
902 | |||
903 | if (attachment) |
||
904 | { |
||
905 | group.RootPart.Flags |= PrimFlags.Phantom; |
||
906 | group.IsAttachment = true; |
||
907 | } |
||
908 | |||
909 | // If we're rezzing an attachment then don't ask |
||
910 | // AddNewSceneObject() to update the client since |
||
911 | // we'll be doing that later on. Scheduling more than |
||
912 | // one full update during the attachment |
||
913 | // process causes some clients to fail to display the |
||
914 | // attachment properly. |
||
915 | m_Scene.AddNewSceneObject(group, true, false); |
||
916 | |||
917 | // if attachment we set it's asset id so object updates |
||
918 | // can reflect that, if not, we set it's position in world. |
||
919 | if (!attachment) |
||
920 | { |
||
921 | group.ScheduleGroupForFullUpdate(); |
||
922 | |||
923 | group.AbsolutePosition = pos + veclist[i]; |
||
924 | } |
||
925 | |||
926 | group.SetGroup(remoteClient.ActiveGroupId, remoteClient); |
||
927 | |||
928 | if (!attachment) |
||
929 | { |
||
930 | SceneObjectPart rootPart = group.RootPart; |
||
931 | |||
932 | if (rootPart.Shape.PCode == (byte)PCode.Prim) |
||
933 | group.ClearPartAttachmentData(); |
||
934 | |||
935 | // Fire on_rez |
||
936 | group.CreateScriptInstances(0, true, m_Scene.DefaultScriptEngine, 1); |
||
937 | rootPart.ParentGroup.ResumeScripts(); |
||
938 | |||
939 | rootPart.ScheduleFullUpdate(); |
||
940 | } |
||
941 | |||
942 | // m_log.DebugFormat( |
||
943 | // "[INVENTORY ACCESS MODULE]: Rezzed {0} {1} {2} ownermask={3:X} nextownermask={4:X} groupmask={5:X} everyonemask={6:X} for {7}", |
||
944 | // group.Name, group.LocalId, group.UUID, |
||
945 | // group.RootPart.OwnerMask, group.RootPart.NextOwnerMask, group.RootPart.GroupMask, group.RootPart.EveryoneMask, |
||
946 | // remoteClient.Name); |
||
947 | } |
||
948 | |||
949 | if (item != null) |
||
950 | DoPostRezWhenFromItem(item, attachment); |
||
951 | |||
952 | return group; |
||
953 | } |
||
954 | |||
955 | /// <summary> |
||
956 | /// Do pre-rez processing when the object comes from an item. |
||
957 | /// </summary> |
||
958 | /// <param name="remoteClient"></param> |
||
959 | /// <param name="item"></param> |
||
960 | /// <param name="objlist"></param> |
||
961 | /// <param name="pos"></param> |
||
962 | /// <param name="veclist"> |
||
963 | /// List of vector position adjustments for a coalesced objects. For ordinary objects |
||
964 | /// this list will contain just Vector3.Zero. The order of adjustments must match the order of objlist |
||
965 | /// </param> |
||
966 | /// <param name="isAttachment"></param> |
||
967 | /// <returns>true if we can processed with rezzing, false if we need to abort</returns> |
||
968 | private bool DoPreRezWhenFromItem( |
||
969 | IClientAPI remoteClient, InventoryItemBase item, List<SceneObjectGroup> objlist, |
||
970 | Vector3 pos, List<Vector3> veclist, bool isAttachment) |
||
971 | { |
||
972 | UUID fromUserInventoryItemId = UUID.Zero; |
||
973 | |||
974 | // If we have permission to copy then link the rezzed object back to the user inventory |
||
975 | // item that it came from. This allows us to enable 'save object to inventory' |
||
976 | if (!m_Scene.Permissions.BypassPermissions()) |
||
977 | { |
||
978 | if ((item.CurrentPermissions & (uint)PermissionMask.Copy) |
||
979 | == (uint)PermissionMask.Copy && (item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0) |
||
980 | { |
||
981 | fromUserInventoryItemId = item.ID; |
||
982 | } |
||
983 | } |
||
984 | else |
||
985 | { |
||
986 | if ((item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0) |
||
987 | { |
||
988 | // Brave new fullperm world |
||
989 | fromUserInventoryItemId = item.ID; |
||
990 | } |
||
991 | } |
||
992 | |||
993 | for (int i = 0; i < objlist.Count; i++) |
||
994 | { |
||
995 | SceneObjectGroup g = objlist[i]; |
||
996 | |||
997 | if (!m_Scene.Permissions.CanRezObject( |
||
998 | g.PrimCount, remoteClient.AgentId, pos + veclist[i]) |
||
999 | && !isAttachment) |
||
1000 | { |
||
1001 | // The client operates in no fail mode. It will |
||
1002 | // have already removed the item from the folder |
||
1003 | // if it's no copy. |
||
1004 | // Put it back if it's not an attachment |
||
1005 | // |
||
1006 | if (((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) && (!isAttachment)) |
||
1007 | remoteClient.SendBulkUpdateInventory(item); |
||
1008 | |||
1009 | ILandObject land = m_Scene.LandChannel.GetLandObject(pos.X, pos.Y); |
||
1010 | remoteClient.SendAlertMessage(string.Format( |
||
1011 | "Can't rez object '{0}' at <{1:F3}, {2:F3}, {3:F3}> on parcel '{4}' in region {5}.", |
||
1012 | item.Name, pos.X, pos.Y, pos.Z, land != null ? land.LandData.Name : "Unknown", m_Scene.Name)); |
||
1013 | |||
1014 | return false; |
||
1015 | } |
||
1016 | } |
||
1017 | |||
1018 | for (int i = 0; i < objlist.Count; i++) |
||
1019 | { |
||
1020 | SceneObjectGroup so = objlist[i]; |
||
1021 | SceneObjectPart rootPart = so.RootPart; |
||
1022 | |||
1023 | // Since renaming the item in the inventory does not |
||
1024 | // affect the name stored in the serialization, transfer |
||
1025 | // the correct name from the inventory to the |
||
1026 | // object itself before we rez. |
||
1027 | // |
||
1028 | // Only do these for the first object if we are rezzing a coalescence. |
||
1029 | if (i == 0) |
||
1030 | { |
||
1031 | rootPart.Name = item.Name; |
||
1032 | rootPart.Description = item.Description; |
||
1033 | rootPart.ObjectSaleType = item.SaleType; |
||
1034 | rootPart.SalePrice = item.SalePrice; |
||
1035 | } |
||
1036 | |||
1037 | so.FromFolderID = item.Folder; |
||
1038 | |||
1039 | // m_log.DebugFormat( |
||
1040 | // "[INVENTORY ACCESS MODULE]: rootPart.OwnedID {0}, item.Owner {1}, item.CurrentPermissions {2:X}", |
||
1041 | // rootPart.OwnerID, item.Owner, item.CurrentPermissions); |
||
1042 | |||
1043 | if ((rootPart.OwnerID != item.Owner) || (item.CurrentPermissions & SceneObjectGroup.SLAM) != 0) |
||
1044 | { |
||
1045 | //Need to kill the for sale here |
||
1046 | rootPart.ObjectSaleType = 0; |
||
1047 | rootPart.SalePrice = 10; |
||
1048 | } |
||
1049 | |||
1050 | foreach (SceneObjectPart part in so.Parts) |
||
1051 | { |
||
1052 | part.FromUserInventoryItemID = fromUserInventoryItemId; |
||
1053 | part.ApplyPermissionsOnRez(item, true, m_Scene); |
||
1054 | } |
||
1055 | |||
1056 | rootPart.TrimPermissions(); |
||
1057 | |||
1058 | if (isAttachment) |
||
1059 | so.FromItemID = item.ID; |
||
1060 | } |
||
1061 | |||
1062 | return true; |
||
1063 | } |
||
1064 | |||
1065 | /// <summary> |
||
1066 | /// Do post-rez processing when the object comes from an item. |
||
1067 | /// </summary> |
||
1068 | /// <param name="item"></param> |
||
1069 | /// <param name="isAttachment"></param> |
||
1070 | private void DoPostRezWhenFromItem(InventoryItemBase item, bool isAttachment) |
||
1071 | { |
||
1072 | if (!m_Scene.Permissions.BypassPermissions()) |
||
1073 | { |
||
1074 | if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) |
||
1075 | { |
||
1076 | // If this is done on attachments, no |
||
1077 | // copy ones will be lost, so avoid it |
||
1078 | // |
||
1079 | if (!isAttachment) |
||
1080 | { |
||
1081 | List<UUID> uuids = new List<UUID>(); |
||
1082 | uuids.Add(item.ID); |
||
1083 | m_Scene.InventoryService.DeleteItems(item.Owner, uuids); |
||
1084 | } |
||
1085 | } |
||
1086 | } |
||
1087 | } |
||
1088 | |||
1089 | protected void AddUserData(SceneObjectGroup sog) |
||
1090 | { |
||
1091 | UserManagementModule.AddUser(sog.RootPart.CreatorID, sog.RootPart.CreatorData); |
||
1092 | foreach (SceneObjectPart sop in sog.Parts) |
||
1093 | UserManagementModule.AddUser(sop.CreatorID, sop.CreatorData); |
||
1094 | } |
||
1095 | |||
1096 | public virtual void TransferInventoryAssets(InventoryItemBase item, UUID sender, UUID receiver) |
||
1097 | { |
||
1098 | } |
||
1099 | |||
1100 | public virtual bool CanGetAgentInventoryItem(IClientAPI remoteClient, UUID itemID, UUID requestID) |
||
1101 | { |
||
1102 | InventoryItemBase assetRequestItem = GetItem(remoteClient.AgentId, itemID); |
||
1103 | |||
1104 | if (assetRequestItem == null) |
||
1105 | { |
||
1106 | ILibraryService lib = m_Scene.RequestModuleInterface<ILibraryService>(); |
||
1107 | |||
1108 | if (lib != null) |
||
1109 | assetRequestItem = lib.LibraryRootFolder.FindItem(itemID); |
||
1110 | |||
1111 | if (assetRequestItem == null) |
||
1112 | return false; |
||
1113 | } |
||
1114 | |||
1115 | // At this point, we need to apply perms |
||
1116 | // only to notecards and scripts. All |
||
1117 | // other asset types are always available |
||
1118 | // |
||
1119 | if (assetRequestItem.AssetType == (int)AssetType.LSLText) |
||
1120 | { |
||
1121 | if (!m_Scene.Permissions.CanViewScript(itemID, UUID.Zero, remoteClient.AgentId)) |
||
1122 | { |
||
1123 | remoteClient.SendAgentAlertMessage("Insufficient permissions to view script", false); |
||
1124 | return false; |
||
1125 | } |
||
1126 | } |
||
1127 | else if (assetRequestItem.AssetType == (int)AssetType.Notecard) |
||
1128 | { |
||
1129 | if (!m_Scene.Permissions.CanViewNotecard(itemID, UUID.Zero, remoteClient.AgentId)) |
||
1130 | { |
||
1131 | remoteClient.SendAgentAlertMessage("Insufficient permissions to view notecard", false); |
||
1132 | return false; |
||
1133 | } |
||
1134 | } |
||
1135 | |||
1136 | if (assetRequestItem.AssetID != requestID) |
||
1137 | { |
||
1138 | m_log.WarnFormat( |
||
1139 | "[INVENTORY ACCESS MODULE]: {0} requested asset {1} from item {2} but this does not match item's asset {3}", |
||
1140 | Name, requestID, itemID, assetRequestItem.AssetID); |
||
1141 | |||
1142 | return false; |
||
1143 | } |
||
1144 | |||
1145 | return true; |
||
1146 | } |
||
1147 | |||
1148 | |||
1149 | public virtual bool IsForeignUser(UUID userID, out string assetServerURL) |
||
1150 | { |
||
1151 | assetServerURL = string.Empty; |
||
1152 | return false; |
||
1153 | } |
||
1154 | |||
1155 | #endregion |
||
1156 | |||
1157 | #region Misc |
||
1158 | |||
1159 | /// <summary> |
||
1160 | /// Create a new asset data structure. |
||
1161 | /// </summary> |
||
1162 | /// <param name="name"></param> |
||
1163 | /// <param name="description"></param> |
||
1164 | /// <param name="invType"></param> |
||
1165 | /// <param name="assetType"></param> |
||
1166 | /// <param name="data"></param> |
||
1167 | /// <returns></returns> |
||
1168 | private AssetBase CreateAsset(string name, string description, sbyte assetType, byte[] data, string creatorID) |
||
1169 | { |
||
1170 | AssetBase asset = new AssetBase(UUID.Random(), name, assetType, creatorID); |
||
1171 | asset.Description = description; |
||
1172 | asset.Data = (data == null) ? new byte[1] : data; |
||
1173 | |||
1174 | return asset; |
||
1175 | } |
||
1176 | |||
1177 | protected virtual InventoryItemBase GetItem(UUID agentID, UUID itemID) |
||
1178 | { |
||
1179 | IInventoryService invService = m_Scene.RequestModuleInterface<IInventoryService>(); |
||
1180 | InventoryItemBase item = new InventoryItemBase(itemID, agentID); |
||
1181 | item = invService.GetItem(item); |
||
1182 | |||
1183 | if (item != null && item.CreatorData != null && item.CreatorData != string.Empty) |
||
1184 | UserManagementModule.AddUser(item.CreatorIdAsUuid, item.CreatorData); |
||
1185 | |||
1186 | return item; |
||
1187 | } |
||
1188 | |||
1189 | #endregion |
||
1190 | } |
||
1191 | } |