clockwerk-opensim-stable – 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, 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 List<InventoryItemBase> CopyToInventory( |
||
297 | DeRezAction action, UUID folderID, |
||
298 | List<SceneObjectGroup> objectGroups, IClientAPI remoteClient, bool asAttachment) |
||
299 | { |
||
300 | List<InventoryItemBase> copiedItems = new List<InventoryItemBase>(); |
||
301 | |||
302 | Dictionary<UUID, List<SceneObjectGroup>> bundlesToCopy = new Dictionary<UUID, List<SceneObjectGroup>>(); |
||
303 | |||
304 | if (CoalesceMultipleObjectsToInventory) |
||
305 | { |
||
306 | // The following code groups the SOG's by owner. No objects |
||
307 | // belonging to different people can be coalesced, for obvious |
||
308 | // reasons. |
||
309 | foreach (SceneObjectGroup g in objectGroups) |
||
310 | { |
||
311 | if (!bundlesToCopy.ContainsKey(g.OwnerID)) |
||
312 | bundlesToCopy[g.OwnerID] = new List<SceneObjectGroup>(); |
||
313 | |||
314 | bundlesToCopy[g.OwnerID].Add(g); |
||
315 | } |
||
316 | } |
||
317 | else |
||
318 | { |
||
319 | // If we don't want to coalesce then put every object in its own bundle. |
||
320 | foreach (SceneObjectGroup g in objectGroups) |
||
321 | { |
||
322 | List<SceneObjectGroup> bundle = new List<SceneObjectGroup>(); |
||
323 | bundle.Add(g); |
||
324 | bundlesToCopy[g.UUID] = bundle; |
||
325 | } |
||
326 | } |
||
327 | |||
328 | // m_log.DebugFormat( |
||
329 | // "[INVENTORY ACCESS MODULE]: Copying {0} object bundles to folder {1} action {2} for {3}", |
||
330 | // bundlesToCopy.Count, folderID, action, remoteClient.Name); |
||
331 | |||
332 | // Each iteration is really a separate asset being created, |
||
333 | // with distinct destinations as well. |
||
334 | foreach (List<SceneObjectGroup> bundle in bundlesToCopy.Values) |
||
335 | copiedItems.Add(CopyBundleToInventory(action, folderID, bundle, remoteClient, asAttachment)); |
||
336 | |||
337 | return copiedItems; |
||
338 | } |
||
339 | |||
340 | /// <summary> |
||
341 | /// Copy a bundle of objects to inventory. If there is only one object, then this will create an object |
||
342 | /// item. If there are multiple objects then these will be saved as a single coalesced item. |
||
343 | /// </summary> |
||
344 | /// <param name="action"></param> |
||
345 | /// <param name="folderID"></param> |
||
346 | /// <param name="objlist"></param> |
||
347 | /// <param name="remoteClient"></param> |
||
348 | /// <param name="asAttachment">Should be true if the bundle is being copied as an attachment. This prevents |
||
349 | /// attempted serialization of any script state which would abort any operating scripts.</param> |
||
350 | /// <returns>The inventory item created by the copy</returns> |
||
351 | protected InventoryItemBase CopyBundleToInventory( |
||
352 | DeRezAction action, UUID folderID, List<SceneObjectGroup> objlist, IClientAPI remoteClient, |
||
353 | bool asAttachment) |
||
354 | { |
||
355 | CoalescedSceneObjects coa = new CoalescedSceneObjects(UUID.Zero); |
||
356 | // Dictionary<UUID, Vector3> originalPositions = new Dictionary<UUID, Vector3>(); |
||
357 | |||
358 | foreach (SceneObjectGroup objectGroup in objlist) |
||
359 | { |
||
360 | if (objectGroup.RootPart.KeyframeMotion != null) |
||
361 | objectGroup.RootPart.KeyframeMotion.Stop(); |
||
362 | objectGroup.RootPart.KeyframeMotion = null; |
||
363 | // Vector3 inventoryStoredPosition = new Vector3 |
||
364 | // (((objectGroup.AbsolutePosition.X > (int)Constants.RegionSize) |
||
365 | // ? 250 |
||
366 | // : objectGroup.AbsolutePosition.X) |
||
367 | // , |
||
368 | // (objectGroup.AbsolutePosition.Y > (int)Constants.RegionSize) |
||
369 | // ? 250 |
||
370 | // : objectGroup.AbsolutePosition.Y, |
||
371 | // objectGroup.AbsolutePosition.Z); |
||
372 | // |
||
373 | // originalPositions[objectGroup.UUID] = objectGroup.AbsolutePosition; |
||
374 | // |
||
375 | // objectGroup.AbsolutePosition = inventoryStoredPosition; |
||
376 | |||
377 | // Make sure all bits but the ones we want are clear |
||
378 | // on take. |
||
379 | // This will be applied to the current perms, so |
||
380 | // it will do what we want. |
||
381 | objectGroup.RootPart.NextOwnerMask &= |
||
382 | ((uint)PermissionMask.Copy | |
||
383 | (uint)PermissionMask.Transfer | |
||
384 | (uint)PermissionMask.Modify | |
||
385 | (uint)PermissionMask.Export); |
||
386 | objectGroup.RootPart.NextOwnerMask |= |
||
387 | (uint)PermissionMask.Move; |
||
388 | |||
389 | coa.Add(objectGroup); |
||
390 | } |
||
391 | |||
392 | string itemXml; |
||
393 | |||
394 | // If we're being called from a script, then trying to serialize that same script's state will not complete |
||
395 | // in any reasonable time period. Therefore, we'll avoid it. The worst that can happen is that if |
||
396 | // the client/server crashes rather than logging out normally, the attachment's scripts will resume |
||
397 | // without state on relog. Arguably, this is what we want anyway. |
||
398 | if (objlist.Count > 1) |
||
399 | itemXml = CoalescedSceneObjectsSerializer.ToXml(coa, !asAttachment); |
||
400 | else |
||
401 | itemXml = SceneObjectSerializer.ToOriginalXmlFormat(objlist[0], !asAttachment); |
||
402 | |||
403 | // // Restore the position of each group now that it has been stored to inventory. |
||
404 | // foreach (SceneObjectGroup objectGroup in objlist) |
||
405 | // objectGroup.AbsolutePosition = originalPositions[objectGroup.UUID]; |
||
406 | |||
407 | InventoryItemBase item = CreateItemForObject(action, remoteClient, objlist[0], folderID); |
||
408 | |||
409 | // m_log.DebugFormat( |
||
410 | // "[INVENTORY ACCESS MODULE]: Created item is {0}", |
||
411 | // item != null ? item.ID.ToString() : "NULL"); |
||
412 | |||
413 | if (item == null) |
||
414 | return null; |
||
415 | |||
416 | // Can't know creator is the same, so null it in inventory |
||
417 | if (objlist.Count > 1) |
||
418 | { |
||
419 | item.CreatorId = UUID.Zero.ToString(); |
||
420 | item.Flags = (uint)InventoryItemFlags.ObjectHasMultipleItems; |
||
421 | } |
||
422 | else |
||
423 | { |
||
424 | item.CreatorId = objlist[0].RootPart.CreatorID.ToString(); |
||
425 | item.CreatorData = objlist[0].RootPart.CreatorData; |
||
426 | item.SaleType = objlist[0].RootPart.ObjectSaleType; |
||
427 | item.SalePrice = objlist[0].RootPart.SalePrice; |
||
428 | } |
||
429 | |||
430 | AssetBase asset = CreateAsset( |
||
431 | objlist[0].GetPartName(objlist[0].RootPart.LocalId), |
||
432 | objlist[0].GetPartDescription(objlist[0].RootPart.LocalId), |
||
433 | (sbyte)AssetType.Object, |
||
434 | Utils.StringToBytes(itemXml), |
||
435 | objlist[0].OwnerID.ToString()); |
||
436 | m_Scene.AssetService.Store(asset); |
||
437 | |||
438 | item.AssetID = asset.FullID; |
||
439 | |||
440 | if (DeRezAction.SaveToExistingUserInventoryItem == action) |
||
441 | { |
||
442 | m_Scene.InventoryService.UpdateItem(item); |
||
443 | } |
||
444 | else |
||
445 | { |
||
446 | AddPermissions(item, objlist[0], objlist, remoteClient); |
||
447 | |||
448 | item.CreationDate = Util.UnixTimeSinceEpoch(); |
||
449 | item.Description = asset.Description; |
||
450 | item.Name = asset.Name; |
||
451 | item.AssetType = asset.Type; |
||
452 | |||
453 | m_Scene.AddInventoryItem(item); |
||
454 | |||
455 | if (remoteClient != null && item.Owner == remoteClient.AgentId) |
||
456 | { |
||
457 | remoteClient.SendInventoryItemCreateUpdate(item, 0); |
||
458 | } |
||
459 | else |
||
460 | { |
||
461 | ScenePresence notifyUser = m_Scene.GetScenePresence(item.Owner); |
||
462 | if (notifyUser != null) |
||
463 | { |
||
464 | notifyUser.ControllingClient.SendInventoryItemCreateUpdate(item, 0); |
||
465 | } |
||
466 | } |
||
467 | } |
||
468 | |||
469 | // This is a hook to do some per-asset post-processing for subclasses that need that |
||
470 | if (remoteClient != null) |
||
471 | ExportAsset(remoteClient.AgentId, asset.FullID); |
||
472 | |||
473 | return item; |
||
474 | } |
||
475 | |||
476 | protected virtual void ExportAsset(UUID agentID, UUID assetID) |
||
477 | { |
||
478 | // nothing to do here |
||
479 | } |
||
480 | |||
481 | /// <summary> |
||
482 | /// Add relevant permissions for an object to the item. |
||
483 | /// </summary> |
||
484 | /// <param name="item"></param> |
||
485 | /// <param name="so"></param> |
||
486 | /// <param name="objsForEffectivePermissions"></param> |
||
487 | /// <param name="remoteClient"></param> |
||
488 | /// <returns></returns> |
||
489 | protected InventoryItemBase AddPermissions( |
||
490 | InventoryItemBase item, SceneObjectGroup so, List<SceneObjectGroup> objsForEffectivePermissions, |
||
491 | IClientAPI remoteClient) |
||
492 | { |
||
493 | uint effectivePerms = (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify | PermissionMask.Move | PermissionMask.Export) | 7; |
||
494 | foreach (SceneObjectGroup grp in objsForEffectivePermissions) |
||
495 | effectivePerms &= grp.GetEffectivePermissions(); |
||
496 | effectivePerms |= (uint)PermissionMask.Move; |
||
497 | |||
498 | if (remoteClient != null && (remoteClient.AgentId != so.RootPart.OwnerID) && m_Scene.Permissions.PropagatePermissions()) |
||
499 | { |
||
500 | uint perms = effectivePerms; |
||
501 | uint nextPerms = (perms & 7) << 13; |
||
502 | if ((nextPerms & (uint)PermissionMask.Copy) == 0) |
||
503 | perms &= ~(uint)PermissionMask.Copy; |
||
504 | if ((nextPerms & (uint)PermissionMask.Transfer) == 0) |
||
505 | perms &= ~(uint)PermissionMask.Transfer; |
||
506 | if ((nextPerms & (uint)PermissionMask.Modify) == 0) |
||
507 | perms &= ~(uint)PermissionMask.Modify; |
||
508 | |||
509 | item.BasePermissions = perms & so.RootPart.NextOwnerMask; |
||
510 | item.CurrentPermissions = item.BasePermissions; |
||
511 | item.NextPermissions = perms & so.RootPart.NextOwnerMask; |
||
512 | item.EveryOnePermissions = so.RootPart.EveryoneMask & so.RootPart.NextOwnerMask; |
||
513 | item.GroupPermissions = so.RootPart.GroupMask & so.RootPart.NextOwnerMask; |
||
514 | |||
515 | // Magic number badness. Maybe this deserves an enum. |
||
516 | // bit 4 (16) is the "Slam" bit, it means treat as passed |
||
517 | // and apply next owner perms on rez |
||
518 | item.CurrentPermissions |= 16; // Slam! |
||
519 | } |
||
520 | else |
||
521 | { |
||
522 | item.BasePermissions = effectivePerms; |
||
523 | item.CurrentPermissions = effectivePerms; |
||
524 | item.NextPermissions = so.RootPart.NextOwnerMask & effectivePerms; |
||
525 | item.EveryOnePermissions = so.RootPart.EveryoneMask & effectivePerms; |
||
526 | item.GroupPermissions = so.RootPart.GroupMask & effectivePerms; |
||
527 | |||
528 | item.CurrentPermissions &= |
||
529 | ((uint)PermissionMask.Copy | |
||
530 | (uint)PermissionMask.Transfer | |
||
531 | (uint)PermissionMask.Modify | |
||
532 | (uint)PermissionMask.Move | |
||
533 | (uint)PermissionMask.Export | |
||
534 | 7); // Preserve folded permissions |
||
535 | } |
||
536 | |||
537 | return item; |
||
538 | } |
||
539 | |||
540 | /// <summary> |
||
541 | /// Create an item using details for the given scene object. |
||
542 | /// </summary> |
||
543 | /// <param name="action"></param> |
||
544 | /// <param name="remoteClient"></param> |
||
545 | /// <param name="so"></param> |
||
546 | /// <param name="folderID"></param> |
||
547 | /// <returns></returns> |
||
548 | protected InventoryItemBase CreateItemForObject( |
||
549 | DeRezAction action, IClientAPI remoteClient, SceneObjectGroup so, UUID folderID) |
||
550 | { |
||
551 | // Get the user info of the item destination |
||
552 | // |
||
553 | UUID userID = UUID.Zero; |
||
554 | |||
555 | if (action == DeRezAction.Take || action == DeRezAction.TakeCopy || |
||
556 | action == DeRezAction.SaveToExistingUserInventoryItem) |
||
557 | { |
||
558 | // Take or take copy require a taker |
||
559 | // Saving changes requires a local user |
||
560 | // |
||
561 | if (remoteClient == null) |
||
562 | return null; |
||
563 | |||
564 | userID = remoteClient.AgentId; |
||
565 | |||
566 | // m_log.DebugFormat( |
||
567 | // "[INVENTORY ACCESS MODULE]: Target of {0} in CreateItemForObject() is {1} {2}", |
||
568 | // action, remoteClient.Name, userID); |
||
569 | } |
||
570 | else if (so.RootPart.OwnerID == so.RootPart.GroupID) |
||
571 | { |
||
572 | // Group owned objects go to the last owner before the object was transferred. |
||
573 | userID = so.RootPart.LastOwnerID; |
||
574 | } |
||
575 | else |
||
576 | { |
||
577 | // Other returns / deletes go to the object owner |
||
578 | // |
||
579 | userID = so.RootPart.OwnerID; |
||
580 | |||
581 | // m_log.DebugFormat( |
||
582 | // "[INVENTORY ACCESS MODULE]: Target of {0} in CreateItemForObject() is object owner {1}", |
||
583 | // action, userID); |
||
584 | } |
||
585 | |||
586 | if (userID == UUID.Zero) // Can't proceed |
||
587 | { |
||
588 | return null; |
||
589 | } |
||
590 | |||
591 | // If we're returning someone's item, it goes back to the |
||
592 | // owner's Lost And Found folder. |
||
593 | // Delete is treated like return in this case |
||
594 | // Deleting your own items makes them go to trash |
||
595 | // |
||
596 | |||
597 | InventoryFolderBase folder = null; |
||
598 | InventoryItemBase item = null; |
||
599 | |||
600 | if (DeRezAction.SaveToExistingUserInventoryItem == action) |
||
601 | { |
||
602 | item = new InventoryItemBase(so.RootPart.FromUserInventoryItemID, userID); |
||
603 | item = m_Scene.InventoryService.GetItem(item); |
||
604 | |||
605 | //item = userInfo.RootFolder.FindItem( |
||
606 | // objectGroup.RootPart.FromUserInventoryItemID); |
||
607 | |||
608 | if (null == item) |
||
609 | { |
||
610 | m_log.DebugFormat( |
||
611 | "[INVENTORY ACCESS MODULE]: Object {0} {1} scheduled for save to inventory has already been deleted.", |
||
612 | so.Name, so.UUID); |
||
613 | |||
614 | return null; |
||
615 | } |
||
616 | } |
||
617 | else |
||
618 | { |
||
619 | // Folder magic |
||
620 | // |
||
621 | if (action == DeRezAction.Delete) |
||
622 | { |
||
623 | // Deleting someone else's item |
||
624 | // |
||
625 | if (remoteClient == null || |
||
626 | so.OwnerID != remoteClient.AgentId) |
||
627 | { |
||
628 | folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); |
||
629 | } |
||
630 | else |
||
631 | { |
||
632 | folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder); |
||
633 | } |
||
634 | } |
||
635 | else if (action == DeRezAction.Return) |
||
636 | { |
||
637 | // Dump to lost + found unconditionally |
||
638 | // |
||
639 | folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); |
||
640 | } |
||
641 | |||
642 | if (folderID == UUID.Zero && folder == null) |
||
643 | { |
||
644 | if (action == DeRezAction.Delete) |
||
645 | { |
||
646 | // Deletes go to trash by default |
||
647 | // |
||
648 | folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder); |
||
649 | } |
||
650 | else |
||
651 | { |
||
652 | if (remoteClient == null || so.RootPart.OwnerID != remoteClient.AgentId) |
||
653 | { |
||
654 | // Taking copy of another person's item. Take to |
||
655 | // Objects folder. |
||
656 | folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.Object); |
||
657 | so.FromFolderID = UUID.Zero; |
||
658 | } |
||
659 | else |
||
660 | { |
||
661 | // Catch all. Use lost & found |
||
662 | // |
||
663 | folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); |
||
664 | } |
||
665 | } |
||
666 | } |
||
667 | |||
668 | // Override and put into where it came from, if it came |
||
669 | // from anywhere in inventory and the owner is taking it back. |
||
670 | // |
||
671 | if (action == DeRezAction.Take || action == DeRezAction.TakeCopy) |
||
672 | { |
||
673 | if (so.FromFolderID != UUID.Zero && so.RootPart.OwnerID == remoteClient.AgentId) |
||
674 | { |
||
675 | InventoryFolderBase f = new InventoryFolderBase(so.FromFolderID, userID); |
||
676 | folder = m_Scene.InventoryService.GetFolder(f); |
||
677 | |||
678 | if(folder.Type == 14 || folder.Type == 16) |
||
679 | { |
||
680 | // folder.Type = 6; |
||
681 | folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.Object); |
||
682 | } |
||
683 | } |
||
684 | } |
||
685 | |||
686 | if (folder == null) // None of the above |
||
687 | { |
||
688 | folder = new InventoryFolderBase(folderID); |
||
689 | |||
690 | if (folder == null) // Nowhere to put it |
||
691 | { |
||
692 | return null; |
||
693 | } |
||
694 | } |
||
695 | |||
696 | item = new InventoryItemBase(); |
||
697 | item.ID = UUID.Random(); |
||
698 | item.InvType = (int)InventoryType.Object; |
||
699 | item.Folder = folder.ID; |
||
700 | item.Owner = userID; |
||
701 | } |
||
702 | |||
703 | return item; |
||
704 | } |
||
705 | |||
706 | public virtual SceneObjectGroup RezObject( |
||
707 | IClientAPI remoteClient, UUID itemID, Vector3 RayEnd, Vector3 RayStart, |
||
708 | UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, |
||
709 | bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment) |
||
710 | { |
||
711 | // m_log.DebugFormat("[INVENTORY ACCESS MODULE]: RezObject for {0}, item {1}", remoteClient.Name, itemID); |
||
712 | |||
713 | InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); |
||
714 | item = m_Scene.InventoryService.GetItem(item); |
||
715 | |||
716 | if (item == null) |
||
717 | { |
||
718 | m_log.WarnFormat( |
||
719 | "[INVENTORY ACCESS MODULE]: Could not find item {0} for {1} in RezObject()", |
||
720 | itemID, remoteClient.Name); |
||
721 | |||
722 | return null; |
||
723 | } |
||
724 | |||
725 | item.Owner = remoteClient.AgentId; |
||
726 | |||
727 | return RezObject( |
||
728 | remoteClient, item, item.AssetID, |
||
729 | RayEnd, RayStart, RayTargetID, BypassRayCast, RayEndIsIntersection, |
||
730 | RezSelected, RemoveItem, fromTaskID, attachment); |
||
731 | } |
||
732 | |||
733 | public virtual SceneObjectGroup RezObject( |
||
734 | IClientAPI remoteClient, InventoryItemBase item, UUID assetID, Vector3 RayEnd, Vector3 RayStart, |
||
735 | UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, |
||
736 | bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment) |
||
737 | { |
||
738 | AssetBase rezAsset = m_Scene.AssetService.Get(assetID.ToString()); |
||
739 | |||
740 | if (rezAsset == null) |
||
741 | { |
||
742 | if (item != null) |
||
743 | { |
||
744 | m_log.WarnFormat( |
||
745 | "[InventoryAccessModule]: Could not find asset {0} for item {1} {2} for {3} in RezObject()", |
||
746 | assetID, item.Name, item.ID, remoteClient.Name); |
||
747 | } |
||
748 | else |
||
749 | { |
||
750 | m_log.WarnFormat( |
||
751 | "[INVENTORY ACCESS MODULE]: Could not find asset {0} for {1} in RezObject()", |
||
752 | assetID, remoteClient.Name); |
||
753 | } |
||
754 | |||
755 | return null; |
||
756 | } |
||
757 | |||
758 | SceneObjectGroup group = null; |
||
759 | |||
760 | string xmlData = Utils.BytesToString(rezAsset.Data); |
||
761 | List<SceneObjectGroup> objlist = new List<SceneObjectGroup>(); |
||
762 | List<Vector3> veclist = new List<Vector3>(); |
||
763 | byte bRayEndIsIntersection = (byte)(RayEndIsIntersection ? 1 : 0); |
||
764 | Vector3 pos; |
||
765 | |||
766 | XmlDocument doc = new XmlDocument(); |
||
767 | doc.LoadXml(xmlData); |
||
768 | XmlElement e = (XmlElement)doc.SelectSingleNode("/CoalescedObject"); |
||
769 | if (e == null || attachment) // Single |
||
770 | { |
||
771 | SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); |
||
772 | |||
773 | objlist.Add(g); |
||
774 | veclist.Add(Vector3.Zero); |
||
775 | |||
776 | float offsetHeight = 0; |
||
777 | pos = m_Scene.GetNewRezLocation( |
||
778 | RayStart, RayEnd, RayTargetID, Quaternion.Identity, |
||
779 | BypassRayCast, bRayEndIsIntersection, true, g.GetAxisAlignedBoundingBox(out offsetHeight), false); |
||
780 | pos.Z += offsetHeight; |
||
781 | } |
||
782 | else |
||
783 | { |
||
784 | XmlElement coll = (XmlElement)e; |
||
785 | float bx = Convert.ToSingle(coll.GetAttribute("x")); |
||
786 | float by = Convert.ToSingle(coll.GetAttribute("y")); |
||
787 | float bz = Convert.ToSingle(coll.GetAttribute("z")); |
||
788 | Vector3 bbox = new Vector3(bx, by, bz); |
||
789 | |||
790 | pos = m_Scene.GetNewRezLocation(RayStart, RayEnd, |
||
791 | RayTargetID, Quaternion.Identity, |
||
792 | BypassRayCast, bRayEndIsIntersection, true, |
||
793 | bbox, false); |
||
794 | |||
795 | pos -= bbox / 2; |
||
796 | |||
797 | XmlNodeList groups = e.SelectNodes("SceneObjectGroup"); |
||
798 | foreach (XmlNode n in groups) |
||
799 | { |
||
800 | SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(n.OuterXml); |
||
801 | |||
802 | objlist.Add(g); |
||
803 | XmlElement el = (XmlElement)n; |
||
804 | |||
805 | string rawX = el.GetAttribute("offsetx"); |
||
806 | string rawY = el.GetAttribute("offsety"); |
||
807 | string rawZ = el.GetAttribute("offsetz"); |
||
808 | // |
||
809 | // m_log.DebugFormat( |
||
810 | // "[INVENTORY ACCESS MODULE]: Converting coalesced object {0} offset <{1}, {2}, {3}>", |
||
811 | // g.Name, rawX, rawY, rawZ); |
||
812 | |||
813 | float x = Convert.ToSingle(rawX); |
||
814 | float y = Convert.ToSingle(rawY); |
||
815 | float z = Convert.ToSingle(rawZ); |
||
816 | veclist.Add(new Vector3(x, y, z)); |
||
817 | } |
||
818 | } |
||
819 | |||
820 | if (item != null && !DoPreRezWhenFromItem(remoteClient, item, objlist, pos, veclist, attachment)) |
||
821 | return null; |
||
822 | |||
823 | for (int i = 0; i < objlist.Count; i++) |
||
824 | { |
||
825 | group = objlist[i]; |
||
826 | |||
827 | // m_log.DebugFormat( |
||
828 | // "[INVENTORY ACCESS MODULE]: Preparing to rez {0} {1} {2} ownermask={3:X} nextownermask={4:X} groupmask={5:X} everyonemask={6:X} for {7}", |
||
829 | // group.Name, group.LocalId, group.UUID, |
||
830 | // group.RootPart.OwnerMask, group.RootPart.NextOwnerMask, group.RootPart.GroupMask, group.RootPart.EveryoneMask, |
||
831 | // remoteClient.Name); |
||
832 | |||
833 | // Vector3 storedPosition = group.AbsolutePosition; |
||
834 | if (group.UUID == UUID.Zero) |
||
835 | { |
||
836 | m_log.Debug("[INVENTORY ACCESS MODULE]: Object has UUID.Zero! Position 3"); |
||
837 | } |
||
838 | |||
839 | foreach (SceneObjectPart part in group.Parts) |
||
840 | { |
||
841 | // Make the rezzer the owner, as this is not necessarily set correctly in the serialized asset. |
||
842 | part.LastOwnerID = part.OwnerID; |
||
843 | part.OwnerID = remoteClient.AgentId; |
||
844 | } |
||
845 | |||
846 | if (!attachment) |
||
847 | { |
||
848 | // If it's rezzed in world, select it. Much easier to |
||
849 | // find small items. |
||
850 | // |
||
851 | foreach (SceneObjectPart part in group.Parts) |
||
852 | { |
||
853 | part.CreateSelected = true; |
||
854 | } |
||
855 | } |
||
856 | |||
857 | group.ResetIDs(); |
||
858 | |||
859 | if (attachment) |
||
860 | { |
||
861 | group.RootPart.Flags |= PrimFlags.Phantom; |
||
862 | group.IsAttachment = true; |
||
863 | } |
||
864 | |||
865 | // If we're rezzing an attachment then don't ask |
||
866 | // AddNewSceneObject() to update the client since |
||
867 | // we'll be doing that later on. Scheduling more than |
||
868 | // one full update during the attachment |
||
869 | // process causes some clients to fail to display the |
||
870 | // attachment properly. |
||
871 | m_Scene.AddNewSceneObject(group, true, false); |
||
872 | |||
873 | // if attachment we set it's asset id so object updates |
||
874 | // can reflect that, if not, we set it's position in world. |
||
875 | if (!attachment) |
||
876 | { |
||
877 | group.ScheduleGroupForFullUpdate(); |
||
878 | |||
879 | group.AbsolutePosition = pos + veclist[i]; |
||
880 | } |
||
881 | |||
882 | group.SetGroup(remoteClient.ActiveGroupId, remoteClient); |
||
883 | |||
884 | if (!attachment) |
||
885 | { |
||
886 | SceneObjectPart rootPart = group.RootPart; |
||
887 | |||
888 | if (rootPart.Shape.PCode == (byte)PCode.Prim) |
||
889 | group.ClearPartAttachmentData(); |
||
890 | |||
891 | // Fire on_rez |
||
892 | group.CreateScriptInstances(0, true, m_Scene.DefaultScriptEngine, 1); |
||
893 | rootPart.ParentGroup.ResumeScripts(); |
||
894 | |||
895 | rootPart.ScheduleFullUpdate(); |
||
896 | } |
||
897 | |||
898 | // m_log.DebugFormat( |
||
899 | // "[INVENTORY ACCESS MODULE]: Rezzed {0} {1} {2} ownermask={3:X} nextownermask={4:X} groupmask={5:X} everyonemask={6:X} for {7}", |
||
900 | // group.Name, group.LocalId, group.UUID, |
||
901 | // group.RootPart.OwnerMask, group.RootPart.NextOwnerMask, group.RootPart.GroupMask, group.RootPart.EveryoneMask, |
||
902 | // remoteClient.Name); |
||
903 | } |
||
904 | |||
905 | if (item != null) |
||
906 | DoPostRezWhenFromItem(item, attachment); |
||
907 | |||
908 | return group; |
||
909 | } |
||
910 | |||
911 | /// <summary> |
||
912 | /// Do pre-rez processing when the object comes from an item. |
||
913 | /// </summary> |
||
914 | /// <param name="remoteClient"></param> |
||
915 | /// <param name="item"></param> |
||
916 | /// <param name="objlist"></param> |
||
917 | /// <param name="pos"></param> |
||
918 | /// <param name="veclist"> |
||
919 | /// List of vector position adjustments for a coalesced objects. For ordinary objects |
||
920 | /// this list will contain just Vector3.Zero. The order of adjustments must match the order of objlist |
||
921 | /// </param> |
||
922 | /// <param name="isAttachment"></param> |
||
923 | /// <returns>true if we can processed with rezzing, false if we need to abort</returns> |
||
924 | private bool DoPreRezWhenFromItem( |
||
925 | IClientAPI remoteClient, InventoryItemBase item, List<SceneObjectGroup> objlist, |
||
926 | Vector3 pos, List<Vector3> veclist, bool isAttachment) |
||
927 | { |
||
928 | UUID fromUserInventoryItemId = UUID.Zero; |
||
929 | |||
930 | // If we have permission to copy then link the rezzed object back to the user inventory |
||
931 | // item that it came from. This allows us to enable 'save object to inventory' |
||
932 | if (!m_Scene.Permissions.BypassPermissions()) |
||
933 | { |
||
934 | if ((item.CurrentPermissions & (uint)PermissionMask.Copy) |
||
935 | == (uint)PermissionMask.Copy && (item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0) |
||
936 | { |
||
937 | fromUserInventoryItemId = item.ID; |
||
938 | } |
||
939 | } |
||
940 | else |
||
941 | { |
||
942 | if ((item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0) |
||
943 | { |
||
944 | // Brave new fullperm world |
||
945 | fromUserInventoryItemId = item.ID; |
||
946 | } |
||
947 | } |
||
948 | |||
949 | for (int i = 0; i < objlist.Count; i++) |
||
950 | { |
||
951 | SceneObjectGroup g = objlist[i]; |
||
952 | |||
953 | if (!m_Scene.Permissions.CanRezObject( |
||
954 | g.PrimCount, remoteClient.AgentId, pos + veclist[i]) |
||
955 | && !isAttachment) |
||
956 | { |
||
957 | // The client operates in no fail mode. It will |
||
958 | // have already removed the item from the folder |
||
959 | // if it's no copy. |
||
960 | // Put it back if it's not an attachment |
||
961 | // |
||
962 | if (((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) && (!isAttachment)) |
||
963 | remoteClient.SendBulkUpdateInventory(item); |
||
964 | |||
965 | ILandObject land = m_Scene.LandChannel.GetLandObject(pos.X, pos.Y); |
||
966 | remoteClient.SendAlertMessage(string.Format( |
||
967 | "Can't rez object '{0}' at <{1:F3}, {2:F3}, {3:F3}> on parcel '{4}' in region {5}.", |
||
968 | item.Name, pos.X, pos.Y, pos.Z, land != null ? land.LandData.Name : "Unknown", m_Scene.Name)); |
||
969 | |||
970 | return false; |
||
971 | } |
||
972 | } |
||
973 | |||
974 | for (int i = 0; i < objlist.Count; i++) |
||
975 | { |
||
976 | SceneObjectGroup so = objlist[i]; |
||
977 | SceneObjectPart rootPart = so.RootPart; |
||
978 | |||
979 | // Since renaming the item in the inventory does not |
||
980 | // affect the name stored in the serialization, transfer |
||
981 | // the correct name from the inventory to the |
||
982 | // object itself before we rez. |
||
983 | // |
||
984 | // Only do these for the first object if we are rezzing a coalescence. |
||
985 | if (i == 0) |
||
986 | { |
||
987 | rootPart.Name = item.Name; |
||
988 | rootPart.Description = item.Description; |
||
989 | rootPart.ObjectSaleType = item.SaleType; |
||
990 | rootPart.SalePrice = item.SalePrice; |
||
991 | } |
||
992 | |||
993 | so.FromFolderID = item.Folder; |
||
994 | |||
995 | // m_log.DebugFormat( |
||
996 | // "[INVENTORY ACCESS MODULE]: rootPart.OwnedID {0}, item.Owner {1}, item.CurrentPermissions {2:X}", |
||
997 | // rootPart.OwnerID, item.Owner, item.CurrentPermissions); |
||
998 | |||
999 | if ((rootPart.OwnerID != item.Owner) || |
||
1000 | (item.CurrentPermissions & 16) != 0) |
||
1001 | { |
||
1002 | //Need to kill the for sale here |
||
1003 | rootPart.ObjectSaleType = 0; |
||
1004 | rootPart.SalePrice = 10; |
||
1005 | |||
1006 | if (m_Scene.Permissions.PropagatePermissions()) |
||
1007 | { |
||
1008 | foreach (SceneObjectPart part in so.Parts) |
||
1009 | { |
||
1010 | if ((item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0) |
||
1011 | { |
||
1012 | part.EveryoneMask = item.EveryOnePermissions; |
||
1013 | part.NextOwnerMask = item.NextPermissions; |
||
1014 | } |
||
1015 | part.GroupMask = 0; // DO NOT propagate here |
||
1016 | } |
||
1017 | |||
1018 | so.ApplyNextOwnerPermissions(); |
||
1019 | } |
||
1020 | } |
||
1021 | |||
1022 | foreach (SceneObjectPart part in so.Parts) |
||
1023 | { |
||
1024 | part.FromUserInventoryItemID = fromUserInventoryItemId; |
||
1025 | |||
1026 | if ((part.OwnerID != item.Owner) || |
||
1027 | (item.CurrentPermissions & 16) != 0) |
||
1028 | { |
||
1029 | part.Inventory.ChangeInventoryOwner(item.Owner); |
||
1030 | part.GroupMask = 0; // DO NOT propagate here |
||
1031 | } |
||
1032 | |||
1033 | part.EveryoneMask = item.EveryOnePermissions; |
||
1034 | part.NextOwnerMask = item.NextPermissions; |
||
1035 | } |
||
1036 | |||
1037 | rootPart.TrimPermissions(); |
||
1038 | |||
1039 | if (isAttachment) |
||
1040 | so.FromItemID = item.ID; |
||
1041 | } |
||
1042 | |||
1043 | return true; |
||
1044 | } |
||
1045 | |||
1046 | /// <summary> |
||
1047 | /// Do post-rez processing when the object comes from an item. |
||
1048 | /// </summary> |
||
1049 | /// <param name="item"></param> |
||
1050 | /// <param name="isAttachment"></param> |
||
1051 | private void DoPostRezWhenFromItem(InventoryItemBase item, bool isAttachment) |
||
1052 | { |
||
1053 | if (!m_Scene.Permissions.BypassPermissions()) |
||
1054 | { |
||
1055 | if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) |
||
1056 | { |
||
1057 | // If this is done on attachments, no |
||
1058 | // copy ones will be lost, so avoid it |
||
1059 | // |
||
1060 | if (!isAttachment) |
||
1061 | { |
||
1062 | List<UUID> uuids = new List<UUID>(); |
||
1063 | uuids.Add(item.ID); |
||
1064 | m_Scene.InventoryService.DeleteItems(item.Owner, uuids); |
||
1065 | } |
||
1066 | } |
||
1067 | } |
||
1068 | } |
||
1069 | |||
1070 | protected void AddUserData(SceneObjectGroup sog) |
||
1071 | { |
||
1072 | UserManagementModule.AddUser(sog.RootPart.CreatorID, sog.RootPart.CreatorData); |
||
1073 | foreach (SceneObjectPart sop in sog.Parts) |
||
1074 | UserManagementModule.AddUser(sop.CreatorID, sop.CreatorData); |
||
1075 | } |
||
1076 | |||
1077 | public virtual void TransferInventoryAssets(InventoryItemBase item, UUID sender, UUID receiver) |
||
1078 | { |
||
1079 | } |
||
1080 | |||
1081 | public virtual bool CanGetAgentInventoryItem(IClientAPI remoteClient, UUID itemID, UUID requestID) |
||
1082 | { |
||
1083 | InventoryItemBase assetRequestItem = GetItem(remoteClient.AgentId, itemID); |
||
1084 | |||
1085 | if (assetRequestItem == null) |
||
1086 | { |
||
1087 | ILibraryService lib = m_Scene.RequestModuleInterface<ILibraryService>(); |
||
1088 | |||
1089 | if (lib != null) |
||
1090 | assetRequestItem = lib.LibraryRootFolder.FindItem(itemID); |
||
1091 | |||
1092 | if (assetRequestItem == null) |
||
1093 | return false; |
||
1094 | } |
||
1095 | |||
1096 | // At this point, we need to apply perms |
||
1097 | // only to notecards and scripts. All |
||
1098 | // other asset types are always available |
||
1099 | // |
||
1100 | if (assetRequestItem.AssetType == (int)AssetType.LSLText) |
||
1101 | { |
||
1102 | if (!m_Scene.Permissions.CanViewScript(itemID, UUID.Zero, remoteClient.AgentId)) |
||
1103 | { |
||
1104 | remoteClient.SendAgentAlertMessage("Insufficient permissions to view script", false); |
||
1105 | return false; |
||
1106 | } |
||
1107 | } |
||
1108 | else if (assetRequestItem.AssetType == (int)AssetType.Notecard) |
||
1109 | { |
||
1110 | if (!m_Scene.Permissions.CanViewNotecard(itemID, UUID.Zero, remoteClient.AgentId)) |
||
1111 | { |
||
1112 | remoteClient.SendAgentAlertMessage("Insufficient permissions to view notecard", false); |
||
1113 | return false; |
||
1114 | } |
||
1115 | } |
||
1116 | |||
1117 | if (assetRequestItem.AssetID != requestID) |
||
1118 | { |
||
1119 | m_log.WarnFormat( |
||
1120 | "[INVENTORY ACCESS MODULE]: {0} requested asset {1} from item {2} but this does not match item's asset {3}", |
||
1121 | Name, requestID, itemID, assetRequestItem.AssetID); |
||
1122 | |||
1123 | return false; |
||
1124 | } |
||
1125 | |||
1126 | return true; |
||
1127 | } |
||
1128 | |||
1129 | |||
1130 | public virtual bool IsForeignUser(UUID userID, out string assetServerURL) |
||
1131 | { |
||
1132 | assetServerURL = string.Empty; |
||
1133 | return false; |
||
1134 | } |
||
1135 | |||
1136 | #endregion |
||
1137 | |||
1138 | #region Misc |
||
1139 | |||
1140 | /// <summary> |
||
1141 | /// Create a new asset data structure. |
||
1142 | /// </summary> |
||
1143 | /// <param name="name"></param> |
||
1144 | /// <param name="description"></param> |
||
1145 | /// <param name="invType"></param> |
||
1146 | /// <param name="assetType"></param> |
||
1147 | /// <param name="data"></param> |
||
1148 | /// <returns></returns> |
||
1149 | private AssetBase CreateAsset(string name, string description, sbyte assetType, byte[] data, string creatorID) |
||
1150 | { |
||
1151 | AssetBase asset = new AssetBase(UUID.Random(), name, assetType, creatorID); |
||
1152 | asset.Description = description; |
||
1153 | asset.Data = (data == null) ? new byte[1] : data; |
||
1154 | |||
1155 | return asset; |
||
1156 | } |
||
1157 | |||
1158 | protected virtual InventoryItemBase GetItem(UUID agentID, UUID itemID) |
||
1159 | { |
||
1160 | IInventoryService invService = m_Scene.RequestModuleInterface<IInventoryService>(); |
||
1161 | InventoryItemBase item = new InventoryItemBase(itemID, agentID); |
||
1162 | item = invService.GetItem(item); |
||
1163 | |||
1164 | if (item != null && item.CreatorData != null && item.CreatorData != string.Empty) |
||
1165 | UserManagementModule.AddUser(item.CreatorIdAsUuid, item.CreatorData); |
||
1166 | |||
1167 | return item; |
||
1168 | } |
||
1169 | |||
1170 | #endregion |
||
1171 | } |
||
1172 | } |