aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/CoreModules')
-rw-r--r--OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs168
-rw-r--r--OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs25
-rw-r--r--OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs127
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs462
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs32
-rw-r--r--OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs25
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs11
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs16
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs16
-rw-r--r--OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs6
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs15
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs15
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs28
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs4
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs106
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs1
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs6
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs8
-rw-r--r--OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs89
20 files changed, 789 insertions, 375 deletions
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
index 9d8082b..eed7cd5 100644
--- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
@@ -41,14 +41,13 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
41 /// </summary> 41 /// </summary>
42 public class AgentAssetTransactions 42 public class AgentAssetTransactions
43 { 43 {
44// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
45 45
46 // Fields 46 // Fields
47 private bool m_dumpAssetsToFile; 47 private bool m_dumpAssetsToFile;
48 private Scene m_Scene; 48 private Scene m_Scene;
49 public UUID UserID; 49 private UUID UserID;
50 public Dictionary<UUID, AssetXferUploader> XferUploaders = 50 private Dictionary<UUID, AssetXferUploader> XferUploaders = new Dictionary<UUID, AssetXferUploader>();
51 new Dictionary<UUID, AssetXferUploader>();
52 51
53 // Methods 52 // Methods
54 public AgentAssetTransactions(UUID agentID, Scene scene, 53 public AgentAssetTransactions(UUID agentID, Scene scene,
@@ -59,36 +58,94 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
59 m_dumpAssetsToFile = dumpAssetsToFile; 58 m_dumpAssetsToFile = dumpAssetsToFile;
60 } 59 }
61 60
62 public AssetXferUploader RequestXferUploader(UUID transactionID) 61 /// <summary>
62 /// Return a xfer uploader if one does not already exist.
63 /// </summary>
64 /// <param name="transactionID"></param>
65 /// <param name="assetID">
66 /// We must transfer the new asset ID into the uploader on creation, otherwise
67 /// we can see race conditions with other threads which can retrieve an item before it is updated with the new
68 /// asset id.
69 /// </param>
70 /// <returns>
71 /// The xfer uploader requested. Null if one is already in existence.
72 /// FIXME: This is a bizarre thing to do, and is probably meant to signal an error condition if multiple
73 /// transfers are made. Needs to be corrected.
74 /// </returns>
75 public AssetXferUploader RequestXferUploader(UUID transactionID, UUID assetID)
63 { 76 {
64 if (!XferUploaders.ContainsKey(transactionID)) 77 lock (XferUploaders)
65 { 78 {
66 AssetXferUploader uploader = new AssetXferUploader(m_Scene, 79 if (!XferUploaders.ContainsKey(transactionID))
67 m_dumpAssetsToFile);
68
69 lock (XferUploaders)
70 { 80 {
81 AssetXferUploader uploader = new AssetXferUploader(this, m_Scene, assetID, m_dumpAssetsToFile);
82
83// m_log.DebugFormat(
84// "[AGENT ASSETS TRANSACTIONS]: Adding asset xfer uploader {0} since it didn't previously exist", transactionID);
85
71 XferUploaders.Add(transactionID, uploader); 86 XferUploaders.Add(transactionID, uploader);
72 }
73 87
74 return uploader; 88 return uploader;
89 }
75 } 90 }
91
92 m_log.WarnFormat("[AGENT ASSETS TRANSACTIONS]: Ignoring request for asset xfer uploader {0} since it already exists", transactionID);
93
76 return null; 94 return null;
77 } 95 }
78 96
79 public void HandleXfer(ulong xferID, uint packetID, byte[] data) 97 public void HandleXfer(ulong xferID, uint packetID, byte[] data)
80 { 98 {
99 AssetXferUploader foundUploader = null;
100
81 lock (XferUploaders) 101 lock (XferUploaders)
82 { 102 {
83 foreach (AssetXferUploader uploader in XferUploaders.Values) 103 foreach (AssetXferUploader uploader in XferUploaders.Values)
84 { 104 {
105// m_log.DebugFormat(
106// "[AGENT ASSETS TRANSACTIONS]: In HandleXfer, inspect xfer upload with xfer id {0}",
107// uploader.XferID);
108
85 if (uploader.XferID == xferID) 109 if (uploader.XferID == xferID)
86 { 110 {
87 uploader.HandleXferPacket(xferID, packetID, data); 111 foundUploader = uploader;
88 break; 112 break;
89 } 113 }
90 } 114 }
91 } 115 }
116
117 if (foundUploader != null)
118 {
119// m_log.DebugFormat(
120// "[AGENT ASSETS TRANSACTIONS]: Found xfer uploader for xfer id {0}, packet id {1}, data length {2}",
121// xferID, packetID, data.Length);
122
123 foundUploader.HandleXferPacket(xferID, packetID, data);
124 }
125 else
126 {
127 m_log.ErrorFormat(
128 "[AGENT ASSET TRANSACTIONS]: Could not find uploader for xfer id {0}, packet id {1}, data length {2}",
129 xferID, packetID, data.Length);
130 }
131 }
132
133 public bool RemoveXferUploader(UUID transactionID)
134 {
135 lock (XferUploaders)
136 {
137 bool removed = XferUploaders.Remove(transactionID);
138
139 if (!removed)
140 m_log.WarnFormat(
141 "[AGENT ASSET TRANSACTIONS]: Received request to remove xfer uploader with transaction ID {0} but none found",
142 transactionID);
143// else
144// m_log.DebugFormat(
145// "[AGENT ASSET TRANSACTIONS]: Removed xfer uploader with transaction ID {0}", transactionID);
146
147 return removed;
148 }
92 } 149 }
93 150
94 public void RequestCreateInventoryItem(IClientAPI remoteClient, 151 public void RequestCreateInventoryItem(IClientAPI remoteClient,
@@ -96,16 +153,24 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
96 string description, string name, sbyte invType, 153 string description, string name, sbyte invType,
97 sbyte type, byte wearableType, uint nextOwnerMask) 154 sbyte type, byte wearableType, uint nextOwnerMask)
98 { 155 {
99 if (XferUploaders.ContainsKey(transactionID)) 156 AssetXferUploader uploader = null;
157
158 lock (XferUploaders)
100 { 159 {
101 XferUploaders[transactionID].RequestCreateInventoryItem( 160 if (XferUploaders.ContainsKey(transactionID))
102 remoteClient, transactionID, folderID, 161 uploader = XferUploaders[transactionID];
103 callbackID, description, name, invType, type,
104 wearableType, nextOwnerMask);
105 } 162 }
106 }
107
108 163
164 if (uploader != null)
165 uploader.RequestCreateInventoryItem(
166 remoteClient, transactionID, folderID,
167 callbackID, description, name, invType, type,
168 wearableType, nextOwnerMask);
169 else
170 m_log.ErrorFormat(
171 "[AGENT ASSET TRANSACTIONS]: Could not find uploader with transaction ID {0} when handling request to create inventory item {1} from {2}",
172 transactionID, name, remoteClient.Name);
173 }
109 174
110 /// <summary> 175 /// <summary>
111 /// Get an uploaded asset. If the data is successfully retrieved, 176 /// Get an uploaded asset. If the data is successfully retrieved,
@@ -113,19 +178,18 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
113 /// </summary> 178 /// </summary>
114 /// <param name="transactionID"></param> 179 /// <param name="transactionID"></param>
115 /// <returns>The asset if the upload has completed, null if it has not.</returns> 180 /// <returns>The asset if the upload has completed, null if it has not.</returns>
116 public AssetBase GetTransactionAsset(UUID transactionID) 181 private AssetBase GetTransactionAsset(UUID transactionID)
117 { 182 {
118 if (XferUploaders.ContainsKey(transactionID)) 183 lock (XferUploaders)
119 { 184 {
120 AssetXferUploader uploader = XferUploaders[transactionID]; 185 if (XferUploaders.ContainsKey(transactionID))
121 AssetBase asset = uploader.GetAssetData();
122
123 lock (XferUploaders)
124 { 186 {
125 XferUploaders.Remove(transactionID); 187 AssetXferUploader uploader = XferUploaders[transactionID];
126 } 188 AssetBase asset = uploader.GetAssetData();
189 RemoveXferUploader(transactionID);
127 190
128 return asset; 191 return asset;
192 }
129 } 193 }
130 194
131 return null; 195 return null;
@@ -135,7 +199,15 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
135 SceneObjectPart part, UUID transactionID, 199 SceneObjectPart part, UUID transactionID,
136 TaskInventoryItem item) 200 TaskInventoryItem item)
137 { 201 {
138 if (XferUploaders.ContainsKey(transactionID)) 202 AssetXferUploader uploader = null;
203
204 lock (XferUploaders)
205 {
206 if (XferUploaders.ContainsKey(transactionID))
207 uploader = XferUploaders[transactionID];
208 }
209
210 if (uploader != null)
139 { 211 {
140 AssetBase asset = GetTransactionAsset(transactionID); 212 AssetBase asset = GetTransactionAsset(transactionID);
141 213
@@ -161,28 +233,34 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
161 m_Scene.AssetService.Store(asset); 233 m_Scene.AssetService.Store(asset);
162 } 234 }
163 } 235 }
236 else
237 {
238 m_log.ErrorFormat(
239 "[AGENT ASSET TRANSACTIONS]: Could not find uploader with transaction ID {0} when handling request to update task inventory item {1} in {2}",
240 transactionID, item.Name, part.Name);
241 }
164 } 242 }
165 243
166 public void RequestUpdateInventoryItem(IClientAPI remoteClient, 244 public void RequestUpdateInventoryItem(IClientAPI remoteClient,
167 UUID transactionID, InventoryItemBase item) 245 UUID transactionID, InventoryItemBase item)
168 { 246 {
169 if (XferUploaders.ContainsKey(transactionID)) 247 AssetXferUploader uploader = null;
170 {
171 AssetBase asset = GetTransactionAsset(transactionID);
172 248
173 if (asset != null) 249 lock (XferUploaders)
174 { 250 {
175 asset.FullID = UUID.Random(); 251 if (XferUploaders.ContainsKey(transactionID))
176 asset.Name = item.Name; 252 uploader = XferUploaders[transactionID];
177 asset.Description = item.Description; 253 }
178 asset.Type = (sbyte)item.AssetType;
179 item.AssetID = asset.FullID;
180
181 m_Scene.AssetService.Store(asset);
182 254
183 IInventoryService invService = m_Scene.InventoryService; 255 if (uploader != null)
184 invService.UpdateItem(item); 256 {
185 } 257 uploader.RequestUpdateInventoryItem(remoteClient, transactionID, item);
258 }
259 else
260 {
261 m_log.ErrorFormat(
262 "[AGENT ASSET TRANSACTIONS]: Could not find uploader with transaction ID {0} when handling request to update inventory item {1} for {2}",
263 transactionID, item.Name, remoteClient.Name);
186 } 264 }
187 } 265 }
188 } 266 }
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs
index 82558de..a28d5d7 100644
--- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs
@@ -172,11 +172,12 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
172 /// <summary> 172 /// <summary>
173 /// Update an inventory item with data that has been received through a 173 /// Update an inventory item with data that has been received through a
174 /// transaction. 174 /// transaction.
175 /// 175 /// </summary>
176 /// <remarks>
176 /// This is called when clothing or body parts are updated (for 177 /// This is called when clothing or body parts are updated (for
177 /// instance, with new textures or colours). It may also be called in 178 /// instance, with new textures or colours). It may also be called in
178 /// other situations. 179 /// other situations.
179 /// </summary> 180 /// </remarks>
180 /// <param name="remoteClient"></param> 181 /// <param name="remoteClient"></param>
181 /// <param name="transactionID"></param> 182 /// <param name="transactionID"></param>
182 /// <param name="item"></param> 183 /// <param name="item"></param>
@@ -184,14 +185,12 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
184 UUID transactionID, InventoryItemBase item) 185 UUID transactionID, InventoryItemBase item)
185 { 186 {
186// m_log.DebugFormat( 187// m_log.DebugFormat(
187// "[TRANSACTIONS MANAGER] Called HandleItemUpdateFromTransaction with item {0}", 188// "[ASSET TRANSACTION MODULE]: Called HandleItemUpdateFromTransaction with item {0}",
188// item.Name); 189// item.Name);
189 190
190 AgentAssetTransactions transactions = 191 AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId);
191 GetUserTransactions(remoteClient.AgentId);
192 192
193 transactions.RequestUpdateInventoryItem(remoteClient, 193 transactions.RequestUpdateInventoryItem(remoteClient, transactionID, item);
194 transactionID, item);
195 } 194 }
196 195
197 /// <summary> 196 /// <summary>
@@ -255,11 +254,8 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
255 } 254 }
256 } 255 }
257 256
258 AgentAssetTransactions transactions = 257 AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId);
259 GetUserTransactions(remoteClient.AgentId); 258 AssetXferUploader uploader = transactions.RequestXferUploader(transaction, assetID);
260
261 AssetXferUploader uploader =
262 transactions.RequestXferUploader(transaction);
263 259
264 if (uploader != null) 260 if (uploader != null)
265 { 261 {
@@ -279,9 +275,8 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
279 public void HandleXfer(IClientAPI remoteClient, ulong xferID, 275 public void HandleXfer(IClientAPI remoteClient, ulong xferID,
280 uint packetID, byte[] data) 276 uint packetID, byte[] data)
281 { 277 {
282 //m_log.Debug("xferID: " + xferID + " packetID: " + packetID + " data!"); 278// m_log.Debug("xferID: " + xferID + " packetID: " + packetID + " data length " + data.Length);
283 AgentAssetTransactions transactions = 279 AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId);
284 GetUserTransactions(remoteClient.AgentId);
285 280
286 transactions.HandleXfer(xferID, packetID, data); 281 transactions.HandleXfer(xferID, packetID, data);
287 } 282 }
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs
index a7929ba..ec4dfd0 100644
--- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs
@@ -40,11 +40,21 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
40 { 40 {
41 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 41 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
42 42
43 /// <summary>
44 /// Reference to the object that holds this uploader. Used to remove ourselves from it's list if we
45 /// are performing a delayed update.
46 /// </summary>
47 AgentAssetTransactions m_transactions;
48
43 private AssetBase m_asset; 49 private AssetBase m_asset;
44 private UUID InventFolder = UUID.Zero; 50 private UUID InventFolder = UUID.Zero;
45 private sbyte invType = 0; 51 private sbyte invType = 0;
52
46 private bool m_createItem = false; 53 private bool m_createItem = false;
47 private uint m_createItemCallback = 0; 54 private uint m_createItemCallback = 0;
55 private bool m_updateItem = false;
56 private InventoryItemBase m_updateItemData;
57
48 private string m_description = String.Empty; 58 private string m_description = String.Empty;
49 private bool m_dumpAssetToFile; 59 private bool m_dumpAssetToFile;
50 private bool m_finished = false; 60 private bool m_finished = false;
@@ -58,9 +68,11 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
58 public ulong XferID; 68 public ulong XferID;
59 private Scene m_Scene; 69 private Scene m_Scene;
60 70
61 public AssetXferUploader(Scene scene, bool dumpAssetToFile) 71 public AssetXferUploader(AgentAssetTransactions transactions, Scene scene, UUID assetID, bool dumpAssetToFile)
62 { 72 {
73 m_transactions = transactions;
63 m_Scene = scene; 74 m_Scene = scene;
75 m_asset = new AssetBase() { FullID = assetID };
64 m_dumpAssetToFile = dumpAssetToFile; 76 m_dumpAssetToFile = dumpAssetToFile;
65 } 77 }
66 78
@@ -73,6 +85,10 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
73 /// <returns>True if the transfer is complete, false otherwise or if the xferID was not valid</returns> 85 /// <returns>True if the transfer is complete, false otherwise or if the xferID was not valid</returns>
74 public bool HandleXferPacket(ulong xferID, uint packetID, byte[] data) 86 public bool HandleXferPacket(ulong xferID, uint packetID, byte[] data)
75 { 87 {
88// m_log.DebugFormat(
89// "[ASSET XFER UPLOADER]: Received packet {0} for xfer {1} (data length {2})",
90// packetID, xferID, data.Length);
91
76 if (XferID == xferID) 92 if (XferID == xferID)
77 { 93 {
78 if (m_asset.Data.Length > 1) 94 if (m_asset.Data.Length > 1)
@@ -107,16 +123,20 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
107 /// <param name="xferID"></param> 123 /// <param name="xferID"></param>
108 /// <param name="packetID"></param> 124 /// <param name="packetID"></param>
109 /// <param name="data"></param> 125 /// <param name="data"></param>
110 /// <returns>True if the transfer is complete, false otherwise</returns> 126 public void Initialise(IClientAPI remoteClient, UUID assetID,
111 public bool Initialise(IClientAPI remoteClient, UUID assetID,
112 UUID transaction, sbyte type, byte[] data, bool storeLocal, 127 UUID transaction, sbyte type, byte[] data, bool storeLocal,
113 bool tempFile) 128 bool tempFile)
114 { 129 {
130// m_log.DebugFormat(
131// "[ASSET XFER UPLOADER]: Initialised xfer from {0}, asset {1}, transaction {2}, type {3}, storeLocal {4}, tempFile {5}, already received data length {6}",
132// remoteClient.Name, assetID, transaction, type, storeLocal, tempFile, data.Length);
133
115 ourClient = remoteClient; 134 ourClient = remoteClient;
116 m_asset = new AssetBase(assetID, "blank", type, 135 m_asset.Name = "blank";
117 remoteClient.AgentId.ToString());
118 m_asset.Data = data;
119 m_asset.Description = "empty"; 136 m_asset.Description = "empty";
137 m_asset.Type = type;
138 m_asset.CreatorID = remoteClient.AgentId.ToString();
139 m_asset.Data = data;
120 m_asset.Local = storeLocal; 140 m_asset.Local = storeLocal;
121 m_asset.Temporary = tempFile; 141 m_asset.Temporary = tempFile;
122 142
@@ -126,21 +146,22 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
126 if (m_asset.Data.Length > 2) 146 if (m_asset.Data.Length > 2)
127 { 147 {
128 SendCompleteMessage(); 148 SendCompleteMessage();
129 return true;
130 } 149 }
131 else 150 else
132 { 151 {
133 RequestStartXfer(); 152 RequestStartXfer();
134 } 153 }
135
136 return false;
137 } 154 }
138 155
139 protected void RequestStartXfer() 156 protected void RequestStartXfer()
140 { 157 {
141 XferID = Util.GetNextXferID(); 158 XferID = Util.GetNextXferID();
142 ourClient.SendXferRequest(XferID, m_asset.Type, m_asset.FullID, 159
143 0, new byte[0]); 160// m_log.DebugFormat(
161// "[ASSET XFER UPLOADER]: Requesting Xfer of asset {0}, type {1}, transfer id {2} from {3}",
162// m_asset.FullID, m_asset.Type, XferID, ourClient.Name);
163
164 ourClient.SendXferRequest(XferID, m_asset.Type, m_asset.FullID, 0, new byte[0]);
144 } 165 }
145 166
146 protected void SendCompleteMessage() 167 protected void SendCompleteMessage()
@@ -148,18 +169,32 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
148 ourClient.SendAssetUploadCompleteMessage(m_asset.Type, true, 169 ourClient.SendAssetUploadCompleteMessage(m_asset.Type, true,
149 m_asset.FullID); 170 m_asset.FullID);
150 171
151 m_finished = true; 172 // We must lock in order to avoid a race with a separate thread dealing with an inventory item or create
152 if (m_createItem) 173 // message from other client UDP.
153 { 174 lock (this)
154 DoCreateItem(m_createItemCallback);
155 }
156 else if (m_storeLocal)
157 { 175 {
158 m_Scene.AssetService.Store(m_asset); 176 m_finished = true;
177 if (m_createItem)
178 {
179 DoCreateItem(m_createItemCallback);
180 }
181 else if (m_updateItem)
182 {
183 StoreAssetForItemUpdate(m_updateItemData);
184
185 // Remove ourselves from the list of transactions if completion was delayed until the transaction
186 // was complete.
187 // TODO: Should probably do the same for create item.
188 m_transactions.RemoveXferUploader(TransactionID);
189 }
190 else if (m_storeLocal)
191 {
192 m_Scene.AssetService.Store(m_asset);
193 }
159 } 194 }
160 195
161 m_log.DebugFormat( 196 m_log.DebugFormat(
162 "[ASSET TRANSACTIONS]: Uploaded asset {0} for transaction {1}", 197 "[ASSET XFER UPLOADER]: Uploaded asset {0} for transaction {1}",
163 m_asset.FullID, TransactionID); 198 m_asset.FullID, TransactionID);
164 199
165 if (m_dumpAssetToFile) 200 if (m_dumpAssetToFile)
@@ -205,18 +240,66 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
205 m_asset.Description = description; 240 m_asset.Description = description;
206 m_asset.Type = type; 241 m_asset.Type = type;
207 242
243 // We must lock to avoid a race with a separate thread uploading the asset.
244 lock (this)
245 {
246 if (m_finished)
247 {
248 DoCreateItem(callbackID);
249 }
250 else
251 {
252 m_createItem = true; //set flag so the inventory item is created when upload is complete
253 m_createItemCallback = callbackID;
254 }
255 }
256 }
257 }
258
259 public void RequestUpdateInventoryItem(IClientAPI remoteClient, UUID transactionID, InventoryItemBase item)
260 {
261 // We must lock to avoid a race with a separate thread uploading the asset.
262 lock (this)
263 {
264 m_asset.Name = item.Name;
265 m_asset.Description = item.Description;
266 m_asset.Type = (sbyte)item.AssetType;
267
268 // We must always store the item at this point even if the asset hasn't finished uploading, in order
269 // to avoid a race condition when the appearance module retrieves the item to set the asset id in
270 // the AvatarAppearance structure.
271 item.AssetID = m_asset.FullID;
272 m_Scene.InventoryService.UpdateItem(item);
273
208 if (m_finished) 274 if (m_finished)
209 { 275 {
210 DoCreateItem(callbackID); 276 StoreAssetForItemUpdate(item);
211 } 277 }
212 else 278 else
213 { 279 {
214 m_createItem = true; //set flag so the inventory item is created when upload is complete 280// m_log.DebugFormat(
215 m_createItemCallback = callbackID; 281// "[ASSET XFER UPLOADER]: Holding update inventory item request {0} for {1} pending completion of asset xfer for transaction {2}",
282// item.Name, remoteClient.Name, transactionID);
283
284 m_updateItem = true;
285 m_updateItemData = item;
216 } 286 }
217 } 287 }
218 } 288 }
219 289
290 /// <summary>
291 /// Store the asset for the given item.
292 /// </summary>
293 /// <param name="item"></param>
294 private void StoreAssetForItemUpdate(InventoryItemBase item)
295 {
296// m_log.DebugFormat(
297// "[ASSET XFER UPLOADER]: Storing asset {0} for earlier item update for {1} for {2}",
298// m_asset.FullID, item.Name, ourClient.Name);
299
300 m_Scene.AssetService.Store(m_asset);
301 }
302
220 private void DoCreateItem(uint callbackID) 303 private void DoCreateItem(uint callbackID)
221 { 304 {
222 m_Scene.AssetService.Store(m_asset); 305 m_Scene.AssetService.Store(m_asset);
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index 996e2ab..b965d75 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
@@ -143,20 +143,26 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
143 143
144 public void SaveChangedAttachments(IScenePresence sp) 144 public void SaveChangedAttachments(IScenePresence sp)
145 { 145 {
146// m_log.DebugFormat("[ATTACHMENTS MODULE]: Saving changed attachments for {0}", sp.Name);
147
146 foreach (SceneObjectGroup grp in sp.GetAttachments()) 148 foreach (SceneObjectGroup grp in sp.GetAttachments())
147 { 149 {
148 if (grp.HasGroupChanged) // Resizer scripts? 150// if (grp.HasGroupChanged) // Resizer scripts?
149 { 151// {
150 grp.IsAttachment = false; 152 grp.IsAttachment = false;
151 grp.AbsolutePosition = grp.RootPart.AttachedPos; 153 grp.AbsolutePosition = grp.RootPart.AttachedPos;
152 UpdateKnownItem(sp.ControllingClient, grp, grp.GetFromItemID(), grp.OwnerID); 154 UpdateKnownItem(sp.ControllingClient, grp);
153 grp.IsAttachment = true; 155 grp.IsAttachment = true;
154 } 156// }
155 } 157 }
156 } 158 }
157 159
158 public void DeleteAttachmentsFromScene(IScenePresence sp, bool silent) 160 public void DeleteAttachmentsFromScene(IScenePresence sp, bool silent)
159 { 161 {
162// m_log.DebugFormat(
163// "[ATTACHMENTS MODULE]: Deleting attachments from scene {0} for {1}, silent = {2}",
164// m_scene.RegionInfo.RegionName, sp.Name, silent);
165
160 foreach (SceneObjectGroup sop in sp.GetAttachments()) 166 foreach (SceneObjectGroup sop in sp.GetAttachments())
161 { 167 {
162 sop.Scene.DeleteSceneObject(sop, silent); 168 sop.Scene.DeleteSceneObject(sop, silent);
@@ -212,7 +218,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
212 m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.GetFromItemID(), remoteClient.AgentId); 218 m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.GetFromItemID(), remoteClient.AgentId);
213 219
214 // Save avatar attachment information 220 // Save avatar attachment information
215 m_log.Info( 221 m_log.Debug(
216 "[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId 222 "[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId
217 + ", AttachmentPoint: " + AttachmentPt); 223 + ", AttachmentPoint: " + AttachmentPt);
218 224
@@ -240,80 +246,83 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
240 246
241 private bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent) 247 private bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent)
242 { 248 {
243// m_log.DebugFormat( 249 lock (sp.AttachmentsSyncLock)
244// "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})",
245// group.Name, group.LocalId, sp.Name, attachmentPt, silent);
246
247 if (sp.GetAttachments(attachmentPt).Contains(group))
248 {
249// m_log.WarnFormat(
250// "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached",
251// group.Name, group.LocalId, sp.Name, AttachmentPt);
252
253 return false;
254 }
255
256 Vector3 attachPos = group.AbsolutePosition;
257
258 // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should
259 // be removed when that functionality is implemented in opensim
260 attachmentPt &= 0x7f;
261
262 // If the attachment point isn't the same as the one previously used
263 // set it's offset position = 0 so that it appears on the attachment point
264 // and not in a weird location somewhere unknown.
265 if (attachmentPt != 0 && attachmentPt != group.AttachmentPoint)
266 {
267 attachPos = Vector3.Zero;
268 }
269
270 // AttachmentPt 0 means the client chose to 'wear' the attachment.
271 if (attachmentPt == 0)
272 {
273 // Check object for stored attachment point
274 attachmentPt = group.AttachmentPoint;
275 }
276
277 // if we still didn't find a suitable attachment point.......
278 if (attachmentPt == 0)
279 {
280 // Stick it on left hand with Zero Offset from the attachment point.
281 attachmentPt = (uint)AttachmentPoint.LeftHand;
282 attachPos = Vector3.Zero;
283 }
284
285 group.AttachmentPoint = attachmentPt;
286 group.AbsolutePosition = attachPos;
287
288 // We also don't want to do any of the inventory operations for an NPC.
289 if (sp.PresenceType != PresenceType.Npc)
290 { 250 {
291 // Remove any previous attachments 251// m_log.DebugFormat(
292 List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt); 252// "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})",
293 253// group.Name, group.LocalId, sp.Name, attachmentPt, silent);
294 // At the moment we can only deal with a single attachment 254
295 if (attachments.Count != 0) 255 if (sp.GetAttachments(attachmentPt).Contains(group))
296 { 256 {
297 UUID oldAttachmentItemID = attachments[0].GetFromItemID(); 257 // m_log.WarnFormat(
258 // "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached",
259 // group.Name, group.LocalId, sp.Name, AttachmentPt);
298 260
299 if (oldAttachmentItemID != UUID.Zero) 261 return false;
300 DetachSingleAttachmentToInv(oldAttachmentItemID, sp);
301 else
302 m_log.WarnFormat(
303 "[ATTACHMENTS MODULE]: When detaching existing attachment {0} {1} at point {2} to make way for {3} {4} for {5}, couldn't find the associated item ID to adjust inventory attachment record!",
304 attachments[0].Name, attachments[0].LocalId, attachmentPt, group.Name, group.LocalId, sp.Name);
305 } 262 }
306
307 // Add the new attachment to inventory if we don't already have it.
308 UUID newAttachmentItemID = group.GetFromItemID();
309 if (newAttachmentItemID == UUID.Zero)
310 newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp.ControllingClient, group).ID;
311 263
312 ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group); 264 Vector3 attachPos = group.AbsolutePosition;
265
266 // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should
267 // be removed when that functionality is implemented in opensim
268 attachmentPt &= 0x7f;
269
270 // If the attachment point isn't the same as the one previously used
271 // set it's offset position = 0 so that it appears on the attachment point
272 // and not in a weird location somewhere unknown.
273 if (attachmentPt != 0 && attachmentPt != group.AttachmentPoint)
274 {
275 attachPos = Vector3.Zero;
276 }
277
278 // AttachmentPt 0 means the client chose to 'wear' the attachment.
279 if (attachmentPt == 0)
280 {
281 // Check object for stored attachment point
282 attachmentPt = group.AttachmentPoint;
283 }
284
285 // if we still didn't find a suitable attachment point.......
286 if (attachmentPt == 0)
287 {
288 // Stick it on left hand with Zero Offset from the attachment point.
289 attachmentPt = (uint)AttachmentPoint.LeftHand;
290 attachPos = Vector3.Zero;
291 }
292
293 group.AttachmentPoint = attachmentPt;
294 group.AbsolutePosition = attachPos;
295
296 // We also don't want to do any of the inventory operations for an NPC.
297 if (sp.PresenceType != PresenceType.Npc)
298 {
299 // Remove any previous attachments
300 List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt);
301
302 // At the moment we can only deal with a single attachment
303 if (attachments.Count != 0)
304 {
305 UUID oldAttachmentItemID = attachments[0].GetFromItemID();
306
307 if (oldAttachmentItemID != UUID.Zero)
308 DetachSingleAttachmentToInv(oldAttachmentItemID, sp);
309 else
310 m_log.WarnFormat(
311 "[ATTACHMENTS MODULE]: When detaching existing attachment {0} {1} at point {2} to make way for {3} {4} for {5}, couldn't find the associated item ID to adjust inventory attachment record!",
312 attachments[0].Name, attachments[0].LocalId, attachmentPt, group.Name, group.LocalId, sp.Name);
313 }
314
315 // Add the new attachment to inventory if we don't already have it.
316 UUID newAttachmentItemID = group.GetFromItemID();
317 if (newAttachmentItemID == UUID.Zero)
318 newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp.ControllingClient, group).ID;
319
320 ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group);
321 }
322
323 AttachToAgent(sp, group, attachmentPt, attachPos, silent);
313 } 324 }
314 325
315 AttachToAgent(sp, group, attachmentPt, attachPos, silent);
316
317 return true; 326 return true;
318 } 327 }
319 328
@@ -322,17 +331,31 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
322 RezMultipleAttachmentsFromInvPacket.HeaderDataBlock header, 331 RezMultipleAttachmentsFromInvPacket.HeaderDataBlock header,
323 RezMultipleAttachmentsFromInvPacket.ObjectDataBlock[] objects) 332 RezMultipleAttachmentsFromInvPacket.ObjectDataBlock[] objects)
324 { 333 {
325 foreach (RezMultipleAttachmentsFromInvPacket.ObjectDataBlock obj in objects) 334 ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId);
335
336 if (sp == null)
326 { 337 {
327 RezSingleAttachmentFromInventory(remoteClient, obj.ItemID, obj.AttachmentPt); 338 m_log.ErrorFormat(
339 "[ATTACHMENTS MODULE]: Could not find presence for client {0} {1} in RezMultipleAttachmentsFromInventory()",
340 remoteClient.Name, remoteClient.AgentId);
341 return;
342 }
343
344 lock (sp.AttachmentsSyncLock)
345 {
346// m_log.DebugFormat("[ATTACHMENTS MODULE]: Rezzing multiple attachments from inventory for {0}", sp.Name);
347
348 foreach (RezMultipleAttachmentsFromInvPacket.ObjectDataBlock obj in objects)
349 {
350 RezSingleAttachmentFromInventory(sp, obj.ItemID, obj.AttachmentPt);
351 }
328 } 352 }
329 } 353 }
330 354
331 public ISceneEntity RezSingleAttachmentFromInventory( 355 public ISceneEntity RezSingleAttachmentFromInventory(IClientAPI remoteClient, UUID itemID, uint AttachmentPt)
332 IClientAPI remoteClient, UUID itemID, uint AttachmentPt)
333 { 356 {
334// m_log.DebugFormat( 357// m_log.DebugFormat(
335// "[ATTACHMENTS MODULE]: Rezzing attachment to point {0} from item {1} for {2}", 358// "[ATTACHMENTS MODULE]: Rezzing attachment to point {0} from item {1} for {2}",
336// (AttachmentPoint)AttachmentPt, itemID, remoteClient.Name); 359// (AttachmentPoint)AttachmentPt, itemID, remoteClient.Name);
337 360
338 ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId); 361 ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId);
@@ -344,11 +367,46 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
344 remoteClient.Name, remoteClient.AgentId); 367 remoteClient.Name, remoteClient.AgentId);
345 return null; 368 return null;
346 } 369 }
347 370
371 return RezSingleAttachmentFromInventory(sp, itemID, AttachmentPt);
372 }
373
374 public ISceneEntity RezSingleAttachmentFromInventory(ScenePresence sp, UUID itemID, uint AttachmentPt)
375 {
376// m_log.DebugFormat(
377// "[ATTACHMENTS MODULE]: RezSingleAttachmentFromInventory to point {0} from item {1} for {2}",
378// (AttachmentPoint)AttachmentPt, itemID, sp.Name);
379
348 // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should 380 // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should
349 // be removed when that functionality is implemented in opensim 381 // be removed when that functionality is implemented in opensim
350 AttachmentPt &= 0x7f; 382 AttachmentPt &= 0x7f;
351 383
384 // Viewer 2/3 sometimes asks to re-wear items that are already worn (and show up in it's inventory as such).
385 // This often happens during login - not sure the exact reason.
386 // For now, we will ignore the request. Unfortunately, this means that we need to dig through all the
387 // ScenePresence attachments. We can't use the data in AvatarAppearance because that's present at login
388 // before anything has actually been attached.
389 bool alreadyOn = false;
390 List<SceneObjectGroup> existingAttachments = sp.GetAttachments();
391 foreach (SceneObjectGroup so in existingAttachments)
392 {
393 if (so.GetFromItemID() == itemID)
394 {
395 alreadyOn = true;
396 break;
397 }
398 }
399
400// if (sp.Appearance.GetAttachmentForItem(itemID) != null)
401 if (alreadyOn)
402 {
403// m_log.WarnFormat(
404// "[ATTACHMENTS MODULE]: Ignoring request by {0} to wear item {1} at {2} since it is already worn",
405// sp.Name, itemID, AttachmentPt);
406
407 return null;
408 }
409
352 SceneObjectGroup att = RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt); 410 SceneObjectGroup att = RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt);
353 411
354 if (att == null) 412 if (att == null)
@@ -363,65 +421,68 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
363 IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>(); 421 IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>();
364 if (invAccess != null) 422 if (invAccess != null)
365 { 423 {
366 SceneObjectGroup objatt; 424 lock (sp.AttachmentsSyncLock)
367
368 if (itemID != UUID.Zero)
369 objatt = invAccess.RezObject(sp.ControllingClient,
370 itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true,
371 false, false, sp.UUID, true);
372 else
373 objatt = invAccess.RezObject(sp.ControllingClient,
374 null, assetID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true,
375 false, false, sp.UUID, true);
376
377// m_log.DebugFormat(
378// "[ATTACHMENTS MODULE]: Retrieved single object {0} for attachment to {1} on point {2}",
379// objatt.Name, remoteClient.Name, AttachmentPt);
380
381 if (objatt != null)
382 { 425 {
383 // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller. 426 SceneObjectGroup objatt;
384 objatt.HasGroupChanged = false; 427
385 bool tainted = false; 428 if (itemID != UUID.Zero)
386 if (attachmentPt != 0 && attachmentPt != objatt.AttachmentPoint) 429 objatt = invAccess.RezObject(sp.ControllingClient,
387 tainted = true; 430 itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true,
388 431 false, false, sp.UUID, true);
389 // This will throw if the attachment fails 432 else
390 try 433 objatt = invAccess.RezObject(sp.ControllingClient,
434 null, assetID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true,
435 false, false, sp.UUID, true);
436
437 // m_log.DebugFormat(
438 // "[ATTACHMENTS MODULE]: Retrieved single object {0} for attachment to {1} on point {2}",
439 // objatt.Name, remoteClient.Name, AttachmentPt);
440
441 if (objatt != null)
391 { 442 {
392 AttachObject(sp, objatt, attachmentPt, false); 443 // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller.
444 objatt.HasGroupChanged = false;
445 bool tainted = false;
446 if (attachmentPt != 0 && attachmentPt != objatt.AttachmentPoint)
447 tainted = true;
448
449 // This will throw if the attachment fails
450 try
451 {
452 AttachObject(sp, objatt, attachmentPt, false);
453 }
454 catch (Exception e)
455 {
456 m_log.ErrorFormat(
457 "[ATTACHMENTS MODULE]: Failed to attach {0} {1} for {2}, exception {3}{4}",
458 objatt.Name, objatt.UUID, sp.Name, e.Message, e.StackTrace);
459
460 // Make sure the object doesn't stick around and bail
461 sp.RemoveAttachment(objatt);
462 m_scene.DeleteSceneObject(objatt, false);
463 return null;
464 }
465
466 if (tainted)
467 objatt.HasGroupChanged = true;
468
469 // Fire after attach, so we don't get messy perms dialogs
470 // 4 == AttachedRez
471 objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 4);
472 objatt.ResumeScripts();
473
474 // Do this last so that event listeners have access to all the effects of the attachment
475 m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, sp.UUID);
476
477 return objatt;
393 } 478 }
394 catch (Exception e) 479 else
395 { 480 {
396 m_log.ErrorFormat( 481 m_log.WarnFormat(
397 "[ATTACHMENTS MODULE]: Failed to attach {0} {1} for {2}, exception {3}{4}", 482 "[ATTACHMENTS MODULE]: Could not retrieve item {0} for attaching to avatar {1} at point {2}",
398 objatt.Name, objatt.UUID, sp.Name, e.Message, e.StackTrace); 483 itemID, sp.Name, attachmentPt);
399
400 // Make sure the object doesn't stick around and bail
401 sp.RemoveAttachment(objatt);
402 m_scene.DeleteSceneObject(objatt, false);
403 return null;
404 } 484 }
405
406 if (tainted)
407 objatt.HasGroupChanged = true;
408
409 // Fire after attach, so we don't get messy perms dialogs
410 // 4 == AttachedRez
411 objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 4);
412 objatt.ResumeScripts();
413
414 // Do this last so that event listeners have access to all the effects of the attachment
415 m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, sp.UUID);
416 }
417 else
418 {
419 m_log.WarnFormat(
420 "[ATTACHMENTS MODULE]: Could not retrieve item {0} for attaching to avatar {1} at point {2}",
421 itemID, sp.Name, attachmentPt);
422 } 485 }
423
424 return objatt;
425 } 486 }
426 487
427 return null; 488 return null;
@@ -438,8 +499,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
438 IScenePresence sp, uint AttachmentPt, UUID itemID, SceneObjectGroup att) 499 IScenePresence sp, uint AttachmentPt, UUID itemID, SceneObjectGroup att)
439 { 500 {
440// m_log.DebugFormat( 501// m_log.DebugFormat(
441// "[USER INVENTORY]: Updating attachment {0} for {1} at {2} using item ID {3}", 502// "[USER INVENTORY]: Updating attachment {0} for {1} at {2} using item ID {3}",
442// att.Name, remoteClient.Name, AttachmentPt, itemID); 503// att.Name, sp.Name, AttachmentPt, itemID);
443 504
444 if (UUID.Zero == itemID) 505 if (UUID.Zero == itemID)
445 { 506 {
@@ -462,6 +523,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
462 523
463 public void DetachObject(uint objectLocalID, IClientAPI remoteClient) 524 public void DetachObject(uint objectLocalID, IClientAPI remoteClient)
464 { 525 {
526// m_log.DebugFormat(
527// "[ATTACHMENTS MODULE]: DetachObject() for object {0} on {1}", objectLocalID, remoteClient.Name);
528
465 SceneObjectGroup group = m_scene.GetGroupByPrim(objectLocalID); 529 SceneObjectGroup group = m_scene.GetGroupByPrim(objectLocalID);
466 if (group != null) 530 if (group != null)
467 { 531 {
@@ -474,14 +538,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
474 ScenePresence presence; 538 ScenePresence presence;
475 if (m_scene.TryGetScenePresence(remoteClient.AgentId, out presence)) 539 if (m_scene.TryGetScenePresence(remoteClient.AgentId, out presence))
476 { 540 {
477 // Save avatar attachment information 541 lock (presence.AttachmentsSyncLock)
478 m_log.Debug("[ATTACHMENTS MODULE]: Detaching from UserID: " + remoteClient.AgentId + ", ItemID: " + itemID); 542 {
479 543 // Save avatar attachment information
480 bool changed = presence.Appearance.DetachAttachment(itemID); 544 m_log.Debug("[ATTACHMENTS MODULE]: Detaching from UserID: " + remoteClient.AgentId + ", ItemID: " + itemID);
481 if (changed && m_scene.AvatarFactory != null)
482 m_scene.AvatarFactory.QueueAppearanceSave(remoteClient.AgentId);
483 545
484 DetachSingleAttachmentToInv(itemID, presence); 546 bool changed = presence.Appearance.DetachAttachment(itemID);
547 if (changed && m_scene.AvatarFactory != null)
548 m_scene.AvatarFactory.QueueAppearanceSave(remoteClient.AgentId);
549
550 DetachSingleAttachmentToInv(itemID, presence);
551 }
485 } 552 }
486 } 553 }
487 554
@@ -489,7 +556,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
489 { 556 {
490// m_log.DebugFormat( 557// m_log.DebugFormat(
491// "[ATTACHMENTS MODULE]: DetachSingleAttachmentToGround() for {0}, object {1}", 558// "[ATTACHMENTS MODULE]: DetachSingleAttachmentToGround() for {0}, object {1}",
492// remoteClient.Name, sceneObjectID); 559// remoteClient.Name, soLocalId);
493 560
494 SceneObjectGroup so = m_scene.GetGroupByPrim(soLocalId); 561 SceneObjectGroup so = m_scene.GetGroupByPrim(soLocalId);
495 562
@@ -508,24 +575,27 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
508 ScenePresence presence; 575 ScenePresence presence;
509 if (m_scene.TryGetScenePresence(remoteClient.AgentId, out presence)) 576 if (m_scene.TryGetScenePresence(remoteClient.AgentId, out presence))
510 { 577 {
511 if (!m_scene.Permissions.CanRezObject( 578 lock (presence.AttachmentsSyncLock)
512 so.PrimCount, remoteClient.AgentId, presence.AbsolutePosition)) 579 {
513 return; 580 if (!m_scene.Permissions.CanRezObject(
581 so.PrimCount, remoteClient.AgentId, presence.AbsolutePosition))
582 return;
514 583
515 bool changed = presence.Appearance.DetachAttachment(inventoryID); 584 bool changed = presence.Appearance.DetachAttachment(inventoryID);
516 if (changed && m_scene.AvatarFactory != null) 585 if (changed && m_scene.AvatarFactory != null)
517 m_scene.AvatarFactory.QueueAppearanceSave(remoteClient.AgentId); 586 m_scene.AvatarFactory.QueueAppearanceSave(remoteClient.AgentId);
518 587
519 presence.RemoveAttachment(so); 588 presence.RemoveAttachment(so);
520 DetachSceneObjectToGround(so, presence); 589 DetachSceneObjectToGround(so, presence);
521 590
522 List<UUID> uuids = new List<UUID>(); 591 List<UUID> uuids = new List<UUID>();
523 uuids.Add(inventoryID); 592 uuids.Add(inventoryID);
524 m_scene.InventoryService.DeleteItems(remoteClient.AgentId, uuids); 593 m_scene.InventoryService.DeleteItems(remoteClient.AgentId, uuids);
525 remoteClient.SendRemoveInventoryItem(inventoryID); 594 remoteClient.SendRemoveInventoryItem(inventoryID);
526 } 595 }
527 596
528 m_scene.EventManager.TriggerOnAttach(so.LocalId, so.UUID, UUID.Zero); 597 m_scene.EventManager.TriggerOnAttach(so.LocalId, so.UUID, UUID.Zero);
598 }
529 } 599 }
530 600
531 /// <summary> 601 /// <summary>
@@ -559,6 +629,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
559 // To LocalId or UUID, *THAT* is the question. How now Brown UUID?? 629 // To LocalId or UUID, *THAT* is the question. How now Brown UUID??
560 private void DetachSingleAttachmentToInv(UUID itemID, IScenePresence sp) 630 private void DetachSingleAttachmentToInv(UUID itemID, IScenePresence sp)
561 { 631 {
632// m_log.DebugFormat("[ATTACHMENTS MODULE]: Detaching item {0} to inventory for {1}", itemID, sp.Name);
633
562 if (itemID == UUID.Zero) // If this happened, someone made a mistake.... 634 if (itemID == UUID.Zero) // If this happened, someone made a mistake....
563 return; 635 return;
564 636
@@ -567,37 +639,29 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
567 EntityBase[] detachEntities = m_scene.GetEntities(); 639 EntityBase[] detachEntities = m_scene.GetEntities();
568 SceneObjectGroup group; 640 SceneObjectGroup group;
569 641
570 foreach (EntityBase entity in detachEntities) 642 lock (sp.AttachmentsSyncLock)
571 { 643 {
572 if (entity is SceneObjectGroup) 644 foreach (EntityBase entity in detachEntities)
573 { 645 {
574 group = (SceneObjectGroup)entity; 646 if (entity is SceneObjectGroup)
575 if (group.GetFromItemID() == itemID)
576 { 647 {
577 m_scene.EventManager.TriggerOnAttach(group.LocalId, itemID, UUID.Zero); 648 group = (SceneObjectGroup)entity;
578 sp.RemoveAttachment(group); 649 if (group.GetFromItemID() == itemID)
579 650 {
580 // Prepare sog for storage 651 m_scene.EventManager.TriggerOnAttach(group.LocalId, itemID, UUID.Zero);
581 group.AttachedAvatar = UUID.Zero; 652 sp.RemoveAttachment(group);
582 653
583 group.ForEachPart( 654 // Prepare sog for storage
584 delegate(SceneObjectPart part) 655 group.AttachedAvatar = UUID.Zero;
585 { 656 group.RootPart.SetParentLocalId(0);
586 // If there are any scripts, 657 group.IsAttachment = false;
587 // then always trigger a new object and state persistence in UpdateKnownItem() 658 group.AbsolutePosition = group.RootPart.AttachedPos;
588 if (part.Inventory.ContainsScripts()) 659
589 group.HasGroupChanged = true; 660 UpdateKnownItem(sp.ControllingClient, group);
590 } 661 m_scene.DeleteSceneObject(group, false);
591 ); 662
592 663 return;
593 group.RootPart.SetParentLocalId(0); 664 }
594 group.IsAttachment = false;
595 group.AbsolutePosition = group.RootPart.AttachedPos;
596
597 UpdateKnownItem(sp.ControllingClient, group, group.GetFromItemID(), group.OwnerID);
598 m_scene.DeleteSceneObject(group, false);
599
600 return;
601 } 665 }
602 } 666 }
603 } 667 }
@@ -628,28 +692,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
628 /// </remarks> 692 /// </remarks>
629 /// <param name="remoteClient"></param> 693 /// <param name="remoteClient"></param>
630 /// <param name="grp"></param> 694 /// <param name="grp"></param>
631 /// <param name="itemID"></param> 695 private void UpdateKnownItem(IClientAPI remoteClient, SceneObjectGroup grp)
632 /// <param name="agentID"></param>
633 public void UpdateKnownItem(IClientAPI remoteClient, SceneObjectGroup grp, UUID itemID, UUID agentID)
634 { 696 {
635 if (grp != null) 697 if (grp.HasGroupChanged || grp.ContainsScripts())
636 { 698 {
637 if (!grp.HasGroupChanged)
638 {
639 m_log.DebugFormat(
640 "[ATTACHMENTS MODULE]: Don't need to update asset for unchanged attachment {0}, attachpoint {1}",
641 grp.UUID, grp.AttachmentPoint);
642
643 return;
644 }
645
646 m_log.DebugFormat( 699 m_log.DebugFormat(
647 "[ATTACHMENTS MODULE]: Updating asset for attachment {0}, attachpoint {1}", 700 "[ATTACHMENTS MODULE]: Updating asset for attachment {0}, attachpoint {1}",
648 grp.UUID, grp.AttachmentPoint); 701 grp.UUID, grp.AttachmentPoint);
649 702
650 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp); 703 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp);
651 704
652 InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); 705 InventoryItemBase item = new InventoryItemBase(grp.GetFromItemID(), remoteClient.AgentId);
653 item = m_scene.InventoryService.GetItem(item); 706 item = m_scene.InventoryService.GetItem(item);
654 707
655 if (item != null) 708 if (item != null)
@@ -675,6 +728,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
675 remoteClient.SendInventoryItemCreateUpdate(item, 0); 728 remoteClient.SendInventoryItemCreateUpdate(item, 0);
676 } 729 }
677 } 730 }
731 else
732 {
733 m_log.DebugFormat(
734 "[ATTACHMENTS MODULE]: Don't need to update asset for unchanged attachment {0}, attachpoint {1}",
735 grp.UUID, grp.AttachmentPoint);
736 }
678 } 737 }
679 738
680 /// <summary> 739 /// <summary>
@@ -692,7 +751,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
692 private void AttachToAgent( 751 private void AttachToAgent(
693 IScenePresence avatar, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent) 752 IScenePresence avatar, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent)
694 { 753 {
695// m_log.DebugFormat("[ATTACHMENTS MODULE]: Adding attachment {0} to avatar {1} in pt {2} pos {3} {4}", 754// m_log.DebugFormat(
755// "[ATTACHMENTS MODULE]: Adding attachment {0} to avatar {1} in pt {2} pos {3} {4}",
696// so.Name, avatar.Name, attachmentpoint, attachOffset, so.RootPart.AttachedPos); 756// so.Name, avatar.Name, attachmentpoint, attachOffset, so.RootPart.AttachedPos);
697 757
698 so.DetachFromBackup(); 758 so.DetachFromBackup();
@@ -745,7 +805,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
745 /// <returns>The user inventory item created that holds the attachment.</returns> 805 /// <returns>The user inventory item created that holds the attachment.</returns>
746 private InventoryItemBase AddSceneObjectAsNewAttachmentInInv(IClientAPI remoteClient, SceneObjectGroup grp) 806 private InventoryItemBase AddSceneObjectAsNewAttachmentInInv(IClientAPI remoteClient, SceneObjectGroup grp)
747 { 807 {
748// m_log.DebugFormat("[SCENE]: Called AddSceneObjectAsAttachment for object {0} {1} for {2} {3} {4}", grp.Name, grp.LocalId, remoteClient.Name, remoteClient.AgentId, AgentId); 808// m_log.DebugFormat(
809// "[ATTACHMENTS MODULE]: Called AddSceneObjectAsAttachment for object {0} {1} for {2}",
810// grp.Name, grp.LocalId, remoteClient.Name);
749 811
750 Vector3 inventoryStoredPosition = new Vector3 812 Vector3 inventoryStoredPosition = new Vector3
751 (((grp.AbsolutePosition.X > (int)Constants.RegionSize) 813 (((grp.AbsolutePosition.X > (int)Constants.RegionSize)
@@ -829,4 +891,4 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
829 return item; 891 return item;
830 } 892 }
831 } 893 }
832} 894} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
index 35183b3..ff3358f 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
@@ -220,6 +220,38 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
220 Assert.That(m_presence.Appearance.GetAttachpoint(attItemId), Is.EqualTo(0)); 220 Assert.That(m_presence.Appearance.GetAttachpoint(attItemId), Is.EqualTo(0));
221 } 221 }
222 222
223 /// <summary>
224 /// Test that attachments don't hang about in the scene when the agent is closed
225 /// </summary>
226 [Test]
227 public void TestRemoveAttachmentsOnAvatarExit()
228 {
229 TestHelpers.InMethod();
230// log4net.Config.XmlConfigurator.Configure();
231
232 UUID userId = TestHelpers.ParseTail(0x1);
233 UUID attItemId = TestHelpers.ParseTail(0x2);
234 UUID attAssetId = TestHelpers.ParseTail(0x3);
235 string attName = "att";
236
237 UserAccountHelpers.CreateUserWithInventory(scene, userId);
238 InventoryItemBase attItem
239 = UserInventoryHelpers.CreateInventoryItem(
240 scene, attName, attItemId, attAssetId, userId, InventoryType.Object);
241
242 AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId);
243 acd.Appearance = new AvatarAppearance();
244 acd.Appearance.SetAttachment((int)AttachmentPoint.Chest, attItem.ID, attItem.AssetID);
245 ScenePresence presence = SceneHelpers.AddScenePresence(scene, acd);
246
247 SceneObjectGroup rezzedAtt = presence.GetAttachments()[0];
248
249 scene.IncomingCloseAgent(presence.UUID);
250
251 // Check that we can't retrieve this attachment from the scene.
252 Assert.That(scene.GetSceneObjectGroup(rezzedAtt.UUID), Is.Null);
253 }
254
223 [Test] 255 [Test]
224 public void TestRezAttachmentsOnAvatarEntrance() 256 public void TestRezAttachmentsOnAvatarEntrance()
225 { 257 {
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
index b6a1564..0cadd83 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
@@ -211,8 +211,17 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
211 // Process the visual params, this may change height as well 211 // Process the visual params, this may change height as well
212 if (visualParams != null) 212 if (visualParams != null)
213 { 213 {
214// string[] visualParamsStrings = new string[visualParams.Length];
215// for (int i = 0; i < visualParams.Length; i++)
216// visualParamsStrings[i] = visualParams[i].ToString();
217// m_log.DebugFormat(
218// "[AVFACTORY]: Setting visual params for {0} to {1}",
219// client.Name, string.Join(", ", visualParamsStrings));
220
221 float oldHeight = sp.Appearance.AvatarHeight;
214 changed = sp.Appearance.SetVisualParams(visualParams); 222 changed = sp.Appearance.SetVisualParams(visualParams);
215 if (sp.Appearance.AvatarHeight > 0) 223
224 if (sp.Appearance.AvatarHeight != oldHeight && sp.Appearance.AvatarHeight > 0)
216 sp.SetHeight(sp.Appearance.AvatarHeight); 225 sp.SetHeight(sp.Appearance.AvatarHeight);
217 } 226 }
218 227
@@ -416,6 +425,13 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
416 425
417 // m_log.WarnFormat("[AVFACTORY] avatar {0} save appearance",agentid); 426 // m_log.WarnFormat("[AVFACTORY] avatar {0} save appearance",agentid);
418 427
428 // This could take awhile since it needs to pull inventory
429 // We need to do it at the point of save so that there is a sufficient delay for any upload of new body part/shape
430 // assets and item asset id changes to complete.
431 // I don't think we need to worry about doing this within m_setAppearanceLock since the queueing avoids
432 // multiple save requests.
433 SetAppearanceAssets(sp.UUID, sp.Appearance);
434
419 m_scene.AvatarService.SetAppearance(agentid, sp.Appearance); 435 m_scene.AvatarService.SetAppearance(agentid, sp.Appearance);
420 } 436 }
421 437
@@ -467,7 +483,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
467 return; 483 return;
468 } 484 }
469 485
470 // m_log.WarnFormat("[AVFACTORY]: Received request for wearables of {0}", client.AgentId); 486// m_log.DebugFormat("[AVFACTORY]: Received request for wearables of {0}", client.Name);
471 487
472 client.SendWearables(sp.Appearance.Wearables, sp.Appearance.Serial++); 488 client.SendWearables(sp.Appearance.Wearables, sp.Appearance.Serial++);
473 } 489 }
@@ -502,9 +518,6 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
502 518
503 avatAppearance.GetAssetsFrom(sp.Appearance); 519 avatAppearance.GetAssetsFrom(sp.Appearance);
504 520
505 // This could take awhile since it needs to pull inventory
506 SetAppearanceAssets(sp.UUID, ref avatAppearance);
507
508 lock (m_setAppearanceLock) 521 lock (m_setAppearanceLock)
509 { 522 {
510 // Update only those fields that we have changed. This is important because the viewer 523 // Update only those fields that we have changed. This is important because the viewer
@@ -538,7 +551,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
538 return true; 551 return true;
539 } 552 }
540 553
541 private void SetAppearanceAssets(UUID userID, ref AvatarAppearance appearance) 554 private void SetAppearanceAssets(UUID userID, AvatarAppearance appearance)
542 { 555 {
543 IInventoryService invService = m_scene.InventoryService; 556 IInventoryService invService = m_scene.InventoryService;
544 557
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs
index 7753c25..d294692 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs
@@ -24,6 +24,7 @@
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 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. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27
27using System; 28using System;
28using System.Collections; 29using System.Collections;
29using System.Collections.Generic; 30using System.Collections.Generic;
@@ -145,14 +146,14 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
145 scene.Entities[toAgentID] is ScenePresence) 146 scene.Entities[toAgentID] is ScenePresence)
146 { 147 {
147// m_log.DebugFormat( 148// m_log.DebugFormat(
148// "[INSTANT MESSAGE]: Looking for root agent {0} in {1}", 149// "[HG INSTANT MESSAGE]: Looking for root agent {0} in {1}",
149// toAgentID.ToString(), scene.RegionInfo.RegionName); 150// toAgentID.ToString(), scene.RegionInfo.RegionName);
150 151
151 ScenePresence user = (ScenePresence) scene.Entities[toAgentID]; 152 ScenePresence user = (ScenePresence) scene.Entities[toAgentID];
152 if (!user.IsChildAgent) 153 if (!user.IsChildAgent)
153 { 154 {
154 // Local message 155 // Local message
155// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", user.Name, toAgentID); 156// m_log.DebugFormat("[HG INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", user.Name, toAgentID);
156 user.ControllingClient.SendInstantMessage(im); 157 user.ControllingClient.SendInstantMessage(im);
157 158
158 // Message sent 159 // Message sent
@@ -166,7 +167,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
166 foreach (Scene scene in m_Scenes) 167 foreach (Scene scene in m_Scenes)
167 { 168 {
168// m_log.DebugFormat( 169// m_log.DebugFormat(
169// "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName); 170// "[HG INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName);
170 171
171 if (scene.Entities.ContainsKey(toAgentID) && 172 if (scene.Entities.ContainsKey(toAgentID) &&
172 scene.Entities[toAgentID] is ScenePresence) 173 scene.Entities[toAgentID] is ScenePresence)
@@ -174,7 +175,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
174 // Local message 175 // Local message
175 ScenePresence user = (ScenePresence) scene.Entities[toAgentID]; 176 ScenePresence user = (ScenePresence) scene.Entities[toAgentID];
176 177
177// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", user.Name, toAgentID); 178// m_log.DebugFormat("[HG INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", user.Name, toAgentID);
178 user.ControllingClient.SendInstantMessage(im); 179 user.ControllingClient.SendInstantMessage(im);
179 180
180 // Message sent 181 // Message sent
@@ -183,7 +184,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
183 } 184 }
184 } 185 }
185 186
186// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID); 187// m_log.DebugFormat("[HG INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID);
187 // Is the user a local user? 188 // Is the user a local user?
188 UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, toAgentID); 189 UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, toAgentID);
189 string url = string.Empty; 190 string url = string.Empty;
diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs
index d687e6a..bc5c1ff 100644
--- a/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs
@@ -154,14 +154,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
154 if (im.dialog == (byte)InstantMessageDialog.RequestTeleport) 154 if (im.dialog == (byte)InstantMessageDialog.RequestTeleport)
155 { 155 {
156 UUID sessionID = new UUID(im.imSessionID); 156 UUID sessionID = new UUID(im.imSessionID);
157 m_log.DebugFormat("[HG LURE MODULE]: RequestTeleport sessionID={0}, regionID={1}, message={2}", im.imSessionID, im.RegionID, im.message); 157
158 m_PendingLures.Add(sessionID, im, 7200); // 2 hours 158 if (!m_PendingLures.Contains(sessionID))
159 {
160 m_log.DebugFormat("[HG LURE MODULE]: RequestTeleport sessionID={0}, regionID={1}, message={2}", im.imSessionID, im.RegionID, im.message);
161 m_PendingLures.Add(sessionID, im, 7200); // 2 hours
162 }
159 163
160 // Forward. We do this, because the IM module explicitly rejects 164 // Forward. We do this, because the IM module explicitly rejects
161 // IMs of this type 165 // IMs of this type
162 if (m_TransferModule != null) 166 if (m_TransferModule != null)
163 m_TransferModule.SendInstantMessage(im, delegate(bool success) { }); 167 m_TransferModule.SendInstantMessage(im, delegate(bool success) { });
164
165 } 168 }
166 } 169 }
167 170
@@ -177,12 +180,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
177 180
178 m_log.DebugFormat("[HG LURE MODULE]: TP invite with message {0}", message); 181 m_log.DebugFormat("[HG LURE MODULE]: TP invite with message {0}", message);
179 182
183 UUID sessionID = UUID.Random();
184
180 GridInstantMessage m = new GridInstantMessage(scene, client.AgentId, 185 GridInstantMessage m = new GridInstantMessage(scene, client.AgentId,
181 client.FirstName+" "+client.LastName, targetid, 186 client.FirstName+" "+client.LastName, targetid,
182 (byte)InstantMessageDialog.RequestTeleport, false, 187 (byte)InstantMessageDialog.RequestTeleport, false,
183 message, UUID.Random(), false, presence.AbsolutePosition, 188 message, sessionID, false, presence.AbsolutePosition,
184 new Byte[0]); 189 new Byte[0]);
185 m.RegionID = client.Scene.RegionInfo.RegionID.Guid; 190 m.RegionID = client.Scene.RegionInfo.RegionID.Guid;
191
192 m_log.DebugFormat("[HG LURE MODULE]: RequestTeleport sessionID={0}, regionID={1}, message={2}", m.imSessionID, m.RegionID, m.message);
193 m_PendingLures.Add(sessionID, m, 7200); // 2 hours
186 194
187 if (m_TransferModule != null) 195 if (m_TransferModule != null)
188 { 196 {
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index ac13d5e..8924c0a 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -59,7 +59,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
59 get { return m_MaxTransferDistance; } 59 get { return m_MaxTransferDistance; }
60 set { m_MaxTransferDistance = value; } 60 set { m_MaxTransferDistance = value; }
61 } 61 }
62
63 62
64 protected bool m_Enabled = false; 63 protected bool m_Enabled = false;
65 protected Scene m_aScene; 64 protected Scene m_aScene;
@@ -68,7 +67,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
68 private ExpiringCache<UUID, ExpiringCache<ulong, DateTime>> m_bannedRegions = 67 private ExpiringCache<UUID, ExpiringCache<ulong, DateTime>> m_bannedRegions =
69 new ExpiringCache<UUID, ExpiringCache<ulong, DateTime>>(); 68 new ExpiringCache<UUID, ExpiringCache<ulong, DateTime>>();
70 69
71
72 #region ISharedRegionModule 70 #region ISharedRegionModule
73 71
74 public Type ReplaceableInterface 72 public Type ReplaceableInterface
@@ -329,6 +327,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
329 if (sp.ParentID != (uint)0) 327 if (sp.ParentID != (uint)0)
330 sp.StandUp(); 328 sp.StandUp();
331 329
330 if (!sp.ValidateAttachments())
331 m_log.DebugFormat(
332 "[ENTITY TRANSFER MODULE]: Failed validation of all attachments for teleport of {0} from {1} to {2}. Continuing.",
333 sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName);
334
332// if (!sp.ValidateAttachments()) 335// if (!sp.ValidateAttachments())
333// { 336// {
334// sp.ControllingClient.SendTeleportFailed("Inconsistent attachment state"); 337// sp.ControllingClient.SendTeleportFailed("Inconsistent attachment state");
@@ -939,7 +942,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
939 /// This Closes child agents on neighbouring regions 942 /// This Closes child agents on neighbouring regions
940 /// Calls an asynchronous method to do so.. so it doesn't lag the sim. 943 /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
941 /// </summary> 944 /// </summary>
942 protected ScenePresence CrossAgentToNewRegionAsync(ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, GridRegion neighbourRegion, bool isFlying, string version) 945 protected ScenePresence CrossAgentToNewRegionAsync(
946 ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, GridRegion neighbourRegion,
947 bool isFlying, string version)
943 { 948 {
944 ulong neighbourHandle = Utils.UIntsToLong((uint)(neighbourx * Constants.RegionSize), (uint)(neighboury * Constants.RegionSize)); 949 ulong neighbourHandle = Utils.UIntsToLong((uint)(neighbourx * Constants.RegionSize), (uint)(neighboury * Constants.RegionSize));
945 950
@@ -949,7 +954,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
949 954
950 if (neighbourRegion != null) 955 if (neighbourRegion != null)
951 { 956 {
952 agent.ValidateAttachments(); 957 if (!agent.ValidateAttachments())
958 m_log.DebugFormat(
959 "[ENTITY TRANSFER MODULE]: Failed validation of all attachments for region crossing of {0} from {1} to {2}. Continuing.",
960 agent.Name, agent.Scene.RegionInfo.RegionName, neighbourRegion.RegionName);
953 961
954 pos = pos + (agent.Velocity); 962 pos = pos + (agent.Velocity);
955 963
diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
index f7003db..bef0d69 100644
--- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
@@ -363,9 +363,9 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
363 lock (m_UserCache) 363 lock (m_UserCache)
364 m_UserCache[user.Id] = user; 364 m_UserCache[user.Id] = user;
365 365
366 m_log.DebugFormat( 366// m_log.DebugFormat(
367 "[USER MANAGEMENT MODULE]: Added user {0} {1} {2} {3}", 367// "[USER MANAGEMENT MODULE]: Added user {0} {1} {2} {3}",
368 user.Id, user.FirstName, user.LastName, user.HomeURL); 368// user.Id, user.FirstName, user.LastName, user.HomeURL);
369 } 369 }
370 370
371 //public void AddUser(UUID uuid, string userData) 371 //public void AddUser(UUID uuid, string userData)
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs
index 1c83f8e..097ff1a 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs
@@ -185,15 +185,18 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
185 public InventoryCollection GetFolderContent(UUID userID, UUID folderID) 185 public InventoryCollection GetFolderContent(UUID userID, UUID folderID)
186 { 186 {
187 InventoryCollection invCol = m_InventoryService.GetFolderContent(userID, folderID); 187 InventoryCollection invCol = m_InventoryService.GetFolderContent(userID, folderID);
188 Util.FireAndForget(delegate 188
189 if (UserManager != null)
189 { 190 {
190 if (UserManager != null) 191 // Protect ourselves against the caller subsequently modifying the items list
192 List<InventoryItemBase> items = new List<InventoryItemBase>(invCol.Items);
193
194 Util.FireAndForget(delegate
191 { 195 {
192 // Protect ourselves against the caller subsequently modifying the items list 196 foreach (InventoryItemBase item in items)
193 foreach (InventoryItemBase item in new List<InventoryItemBase>(invCol.Items))
194 UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData); 197 UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData);
195 } 198 });
196 }); 199 }
197 200
198 return invCol; 201 return invCol;
199 } 202 }
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs
index c9c716c..73ab4e3 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs
@@ -193,15 +193,18 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
193 public InventoryCollection GetFolderContent(UUID userID, UUID folderID) 193 public InventoryCollection GetFolderContent(UUID userID, UUID folderID)
194 { 194 {
195 InventoryCollection invCol = m_RemoteConnector.GetFolderContent(userID, folderID); 195 InventoryCollection invCol = m_RemoteConnector.GetFolderContent(userID, folderID);
196 Util.FireAndForget(delegate 196
197 if (UserManager != null)
197 { 198 {
198 if (UserManager != null) 199 // Protect ourselves against the caller subsequently modifying the items list
200 List<InventoryItemBase> items = new List<InventoryItemBase>(invCol.Items);
201
202 Util.FireAndForget(delegate
199 { 203 {
200 // Protect ourselves against the caller subsequently modifying the items list 204 foreach (InventoryItemBase item in items)
201 foreach (InventoryItemBase item in new List<InventoryItemBase>(invCol.Items))
202 UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData); 205 UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData);
203 } 206 });
204 }); 207 }
205 208
206 return invCol; 209 return invCol;
207 } 210 }
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs
index 30ebb21..0a0ce3c 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs
@@ -45,7 +45,12 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
45 LogManager.GetLogger( 45 LogManager.GetLogger(
46 MethodBase.GetCurrentMethod().DeclaringType); 46 MethodBase.GetCurrentMethod().DeclaringType);
47 47
48 private IUserAccountService m_UserService; 48 /// <summary>
49 /// This is not on the IUserAccountService. It's only being used so that standalone scenes can punch through
50 /// to a local UserAccountService when setting up an estate manager.
51 /// </summary>
52 public IUserAccountService UserAccountService { get; private set; }
53
49 private UserAccountCache m_Cache; 54 private UserAccountCache m_Cache;
50 55
51 private bool m_Enabled = false; 56 private bool m_Enabled = false;
@@ -86,9 +91,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
86 } 91 }
87 92
88 Object[] args = new Object[] { source }; 93 Object[] args = new Object[] { source };
89 m_UserService = ServerUtils.LoadPlugin<IUserAccountService>(serviceDll, args); 94 UserAccountService = ServerUtils.LoadPlugin<IUserAccountService>(serviceDll, args);
90 95
91 if (m_UserService == null) 96 if (UserAccountService == null)
92 { 97 {
93 m_log.ErrorFormat( 98 m_log.ErrorFormat(
94 "[LOCAL USER ACCOUNT SERVICE CONNECTOR]: Cannot load user account service specified as {0}", serviceDll); 99 "[LOCAL USER ACCOUNT SERVICE CONNECTOR]: Cannot load user account service specified as {0}", serviceDll);
@@ -119,7 +124,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
119 if (!m_Enabled) 124 if (!m_Enabled)
120 return; 125 return;
121 126
122 scene.RegisterModuleInterface<IUserAccountService>(m_UserService); 127 // FIXME: Why do we bother setting this module and caching up if we just end up registering the inner
128 // user account service?!
129 scene.RegisterModuleInterface<IUserAccountService>(UserAccountService);
123 } 130 }
124 131
125 public void RemoveRegion(Scene scene) 132 public void RemoveRegion(Scene scene)
@@ -147,7 +154,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
147 if (inCache) 154 if (inCache)
148 return account; 155 return account;
149 156
150 account = m_UserService.GetUserAccount(scopeID, userID); 157 account = UserAccountService.GetUserAccount(scopeID, userID);
151 m_Cache.Cache(userID, account); 158 m_Cache.Cache(userID, account);
152 159
153 return account; 160 return account;
@@ -160,7 +167,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
160 if (inCache) 167 if (inCache)
161 return account; 168 return account;
162 169
163 account = m_UserService.GetUserAccount(scopeID, firstName, lastName); 170 account = UserAccountService.GetUserAccount(scopeID, firstName, lastName);
164 if (account != null) 171 if (account != null)
165 m_Cache.Cache(account.PrincipalID, account); 172 m_Cache.Cache(account.PrincipalID, account);
166 173
@@ -169,22 +176,21 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
169 176
170 public UserAccount GetUserAccount(UUID scopeID, string Email) 177 public UserAccount GetUserAccount(UUID scopeID, string Email)
171 { 178 {
172 return m_UserService.GetUserAccount(scopeID, Email); 179 return UserAccountService.GetUserAccount(scopeID, Email);
173 } 180 }
174 181
175 public List<UserAccount> GetUserAccounts(UUID scopeID, string query) 182 public List<UserAccount> GetUserAccounts(UUID scopeID, string query)
176 { 183 {
177 return m_UserService.GetUserAccounts(scopeID, query); 184 return UserAccountService.GetUserAccounts(scopeID, query);
178 } 185 }
179 186
180 // Update all updatable fields 187 // Update all updatable fields
181 // 188 //
182 public bool StoreUserAccount(UserAccount data) 189 public bool StoreUserAccount(UserAccount data)
183 { 190 {
184 return m_UserService.StoreUserAccount(data); 191 return UserAccountService.StoreUserAccount(data);
185 } 192 }
186 193
187 #endregion 194 #endregion
188
189 } 195 }
190} 196} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
index 48130e7..587d260 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
@@ -284,8 +284,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
284 part.LastOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; 284 part.LastOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
285 285
286 // And zap any troublesome sit target information 286 // And zap any troublesome sit target information
287 part.SitTargetOrientation = new Quaternion(0, 0, 0, 1); 287// part.SitTargetOrientation = new Quaternion(0, 0, 0, 1);
288 part.SitTargetPosition = new Vector3(0, 0, 0); 288// part.SitTargetPosition = new Vector3(0, 0, 0);
289 289
290 // Fix ownership/creator of inventory items 290 // Fix ownership/creator of inventory items
291 // Not doing so results in inventory items 291 // Not doing so results in inventory items
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs
index 10a83ee..b895afe 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs
@@ -127,6 +127,12 @@ namespace OpenSim.Region.CoreModules.World.Archiver
127 127
128 EntityBase[] entities = m_scene.GetEntities(); 128 EntityBase[] entities = m_scene.GetEntities();
129 List<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>(); 129 List<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>();
130
131 string checkPermissions = null;
132 int numObjectsSkippedPermissions = 0;
133 Object temp;
134 if (options.TryGetValue("checkPermissions", out temp))
135 checkPermissions = (string)temp;
130 136
131 // Filter entities so that we only have scene objects. 137 // Filter entities so that we only have scene objects.
132 // FIXME: Would be nicer to have this as a proper list in SceneGraph, since lots of methods 138 // FIXME: Would be nicer to have this as a proper list in SceneGraph, since lots of methods
@@ -136,9 +142,19 @@ namespace OpenSim.Region.CoreModules.World.Archiver
136 if (entity is SceneObjectGroup) 142 if (entity is SceneObjectGroup)
137 { 143 {
138 SceneObjectGroup sceneObject = (SceneObjectGroup)entity; 144 SceneObjectGroup sceneObject = (SceneObjectGroup)entity;
139 145
140 if (!sceneObject.IsDeleted && !sceneObject.IsAttachment) 146 if (!sceneObject.IsDeleted && !sceneObject.IsAttachment)
141 sceneObjects.Add((SceneObjectGroup)entity); 147 {
148 if (!CanUserArchiveObject(m_scene.RegionInfo.EstateSettings.EstateOwner, sceneObject, checkPermissions))
149 {
150 // The user isn't allowed to copy/transfer this object, so it will not be included in the OAR.
151 ++numObjectsSkippedPermissions;
152 }
153 else
154 {
155 sceneObjects.Add(sceneObject);
156 }
157 }
142 } 158 }
143 } 159 }
144 160
@@ -159,7 +175,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver
159 { 175 {
160 m_log.DebugFormat("[ARCHIVER]: Not saving assets since --noassets was specified"); 176 m_log.DebugFormat("[ARCHIVER]: Not saving assets since --noassets was specified");
161 } 177 }
162 178
179 if (numObjectsSkippedPermissions > 0)
180 {
181 m_log.DebugFormat(
182 "[ARCHIVER]: {0} scene objects skipped due to lack of permissions",
183 numObjectsSkippedPermissions);
184 }
185
163 // Make sure that we also request terrain texture assets 186 // Make sure that we also request terrain texture assets
164 RegionSettings regionSettings = m_scene.RegionInfo.RegionSettings; 187 RegionSettings regionSettings = m_scene.RegionInfo.RegionSettings;
165 188
@@ -211,6 +234,83 @@ namespace OpenSim.Region.CoreModules.World.Archiver
211 } 234 }
212 235
213 /// <summary> 236 /// <summary>
237 /// Checks whether the user has permission to export an object group to an OAR.
238 /// </summary>
239 /// <param name="user">The user</param>
240 /// <param name="objGroup">The object group</param>
241 /// <param name="checkPermissions">Which permissions to check: "C" = Copy, "T" = Transfer</param>
242 /// <returns>Whether the user is allowed to export the object to an OAR</returns>
243 private bool CanUserArchiveObject(UUID user, SceneObjectGroup objGroup, string checkPermissions)
244 {
245 if (checkPermissions == null)
246 return true;
247
248 IPermissionsModule module = m_scene.RequestModuleInterface<IPermissionsModule>();
249 if (module == null)
250 return true; // this shouldn't happen
251
252 // Check whether the user is permitted to export all of the parts in the SOG. If any
253 // part can't be exported then the entire SOG can't be exported.
254
255 bool permitted = true;
256 //int primNumber = 1;
257
258 foreach (SceneObjectPart obj in objGroup.Parts)
259 {
260 uint perm;
261 PermissionClass permissionClass = module.GetPermissionClass(user, obj);
262 switch (permissionClass)
263 {
264 case PermissionClass.Owner:
265 perm = obj.BaseMask;
266 break;
267 case PermissionClass.Group:
268 perm = obj.GroupMask | obj.EveryoneMask;
269 break;
270 case PermissionClass.Everyone:
271 default:
272 perm = obj.EveryoneMask;
273 break;
274 }
275
276 bool canCopy = (perm & (uint)PermissionMask.Copy) != 0;
277 bool canTransfer = (perm & (uint)PermissionMask.Transfer) != 0;
278
279 // Special case: if Everyone can copy the object then this implies it can also be
280 // Transferred.
281 // However, if the user is the Owner then we don't check EveryoneMask, because it seems that the mask
282 // always (incorrectly) includes the Copy bit set in this case. But that's a mistake: the viewer
283 // does NOT show that the object has Everyone-Copy permissions, and doesn't allow it to be copied.
284 if (permissionClass != PermissionClass.Owner)
285 {
286 canTransfer |= (obj.EveryoneMask & (uint)PermissionMask.Copy) != 0;
287 }
288
289
290 bool partPermitted = true;
291 if (checkPermissions.Contains("C") && !canCopy)
292 partPermitted = false;
293 if (checkPermissions.Contains("T") && !canTransfer)
294 partPermitted = false;
295
296 //string name = (objGroup.PrimCount == 1) ? objGroup.Name : string.Format("{0} ({1}/{2})", obj.Name, primNumber, objGroup.PrimCount);
297 //m_log.DebugFormat("[ARCHIVER]: Object permissions: {0}: Base={1:X4}, Owner={2:X4}, Everyone={3:X4}, permissionClass={4}, checkPermissions={5}, canCopy={6}, canTransfer={7}, permitted={8}",
298 // name, obj.BaseMask, obj.OwnerMask, obj.EveryoneMask,
299 // permissionClass, checkPermissions, canCopy, canTransfer, permitted);
300
301 if (!partPermitted)
302 {
303 permitted = false;
304 break;
305 }
306
307 //++primNumber;
308 }
309
310 return permitted;
311 }
312
313 /// <summary>
214 /// Create the control file for the most up to date archive 314 /// Create the control file for the most up to date archive
215 /// </summary> 315 /// </summary>
216 /// <returns></returns> 316 /// <returns></returns>
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs
index 08eb80c..f44a3ba 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs
@@ -128,6 +128,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
128// ops.Add("v|version=", delegate(string v) { options["version"] = v; }); 128// ops.Add("v|version=", delegate(string v) { options["version"] = v; });
129 ops.Add("p|profile=", delegate(string v) { options["profile"] = v; }); 129 ops.Add("p|profile=", delegate(string v) { options["profile"] = v; });
130 ops.Add("noassets", delegate(string v) { options["noassets"] = v != null; }); 130 ops.Add("noassets", delegate(string v) { options["noassets"] = v != null; });
131 ops.Add("perm=", delegate(string v) { options["checkPermissions"] = v; });
131 132
132 List<string> mainParams = ops.Parse(cmdparams); 133 List<string> mainParams = ops.Parse(cmdparams);
133 134
diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
index b185d9b..e798e5e 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
@@ -318,6 +318,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
318 new ArchiveWriteRequestPreparation(null, (Stream)null, Guid.Empty).CreateControlFile(new Dictionary<string, Object>())); 318 new ArchiveWriteRequestPreparation(null, (Stream)null, Guid.Empty).CreateControlFile(new Dictionary<string, Object>()));
319 319
320 SceneObjectPart part1 = CreateSceneObjectPart1(); 320 SceneObjectPart part1 = CreateSceneObjectPart1();
321
322 part1.SitTargetOrientation = new Quaternion(0.2f, 0.3f, 0.4f, 0.5f);
323 part1.SitTargetPosition = new Vector3(1, 2, 3);
324
321 SceneObjectGroup object1 = new SceneObjectGroup(part1); 325 SceneObjectGroup object1 = new SceneObjectGroup(part1);
322 326
323 // Let's put some inventory items into our object 327 // Let's put some inventory items into our object
@@ -390,6 +394,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
390 object1PartLoaded.RotationOffset, Is.EqualTo(part1.RotationOffset), "object1 rotation offset not equal"); 394 object1PartLoaded.RotationOffset, Is.EqualTo(part1.RotationOffset), "object1 rotation offset not equal");
391 Assert.That( 395 Assert.That(
392 object1PartLoaded.OffsetPosition, Is.EqualTo(part1.OffsetPosition), "object1 offset position not equal"); 396 object1PartLoaded.OffsetPosition, Is.EqualTo(part1.OffsetPosition), "object1 offset position not equal");
397 Assert.That(object1PartLoaded.SitTargetOrientation, Is.EqualTo(part1.SitTargetOrientation));
398 Assert.That(object1PartLoaded.SitTargetPosition, Is.EqualTo(part1.SitTargetPosition));
393 399
394 TaskInventoryItem loadedSoundItem = object1PartLoaded.Inventory.GetInventoryItems(soundItemName)[0]; 400 TaskInventoryItem loadedSoundItem = object1PartLoaded.Inventory.GetInventoryItems(soundItemName)[0];
395 Assert.That(loadedSoundItem, Is.Not.Null, "loaded sound item was null"); 401 Assert.That(loadedSoundItem, Is.Not.Null, "loaded sound item was null");
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
index 94c1417..c199a77 100644
--- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
@@ -968,10 +968,10 @@ namespace OpenSim.Region.CoreModules.World.Estate
968 args.terrainDetail2 = Scene.RegionInfo.RegionSettings.TerrainTexture3; 968 args.terrainDetail2 = Scene.RegionInfo.RegionSettings.TerrainTexture3;
969 args.terrainDetail3 = Scene.RegionInfo.RegionSettings.TerrainTexture4; 969 args.terrainDetail3 = Scene.RegionInfo.RegionSettings.TerrainTexture4;
970 970
971 m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 1 {0} for region {1}", args.terrainDetail0, Scene.RegionInfo.RegionName); 971// m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 1 {0} for region {1}", args.terrainDetail0, Scene.RegionInfo.RegionName);
972 m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 2 {0} for region {1}", args.terrainDetail1, Scene.RegionInfo.RegionName); 972// m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 2 {0} for region {1}", args.terrainDetail1, Scene.RegionInfo.RegionName);
973 m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 3 {0} for region {1}", args.terrainDetail2, Scene.RegionInfo.RegionName); 973// m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 3 {0} for region {1}", args.terrainDetail2, Scene.RegionInfo.RegionName);
974 m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 4 {0} for region {1}", args.terrainDetail3, Scene.RegionInfo.RegionName); 974// m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 4 {0} for region {1}", args.terrainDetail3, Scene.RegionInfo.RegionName);
975 975
976 remoteClient.SendRegionHandshake(Scene.RegionInfo,args); 976 remoteClient.SendRegionHandshake(Scene.RegionInfo,args);
977 } 977 }
diff --git a/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs b/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
index 8b78701..1e4f0a4 100644
--- a/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
+++ b/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
@@ -101,7 +101,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.BuySell
101 101
102 part.ParentGroup.HasGroupChanged = true; 102 part.ParentGroup.HasGroupChanged = true;
103 103
104 part.GetProperties(client); 104 part.SendPropertiesToClient(client);
105 } 105 }
106 106
107 public bool BuyObject(IClientAPI remoteClient, UUID categoryID, uint localID, byte saleType, int salePrice) 107 public bool BuyObject(IClientAPI remoteClient, UUID categoryID, uint localID, byte saleType, int salePrice)
@@ -142,7 +142,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.BuySell
142 part.SalePrice = 10; 142 part.SalePrice = 10;
143 143
144 group.HasGroupChanged = true; 144 group.HasGroupChanged = true;
145 part.GetProperties(remoteClient); 145 part.SendPropertiesToClient(remoteClient);
146 part.TriggerScriptChangedEvent(Changed.OWNER); 146 part.TriggerScriptChangedEvent(Changed.OWNER);
147 group.ResumeScripts(); 147 group.ResumeScripts();
148 part.ScheduleFullUpdate(); 148 part.ScheduleFullUpdate();
diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
index b9bd9a4..3b661ed 100644
--- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
+++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
@@ -39,7 +39,7 @@ using OpenSim.Services.Interfaces;
39 39
40namespace OpenSim.Region.CoreModules.World.Permissions 40namespace OpenSim.Region.CoreModules.World.Permissions
41{ 41{
42 public class PermissionsModule : IRegionModule 42 public class PermissionsModule : IRegionModule, IPermissionsModule
43 { 43 {
44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
45 45
@@ -150,6 +150,8 @@ namespace OpenSim.Region.CoreModules.World.Permissions
150 else 150 else
151 m_log.Debug("[PERMISSIONS]: Enabling all region service permission checks"); 151 m_log.Debug("[PERMISSIONS]: Enabling all region service permission checks");
152 152
153 scene.RegisterModuleInterface<IPermissionsModule>(this);
154
153 //Register functions with Scene External Checks! 155 //Register functions with Scene External Checks!
154 m_scene.Permissions.OnBypassPermissions += BypassPermissions; 156 m_scene.Permissions.OnBypassPermissions += BypassPermissions;
155 m_scene.Permissions.OnSetBypassPermissions += SetBypassPermissions; 157 m_scene.Permissions.OnSetBypassPermissions += SetBypassPermissions;
@@ -574,46 +576,18 @@ namespace OpenSim.Region.CoreModules.World.Permissions
574 if (objectOwner != UUID.Zero) 576 if (objectOwner != UUID.Zero)
575 objectEveryoneMask |= (uint)PrimFlags.ObjectAnyOwner; 577 objectEveryoneMask |= (uint)PrimFlags.ObjectAnyOwner;
576 578
577 if (m_bypassPermissions) 579 PermissionClass permissionClass = GetPermissionClass(user, task);
578 return objectOwnerMask;
579
580 // Object owners should be able to edit their own content
581 if (user == objectOwner)
582 return objectOwnerMask;
583
584 if (IsFriendWithPerms(user, objectOwner))
585 {
586 return objectOwnerMask;
587 }
588 // Estate users should be able to edit anything in the sim if RegionOwnerIsGod is set
589 if (m_RegionOwnerIsGod && IsEstateManager(user) && !IsAdministrator(objectOwner))
590 {
591 return objectOwnerMask;
592 }
593
594 // Admin should be able to edit anything in the sim (including admin objects)
595 if (IsAdministrator(user))
596 {
597 return objectOwnerMask;
598 }
599 580
600 // Users should be able to edit what is over their land. 581 switch (permissionClass)
601 Vector3 taskPos = task.AbsolutePosition;
602 ILandObject parcel = m_scene.LandChannel.GetLandObject(taskPos.X, taskPos.Y);
603 if (parcel != null && parcel.LandData.OwnerID == user && m_ParcelOwnerIsGod)
604 { 582 {
605 // Admin objects should not be editable by the above 583 case PermissionClass.Owner:
606 if (!IsAdministrator(objectOwner))
607 {
608 return objectOwnerMask; 584 return objectOwnerMask;
609 } 585 case PermissionClass.Group:
586 return objectGroupMask | objectEveryoneMask;
587 case PermissionClass.Everyone:
588 default:
589 return objectEveryoneMask;
610 } 590 }
611
612 // Group permissions
613 if ((task.GroupID != UUID.Zero) && IsGroupMember(task.GroupID, user, 0))
614 return objectGroupMask | objectEveryoneMask;
615
616 return objectEveryoneMask;
617 } 591 }
618 592
619 private uint ApplyObjectModifyMasks(uint setPermissionMask, uint objectFlagsMask) 593 private uint ApplyObjectModifyMasks(uint setPermissionMask, uint objectFlagsMask)
@@ -644,6 +618,47 @@ namespace OpenSim.Region.CoreModules.World.Permissions
644 return objectFlagsMask; 618 return objectFlagsMask;
645 } 619 }
646 620
621 public PermissionClass GetPermissionClass(UUID user, SceneObjectPart obj)
622 {
623 if (obj == null)
624 return PermissionClass.Everyone;
625
626 if (m_bypassPermissions)
627 return PermissionClass.Owner;
628
629 // Object owners should be able to edit their own content
630 UUID objectOwner = obj.OwnerID;
631 if (user == objectOwner)
632 return PermissionClass.Owner;
633
634 if (IsFriendWithPerms(user, objectOwner))
635 return PermissionClass.Owner;
636
637 // Estate users should be able to edit anything in the sim if RegionOwnerIsGod is set
638 if (m_RegionOwnerIsGod && IsEstateManager(user) && !IsAdministrator(objectOwner))
639 return PermissionClass.Owner;
640
641 // Admin should be able to edit anything in the sim (including admin objects)
642 if (IsAdministrator(user))
643 return PermissionClass.Owner;
644
645 // Users should be able to edit what is over their land.
646 Vector3 taskPos = obj.AbsolutePosition;
647 ILandObject parcel = m_scene.LandChannel.GetLandObject(taskPos.X, taskPos.Y);
648 if (parcel != null && parcel.LandData.OwnerID == user && m_ParcelOwnerIsGod)
649 {
650 // Admin objects should not be editable by the above
651 if (!IsAdministrator(objectOwner))
652 return PermissionClass.Owner;
653 }
654
655 // Group permissions
656 if ((obj.GroupID != UUID.Zero) && IsGroupMember(obj.GroupID, user, 0))
657 return PermissionClass.Group;
658
659 return PermissionClass.Everyone;
660 }
661
647 /// <summary> 662 /// <summary>
648 /// General permissions checks for any operation involving an object. These supplement more specific checks 663 /// General permissions checks for any operation involving an object. These supplement more specific checks
649 /// implemented by callers. 664 /// implemented by callers.