opensim-development – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | eva | 1 | /* |
2 | * Copyright (c) Contributors, http://opensimulator.org/ |
||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. |
||
4 | * |
||
5 | * Redistribution and use in source and binary forms, with or without |
||
6 | * modification, are permitted provided that the following conditions are met: |
||
7 | * * Redistributions of source code must retain the above copyright |
||
8 | * notice, this list of conditions and the following disclaimer. |
||
9 | * * Redistributions in binary form must reproduce the above copyright |
||
10 | * notice, this list of conditions and the following disclaimer in the |
||
11 | * documentation and/or other materials provided with the distribution. |
||
12 | * * Neither the name of the OpenSimulator Project nor the |
||
13 | * names of its contributors may be used to endorse or promote products |
||
14 | * derived from this software without specific prior written permission. |
||
15 | * |
||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY |
||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY |
||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||
26 | */ |
||
27 | |||
28 | using System; |
||
29 | using System.Collections.Generic; |
||
30 | using System.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 | item.CreatorId = objlist[0].RootPart.CreatorID.ToString(); |
||
417 | item.CreatorData = objlist[0].RootPart.CreatorData; |
||
418 | |||
419 | if (objlist.Count > 1) |
||
420 | { |
||
421 | item.Flags = (uint)InventoryItemFlags.ObjectHasMultipleItems; |
||
422 | |||
423 | // If the objects have different creators then don't specify a creator at all |
||
424 | foreach (SceneObjectGroup objectGroup in objlist) |
||
425 | { |
||
426 | if ((objectGroup.RootPart.CreatorID.ToString() != item.CreatorId) |
||
427 | || (objectGroup.RootPart.CreatorData.ToString() != item.CreatorData)) |
||
428 | { |
||
429 | item.CreatorId = UUID.Zero.ToString(); |
||
430 | item.CreatorData = string.Empty; |
||
431 | break; |
||
432 | } |
||
433 | } |
||
434 | } |
||
435 | else |
||
436 | { |
||
437 | item.SaleType = objlist[0].RootPart.ObjectSaleType; |
||
438 | item.SalePrice = objlist[0].RootPart.SalePrice; |
||
439 | } |
||
440 | |||
441 | AssetBase asset = CreateAsset( |
||
442 | objlist[0].GetPartName(objlist[0].RootPart.LocalId), |
||
443 | objlist[0].GetPartDescription(objlist[0].RootPart.LocalId), |
||
444 | (sbyte)AssetType.Object, |
||
445 | Utils.StringToBytes(itemXml), |
||
446 | objlist[0].OwnerID.ToString()); |
||
447 | m_Scene.AssetService.Store(asset); |
||
448 | |||
449 | item.AssetID = asset.FullID; |
||
450 | |||
451 | if (DeRezAction.SaveToExistingUserInventoryItem == action) |
||
452 | { |
||
453 | m_Scene.InventoryService.UpdateItem(item); |
||
454 | } |
||
455 | else |
||
456 | { |
||
457 | item.CreationDate = Util.UnixTimeSinceEpoch(); |
||
458 | item.Description = asset.Description; |
||
459 | item.Name = asset.Name; |
||
460 | item.AssetType = asset.Type; |
||
461 | |||
462 | AddPermissions(item, objlist[0], objlist, remoteClient); |
||
463 | |||
464 | m_Scene.AddInventoryItem(item); |
||
465 | |||
466 | if (remoteClient != null && item.Owner == remoteClient.AgentId) |
||
467 | { |
||
468 | remoteClient.SendInventoryItemCreateUpdate(item, 0); |
||
469 | } |
||
470 | else |
||
471 | { |
||
472 | ScenePresence notifyUser = m_Scene.GetScenePresence(item.Owner); |
||
473 | if (notifyUser != null) |
||
474 | { |
||
475 | notifyUser.ControllingClient.SendInventoryItemCreateUpdate(item, 0); |
||
476 | } |
||
477 | } |
||
478 | } |
||
479 | |||
480 | // This is a hook to do some per-asset post-processing for subclasses that need that |
||
481 | if (remoteClient != null) |
||
482 | ExportAsset(remoteClient.AgentId, asset.FullID); |
||
483 | |||
484 | return item; |
||
485 | } |
||
486 | |||
487 | protected virtual void ExportAsset(UUID agentID, UUID assetID) |
||
488 | { |
||
489 | // nothing to do here |
||
490 | } |
||
491 | |||
492 | /// <summary> |
||
493 | /// Add relevant permissions for an object to the item. |
||
494 | /// </summary> |
||
495 | /// <param name="item"></param> |
||
496 | /// <param name="so"></param> |
||
497 | /// <param name="objsForEffectivePermissions"></param> |
||
498 | /// <param name="remoteClient"></param> |
||
499 | /// <returns></returns> |
||
500 | protected InventoryItemBase AddPermissions( |
||
501 | InventoryItemBase item, SceneObjectGroup so, List<SceneObjectGroup> objsForEffectivePermissions, |
||
502 | IClientAPI remoteClient) |
||
503 | { |
||
504 | uint effectivePerms = (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify | PermissionMask.Move | PermissionMask.Export) | 7; |
||
505 | uint allObjectsNextOwnerPerms = 0x7fffffff; |
||
506 | uint allObjectsEveryOnePerms = 0x7fffffff; |
||
507 | uint allObjectsGroupPerms = 0x7fffffff; |
||
508 | |||
509 | foreach (SceneObjectGroup grp in objsForEffectivePermissions) |
||
510 | { |
||
511 | effectivePerms &= grp.GetEffectivePermissions(); |
||
512 | allObjectsNextOwnerPerms &= grp.RootPart.NextOwnerMask; |
||
513 | allObjectsEveryOnePerms &= grp.RootPart.EveryoneMask; |
||
514 | allObjectsGroupPerms &= grp.RootPart.GroupMask; |
||
515 | } |
||
516 | effectivePerms |= (uint)PermissionMask.Move; |
||
517 | |||
518 | //PermissionsUtil.LogPermissions(item.Name, "Before AddPermissions", item.BasePermissions, item.CurrentPermissions, item.NextPermissions); |
||
519 | |||
520 | if (remoteClient != null && (remoteClient.AgentId != so.RootPart.OwnerID) && m_Scene.Permissions.PropagatePermissions()) |
||
521 | { |
||
522 | uint perms = effectivePerms; |
||
523 | PermissionsUtil.ApplyFoldedPermissions(effectivePerms, ref perms); |
||
524 | |||
525 | item.BasePermissions = perms & allObjectsNextOwnerPerms; |
||
526 | item.CurrentPermissions = item.BasePermissions; |
||
527 | item.NextPermissions = perms & allObjectsNextOwnerPerms; |
||
528 | item.EveryOnePermissions = allObjectsEveryOnePerms & allObjectsNextOwnerPerms; |
||
529 | item.GroupPermissions = allObjectsGroupPerms & allObjectsNextOwnerPerms; |
||
530 | |||
531 | // apply next owner perms on rez |
||
532 | item.CurrentPermissions |= SceneObjectGroup.SLAM; |
||
533 | } |
||
534 | else |
||
535 | { |
||
536 | item.BasePermissions = effectivePerms; |
||
537 | item.CurrentPermissions = effectivePerms; |
||
538 | item.NextPermissions = allObjectsNextOwnerPerms & effectivePerms; |
||
539 | item.EveryOnePermissions = allObjectsEveryOnePerms & effectivePerms; |
||
540 | item.GroupPermissions = allObjectsGroupPerms & effectivePerms; |
||
541 | |||
542 | item.CurrentPermissions &= |
||
543 | ((uint)PermissionMask.Copy | |
||
544 | (uint)PermissionMask.Transfer | |
||
545 | (uint)PermissionMask.Modify | |
||
546 | (uint)PermissionMask.Move | |
||
547 | (uint)PermissionMask.Export | |
||
548 | 7); // Preserve folded permissions |
||
549 | } |
||
550 | |||
551 | //PermissionsUtil.LogPermissions(item.Name, "After AddPermissions", item.BasePermissions, item.CurrentPermissions, item.NextPermissions); |
||
552 | |||
553 | return item; |
||
554 | } |
||
555 | |||
556 | /// <summary> |
||
557 | /// Create an item using details for the given scene object. |
||
558 | /// </summary> |
||
559 | /// <param name="action"></param> |
||
560 | /// <param name="remoteClient"></param> |
||
561 | /// <param name="so"></param> |
||
562 | /// <param name="folderID"></param> |
||
563 | /// <returns></returns> |
||
564 | protected InventoryItemBase CreateItemForObject( |
||
565 | DeRezAction action, IClientAPI remoteClient, SceneObjectGroup so, UUID folderID) |
||
566 | { |
||
567 | // Get the user info of the item destination |
||
568 | // |
||
569 | UUID userID = UUID.Zero; |
||
570 | |||
571 | if (action == DeRezAction.Take || action == DeRezAction.TakeCopy || |
||
572 | action == DeRezAction.SaveToExistingUserInventoryItem) |
||
573 | { |
||
574 | // Take or take copy require a taker |
||
575 | // Saving changes requires a local user |
||
576 | // |
||
577 | if (remoteClient == null) |
||
578 | return null; |
||
579 | |||
580 | userID = remoteClient.AgentId; |
||
581 | |||
582 | // m_log.DebugFormat( |
||
583 | // "[INVENTORY ACCESS MODULE]: Target of {0} in CreateItemForObject() is {1} {2}", |
||
584 | // action, remoteClient.Name, userID); |
||
585 | } |
||
586 | else if (so.RootPart.OwnerID == so.RootPart.GroupID) |
||
587 | { |
||
588 | // Group owned objects go to the last owner before the object was transferred. |
||
589 | userID = so.RootPart.LastOwnerID; |
||
590 | } |
||
591 | else |
||
592 | { |
||
593 | // Other returns / deletes go to the object owner |
||
594 | // |
||
595 | userID = so.RootPart.OwnerID; |
||
596 | |||
597 | // m_log.DebugFormat( |
||
598 | // "[INVENTORY ACCESS MODULE]: Target of {0} in CreateItemForObject() is object owner {1}", |
||
599 | // action, userID); |
||
600 | } |
||
601 | |||
602 | if (userID == UUID.Zero) // Can't proceed |
||
603 | { |
||
604 | return null; |
||
605 | } |
||
606 | |||
607 | // If we're returning someone's item, it goes back to the |
||
608 | // owner's Lost And Found folder. |
||
609 | // Delete is treated like return in this case |
||
610 | // Deleting your own items makes them go to trash |
||
611 | // |
||
612 | |||
613 | InventoryFolderBase folder = null; |
||
614 | InventoryItemBase item = null; |
||
615 | |||
616 | if (DeRezAction.SaveToExistingUserInventoryItem == action) |
||
617 | { |
||
618 | item = new InventoryItemBase(so.RootPart.FromUserInventoryItemID, userID); |
||
619 | item = m_Scene.InventoryService.GetItem(item); |
||
620 | |||
621 | //item = userInfo.RootFolder.FindItem( |
||
622 | // objectGroup.RootPart.FromUserInventoryItemID); |
||
623 | |||
624 | if (null == item) |
||
625 | { |
||
626 | m_log.DebugFormat( |
||
627 | "[INVENTORY ACCESS MODULE]: Object {0} {1} scheduled for save to inventory has already been deleted.", |
||
628 | so.Name, so.UUID); |
||
629 | |||
630 | return null; |
||
631 | } |
||
632 | } |
||
633 | else |
||
634 | { |
||
635 | // Folder magic |
||
636 | // |
||
637 | if (action == DeRezAction.Delete) |
||
638 | { |
||
639 | // Deleting someone else's item |
||
640 | // |
||
641 | if (remoteClient == null || |
||
642 | so.OwnerID != remoteClient.AgentId) |
||
643 | { |
||
644 | folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); |
||
645 | } |
||
646 | else |
||
647 | { |
||
648 | folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder); |
||
649 | } |
||
650 | } |
||
651 | else if (action == DeRezAction.Return) |
||
652 | { |
||
653 | // Dump to lost + found unconditionally |
||
654 | // |
||
655 | folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); |
||
656 | } |
||
657 | |||
658 | if (folderID == UUID.Zero && folder == null) |
||
659 | { |
||
660 | if (action == DeRezAction.Delete) |
||
661 | { |
||
662 | // Deletes go to trash by default |
||
663 | // |
||
664 | folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder); |
||
665 | } |
||
666 | else |
||
667 | { |
||
668 | if (remoteClient == null || so.RootPart.OwnerID != remoteClient.AgentId) |
||
669 | { |
||
670 | // Taking copy of another person's item. Take to |
||
671 | // Objects folder. |
||
672 | folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.Object); |
||
673 | so.FromFolderID = UUID.Zero; |
||
674 | } |
||
675 | else |
||
676 | { |
||
677 | // Catch all. Use lost & found |
||
678 | // |
||
679 | folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); |
||
680 | } |
||
681 | } |
||
682 | } |
||
683 | |||
684 | // Override and put into where it came from, if it came |
||
685 | // from anywhere in inventory and the owner is taking it back. |
||
686 | // |
||
687 | if (action == DeRezAction.Take || action == DeRezAction.TakeCopy) |
||
688 | { |
||
689 | if (so.FromFolderID != UUID.Zero && so.RootPart.OwnerID == remoteClient.AgentId) |
||
690 | { |
||
691 | InventoryFolderBase f = new InventoryFolderBase(so.FromFolderID, userID); |
||
692 | folder = m_Scene.InventoryService.GetFolder(f); |
||
693 | |||
694 | if(folder.Type == 14 || folder.Type == 16) |
||
695 | { |
||
696 | // folder.Type = 6; |
||
697 | folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.Object); |
||
698 | } |
||
699 | } |
||
700 | } |
||
701 | |||
702 | if (folder == null) // None of the above |
||
703 | { |
||
704 | folder = new InventoryFolderBase(folderID); |
||
705 | |||
706 | if (folder == null) // Nowhere to put it |
||
707 | { |
||
708 | return null; |
||
709 | } |
||
710 | } |
||
711 | |||
712 | item = new InventoryItemBase(); |
||
713 | item.ID = UUID.Random(); |
||
714 | item.InvType = (int)InventoryType.Object; |
||
715 | item.Folder = folder.ID; |
||
716 | item.Owner = userID; |
||
717 | } |
||
718 | |||
719 | return item; |
||
720 | } |
||
721 | |||
722 | public virtual SceneObjectGroup RezObject( |
||
723 | IClientAPI remoteClient, UUID itemID, Vector3 RayEnd, Vector3 RayStart, |
||
724 | UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, |
||
725 | bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment) |
||
726 | { |
||
727 | // m_log.DebugFormat("[INVENTORY ACCESS MODULE]: RezObject for {0}, item {1}", remoteClient.Name, itemID); |
||
728 | |||
729 | InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); |
||
730 | item = m_Scene.InventoryService.GetItem(item); |
||
731 | |||
732 | if (item == null) |
||
733 | { |
||
734 | m_log.WarnFormat( |
||
735 | "[INVENTORY ACCESS MODULE]: Could not find item {0} for {1} in RezObject()", |
||
736 | itemID, remoteClient.Name); |
||
737 | |||
738 | return null; |
||
739 | } |
||
740 | |||
741 | item.Owner = remoteClient.AgentId; |
||
742 | |||
743 | return RezObject( |
||
744 | remoteClient, item, item.AssetID, |
||
745 | RayEnd, RayStart, RayTargetID, BypassRayCast, RayEndIsIntersection, |
||
746 | RezSelected, RemoveItem, fromTaskID, attachment); |
||
747 | } |
||
748 | |||
749 | public virtual SceneObjectGroup RezObject( |
||
750 | IClientAPI remoteClient, InventoryItemBase item, UUID assetID, Vector3 RayEnd, Vector3 RayStart, |
||
751 | UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, |
||
752 | bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment) |
||
753 | { |
||
754 | AssetBase rezAsset = m_Scene.AssetService.Get(assetID.ToString()); |
||
755 | |||
756 | if (rezAsset == null) |
||
757 | { |
||
758 | if (item != null) |
||
759 | { |
||
760 | m_log.WarnFormat( |
||
761 | "[InventoryAccessModule]: Could not find asset {0} for item {1} {2} for {3} in RezObject()", |
||
762 | assetID, item.Name, item.ID, remoteClient.Name); |
||
763 | } |
||
764 | else |
||
765 | { |
||
766 | m_log.WarnFormat( |
||
767 | "[INVENTORY ACCESS MODULE]: Could not find asset {0} for {1} in RezObject()", |
||
768 | assetID, remoteClient.Name); |
||
769 | } |
||
770 | |||
771 | return null; |
||
772 | } |
||
773 | |||
774 | SceneObjectGroup group = null; |
||
775 | |||
776 | List<SceneObjectGroup> objlist; |
||
777 | List<Vector3> veclist; |
||
778 | Vector3 bbox; |
||
779 | float offsetHeight; |
||
780 | byte bRayEndIsIntersection = (byte)(RayEndIsIntersection ? 1 : 0); |
||
781 | Vector3 pos; |
||
782 | |||
783 | bool single = m_Scene.GetObjectsToRez(rezAsset.Data, attachment, out objlist, out veclist, out bbox, out offsetHeight); |
||
784 | |||
785 | if (single) |
||
786 | { |
||
787 | pos = m_Scene.GetNewRezLocation( |
||
788 | RayStart, RayEnd, RayTargetID, Quaternion.Identity, |
||
789 | BypassRayCast, bRayEndIsIntersection, true, bbox, false); |
||
790 | pos.Z += offsetHeight; |
||
791 | } |
||
792 | else |
||
793 | { |
||
794 | pos = m_Scene.GetNewRezLocation(RayStart, RayEnd, |
||
795 | RayTargetID, Quaternion.Identity, |
||
796 | BypassRayCast, bRayEndIsIntersection, true, |
||
797 | bbox, false); |
||
798 | pos -= bbox / 2; |
||
799 | } |
||
800 | |||
801 | if (item != null && !DoPreRezWhenFromItem(remoteClient, item, objlist, pos, veclist, attachment)) |
||
802 | return null; |
||
803 | |||
804 | for (int i = 0; i < objlist.Count; i++) |
||
805 | { |
||
806 | group = objlist[i]; |
||
807 | |||
808 | // m_log.DebugFormat( |
||
809 | // "[INVENTORY ACCESS MODULE]: Preparing to rez {0} {1} {2} ownermask={3:X} nextownermask={4:X} groupmask={5:X} everyonemask={6:X} for {7}", |
||
810 | // group.Name, group.LocalId, group.UUID, |
||
811 | // group.RootPart.OwnerMask, group.RootPart.NextOwnerMask, group.RootPart.GroupMask, group.RootPart.EveryoneMask, |
||
812 | // remoteClient.Name); |
||
813 | |||
814 | // Vector3 storedPosition = group.AbsolutePosition; |
||
815 | if (group.UUID == UUID.Zero) |
||
816 | { |
||
817 | m_log.Debug("[INVENTORY ACCESS MODULE]: Object has UUID.Zero! Position 3"); |
||
818 | } |
||
819 | |||
820 | // if this was previously an attachment and is now being rezzed, |
||
821 | // save the old attachment info. |
||
822 | if (group.IsAttachment == false && group.RootPart.Shape.State != 0) |
||
823 | { |
||
824 | group.RootPart.AttachedPos = group.AbsolutePosition; |
||
825 | group.RootPart.Shape.LastAttachPoint = (byte)group.AttachmentPoint; |
||
826 | } |
||
827 | |||
828 | if (item == null) |
||
829 | { |
||
830 | // Change ownership. Normally this is done in DoPreRezWhenFromItem(), but in this case we must do it here. |
||
831 | foreach (SceneObjectPart part in group.Parts) |
||
832 | { |
||
833 | // Make the rezzer the owner, as this is not necessarily set correctly in the serialized asset. |
||
834 | part.LastOwnerID = part.OwnerID; |
||
835 | part.OwnerID = remoteClient.AgentId; |
||
836 | } |
||
837 | } |
||
838 | |||
839 | if (!attachment) |
||
840 | { |
||
841 | // If it's rezzed in world, select it. Much easier to |
||
842 | // find small items. |
||
843 | // |
||
844 | foreach (SceneObjectPart part in group.Parts) |
||
845 | { |
||
846 | part.CreateSelected = true; |
||
847 | } |
||
848 | } |
||
849 | |||
850 | group.ResetIDs(); |
||
851 | |||
852 | if (attachment) |
||
853 | { |
||
854 | group.RootPart.Flags |= PrimFlags.Phantom; |
||
855 | group.IsAttachment = true; |
||
856 | } |
||
857 | |||
858 | // If we're rezzing an attachment then don't ask |
||
859 | // AddNewSceneObject() to update the client since |
||
860 | // we'll be doing that later on. Scheduling more than |
||
861 | // one full update during the attachment |
||
862 | // process causes some clients to fail to display the |
||
863 | // attachment properly. |
||
864 | m_Scene.AddNewSceneObject(group, true, false); |
||
865 | |||
866 | // if attachment we set it's asset id so object updates |
||
867 | // can reflect that, if not, we set it's position in world. |
||
868 | if (!attachment) |
||
869 | { |
||
870 | group.ScheduleGroupForFullUpdate(); |
||
871 | |||
872 | group.AbsolutePosition = pos + veclist[i]; |
||
873 | } |
||
874 | |||
875 | group.SetGroup(remoteClient.ActiveGroupId, remoteClient); |
||
876 | |||
877 | if (!attachment) |
||
878 | { |
||
879 | SceneObjectPart rootPart = group.RootPart; |
||
880 | |||
881 | if (rootPart.Shape.PCode == (byte)PCode.Prim) |
||
882 | group.ClearPartAttachmentData(); |
||
883 | |||
884 | // Fire on_rez |
||
885 | group.CreateScriptInstances(0, true, m_Scene.DefaultScriptEngine, 1); |
||
886 | rootPart.ParentGroup.ResumeScripts(); |
||
887 | |||
888 | rootPart.ScheduleFullUpdate(); |
||
889 | } |
||
890 | |||
891 | // m_log.DebugFormat( |
||
892 | // "[INVENTORY ACCESS MODULE]: Rezzed {0} {1} {2} ownermask={3:X} nextownermask={4:X} groupmask={5:X} everyonemask={6:X} for {7}", |
||
893 | // group.Name, group.LocalId, group.UUID, |
||
894 | // group.RootPart.OwnerMask, group.RootPart.NextOwnerMask, group.RootPart.GroupMask, group.RootPart.EveryoneMask, |
||
895 | // remoteClient.Name); |
||
896 | } |
||
897 | |||
898 | if (item != null) |
||
899 | DoPostRezWhenFromItem(item, attachment); |
||
900 | |||
901 | return group; |
||
902 | } |
||
903 | |||
904 | /// <summary> |
||
905 | /// Do pre-rez processing when the object comes from an item. |
||
906 | /// </summary> |
||
907 | /// <param name="remoteClient"></param> |
||
908 | /// <param name="item"></param> |
||
909 | /// <param name="objlist"></param> |
||
910 | /// <param name="pos"></param> |
||
911 | /// <param name="veclist"> |
||
912 | /// List of vector position adjustments for a coalesced objects. For ordinary objects |
||
913 | /// this list will contain just Vector3.Zero. The order of adjustments must match the order of objlist |
||
914 | /// </param> |
||
915 | /// <param name="isAttachment"></param> |
||
916 | /// <returns>true if we can processed with rezzing, false if we need to abort</returns> |
||
917 | private bool DoPreRezWhenFromItem( |
||
918 | IClientAPI remoteClient, InventoryItemBase item, List<SceneObjectGroup> objlist, |
||
919 | Vector3 pos, List<Vector3> veclist, bool isAttachment) |
||
920 | { |
||
921 | UUID fromUserInventoryItemId = UUID.Zero; |
||
922 | |||
923 | // If we have permission to copy then link the rezzed object back to the user inventory |
||
924 | // item that it came from. This allows us to enable 'save object to inventory' |
||
925 | if (!m_Scene.Permissions.BypassPermissions()) |
||
926 | { |
||
927 | if ((item.CurrentPermissions & (uint)PermissionMask.Copy) |
||
928 | == (uint)PermissionMask.Copy && (item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0) |
||
929 | { |
||
930 | fromUserInventoryItemId = item.ID; |
||
931 | } |
||
932 | } |
||
933 | else |
||
934 | { |
||
935 | if ((item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0) |
||
936 | { |
||
937 | // Brave new fullperm world |
||
938 | fromUserInventoryItemId = item.ID; |
||
939 | } |
||
940 | } |
||
941 | |||
942 | for (int i = 0; i < objlist.Count; i++) |
||
943 | { |
||
944 | SceneObjectGroup g = objlist[i]; |
||
945 | |||
946 | if (!m_Scene.Permissions.CanRezObject( |
||
947 | g.PrimCount, remoteClient.AgentId, pos + veclist[i]) |
||
948 | && !isAttachment) |
||
949 | { |
||
950 | // The client operates in no fail mode. It will |
||
951 | // have already removed the item from the folder |
||
952 | // if it's no copy. |
||
953 | // Put it back if it's not an attachment |
||
954 | // |
||
955 | if (((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) && (!isAttachment)) |
||
956 | remoteClient.SendBulkUpdateInventory(item); |
||
957 | |||
958 | ILandObject land = m_Scene.LandChannel.GetLandObject(pos.X, pos.Y); |
||
959 | remoteClient.SendAlertMessage(string.Format( |
||
960 | "Can't rez object '{0}' at <{1:F3}, {2:F3}, {3:F3}> on parcel '{4}' in region {5}.", |
||
961 | item.Name, pos.X, pos.Y, pos.Z, land != null ? land.LandData.Name : "Unknown", m_Scene.Name)); |
||
962 | |||
963 | return false; |
||
964 | } |
||
965 | } |
||
966 | |||
967 | for (int i = 0; i < objlist.Count; i++) |
||
968 | { |
||
969 | SceneObjectGroup so = objlist[i]; |
||
970 | SceneObjectPart rootPart = so.RootPart; |
||
971 | |||
972 | // Since renaming the item in the inventory does not |
||
973 | // affect the name stored in the serialization, transfer |
||
974 | // the correct name from the inventory to the |
||
975 | // object itself before we rez. |
||
976 | // |
||
977 | // Only do these for the first object if we are rezzing a coalescence. |
||
978 | if (i == 0) |
||
979 | { |
||
980 | rootPart.Name = item.Name; |
||
981 | rootPart.Description = item.Description; |
||
982 | rootPart.ObjectSaleType = item.SaleType; |
||
983 | rootPart.SalePrice = item.SalePrice; |
||
984 | } |
||
985 | |||
986 | so.FromFolderID = item.Folder; |
||
987 | |||
988 | // m_log.DebugFormat( |
||
989 | // "[INVENTORY ACCESS MODULE]: rootPart.OwnedID {0}, item.Owner {1}, item.CurrentPermissions {2:X}", |
||
990 | // rootPart.OwnerID, item.Owner, item.CurrentPermissions); |
||
991 | |||
992 | if ((rootPart.OwnerID != item.Owner) || (item.CurrentPermissions & SceneObjectGroup.SLAM) != 0) |
||
993 | { |
||
994 | //Need to kill the for sale here |
||
995 | rootPart.ObjectSaleType = 0; |
||
996 | rootPart.SalePrice = 10; |
||
997 | } |
||
998 | |||
999 | foreach (SceneObjectPart part in so.Parts) |
||
1000 | { |
||
1001 | part.FromUserInventoryItemID = fromUserInventoryItemId; |
||
1002 | part.ApplyPermissionsOnRez(item, true, m_Scene); |
||
1003 | } |
||
1004 | |||
1005 | rootPart.TrimPermissions(); |
||
1006 | |||
1007 | if (isAttachment) |
||
1008 | so.FromItemID = item.ID; |
||
1009 | } |
||
1010 | |||
1011 | return true; |
||
1012 | } |
||
1013 | |||
1014 | /// <summary> |
||
1015 | /// Do post-rez processing when the object comes from an item. |
||
1016 | /// </summary> |
||
1017 | /// <param name="item"></param> |
||
1018 | /// <param name="isAttachment"></param> |
||
1019 | private void DoPostRezWhenFromItem(InventoryItemBase item, bool isAttachment) |
||
1020 | { |
||
1021 | if (!m_Scene.Permissions.BypassPermissions()) |
||
1022 | { |
||
1023 | if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) |
||
1024 | { |
||
1025 | // If this is done on attachments, no |
||
1026 | // copy ones will be lost, so avoid it |
||
1027 | // |
||
1028 | if (!isAttachment) |
||
1029 | { |
||
1030 | List<UUID> uuids = new List<UUID>(); |
||
1031 | uuids.Add(item.ID); |
||
1032 | m_Scene.InventoryService.DeleteItems(item.Owner, uuids); |
||
1033 | } |
||
1034 | } |
||
1035 | } |
||
1036 | } |
||
1037 | |||
1038 | protected void AddUserData(SceneObjectGroup sog) |
||
1039 | { |
||
1040 | UserManagementModule.AddUser(sog.RootPart.CreatorID, sog.RootPart.CreatorData); |
||
1041 | foreach (SceneObjectPart sop in sog.Parts) |
||
1042 | UserManagementModule.AddUser(sop.CreatorID, sop.CreatorData); |
||
1043 | } |
||
1044 | |||
1045 | public virtual void TransferInventoryAssets(InventoryItemBase item, UUID sender, UUID receiver) |
||
1046 | { |
||
1047 | } |
||
1048 | |||
1049 | public virtual bool CanGetAgentInventoryItem(IClientAPI remoteClient, UUID itemID, UUID requestID) |
||
1050 | { |
||
1051 | InventoryItemBase assetRequestItem = GetItem(remoteClient.AgentId, itemID); |
||
1052 | |||
1053 | if (assetRequestItem == null) |
||
1054 | { |
||
1055 | ILibraryService lib = m_Scene.RequestModuleInterface<ILibraryService>(); |
||
1056 | |||
1057 | if (lib != null) |
||
1058 | assetRequestItem = lib.LibraryRootFolder.FindItem(itemID); |
||
1059 | |||
1060 | if (assetRequestItem == null) |
||
1061 | return false; |
||
1062 | } |
||
1063 | |||
1064 | // At this point, we need to apply perms |
||
1065 | // only to notecards and scripts. All |
||
1066 | // other asset types are always available |
||
1067 | // |
||
1068 | if (assetRequestItem.AssetType == (int)AssetType.LSLText) |
||
1069 | { |
||
1070 | if (!m_Scene.Permissions.CanViewScript(itemID, UUID.Zero, remoteClient.AgentId)) |
||
1071 | { |
||
1072 | remoteClient.SendAgentAlertMessage("Insufficient permissions to view script", false); |
||
1073 | return false; |
||
1074 | } |
||
1075 | } |
||
1076 | else if (assetRequestItem.AssetType == (int)AssetType.Notecard) |
||
1077 | { |
||
1078 | if (!m_Scene.Permissions.CanViewNotecard(itemID, UUID.Zero, remoteClient.AgentId)) |
||
1079 | { |
||
1080 | remoteClient.SendAgentAlertMessage("Insufficient permissions to view notecard", false); |
||
1081 | return false; |
||
1082 | } |
||
1083 | } |
||
1084 | |||
1085 | if (assetRequestItem.AssetID != requestID) |
||
1086 | { |
||
1087 | m_log.WarnFormat( |
||
1088 | "[INVENTORY ACCESS MODULE]: {0} requested asset {1} from item {2} but this does not match item's asset {3}", |
||
1089 | Name, requestID, itemID, assetRequestItem.AssetID); |
||
1090 | |||
1091 | return false; |
||
1092 | } |
||
1093 | |||
1094 | return true; |
||
1095 | } |
||
1096 | |||
1097 | |||
1098 | public virtual bool IsForeignUser(UUID userID, out string assetServerURL) |
||
1099 | { |
||
1100 | assetServerURL = string.Empty; |
||
1101 | return false; |
||
1102 | } |
||
1103 | |||
1104 | #endregion |
||
1105 | |||
1106 | #region Misc |
||
1107 | |||
1108 | /// <summary> |
||
1109 | /// Create a new asset data structure. |
||
1110 | /// </summary> |
||
1111 | /// <param name="name"></param> |
||
1112 | /// <param name="description"></param> |
||
1113 | /// <param name="invType"></param> |
||
1114 | /// <param name="assetType"></param> |
||
1115 | /// <param name="data"></param> |
||
1116 | /// <returns></returns> |
||
1117 | private AssetBase CreateAsset(string name, string description, sbyte assetType, byte[] data, string creatorID) |
||
1118 | { |
||
1119 | AssetBase asset = new AssetBase(UUID.Random(), name, assetType, creatorID); |
||
1120 | asset.Description = description; |
||
1121 | asset.Data = (data == null) ? new byte[1] : data; |
||
1122 | |||
1123 | return asset; |
||
1124 | } |
||
1125 | |||
1126 | protected virtual InventoryItemBase GetItem(UUID agentID, UUID itemID) |
||
1127 | { |
||
1128 | IInventoryService invService = m_Scene.RequestModuleInterface<IInventoryService>(); |
||
1129 | InventoryItemBase item = new InventoryItemBase(itemID, agentID); |
||
1130 | item = invService.GetItem(item); |
||
1131 | |||
1132 | if (item != null && item.CreatorData != null && item.CreatorData != string.Empty) |
||
1133 | UserManagementModule.AddUser(item.CreatorIdAsUuid, item.CreatorData); |
||
1134 | |||
1135 | return item; |
||
1136 | } |
||
1137 | |||
1138 | #endregion |
||
1139 | } |
||
1140 | } |