aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Framework/EstateSettings.cs6
-rw-r--r--OpenSim/Framework/Tests/MundaneFrameworkTests.cs4
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs46
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs87
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs124
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs17
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandObject.cs7
-rw-r--r--OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityInventory.cs22
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEstateModule.cs3
-rw-r--r--OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs48
-rw-r--r--OpenSim/Region/Framework/Interfaces/IScriptModule.cs16
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs3
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs86
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs150
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs63
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectSpatialTests.cs154
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStore.cs500
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs430
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs490
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs88
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs6
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs120
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs6
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs3
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs3
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs20
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs10
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/XEngine.cs92
-rw-r--r--OpenSim/Region/UserStatistics/WebStatsModule.cs153
-rw-r--r--OpenSim/Services/Connectors/Grid/GridServiceConnector.cs23
-rw-r--r--OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs106
36 files changed, 2443 insertions, 457 deletions
diff --git a/OpenSim/Framework/EstateSettings.cs b/OpenSim/Framework/EstateSettings.cs
index 142b783..9020761 100644
--- a/OpenSim/Framework/EstateSettings.cs
+++ b/OpenSim/Framework/EstateSettings.cs
@@ -346,7 +346,7 @@ namespace OpenSim.Framework
346 l_EstateManagers.Remove(avatarID); 346 l_EstateManagers.Remove(avatarID);
347 } 347 }
348 348
349 public bool IsEstateManager(UUID avatarID) 349 public bool IsEstateManagerOrOwner(UUID avatarID)
350 { 350 {
351 if (IsEstateOwner(avatarID)) 351 if (IsEstateOwner(avatarID))
352 return true; 352 return true;
@@ -368,7 +368,7 @@ namespace OpenSim.Framework
368 if (ban.BannedUserID == avatarID) 368 if (ban.BannedUserID == avatarID)
369 return true; 369 return true;
370 370
371 if (!IsEstateManager(avatarID) && !HasAccess(avatarID)) 371 if (!IsEstateManagerOrOwner(avatarID) && !HasAccess(avatarID))
372 { 372 {
373 if (DenyMinors) 373 if (DenyMinors)
374 { 374 {
@@ -411,7 +411,7 @@ namespace OpenSim.Framework
411 411
412 public bool HasAccess(UUID user) 412 public bool HasAccess(UUID user)
413 { 413 {
414 if (IsEstateManager(user)) 414 if (IsEstateManagerOrOwner(user))
415 return true; 415 return true;
416 416
417 return l_EstateAccess.Contains(user); 417 return l_EstateAccess.Contains(user);
diff --git a/OpenSim/Framework/Tests/MundaneFrameworkTests.cs b/OpenSim/Framework/Tests/MundaneFrameworkTests.cs
index 34a3f15..6fde488 100644
--- a/OpenSim/Framework/Tests/MundaneFrameworkTests.cs
+++ b/OpenSim/Framework/Tests/MundaneFrameworkTests.cs
@@ -227,10 +227,10 @@ namespace OpenSim.Framework.Tests
227 es.AddEstateManager(UUID.Zero); 227 es.AddEstateManager(UUID.Zero);
228 228
229 es.AddEstateManager(bannedUserId); 229 es.AddEstateManager(bannedUserId);
230 Assert.IsTrue(es.IsEstateManager(bannedUserId), "bannedUserId should be EstateManager but isn't."); 230 Assert.IsTrue(es.IsEstateManagerOrOwner(bannedUserId), "bannedUserId should be EstateManager but isn't.");
231 231
232 es.RemoveEstateManager(bannedUserId); 232 es.RemoveEstateManager(bannedUserId);
233 Assert.IsFalse(es.IsEstateManager(bannedUserId), "bannedUserID is estateManager but shouldn't be"); 233 Assert.IsFalse(es.IsEstateManagerOrOwner(bannedUserId), "bannedUserID is estateManager but shouldn't be");
234 234
235 Assert.IsFalse(es.HasAccess(bannedUserId), "bannedUserID has access but shouldn't"); 235 Assert.IsFalse(es.HasAccess(bannedUserId), "bannedUserID has access but shouldn't");
236 236
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
index f64c161..fc6325d 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
@@ -162,7 +162,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
162 } 162 }
163 } 163 }
164 164
165 protected void InitModule(IConfigSource config) 165 protected virtual void InitModule(IConfigSource config)
166 { 166 {
167 IConfig friendsConfig = config.Configs["Friends"]; 167 IConfig friendsConfig = config.Configs["Friends"];
168 if (friendsConfig != null) 168 if (friendsConfig != null)
@@ -546,7 +546,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
546 } 546 }
547 } 547 }
548 548
549 private void OnInstantMessage(IClientAPI client, GridInstantMessage im) 549 protected virtual void OnInstantMessage(IClientAPI client, GridInstantMessage im)
550 { 550 {
551 if ((InstantMessageDialog)im.dialog == InstantMessageDialog.FriendshipOffered) 551 if ((InstantMessageDialog)im.dialog == InstantMessageDialog.FriendshipOffered)
552 { 552 {
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs
index 9a6d277..3728b85 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs
@@ -50,6 +50,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
50 { 50 {
51 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 51 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
52 52
53 private int m_levelHGFriends = 0;
54
53 IUserManagement m_uMan; 55 IUserManagement m_uMan;
54 public IUserManagement UserManagementModule 56 public IUserManagement UserManagementModule
55 { 57 {
@@ -87,6 +89,21 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
87 m_StatusNotifier = new HGStatusNotifier(this); 89 m_StatusNotifier = new HGStatusNotifier(this);
88 } 90 }
89 91
92 protected override void InitModule(IConfigSource config)
93 {
94 base.InitModule(config);
95
96 // Additionally to the base method
97 IConfig friendsConfig = config.Configs["HGFriendsModule"];
98 if (friendsConfig != null)
99 {
100 m_levelHGFriends = friendsConfig.GetInt("LevelHGFriends", 0);
101
102 // TODO: read in all config variables pertaining to
103 // HG friendship permissions
104 }
105 }
106
90 #endregion 107 #endregion
91 108
92 #region IFriendsSimConnector 109 #region IFriendsSimConnector
@@ -105,6 +122,35 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
105 122
106 #endregion 123 #endregion
107 124
125 protected override void OnInstantMessage(IClientAPI client, GridInstantMessage im)
126 {
127 if ((InstantMessageDialog)im.dialog == InstantMessageDialog.FriendshipOffered)
128 {
129 // we got a friendship offer
130 UUID principalID = new UUID(im.fromAgentID);
131 UUID friendID = new UUID(im.toAgentID);
132
133 // Check if friendID is foreigner and if principalID has the permission
134 // to request friendships with foreigners. If not, return immediately.
135 if (!UserManagementModule.IsLocalGridUser(friendID))
136 {
137 ScenePresence avatar = null;
138 ((Scene)client.Scene).TryGetScenePresence(principalID, out avatar);
139
140 if (avatar == null)
141 return;
142
143 if (avatar.UserLevel < m_levelHGFriends)
144 {
145 client.SendAgentAlertMessage("Unable to send friendship invitation to foreigner. Insufficient permissions.", false);
146 return;
147 }
148 }
149 }
150
151 base.OnInstantMessage(client, im);
152 }
153
108 protected override void OnApproveFriendRequest(IClientAPI client, UUID friendID, List<UUID> callingCardFolders) 154 protected override void OnApproveFriendRequest(IClientAPI client, UUID friendID, List<UUID> callingCardFolders)
109 { 155 {
110 // Update the local cache. Yes, we need to do it right here 156 // Update the local cache. Yes, we need to do it right here
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
index 8560c73..0ee7606 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
@@ -91,7 +91,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
91 /// Constructor 91 /// Constructor
92 /// </summary> 92 /// </summary>
93 public InventoryArchiveWriteRequest( 93 public InventoryArchiveWriteRequest(
94 Guid id, InventoryArchiverModule module, Scene scene, 94 Guid id, InventoryArchiverModule module, Scene scene,
95 UserAccount userInfo, string invPath, string savePath) 95 UserAccount userInfo, string invPath, string savePath)
96 : this( 96 : this(
97 id, 97 id,
@@ -107,7 +107,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
107 /// Constructor 107 /// Constructor
108 /// </summary> 108 /// </summary>
109 public InventoryArchiveWriteRequest( 109 public InventoryArchiveWriteRequest(
110 Guid id, InventoryArchiverModule module, Scene scene, 110 Guid id, InventoryArchiverModule module, Scene scene,
111 UserAccount userInfo, string invPath, Stream saveStream) 111 UserAccount userInfo, string invPath, Stream saveStream)
112 { 112 {
113 m_id = id; 113 m_id = id;
@@ -125,7 +125,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
125 { 125 {
126 Exception reportedException = null; 126 Exception reportedException = null;
127 bool succeeded = true; 127 bool succeeded = true;
128 128
129 try 129 try
130 { 130 {
131 m_archiveWriter.Close(); 131 m_archiveWriter.Close();
@@ -146,6 +146,21 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
146 146
147 protected void SaveInvItem(InventoryItemBase inventoryItem, string path, Dictionary<string, object> options, IUserAccountService userAccountService) 147 protected void SaveInvItem(InventoryItemBase inventoryItem, string path, Dictionary<string, object> options, IUserAccountService userAccountService)
148 { 148 {
149 if (options.ContainsKey("exclude"))
150 {
151 if (((List<String>)options["exclude"]).Contains(inventoryItem.Name) ||
152 ((List<String>)options["exclude"]).Contains(inventoryItem.ID.ToString()))
153 {
154 if (options.ContainsKey("verbose"))
155 {
156 m_log.InfoFormat(
157 "[INVENTORY ARCHIVER]: Skipping inventory item {0} {1} at {2}",
158 inventoryItem.Name, inventoryItem.ID, path);
159 }
160 return;
161 }
162 }
163
149 if (options.ContainsKey("verbose")) 164 if (options.ContainsKey("verbose"))
150 m_log.InfoFormat( 165 m_log.InfoFormat(
151 "[INVENTORY ARCHIVER]: Saving item {0} {1} with asset {2}", 166 "[INVENTORY ARCHIVER]: Saving item {0} {1} with asset {2}",
@@ -175,9 +190,27 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
175 /// <param name="options"></param> 190 /// <param name="options"></param>
176 /// <param name="userAccountService"></param> 191 /// <param name="userAccountService"></param>
177 protected void SaveInvFolder( 192 protected void SaveInvFolder(
178 InventoryFolderBase inventoryFolder, string path, bool saveThisFolderItself, 193 InventoryFolderBase inventoryFolder, string path, bool saveThisFolderItself,
179 Dictionary<string, object> options, IUserAccountService userAccountService) 194 Dictionary<string, object> options, IUserAccountService userAccountService)
180 { 195 {
196 if (options.ContainsKey("excludefolders"))
197 {
198 if (((List<String>)options["excludefolders"]).Contains(inventoryFolder.Name) ||
199 ((List<String>)options["excludefolders"]).Contains(inventoryFolder.ID.ToString()))
200 {
201 if (options.ContainsKey("verbose"))
202 {
203 m_log.InfoFormat(
204 "[INVENTORY ARCHIVER]: Skipping folder {0} at {1}",
205 inventoryFolder.Name, path);
206 }
207 return;
208 }
209 }
210
211 if (options.ContainsKey("verbose"))
212 m_log.InfoFormat("[INVENTORY ARCHIVER]: Saving folder {0}", inventoryFolder.Name);
213
181 if (saveThisFolderItself) 214 if (saveThisFolderItself)
182 { 215 {
183 path += CreateArchiveFolderName(inventoryFolder); 216 path += CreateArchiveFolderName(inventoryFolder);
@@ -186,7 +219,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
186 m_archiveWriter.WriteDir(path); 219 m_archiveWriter.WriteDir(path);
187 } 220 }
188 221
189 InventoryCollection contents 222 InventoryCollection contents
190 = m_scene.InventoryService.GetFolderContent(inventoryFolder.Owner, inventoryFolder.ID); 223 = m_scene.InventoryService.GetFolderContent(inventoryFolder.Owner, inventoryFolder.ID);
191 224
192 foreach (InventoryFolderBase childFolder in contents.Folders) 225 foreach (InventoryFolderBase childFolder in contents.Folders)
@@ -213,16 +246,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
213 InventoryFolderBase inventoryFolder = null; 246 InventoryFolderBase inventoryFolder = null;
214 InventoryItemBase inventoryItem = null; 247 InventoryItemBase inventoryItem = null;
215 InventoryFolderBase rootFolder = m_scene.InventoryService.GetRootFolder(m_userInfo.PrincipalID); 248 InventoryFolderBase rootFolder = m_scene.InventoryService.GetRootFolder(m_userInfo.PrincipalID);
216 249
217 bool saveFolderContentsOnly = false; 250 bool saveFolderContentsOnly = false;
218 251
219 // Eliminate double slashes and any leading / on the path. 252 // Eliminate double slashes and any leading / on the path.
220 string[] components 253 string[] components
221 = m_invPath.Split( 254 = m_invPath.Split(
222 new string[] { InventoryFolderImpl.PATH_DELIMITER }, StringSplitOptions.RemoveEmptyEntries); 255 new string[] { InventoryFolderImpl.PATH_DELIMITER }, StringSplitOptions.RemoveEmptyEntries);
223 256
224 int maxComponentIndex = components.Length - 1; 257 int maxComponentIndex = components.Length - 1;
225 258
226 // If the path terminates with a STAR then later on we want to archive all nodes in the folder but not the 259 // If the path terminates with a STAR then later on we want to archive all nodes in the folder but not the
227 // folder itself. This may get more sophisicated later on 260 // folder itself. This may get more sophisicated later on
228 if (maxComponentIndex >= 0 && components[maxComponentIndex] == STAR_WILDCARD) 261 if (maxComponentIndex >= 0 && components[maxComponentIndex] == STAR_WILDCARD)
@@ -230,13 +263,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
230 saveFolderContentsOnly = true; 263 saveFolderContentsOnly = true;
231 maxComponentIndex--; 264 maxComponentIndex--;
232 } 265 }
233 266
234 m_invPath = String.Empty; 267 m_invPath = String.Empty;
235 for (int i = 0; i <= maxComponentIndex; i++) 268 for (int i = 0; i <= maxComponentIndex; i++)
236 { 269 {
237 m_invPath += components[i] + InventoryFolderImpl.PATH_DELIMITER; 270 m_invPath += components[i] + InventoryFolderImpl.PATH_DELIMITER;
238 } 271 }
239 272
240 // Annoyingly Split actually returns the original string if the input string consists only of delimiters 273 // Annoyingly Split actually returns the original string if the input string consists only of delimiters
241 // Therefore if we still start with a / after the split, then we need the root folder 274 // Therefore if we still start with a / after the split, then we need the root folder
242 if (m_invPath.Length == 0) 275 if (m_invPath.Length == 0)
@@ -246,25 +279,25 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
246 else 279 else
247 { 280 {
248 m_invPath = m_invPath.Remove(m_invPath.LastIndexOf(InventoryFolderImpl.PATH_DELIMITER)); 281 m_invPath = m_invPath.Remove(m_invPath.LastIndexOf(InventoryFolderImpl.PATH_DELIMITER));
249 List<InventoryFolderBase> candidateFolders 282 List<InventoryFolderBase> candidateFolders
250 = InventoryArchiveUtils.FindFolderByPath(m_scene.InventoryService, rootFolder, m_invPath); 283 = InventoryArchiveUtils.FindFolderByPath(m_scene.InventoryService, rootFolder, m_invPath);
251 if (candidateFolders.Count > 0) 284 if (candidateFolders.Count > 0)
252 inventoryFolder = candidateFolders[0]; 285 inventoryFolder = candidateFolders[0];
253 } 286 }
254 287
255 // The path may point to an item instead 288 // The path may point to an item instead
256 if (inventoryFolder == null) 289 if (inventoryFolder == null)
257 inventoryItem = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, rootFolder, m_invPath); 290 inventoryItem = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, rootFolder, m_invPath);
258 291
259 if (null == inventoryFolder && null == inventoryItem) 292 if (null == inventoryFolder && null == inventoryItem)
260 { 293 {
261 // We couldn't find the path indicated 294 // We couldn't find the path indicated
262 string errorMessage = string.Format("Aborted save. Could not find inventory path {0}", m_invPath); 295 string errorMessage = string.Format("Aborted save. Could not find inventory path {0}", m_invPath);
263 Exception e = new InventoryArchiverException(errorMessage); 296 Exception e = new InventoryArchiverException(errorMessage);
264 m_module.TriggerInventoryArchiveSaved(m_id, false, m_userInfo, m_invPath, m_saveStream, e); 297 m_module.TriggerInventoryArchiveSaved(m_id, false, m_userInfo, m_invPath, m_saveStream, e);
265 throw e; 298 throw e;
266 } 299 }
267 300
268 m_archiveWriter = new TarArchiveWriter(m_saveStream); 301 m_archiveWriter = new TarArchiveWriter(m_saveStream);
269 302
270 m_log.InfoFormat("[INVENTORY ARCHIVER]: Adding control file to archive."); 303 m_log.InfoFormat("[INVENTORY ARCHIVER]: Adding control file to archive.");
@@ -278,10 +311,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
278 { 311 {
279 m_log.DebugFormat( 312 m_log.DebugFormat(
280 "[INVENTORY ARCHIVER]: Found folder {0} {1} at {2}", 313 "[INVENTORY ARCHIVER]: Found folder {0} {1} at {2}",
281 inventoryFolder.Name, 314 inventoryFolder.Name,
282 inventoryFolder.ID, 315 inventoryFolder.ID,
283 m_invPath == String.Empty ? InventoryFolderImpl.PATH_DELIMITER : m_invPath); 316 m_invPath == String.Empty ? InventoryFolderImpl.PATH_DELIMITER : m_invPath);
284 317
285 //recurse through all dirs getting dirs and files 318 //recurse through all dirs getting dirs and files
286 SaveInvFolder(inventoryFolder, ArchiveConstants.INVENTORY_PATH, !saveFolderContentsOnly, options, userAccountService); 319 SaveInvFolder(inventoryFolder, ArchiveConstants.INVENTORY_PATH, !saveFolderContentsOnly, options, userAccountService);
287 } 320 }
@@ -290,10 +323,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
290 m_log.DebugFormat( 323 m_log.DebugFormat(
291 "[INVENTORY ARCHIVER]: Found item {0} {1} at {2}", 324 "[INVENTORY ARCHIVER]: Found item {0} {1} at {2}",
292 inventoryItem.Name, inventoryItem.ID, m_invPath); 325 inventoryItem.Name, inventoryItem.ID, m_invPath);
293 326
294 SaveInvItem(inventoryItem, ArchiveConstants.INVENTORY_PATH, options, userAccountService); 327 SaveInvItem(inventoryItem, ArchiveConstants.INVENTORY_PATH, options, userAccountService);
295 } 328 }
296 329
297 // Don't put all this profile information into the archive right now. 330 // Don't put all this profile information into the archive right now.
298 //SaveUsers(); 331 //SaveUsers();
299 332
@@ -352,7 +385,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
352 /// 385 ///
353 /// These names are prepended with an inventory folder's UUID so that more than one folder can have the 386 /// These names are prepended with an inventory folder's UUID so that more than one folder can have the
354 /// same name 387 /// same name
355 /// 388 ///
356 /// <param name="folder"></param> 389 /// <param name="folder"></param>
357 /// <returns></returns> 390 /// <returns></returns>
358 public static string CreateArchiveFolderName(InventoryFolderBase folder) 391 public static string CreateArchiveFolderName(InventoryFolderBase folder)
@@ -366,7 +399,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
366 /// 399 ///
367 /// These names are prepended with an inventory item's UUID so that more than one item can have the 400 /// These names are prepended with an inventory item's UUID so that more than one item can have the
368 /// same name 401 /// same name
369 /// 402 ///
370 /// <param name="item"></param> 403 /// <param name="item"></param>
371 /// <returns></returns> 404 /// <returns></returns>
372 public static string CreateArchiveItemName(InventoryItemBase item) 405 public static string CreateArchiveItemName(InventoryItemBase item)
@@ -412,7 +445,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
412 public string CreateControlFile(Dictionary<string, object> options) 445 public string CreateControlFile(Dictionary<string, object> options)
413 { 446 {
414 int majorVersion, minorVersion; 447 int majorVersion, minorVersion;
415 448
416 if (options.ContainsKey("home")) 449 if (options.ContainsKey("home"))
417 { 450 {
418 majorVersion = 1; 451 majorVersion = 1;
@@ -422,10 +455,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
422 { 455 {
423 majorVersion = 0; 456 majorVersion = 0;
424 minorVersion = 3; 457 minorVersion = 3;
425 } 458 }
426 459
427 m_log.InfoFormat("[INVENTORY ARCHIVER]: Creating version {0}.{1} IAR", majorVersion, minorVersion); 460 m_log.InfoFormat("[INVENTORY ARCHIVER]: Creating version {0}.{1} IAR", majorVersion, minorVersion);
428 461
429 StringWriter sw = new StringWriter(); 462 StringWriter sw = new StringWriter();
430 XmlTextWriter xtw = new XmlTextWriter(sw); 463 XmlTextWriter xtw = new XmlTextWriter(sw);
431 xtw.Formatting = Formatting.Indented; 464 xtw.Formatting = Formatting.Indented;
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
index ac22c3f..cf87010 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
@@ -47,18 +47,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
47 public class InventoryArchiverModule : IRegionModule, IInventoryArchiverModule 47 public class InventoryArchiverModule : IRegionModule, IInventoryArchiverModule
48 { 48 {
49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50 50
51 public string Name { get { return "Inventory Archiver Module"; } } 51 public string Name { get { return "Inventory Archiver Module"; } }
52 52
53 public bool IsSharedModule { get { return true; } } 53 public bool IsSharedModule { get { return true; } }
54 54
55 /// <value> 55 /// <value>
56 /// Enable or disable checking whether the iar user is actually logged in 56 /// Enable or disable checking whether the iar user is actually logged in
57 /// </value> 57 /// </value>
58// public bool DisablePresenceChecks { get; set; } 58// public bool DisablePresenceChecks { get; set; }
59 59
60 public event InventoryArchiveSaved OnInventoryArchiveSaved; 60 public event InventoryArchiveSaved OnInventoryArchiveSaved;
61 61
62 /// <summary> 62 /// <summary>
63 /// The file to load and save inventory if no filename has been specified 63 /// The file to load and save inventory if no filename has been specified
64 /// </summary> 64 /// </summary>
@@ -68,7 +68,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
68 /// Pending save completions initiated from the console 68 /// Pending save completions initiated from the console
69 /// </value> 69 /// </value>
70 protected List<Guid> m_pendingConsoleSaves = new List<Guid>(); 70 protected List<Guid> m_pendingConsoleSaves = new List<Guid>();
71 71
72 /// <value> 72 /// <value>
73 /// All scenes that this module knows about 73 /// All scenes that this module knows about
74 /// </value> 74 /// </value>
@@ -106,7 +106,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
106 { 106 {
107 scene.RegisterModuleInterface<IInventoryArchiverModule>(this); 107 scene.RegisterModuleInterface<IInventoryArchiverModule>(this);
108 OnInventoryArchiveSaved += SaveInvConsoleCommandCompleted; 108 OnInventoryArchiveSaved += SaveInvConsoleCommandCompleted;
109 109
110 scene.AddCommand( 110 scene.AddCommand(
111 "Archiving", this, "load iar", 111 "Archiving", this, "load iar",
112 "load iar [-m|--merge] <first> <last> <inventory path> <password> [<IAR path>]", 112 "load iar [-m|--merge] <first> <last> <inventory path> <password> [<IAR path>]",
@@ -119,11 +119,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
119 + "<IAR path> is the filesystem path or URI from which to load the IAR." 119 + "<IAR path> is the filesystem path or URI from which to load the IAR."
120 + string.Format(" If this is not given then the filename {0} in the current directory is used", DEFAULT_INV_BACKUP_FILENAME), 120 + string.Format(" If this is not given then the filename {0} in the current directory is used", DEFAULT_INV_BACKUP_FILENAME),
121 HandleLoadInvConsoleCommand); 121 HandleLoadInvConsoleCommand);
122 122
123 scene.AddCommand( 123 scene.AddCommand(
124 "Archiving", this, "save iar", 124 "Archiving", this, "save iar",
125 "save iar [-h|--home=<url>] [--noassets] <first> <last> <inventory path> <password> [<IAR path>] [-c|--creators] [-v|--verbose]", 125 "save iar [-h|--home=<url>] [--noassets] <first> <last> <inventory path> <password> [<IAR path>] [-c|--creators] [-e|--exclude=<name/uuid>] [-f|--excludefolder=<foldername/uuid>] [-v|--verbose]",
126 "Save user inventory archive (IAR).", 126 "Save user inventory archive (IAR).",
127 "<first> is the user's first name.\n" 127 "<first> is the user's first name.\n"
128 + "<last> is the user's last name.\n" 128 + "<last> is the user's last name.\n"
129 + "<inventory path> is the path inside the user's inventory for the folder/item to be saved.\n" 129 + "<inventory path> is the path inside the user's inventory for the folder/item to be saved.\n"
@@ -131,32 +131,34 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
131 + string.Format(" If this is not given then the filename {0} in the current directory is used.\n", DEFAULT_INV_BACKUP_FILENAME) 131 + string.Format(" If this is not given then the filename {0} in the current directory is used.\n", DEFAULT_INV_BACKUP_FILENAME)
132 + "-h|--home=<url> adds the url of the profile service to the saved user information.\n" 132 + "-h|--home=<url> adds the url of the profile service to the saved user information.\n"
133 + "-c|--creators preserves information about foreign creators.\n" 133 + "-c|--creators preserves information about foreign creators.\n"
134 + "-e|--exclude=<name/uuid> don't save the inventory item in archive" + Environment.NewLine
135 + "-f|--excludefolder=<folder/uuid> don't save contents of the folder in archive" + Environment.NewLine
134 + "-v|--verbose extra debug messages.\n" 136 + "-v|--verbose extra debug messages.\n"
135 + "--noassets stops assets being saved to the IAR.", 137 + "--noassets stops assets being saved to the IAR.",
136 HandleSaveInvConsoleCommand); 138 HandleSaveInvConsoleCommand);
137 139
138 m_aScene = scene; 140 m_aScene = scene;
139 } 141 }
140 142
141 m_scenes[scene.RegionInfo.RegionID] = scene; 143 m_scenes[scene.RegionInfo.RegionID] = scene;
142 } 144 }
143 145
144 public void PostInitialise() {} 146 public void PostInitialise() {}
145 147
146 public void Close() {} 148 public void Close() {}
147 149
148 /// <summary> 150 /// <summary>
149 /// Trigger the inventory archive saved event. 151 /// Trigger the inventory archive saved event.
150 /// </summary> 152 /// </summary>
151 protected internal void TriggerInventoryArchiveSaved( 153 protected internal void TriggerInventoryArchiveSaved(
152 Guid id, bool succeeded, UserAccount userInfo, string invPath, Stream saveStream, 154 Guid id, bool succeeded, UserAccount userInfo, string invPath, Stream saveStream,
153 Exception reportedException) 155 Exception reportedException)
154 { 156 {
155 InventoryArchiveSaved handlerInventoryArchiveSaved = OnInventoryArchiveSaved; 157 InventoryArchiveSaved handlerInventoryArchiveSaved = OnInventoryArchiveSaved;
156 if (handlerInventoryArchiveSaved != null) 158 if (handlerInventoryArchiveSaved != null)
157 handlerInventoryArchiveSaved(id, succeeded, userInfo, invPath, saveStream, reportedException); 159 handlerInventoryArchiveSaved(id, succeeded, userInfo, invPath, saveStream, reportedException);
158 } 160 }
159 161
160 public bool ArchiveInventory( 162 public bool ArchiveInventory(
161 Guid id, string firstName, string lastName, string invPath, string pass, Stream saveStream) 163 Guid id, string firstName, string lastName, string invPath, string pass, Stream saveStream)
162 { 164 {
@@ -164,7 +166,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
164 } 166 }
165 167
166 public bool ArchiveInventory( 168 public bool ArchiveInventory(
167 Guid id, string firstName, string lastName, string invPath, string pass, Stream saveStream, 169 Guid id, string firstName, string lastName, string invPath, string pass, Stream saveStream,
168 Dictionary<string, object> options) 170 Dictionary<string, object> options)
169 { 171 {
170 if (m_scenes.Count > 0) 172 if (m_scenes.Count > 0)
@@ -188,7 +190,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
188 190
189 return false; 191 return false;
190 } 192 }
191 193
192 return true; 194 return true;
193// } 195// }
194// else 196// else
@@ -202,15 +204,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
202 204
203 return false; 205 return false;
204 } 206 }
205 207
206 public bool ArchiveInventory( 208 public bool ArchiveInventory(
207 Guid id, string firstName, string lastName, string invPath, string pass, string savePath, 209 Guid id, string firstName, string lastName, string invPath, string pass, string savePath,
208 Dictionary<string, object> options) 210 Dictionary<string, object> options)
209 { 211 {
210 if (m_scenes.Count > 0) 212 if (m_scenes.Count > 0)
211 { 213 {
212 UserAccount userInfo = GetUserInfo(firstName, lastName, pass); 214 UserAccount userInfo = GetUserInfo(firstName, lastName, pass);
213 215
214 if (userInfo != null) 216 if (userInfo != null)
215 { 217 {
216// if (CheckPresence(userInfo.PrincipalID)) 218// if (CheckPresence(userInfo.PrincipalID))
@@ -228,7 +230,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
228 230
229 return false; 231 return false;
230 } 232 }
231 233
232 return true; 234 return true;
233// } 235// }
234// else 236// else
@@ -239,7 +241,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
239// } 241// }
240 } 242 }
241 } 243 }
242 244
243 return false; 245 return false;
244 } 246 }
245 247
@@ -247,9 +249,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
247 { 249 {
248 return DearchiveInventory(firstName, lastName, invPath, pass, loadStream, new Dictionary<string, object>()); 250 return DearchiveInventory(firstName, lastName, invPath, pass, loadStream, new Dictionary<string, object>());
249 } 251 }
250 252
251 public bool DearchiveInventory( 253 public bool DearchiveInventory(
252 string firstName, string lastName, string invPath, string pass, Stream loadStream, 254 string firstName, string lastName, string invPath, string pass, Stream loadStream,
253 Dictionary<string, object> options) 255 Dictionary<string, object> options)
254 { 256 {
255 if (m_scenes.Count > 0) 257 if (m_scenes.Count > 0)
@@ -295,22 +297,22 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
295 297
296 return false; 298 return false;
297 } 299 }
298 300
299 public bool DearchiveInventory( 301 public bool DearchiveInventory(
300 string firstName, string lastName, string invPath, string pass, string loadPath, 302 string firstName, string lastName, string invPath, string pass, string loadPath,
301 Dictionary<string, object> options) 303 Dictionary<string, object> options)
302 { 304 {
303 if (m_scenes.Count > 0) 305 if (m_scenes.Count > 0)
304 { 306 {
305 UserAccount userInfo = GetUserInfo(firstName, lastName, pass); 307 UserAccount userInfo = GetUserInfo(firstName, lastName, pass);
306 308
307 if (userInfo != null) 309 if (userInfo != null)
308 { 310 {
309// if (CheckPresence(userInfo.PrincipalID)) 311// if (CheckPresence(userInfo.PrincipalID))
310// { 312// {
311 InventoryArchiveReadRequest request; 313 InventoryArchiveReadRequest request;
312 bool merge = (options.ContainsKey("merge") ? (bool)options["merge"] : false); 314 bool merge = (options.ContainsKey("merge") ? (bool)options["merge"] : false);
313 315
314 try 316 try
315 { 317 {
316 request = new InventoryArchiveReadRequest(m_aScene, userInfo, invPath, loadPath, merge); 318 request = new InventoryArchiveReadRequest(m_aScene, userInfo, invPath, loadPath, merge);
@@ -324,7 +326,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
324 326
325 return false; 327 return false;
326 } 328 }
327 329
328 UpdateClientWithLoadedNodes(userInfo, request.Execute()); 330 UpdateClientWithLoadedNodes(userInfo, request.Execute());
329 331
330 return true; 332 return true;
@@ -340,7 +342,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
340 342
341 return false; 343 return false;
342 } 344 }
343 345
344 /// <summary> 346 /// <summary>
345 /// Load inventory from an inventory file archive 347 /// Load inventory from an inventory file archive
346 /// </summary> 348 /// </summary>
@@ -351,26 +353,26 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
351 { 353 {
352 Dictionary<string, object> options = new Dictionary<string, object>(); 354 Dictionary<string, object> options = new Dictionary<string, object>();
353 OptionSet optionSet = new OptionSet().Add("m|merge", delegate (string v) { options["merge"] = v != null; }); 355 OptionSet optionSet = new OptionSet().Add("m|merge", delegate (string v) { options["merge"] = v != null; });
354 356
355 List<string> mainParams = optionSet.Parse(cmdparams); 357 List<string> mainParams = optionSet.Parse(cmdparams);
356 358
357 if (mainParams.Count < 6) 359 if (mainParams.Count < 6)
358 { 360 {
359 m_log.Error( 361 m_log.Error(
360 "[INVENTORY ARCHIVER]: usage is load iar [-m|--merge] <first name> <last name> <inventory path> <user password> [<load file path>]"); 362 "[INVENTORY ARCHIVER]: usage is load iar [-m|--merge] <first name> <last name> <inventory path> <user password> [<load file path>]");
361 return; 363 return;
362 } 364 }
363 365
364 string firstName = mainParams[2]; 366 string firstName = mainParams[2];
365 string lastName = mainParams[3]; 367 string lastName = mainParams[3];
366 string invPath = mainParams[4]; 368 string invPath = mainParams[4];
367 string pass = mainParams[5]; 369 string pass = mainParams[5];
368 string loadPath = (mainParams.Count > 6 ? mainParams[6] : DEFAULT_INV_BACKUP_FILENAME); 370 string loadPath = (mainParams.Count > 6 ? mainParams[6] : DEFAULT_INV_BACKUP_FILENAME);
369 371
370 m_log.InfoFormat( 372 m_log.InfoFormat(
371 "[INVENTORY ARCHIVER]: Loading archive {0} to inventory path {1} for {2} {3}", 373 "[INVENTORY ARCHIVER]: Loading archive {0} to inventory path {1} for {2} {3}",
372 loadPath, invPath, firstName, lastName); 374 loadPath, invPath, firstName, lastName);
373 375
374 if (DearchiveInventory(firstName, lastName, invPath, pass, loadPath, options)) 376 if (DearchiveInventory(firstName, lastName, invPath, pass, loadPath, options))
375 m_log.InfoFormat( 377 m_log.InfoFormat(
376 "[INVENTORY ARCHIVER]: Loaded archive {0} for {1} {2}", 378 "[INVENTORY ARCHIVER]: Loaded archive {0} for {1} {2}",
@@ -381,7 +383,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
381 m_log.ErrorFormat("[INVENTORY ARCHIVER]: {0}", e.Message); 383 m_log.ErrorFormat("[INVENTORY ARCHIVER]: {0}", e.Message);
382 } 384 }
383 } 385 }
384 386
385 /// <summary> 387 /// <summary>
386 /// Save inventory to a file archive 388 /// Save inventory to a file archive
387 /// </summary> 389 /// </summary>
@@ -398,6 +400,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
398 ops.Add("v|verbose", delegate(string v) { options["verbose"] = v; }); 400 ops.Add("v|verbose", delegate(string v) { options["verbose"] = v; });
399 ops.Add("c|creators", delegate(string v) { options["creators"] = v; }); 401 ops.Add("c|creators", delegate(string v) { options["creators"] = v; });
400 ops.Add("noassets", delegate(string v) { options["noassets"] = v != null; }); 402 ops.Add("noassets", delegate(string v) { options["noassets"] = v != null; });
403 ops.Add("e|exclude=", delegate(string v)
404 {
405 if (!options.ContainsKey("exclude"))
406 options["exclude"] = new List<String>();
407 ((List<String>)options["exclude"]).Add(v);
408 });
409 ops.Add("f|excludefolder=", delegate(string v)
410 {
411 if (!options.ContainsKey("excludefolders"))
412 options["excludefolders"] = new List<String>();
413 ((List<String>)options["excludefolders"]).Add(v);
414 });
401 415
402 List<string> mainParams = ops.Parse(cmdparams); 416 List<string> mainParams = ops.Parse(cmdparams);
403 417
@@ -406,10 +420,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
406 if (mainParams.Count < 6) 420 if (mainParams.Count < 6)
407 { 421 {
408 m_log.Error( 422 m_log.Error(
409 "[INVENTORY ARCHIVER]: usage is save iar [-h|--home=<url>] [--noassets] <first name> <last name> <inventory path> <user password> [<save file path>] [-c|--creators] [-v|--verbose]"); 423 "[INVENTORY ARCHIVER]: save iar [-h|--home=<url>] [--noassets] <first> <last> <inventory path> <password> [<IAR path>] [-c|--creators] [-e|--exclude=<name/uuid>] [-f|--excludefolder=<foldername/uuid>] [-v|--verbose]");
410 return; 424 return;
411 } 425 }
412 426
413 if (options.ContainsKey("home")) 427 if (options.ContainsKey("home"))
414 m_log.WarnFormat("[INVENTORY ARCHIVER]: Please be aware that inventory archives with creator information are not compatible with OpenSim 0.7.0.2 and earlier. Do not use the -home option if you want to produce a compatible IAR"); 428 m_log.WarnFormat("[INVENTORY ARCHIVER]: Please be aware that inventory archives with creator information are not compatible with OpenSim 0.7.0.2 and earlier. Do not use the -home option if you want to produce a compatible IAR");
415 429
@@ -418,7 +432,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
418 string invPath = mainParams[4]; 432 string invPath = mainParams[4];
419 string pass = mainParams[5]; 433 string pass = mainParams[5];
420 string savePath = (mainParams.Count > 6 ? mainParams[6] : DEFAULT_INV_BACKUP_FILENAME); 434 string savePath = (mainParams.Count > 6 ? mainParams[6] : DEFAULT_INV_BACKUP_FILENAME);
421 435
422 m_log.InfoFormat( 436 m_log.InfoFormat(
423 "[INVENTORY ARCHIVER]: Saving archive {0} using inventory path {1} for {2} {3}", 437 "[INVENTORY ARCHIVER]: Saving archive {0} using inventory path {1} for {2} {3}",
424 savePath, invPath, firstName, lastName); 438 savePath, invPath, firstName, lastName);
@@ -433,9 +447,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
433 m_log.ErrorFormat("[INVENTORY ARCHIVER]: {0}", e.Message); 447 m_log.ErrorFormat("[INVENTORY ARCHIVER]: {0}", e.Message);
434 } 448 }
435 } 449 }
436 450
437 private void SaveInvConsoleCommandCompleted( 451 private void SaveInvConsoleCommandCompleted(
438 Guid id, bool succeeded, UserAccount userInfo, string invPath, Stream saveStream, 452 Guid id, bool succeeded, UserAccount userInfo, string invPath, Stream saveStream,
439 Exception reportedException) 453 Exception reportedException)
440 { 454 {
441 lock (m_pendingConsoleSaves) 455 lock (m_pendingConsoleSaves)
@@ -445,7 +459,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
445 else 459 else
446 return; 460 return;
447 } 461 }
448 462
449 if (succeeded) 463 if (succeeded)
450 { 464 {
451 m_log.InfoFormat("[INVENTORY ARCHIVER]: Saved archive for {0} {1}", userInfo.FirstName, userInfo.LastName); 465 m_log.InfoFormat("[INVENTORY ARCHIVER]: Saved archive for {0} {1}", userInfo.FirstName, userInfo.LastName);
@@ -453,11 +467,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
453 else 467 else
454 { 468 {
455 m_log.ErrorFormat( 469 m_log.ErrorFormat(
456 "[INVENTORY ARCHIVER]: Archive save for {0} {1} failed - {2}", 470 "[INVENTORY ARCHIVER]: Archive save for {0} {1} failed - {2}",
457 userInfo.FirstName, userInfo.LastName, reportedException.Message); 471 userInfo.FirstName, userInfo.LastName, reportedException.Message);
458 } 472 }
459 } 473 }
460 474
461 /// <summary> 475 /// <summary>
462 /// Get user information for the given name. 476 /// Get user information for the given name.
463 /// </summary> 477 /// </summary>
@@ -467,13 +481,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
467 /// <returns></returns> 481 /// <returns></returns>
468 protected UserAccount GetUserInfo(string firstName, string lastName, string pass) 482 protected UserAccount GetUserInfo(string firstName, string lastName, string pass)
469 { 483 {
470 UserAccount account 484 UserAccount account
471 = m_aScene.UserAccountService.GetUserAccount(m_aScene.RegionInfo.ScopeID, firstName, lastName); 485 = m_aScene.UserAccountService.GetUserAccount(m_aScene.RegionInfo.ScopeID, firstName, lastName);
472 486
473 if (null == account) 487 if (null == account)
474 { 488 {
475 m_log.ErrorFormat( 489 m_log.ErrorFormat(
476 "[INVENTORY ARCHIVER]: Failed to find user info for {0} {1}", 490 "[INVENTORY ARCHIVER]: Failed to find user info for {0} {1}",
477 firstName, lastName); 491 firstName, lastName);
478 return null; 492 return null;
479 } 493 }
@@ -488,7 +502,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
488 else 502 else
489 { 503 {
490 m_log.ErrorFormat( 504 m_log.ErrorFormat(
491 "[INVENTORY ARCHIVER]: Password for user {0} {1} incorrect. Please try again.", 505 "[INVENTORY ARCHIVER]: Password for user {0} {1} incorrect. Please try again.",
492 firstName, lastName); 506 firstName, lastName);
493 return null; 507 return null;
494 } 508 }
@@ -499,7 +513,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
499 return null; 513 return null;
500 } 514 }
501 } 515 }
502 516
503 /// <summary> 517 /// <summary>
504 /// Notify the client of loaded nodes if they are logged in 518 /// Notify the client of loaded nodes if they are logged in
505 /// </summary> 519 /// </summary>
@@ -508,22 +522,22 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
508 { 522 {
509 if (loadedNodes.Count == 0) 523 if (loadedNodes.Count == 0)
510 return; 524 return;
511 525
512 foreach (Scene scene in m_scenes.Values) 526 foreach (Scene scene in m_scenes.Values)
513 { 527 {
514 ScenePresence user = scene.GetScenePresence(userInfo.PrincipalID); 528 ScenePresence user = scene.GetScenePresence(userInfo.PrincipalID);
515 529
516 if (user != null && !user.IsChildAgent) 530 if (user != null && !user.IsChildAgent)
517 { 531 {
518 foreach (InventoryNodeBase node in loadedNodes) 532 foreach (InventoryNodeBase node in loadedNodes)
519 { 533 {
520// m_log.DebugFormat( 534// m_log.DebugFormat(
521// "[INVENTORY ARCHIVER]: Notifying {0} of loaded inventory node {1}", 535// "[INVENTORY ARCHIVER]: Notifying {0} of loaded inventory node {1}",
522// user.Name, node.Name); 536// user.Name, node.Name);
523 537
524 user.ControllingClient.SendBulkUpdateInventory(node); 538 user.ControllingClient.SendBulkUpdateInventory(node);
525 } 539 }
526 540
527 break; 541 break;
528 } 542 }
529 } 543 }
@@ -538,7 +552,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
538// { 552// {
539// if (DisablePresenceChecks) 553// if (DisablePresenceChecks)
540// return true; 554// return true;
541// 555//
542// foreach (Scene scene in m_scenes.Values) 556// foreach (Scene scene in m_scenes.Values)
543// { 557// {
544// ScenePresence p; 558// ScenePresence p;
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
index 1e743c3..ddc2a07 100644
--- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
@@ -168,12 +168,18 @@ namespace OpenSim.Region.CoreModules.World.Estate
168 sendRegionInfoPacketToAll(); 168 sendRegionInfoPacketToAll();
169 } 169 }
170 170
171 public void setEstateTerrainBaseTexture(IClientAPI remoteClient, int corner, UUID texture) 171 public void setEstateTerrainBaseTexture(int level, UUID texture)
172 {
173 setEstateTerrainBaseTexture(null, level, texture);
174 sendRegionHandshakeToAll();
175 }
176
177 public void setEstateTerrainBaseTexture(IClientAPI remoteClient, int level, UUID texture)
172 { 178 {
173 if (texture == UUID.Zero) 179 if (texture == UUID.Zero)
174 return; 180 return;
175 181
176 switch (corner) 182 switch (level)
177 { 183 {
178 case 0: 184 case 0:
179 Scene.RegionInfo.RegionSettings.TerrainTexture1 = texture; 185 Scene.RegionInfo.RegionSettings.TerrainTexture1 = texture;
@@ -193,6 +199,11 @@ namespace OpenSim.Region.CoreModules.World.Estate
193 sendRegionInfoPacketToAll(); 199 sendRegionInfoPacketToAll();
194 } 200 }
195 201
202 public void setEstateTerrainTextureHeights(int corner, float lowValue, float highValue)
203 {
204 setEstateTerrainTextureHeights(null, corner, lowValue, highValue);
205 }
206
196 public void setEstateTerrainTextureHeights(IClientAPI client, int corner, float lowValue, float highValue) 207 public void setEstateTerrainTextureHeights(IClientAPI client, int corner, float lowValue, float highValue)
197 { 208 {
198 switch (corner) 209 switch (corner)
@@ -987,7 +998,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
987 { 998 {
988 RegionHandshakeArgs args = new RegionHandshakeArgs(); 999 RegionHandshakeArgs args = new RegionHandshakeArgs();
989 1000
990 args.isEstateManager = Scene.RegionInfo.EstateSettings.IsEstateManager(remoteClient.AgentId); 1001 args.isEstateManager = Scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(remoteClient.AgentId);
991 if (Scene.RegionInfo.EstateSettings.EstateOwner != UUID.Zero && Scene.RegionInfo.EstateSettings.EstateOwner == remoteClient.AgentId) 1002 if (Scene.RegionInfo.EstateSettings.EstateOwner != UUID.Zero && Scene.RegionInfo.EstateSettings.EstateOwner == remoteClient.AgentId)
992 args.isEstateManager = true; 1003 args.isEstateManager = true;
993 1004
diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
index 509c4d7..16792b3 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
@@ -447,7 +447,10 @@ namespace OpenSim.Region.CoreModules.World.Land
447 { 447 {
448 bool isMember; 448 bool isMember;
449 if (m_groupMemberCache.TryGetValue(avatar, out isMember)) 449 if (m_groupMemberCache.TryGetValue(avatar, out isMember))
450 {
451 m_groupMemberCache.Update(avatar, isMember, m_groupMemberCacheTimeout);
450 return isMember; 452 return isMember;
453 }
451 454
452 IGroupsModule groupsModule = m_scene.RequestModuleInterface<IGroupsModule>(); 455 IGroupsModule groupsModule = m_scene.RequestModuleInterface<IGroupsModule>();
453 if (groupsModule == null) 456 if (groupsModule == null)
@@ -484,7 +487,7 @@ namespace OpenSim.Region.CoreModules.World.Land
484 if (m_scene.Permissions.IsAdministrator(avatar)) 487 if (m_scene.Permissions.IsAdministrator(avatar))
485 return false; 488 return false;
486 489
487 if (m_scene.RegionInfo.EstateSettings.IsEstateManager(avatar)) 490 if (m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(avatar))
488 return false; 491 return false;
489 492
490 if (avatar == LandData.OwnerID) 493 if (avatar == LandData.OwnerID)
@@ -514,7 +517,7 @@ namespace OpenSim.Region.CoreModules.World.Land
514 if (m_scene.Permissions.IsAdministrator(avatar)) 517 if (m_scene.Permissions.IsAdministrator(avatar))
515 return false; 518 return false;
516 519
517 if (m_scene.RegionInfo.EstateSettings.IsEstateManager(avatar)) 520 if (m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(avatar))
518 return false; 521 return false;
519 522
520 if (avatar == LandData.OwnerID) 523 if (avatar == LandData.OwnerID)
diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs
index f5a5c92..06fea58 100644
--- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs
+++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs
@@ -282,7 +282,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
282 sb.AppendFormat("Location: {0} @ {1}\n", sop.AbsolutePosition, sop.ParentGroup.Scene.RegionInfo.RegionName); 282 sb.AppendFormat("Location: {0} @ {1}\n", sop.AbsolutePosition, sop.ParentGroup.Scene.RegionInfo.RegionName);
283 sb.AppendFormat("Parent: {0}", 283 sb.AppendFormat("Parent: {0}",
284 sop.IsRoot ? "Is Root\n" : string.Format("{0} {1}\n", sop.ParentGroup.Name, sop.ParentGroup.UUID)); 284 sop.IsRoot ? "Is Root\n" : string.Format("{0} {1}\n", sop.ParentGroup.Name, sop.ParentGroup.UUID));
285 sb.AppendFormat("Parts: {0}\n", !sop.IsRoot ? "1" : sop.ParentGroup.PrimCount.ToString());; 285 sb.AppendFormat("Link number: {0}\n", sop.LinkNum);
286 286
287 return sb; 287 return sb;
288 } 288 }
diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
index 82ccaf8..881b24a 100644
--- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
+++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
@@ -503,7 +503,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
503 { 503 {
504 if (user == UUID.Zero) return false; 504 if (user == UUID.Zero) return false;
505 505
506 return m_scene.RegionInfo.EstateSettings.IsEstateManager(user); 506 return m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(user);
507 } 507 }
508 508
509#endregion 509#endregion
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
index 32f4eea..8732ec0 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
@@ -174,7 +174,17 @@ namespace OpenSim.Region.Framework.Interfaces
174 /// If no inventory item has that name then an empty list is returned. 174 /// If no inventory item has that name then an empty list is returned.
175 /// </returns> 175 /// </returns>
176 List<TaskInventoryItem> GetInventoryItems(string name); 176 List<TaskInventoryItem> GetInventoryItems(string name);
177 177
178 /// <summary>
179 /// Get inventory items by type.
180 /// </summary>
181 /// <param type="name"></param>
182 /// <returns>
183 /// A list of inventory items of that type.
184 /// If no inventory items of that type then an empty list is returned.
185 /// </returns>
186 List<TaskInventoryItem> GetInventoryItems(InventoryType type);
187
178 /// <summary> 188 /// <summary>
179 /// Get the scene object referenced by an inventory item. 189 /// Get the scene object referenced by an inventory item.
180 /// </summary> 190 /// </summary>
@@ -228,6 +238,16 @@ namespace OpenSim.Region.Framework.Interfaces
228 bool ContainsScripts(); 238 bool ContainsScripts();
229 239
230 /// <summary> 240 /// <summary>
241 /// Returns the count of scripts contained
242 /// </summary></returns>
243 int ScriptCount();
244
245 /// <summary>
246 /// Returns the count of running scripts contained
247 /// </summary></returns>
248 int RunningScriptCount();
249
250 /// <summary>
231 /// Get the uuids of all items in this inventory 251 /// Get the uuids of all items in this inventory
232 /// </summary> 252 /// </summary>
233 /// <returns></returns> 253 /// <returns></returns>
diff --git a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
index 72e79ed..ca2ad94 100644
--- a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
@@ -47,5 +47,8 @@ namespace OpenSim.Region.Framework.Interfaces
47 void sendRegionHandshakeToAll(); 47 void sendRegionHandshakeToAll();
48 void TriggerEstateInfoChange(); 48 void TriggerEstateInfoChange();
49 void TriggerRegionInfoChange(); 49 void TriggerRegionInfoChange();
50
51 void setEstateTerrainBaseTexture(int level, UUID texture);
52 void setEstateTerrainTextureHeights(int corner, float lowValue, float highValue);
50 } 53 }
51} 54}
diff --git a/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs b/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs
new file mode 100644
index 0000000..baac6e8
--- /dev/null
+++ b/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs
@@ -0,0 +1,48 @@
1/*
2 * Copyright (c) Contributors
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Reflection;
30using OpenMetaverse;
31
32namespace OpenSim.Region.Framework.Interfaces
33{
34 public delegate void TakeValueCallback(string s);
35
36 public interface IJsonStoreModule
37 {
38 bool CreateStore(string value, out UUID result);
39 bool DestroyStore(UUID storeID);
40 bool TestPath(UUID storeID, string path, bool useJson);
41 bool SetValue(UUID storeID, string path, string value, bool useJson);
42 bool RemoveValue(UUID storeID, string path);
43 bool GetValue(UUID storeID, string path, bool useJson, out string value);
44
45 void TakeValue(UUID storeID, string path, bool useJson, TakeValueCallback cback);
46 void ReadValue(UUID storeID, string path, bool useJson, TakeValueCallback cback);
47 }
48}
diff --git a/OpenSim/Region/Framework/Interfaces/IScriptModule.cs b/OpenSim/Region/Framework/Interfaces/IScriptModule.cs
index ce66100..143af48 100644
--- a/OpenSim/Region/Framework/Interfaces/IScriptModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IScriptModule.cs
@@ -71,6 +71,12 @@ namespace OpenSim.Region.Framework.Interfaces
71 71
72 bool HasScript(UUID itemID, out bool running); 72 bool HasScript(UUID itemID, out bool running);
73 73
74 /// <summary>
75 /// Returns true if a script is running.
76 /// </summary>
77 /// <param name="itemID">The item ID of the script.</param>
78 bool GetScriptState(UUID itemID);
79
74 void SaveAllState(); 80 void SaveAllState();
75 81
76 /// <summary> 82 /// <summary>
@@ -79,6 +85,14 @@ namespace OpenSim.Region.Framework.Interfaces
79 void StartProcessing(); 85 void StartProcessing();
80 86
81 /// <summary> 87 /// <summary>
88 /// Get the execution times of all scripts in the given array if they are currently running.
89 /// </summary>
90 /// <returns>
91 /// A float the value is a representative execution time in milliseconds of all scripts in that Array.
92 /// </returns>
93 float GetScriptExecutionTime(List<UUID> itemIDs);
94
95 /// <summary>
82 /// Get the execution times of all scripts in each object. 96 /// Get the execution times of all scripts in each object.
83 /// </summary> 97 /// </summary>
84 /// <returns> 98 /// <returns>
@@ -87,4 +101,4 @@ namespace OpenSim.Region.Framework.Interfaces
87 /// </returns> 101 /// </returns>
88 Dictionary<uint, float> GetObjectScriptsExecutionTimes(); 102 Dictionary<uint, float> GetObjectScriptsExecutionTimes();
89 } 103 }
90} \ No newline at end of file 104}
diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
index b806d91..77e808e 100644
--- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
@@ -156,7 +156,9 @@ namespace OpenSim.Region.Framework.Scenes
156 // that the region position is cached or performance will degrade 156 // that the region position is cached or performance will degrade
157 Utils.LongToUInts(regionHandle, out x, out y); 157 Utils.LongToUInts(regionHandle, out x, out y);
158 GridRegion dest = m_scene.GridService.GetRegionByPosition(UUID.Zero, (int)x, (int)y); 158 GridRegion dest = m_scene.GridService.GetRegionByPosition(UUID.Zero, (int)x, (int)y);
159// bool v = true; 159 if (dest == null)
160 continue;
161
160 if (!simulatorList.Contains(dest.ServerURI)) 162 if (!simulatorList.Contains(dest.ServerURI))
161 { 163 {
162 // we havent seen this simulator before, add it to the list 164 // we havent seen this simulator before, add it to the list
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index b7dc335..f6f6a1a 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -101,6 +101,9 @@ namespace OpenSim.Region.Framework.Scenes
101 /// </summary> 101 /// </summary>
102 protected internal Dictionary<uint, SceneObjectGroup> SceneObjectGroupsByLocalPartID = new Dictionary<uint, SceneObjectGroup>(); 102 protected internal Dictionary<uint, SceneObjectGroup> SceneObjectGroupsByLocalPartID = new Dictionary<uint, SceneObjectGroup>();
103 103
104 /// <summary>
105 /// Lock to prevent object group update, linking and delinking operations from running concurrently.
106 /// </summary>
104 private Object m_updateLock = new Object(); 107 private Object m_updateLock = new Object();
105 108
106 #endregion 109 #endregion
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 47020af..cb0a57a 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -2590,6 +2590,10 @@ namespace OpenSim.Region.Framework.Scenes
2590 /// <summary> 2590 /// <summary>
2591 /// Link the prims in a given group to this group 2591 /// Link the prims in a given group to this group
2592 /// </summary> 2592 /// </summary>
2593 /// <remarks>
2594 /// Do not call this method directly - use Scene.LinkObjects() instead to avoid races between threads.
2595 /// FIXME: There are places where scripts call these methods directly without locking. This is a potential race condition.
2596 /// </remarks>
2593 /// <param name="objectGroup">The group of prims which should be linked to this group</param> 2597 /// <param name="objectGroup">The group of prims which should be linked to this group</param>
2594 public void LinkToGroup(SceneObjectGroup objectGroup) 2598 public void LinkToGroup(SceneObjectGroup objectGroup)
2595 { 2599 {
@@ -2720,6 +2724,11 @@ namespace OpenSim.Region.Framework.Scenes
2720 /// Delink the given prim from this group. The delinked prim is established as 2724 /// Delink the given prim from this group. The delinked prim is established as
2721 /// an independent SceneObjectGroup. 2725 /// an independent SceneObjectGroup.
2722 /// </summary> 2726 /// </summary>
2727 /// <remarks>
2728 /// FIXME: This method should not be called directly since it bypasses update locking, allowing a potential race
2729 /// condition. But currently there is no
2730 /// alternative method that does take a lonk to delink a single prim.
2731 /// </remarks>
2723 /// <param name="partID"></param> 2732 /// <param name="partID"></param>
2724 /// <returns>The object group of the newly delinked prim. Null if part could not be found</returns> 2733 /// <returns>The object group of the newly delinked prim. Null if part could not be found</returns>
2725 public SceneObjectGroup DelinkFromGroup(uint partID) 2734 public SceneObjectGroup DelinkFromGroup(uint partID)
@@ -2731,6 +2740,11 @@ namespace OpenSim.Region.Framework.Scenes
2731 /// Delink the given prim from this group. The delinked prim is established as 2740 /// Delink the given prim from this group. The delinked prim is established as
2732 /// an independent SceneObjectGroup. 2741 /// an independent SceneObjectGroup.
2733 /// </summary> 2742 /// </summary>
2743 /// <remarks>
2744 /// FIXME: This method should not be called directly since it bypasses update locking, allowing a potential race
2745 /// condition. But currently there is no
2746 /// alternative method that does take a lonk to delink a single prim.
2747 /// </remarks>
2734 /// <param name="partID"></param> 2748 /// <param name="partID"></param>
2735 /// <param name="sendEvents"></param> 2749 /// <param name="sendEvents"></param>
2736 /// <returns>The object group of the newly delinked prim. Null if part could not be found</returns> 2750 /// <returns>The object group of the newly delinked prim. Null if part could not be found</returns>
@@ -2756,6 +2770,11 @@ namespace OpenSim.Region.Framework.Scenes
2756 /// Delink the given prim from this group. The delinked prim is established as 2770 /// Delink the given prim from this group. The delinked prim is established as
2757 /// an independent SceneObjectGroup. 2771 /// an independent SceneObjectGroup.
2758 /// </summary> 2772 /// </summary>
2773 /// <remarks>
2774 /// FIXME: This method should not be called directly since it bypasses update locking, allowing a potential race
2775 /// condition. But currently there is no
2776 /// alternative method that does take a lonk to delink a single prim.
2777 /// </remarks>
2759 /// <param name="partID"></param> 2778 /// <param name="partID"></param>
2760 /// <param name="sendEvents"></param> 2779 /// <param name="sendEvents"></param>
2761 /// <returns>The object group of the newly delinked prim.</returns> 2780 /// <returns>The object group of the newly delinked prim.</returns>
@@ -4051,7 +4070,72 @@ namespace OpenSim.Region.Framework.Scenes
4051 for (int i = 0; i < parts.Length; i++) 4070 for (int i = 0; i < parts.Length; i++)
4052 parts[i].TriggerScriptChangedEvent(val); 4071 parts[i].TriggerScriptChangedEvent(val);
4053 } 4072 }
4054 4073
4074 /// <summary>
4075 /// Returns a count of the number of scripts in this groups parts.
4076 /// </summary>
4077 public int ScriptCount()
4078 {
4079 int count = 0;
4080 SceneObjectPart[] parts = m_parts.GetArray();
4081 for (int i = 0; i < parts.Length; i++)
4082 count += parts[i].Inventory.ScriptCount();
4083
4084 return count;
4085 }
4086
4087 /// <summary>
4088 /// A float the value is a representative execution time in milliseconds of all scripts in the link set.
4089 /// </summary>
4090 public float ScriptExecutionTime()
4091 {
4092 IScriptModule[] engines = Scene.RequestModuleInterfaces<IScriptModule>();
4093
4094 if (engines.Length == 0) // No engine at all
4095 return 0.0f;
4096
4097 float time = 0.0f;
4098
4099 // get all the scripts in all parts
4100 SceneObjectPart[] parts = m_parts.GetArray();
4101 List<TaskInventoryItem> scripts = new List<TaskInventoryItem>();
4102 for (int i = 0; i < parts.Length; i++)
4103 {
4104 scripts.AddRange(parts[i].Inventory.GetInventoryItems(InventoryType.LSL));
4105 }
4106 // extract the UUIDs
4107 List<UUID> ids = new List<UUID>(scripts.Count);
4108 foreach (TaskInventoryItem script in scripts)
4109 {
4110 if (!ids.Contains(script.ItemID))
4111 {
4112 ids.Add(script.ItemID);
4113 }
4114 }
4115 // Offer the list of script UUIDs to each engine found and accumulate the time
4116 foreach (IScriptModule e in engines)
4117 {
4118 if (e != null)
4119 {
4120 time += e.GetScriptExecutionTime(ids);
4121 }
4122 }
4123 return time;
4124 }
4125
4126 /// <summary>
4127 /// Returns a count of the number of running scripts in this groups parts.
4128 /// </summary>
4129 public int RunningScriptCount()
4130 {
4131 int count = 0;
4132 SceneObjectPart[] parts = m_parts.GetArray();
4133 for (int i = 0; i < parts.Length; i++)
4134 count += parts[i].Inventory.RunningScriptCount();
4135
4136 return count;
4137 }
4138
4055 public override string ToString() 4139 public override string ToString()
4056 { 4140 {
4057 return String.Format("{0} {1} ({2})", Name, UUID, AbsolutePosition); 4141 return String.Format("{0} {1} ({2})", Name, UUID, AbsolutePosition);
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index a2649ee..36cb09a 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -267,14 +267,9 @@ namespace OpenSim.Region.Framework.Scenes
267 /// </summary> 267 /// </summary>
268 public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource) 268 public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource)
269 { 269 {
270 Items.LockItemsForRead(true); 270 List<TaskInventoryItem> scripts = GetInventoryItems(InventoryType.LSL);
271 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values); 271 foreach (TaskInventoryItem item in scripts)
272 Items.LockItemsForRead(false); 272 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource);
273 foreach (TaskInventoryItem item in items)
274 {
275 if ((int)InventoryType.LSL == item.InvType)
276 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource);
277 }
278 } 273 }
279 274
280 public ArrayList GetScriptErrors(UUID itemID) 275 public ArrayList GetScriptErrors(UUID itemID)
@@ -305,17 +300,11 @@ namespace OpenSim.Region.Framework.Scenes
305 /// </param> 300 /// </param>
306 public void RemoveScriptInstances(bool sceneObjectBeingDeleted) 301 public void RemoveScriptInstances(bool sceneObjectBeingDeleted)
307 { 302 {
308 Items.LockItemsForRead(true); 303 List<TaskInventoryItem> scripts = GetInventoryItems(InventoryType.LSL);
309 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values); 304 foreach (TaskInventoryItem item in scripts)
310 Items.LockItemsForRead(false);
311
312 foreach (TaskInventoryItem item in items)
313 { 305 {
314 if ((int)InventoryType.LSL == item.InvType) 306 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted);
315 { 307 m_part.RemoveScriptEvents(item.ItemID);
316 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted);
317 m_part.RemoveScriptEvents(item.ItemID);
318 }
319 } 308 }
320 } 309 }
321 310
@@ -1280,9 +1269,57 @@ namespace OpenSim.Region.Framework.Scenes
1280 return true; 1269 return true;
1281 } 1270 }
1282 } 1271 }
1272
1283 return false; 1273 return false;
1284 } 1274 }
1285 1275
1276 /// <summary>
1277 /// Returns the count of scripts in this parts inventory.
1278 /// </summary>
1279 /// <returns></returns>
1280 public int ScriptCount()
1281 {
1282 int count = 0;
1283 Items.LockItemsForRead(true);
1284 foreach (TaskInventoryItem item in m_items.Values)
1285 {
1286 if (item.InvType == (int)InventoryType.LSL)
1287 {
1288 count++;
1289 }
1290 }
1291 Items.LockItemsForRead(false);
1292 return count;
1293 }
1294 /// <summary>
1295 /// Returns the count of running scripts in this parts inventory.
1296 /// </summary>
1297 /// <returns></returns>
1298 public int RunningScriptCount()
1299 {
1300 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
1301 if (engines.Length == 0)
1302 return 0;
1303
1304 int count = 0;
1305 List<TaskInventoryItem> scripts = GetInventoryItems(InventoryType.LSL);
1306
1307 foreach (TaskInventoryItem item in scripts)
1308 {
1309 foreach (IScriptModule engine in engines)
1310 {
1311 if (engine != null)
1312 {
1313 if (engine.GetScriptState(item.ItemID))
1314 {
1315 count++;
1316 }
1317 }
1318 }
1319 }
1320 return count;
1321 }
1322
1286 public List<UUID> GetInventoryList() 1323 public List<UUID> GetInventoryList()
1287 { 1324 {
1288 List<UUID> ret = new List<UUID>(); 1325 List<UUID> ret = new List<UUID>();
@@ -1297,22 +1334,24 @@ namespace OpenSim.Region.Framework.Scenes
1297 { 1334 {
1298 List<TaskInventoryItem> ret = new List<TaskInventoryItem>(); 1335 List<TaskInventoryItem> ret = new List<TaskInventoryItem>();
1299 1336
1300 lock (m_items) 1337 Items.LockItemsForRead(true);
1301 ret = new List<TaskInventoryItem>(m_items.Values); 1338 ret = new List<TaskInventoryItem>(m_items.Values);
1339 Items.LockItemsForRead(false);
1302 1340
1303 return ret; 1341 return ret;
1304 } 1342 }
1305 1343
1306 public List<TaskInventoryItem> GetInventoryScripts() 1344 public List<TaskInventoryItem> GetInventoryItems(InventoryType type)
1307 { 1345 {
1308 List<TaskInventoryItem> ret = new List<TaskInventoryItem>(); 1346 List<TaskInventoryItem> ret = new List<TaskInventoryItem>();
1309 1347
1310 lock (m_items) 1348 Items.LockItemsForRead(true);
1311 { 1349
1312 foreach (TaskInventoryItem item in m_items.Values) 1350 foreach (TaskInventoryItem item in m_items.Values)
1313 if (item.InvType == (int)InventoryType.LSL) 1351 if (item.InvType == (int)type)
1314 ret.Add(item); 1352 ret.Add(item);
1315 } 1353
1354 Items.LockItemsForRead(false);
1316 1355
1317 return ret; 1356 return ret;
1318 } 1357 }
@@ -1334,35 +1373,32 @@ namespace OpenSim.Region.Framework.Scenes
1334 if (engines.Length == 0) // No engine at all 1373 if (engines.Length == 0) // No engine at all
1335 return ret; 1374 return ret;
1336 1375
1337 Items.LockItemsForRead(true); 1376 List<TaskInventoryItem> scripts = GetInventoryItems(InventoryType.LSL);
1338 foreach (TaskInventoryItem item in m_items.Values) 1377
1378 foreach (TaskInventoryItem item in scripts)
1339 { 1379 {
1340 if (item.InvType == (int)InventoryType.LSL) 1380 foreach (IScriptModule e in engines)
1341 { 1381 {
1342 foreach (IScriptModule e in engines) 1382 if (e != null)
1343 { 1383 {
1344 if (e != null) 1384 string n = e.GetXMLState(item.ItemID);
1385 if (n != String.Empty)
1345 { 1386 {
1346 string n = e.GetXMLState(item.ItemID); 1387 if (oldIDs)
1347 if (n != String.Empty) 1388 {
1389 if (!ret.ContainsKey(item.OldItemID))
1390 ret[item.OldItemID] = n;
1391 }
1392 else
1348 { 1393 {
1349 if (oldIDs) 1394 if (!ret.ContainsKey(item.ItemID))
1350 { 1395 ret[item.ItemID] = n;
1351 if (!ret.ContainsKey(item.OldItemID))
1352 ret[item.OldItemID] = n;
1353 }
1354 else
1355 {
1356 if (!ret.ContainsKey(item.ItemID))
1357 ret[item.ItemID] = n;
1358 }
1359 break;
1360 } 1396 }
1397 break;
1361 } 1398 }
1362 } 1399 }
1363 } 1400 }
1364 } 1401 }
1365 Items.LockItemsForRead(false);
1366 return ret; 1402 return ret;
1367 } 1403 }
1368 1404
@@ -1372,27 +1408,21 @@ namespace OpenSim.Region.Framework.Scenes
1372 if (engines.Length == 0) 1408 if (engines.Length == 0)
1373 return; 1409 return;
1374 1410
1411 List<TaskInventoryItem> scripts = GetInventoryItems(InventoryType.LSL);
1375 1412
1376 Items.LockItemsForRead(true); 1413 foreach (TaskInventoryItem item in scripts)
1377
1378 foreach (TaskInventoryItem item in m_items.Values)
1379 { 1414 {
1380 if (item.InvType == (int)InventoryType.LSL) 1415 foreach (IScriptModule engine in engines)
1381 { 1416 {
1382 foreach (IScriptModule engine in engines) 1417 if (engine != null)
1383 { 1418 {
1384 if (engine != null) 1419 if (item.OwnerChanged)
1385 { 1420 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER });
1386 if (item.OwnerChanged) 1421 item.OwnerChanged = false;
1387 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER }); 1422 engine.ResumeScript(item.ItemID);
1388 item.OwnerChanged = false;
1389 engine.ResumeScript(item.ItemID);
1390 }
1391 } 1423 }
1392 } 1424 }
1393 } 1425 }
1394
1395 Items.LockItemsForRead(false);
1396 } 1426 }
1397 } 1427 }
1398} 1428}
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 1211792..ac791ae 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -3542,6 +3542,63 @@ namespace OpenSim.Region.Framework.Scenes
3542 return m_attachments.Count > 0; 3542 return m_attachments.Count > 0;
3543 } 3543 }
3544 3544
3545 /// <summary>
3546 /// Returns the total count of scripts in all parts inventories.
3547 /// </summary>
3548 public int ScriptCount()
3549 {
3550 int count = 0;
3551 lock (m_attachments)
3552 {
3553 foreach (SceneObjectGroup gobj in m_attachments)
3554 {
3555 if (gobj != null)
3556 {
3557 count += gobj.ScriptCount();
3558 }
3559 }
3560 }
3561 return count;
3562 }
3563
3564 /// <summary>
3565 /// A float the value is a representative execution time in milliseconds of all scripts in all attachments.
3566 /// </summary>
3567 public float ScriptExecutionTime()
3568 {
3569 float time = 0.0f;
3570 lock (m_attachments)
3571 {
3572 foreach (SceneObjectGroup gobj in m_attachments)
3573 {
3574 if (gobj != null)
3575 {
3576 time += gobj.ScriptExecutionTime();
3577 }
3578 }
3579 }
3580 return time;
3581 }
3582
3583 /// <summary>
3584 /// Returns the total count of running scripts in all parts.
3585 /// </summary>
3586 public int RunningScriptCount()
3587 {
3588 int count = 0;
3589 lock (m_attachments)
3590 {
3591 foreach (SceneObjectGroup gobj in m_attachments)
3592 {
3593 if (gobj != null)
3594 {
3595 count += gobj.RunningScriptCount();
3596 }
3597 }
3598 }
3599 return count;
3600 }
3601
3545 public bool HasScriptedAttachments() 3602 public bool HasScriptedAttachments()
3546 { 3603 {
3547 lock (m_attachments) 3604 lock (m_attachments)
@@ -3899,7 +3956,7 @@ namespace OpenSim.Region.Framework.Scenes
3899 land.LandData.UserLocation != Vector3.Zero && 3956 land.LandData.UserLocation != Vector3.Zero &&
3900 land.LandData.OwnerID != m_uuid && 3957 land.LandData.OwnerID != m_uuid &&
3901 (!m_scene.Permissions.IsGod(m_uuid)) && 3958 (!m_scene.Permissions.IsGod(m_uuid)) &&
3902 (!m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid))) 3959 (!m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_uuid)))
3903 { 3960 {
3904 float curr = Vector3.Distance(AbsolutePosition, pos); 3961 float curr = Vector3.Distance(AbsolutePosition, pos);
3905 if (Vector3.Distance(land.LandData.UserLocation, pos) < curr) 3962 if (Vector3.Distance(land.LandData.UserLocation, pos) < curr)
@@ -3919,7 +3976,7 @@ namespace OpenSim.Region.Framework.Scenes
3919 { 3976 {
3920 if (GodLevel < 200 && 3977 if (GodLevel < 200 &&
3921 ((!m_scene.Permissions.IsGod(m_uuid) && 3978 ((!m_scene.Permissions.IsGod(m_uuid) &&
3922 !m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid)) || 3979 !m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_uuid)) ||
3923 (m_teleportFlags & TeleportFlags.ViaLocation) != 0 || 3980 (m_teleportFlags & TeleportFlags.ViaLocation) != 0 ||
3924 (m_teleportFlags & Constants.TeleportFlags.ViaHGLogin) != 0)) 3981 (m_teleportFlags & Constants.TeleportFlags.ViaHGLogin) != 0))
3925 { 3982 {
@@ -3993,7 +4050,7 @@ namespace OpenSim.Region.Framework.Scenes
3993 GodLevel < 200 && 4050 GodLevel < 200 &&
3994 ((land.LandData.OwnerID != m_uuid && 4051 ((land.LandData.OwnerID != m_uuid &&
3995 !m_scene.Permissions.IsGod(m_uuid) && 4052 !m_scene.Permissions.IsGod(m_uuid) &&
3996 !m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid)) || 4053 !m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_uuid)) ||
3997 (m_teleportFlags & TeleportFlags.ViaLocation) != 0 || 4054 (m_teleportFlags & TeleportFlags.ViaLocation) != 0 ||
3998 (m_teleportFlags & Constants.TeleportFlags.ViaHGLogin) != 0)) 4055 (m_teleportFlags & Constants.TeleportFlags.ViaHGLogin) != 0))
3999 { 4056 {
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectSpatialTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectSpatialTests.cs
new file mode 100644
index 0000000..9fea3c6
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectSpatialTests.cs
@@ -0,0 +1,154 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Reflection;
30using System.Threading;
31using NUnit.Framework;
32using OpenMetaverse;
33using OpenSim.Framework;
34using OpenSim.Framework.Communications;
35using OpenSim.Region.Framework.Scenes;
36using OpenSim.Tests.Common;
37using OpenSim.Tests.Common.Mock;
38
39namespace OpenSim.Region.Framework.Scenes.Tests
40{
41 /// <summary>
42 /// Spatial scene object tests (will eventually cover root and child part position, rotation properties, etc.)
43 /// </summary>
44 [TestFixture]
45 public class SceneObjectSpatialTests
46 {
47 TestScene m_scene;
48 UUID m_ownerId = TestHelpers.ParseTail(0x1);
49
50 [SetUp]
51 public void SetUp()
52 {
53 m_scene = SceneHelpers.SetupScene();
54 }
55
56 [Test]
57 public void TestGetSceneObjectGroupPosition()
58 {
59 TestHelpers.InMethod();
60
61 Vector3 position = new Vector3(10, 20, 30);
62
63 SceneObjectGroup so
64 = SceneHelpers.CreateSceneObject(1, m_ownerId, "obj1", 0x10);
65 so.AbsolutePosition = position;
66 m_scene.AddNewSceneObject(so, false);
67
68 Assert.That(so.AbsolutePosition, Is.EqualTo(position));
69 }
70
71 [Test]
72 public void TestGetRootPartPosition()
73 {
74 TestHelpers.InMethod();
75
76 Vector3 partPosition = new Vector3(10, 20, 30);
77
78 SceneObjectGroup so
79 = SceneHelpers.CreateSceneObject(1, m_ownerId, "obj1", 0x10);
80 so.AbsolutePosition = partPosition;
81 m_scene.AddNewSceneObject(so, false);
82
83 Assert.That(so.RootPart.AbsolutePosition, Is.EqualTo(partPosition));
84 Assert.That(so.RootPart.GroupPosition, Is.EqualTo(partPosition));
85 Assert.That(so.RootPart.GetWorldPosition(), Is.EqualTo(partPosition));
86 Assert.That(so.RootPart.RelativePosition, Is.EqualTo(partPosition));
87 Assert.That(so.RootPart.OffsetPosition, Is.EqualTo(Vector3.Zero));
88 }
89
90 [Test]
91 public void TestGetChildPartPosition()
92 {
93 TestHelpers.InMethod();
94
95 Vector3 rootPartPosition = new Vector3(10, 20, 30);
96 Vector3 childOffsetPosition = new Vector3(2, 3, 4);
97
98 SceneObjectGroup so
99 = SceneHelpers.CreateSceneObject(2, m_ownerId, "obj1", 0x10);
100 so.AbsolutePosition = rootPartPosition;
101 so.Parts[1].OffsetPosition = childOffsetPosition;
102
103 m_scene.AddNewSceneObject(so, false);
104
105 // Calculate child absolute position.
106 Vector3 childPosition = new Vector3(rootPartPosition + childOffsetPosition);
107
108 SceneObjectPart childPart = so.Parts[1];
109 Assert.That(childPart.AbsolutePosition, Is.EqualTo(childPosition));
110 Assert.That(childPart.GroupPosition, Is.EqualTo(rootPartPosition));
111 Assert.That(childPart.GetWorldPosition(), Is.EqualTo(childPosition));
112 Assert.That(childPart.RelativePosition, Is.EqualTo(childOffsetPosition));
113 Assert.That(childPart.OffsetPosition, Is.EqualTo(childOffsetPosition));
114 }
115
116 [Test]
117 public void TestGetChildPartPositionAfterObjectRotation()
118 {
119 TestHelpers.InMethod();
120
121 Vector3 rootPartPosition = new Vector3(10, 20, 30);
122 Vector3 childOffsetPosition = new Vector3(2, 3, 4);
123
124 SceneObjectGroup so
125 = SceneHelpers.CreateSceneObject(2, m_ownerId, "obj1", 0x10);
126 so.AbsolutePosition = rootPartPosition;
127 so.Parts[1].OffsetPosition = childOffsetPosition;
128
129 m_scene.AddNewSceneObject(so, false);
130
131 so.UpdateGroupRotationR(Quaternion.CreateFromEulers(0, 0, -90 * Utils.DEG_TO_RAD));
132
133 // Calculate child absolute position.
134 Vector3 rotatedChildOffsetPosition
135 = new Vector3(childOffsetPosition.Y, -childOffsetPosition.X, childOffsetPosition.Z);
136
137 Vector3 childPosition = new Vector3(rootPartPosition + rotatedChildOffsetPosition);
138
139 SceneObjectPart childPart = so.Parts[1];
140
141 // FIXME: Should be childPosition after rotation?
142 Assert.That(childPart.AbsolutePosition, Is.EqualTo(rootPartPosition + childOffsetPosition));
143
144 Assert.That(childPart.GroupPosition, Is.EqualTo(rootPartPosition));
145 Assert.That(childPart.GetWorldPosition(), Is.EqualTo(childPosition));
146
147 // Relative to root part as (0, 0, 0)
148 Assert.That(childPart.RelativePosition, Is.EqualTo(childOffsetPosition));
149
150 // Relative to root part as (0, 0, 0)
151 Assert.That(childPart.OffsetPosition, Is.EqualTo(childOffsetPosition));
152 }
153 }
154} \ No newline at end of file
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStore.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStore.cs
new file mode 100644
index 0000000..34894ba
--- /dev/null
+++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStore.cs
@@ -0,0 +1,500 @@
1/*
2 * Copyright (c) Contributors
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using Mono.Addins;
28
29using System;
30using System.Reflection;
31using System.Threading;
32using System.Text;
33using System.Net;
34using System.Net.Sockets;
35using log4net;
36using Nini.Config;
37using OpenMetaverse;
38using OpenMetaverse.StructuredData;
39using OpenSim.Framework;
40using OpenSim.Region.Framework.Interfaces;
41using OpenSim.Region.Framework.Scenes;
42using System.Collections.Generic;
43using System.Text.RegularExpressions;
44
45namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
46{
47 public class JsonStore
48 {
49 private static readonly ILog m_log =
50 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51
52 private OSD m_ValueStore;
53
54 protected class TakeValueCallbackClass
55 {
56 public string Path { get; set; }
57 public bool UseJson { get; set; }
58 public TakeValueCallback Callback { get; set; }
59
60 public TakeValueCallbackClass(string spath, bool usejson, TakeValueCallback cback)
61 {
62 Path = spath;
63 UseJson = usejson;
64 Callback = cback;
65 }
66 }
67
68 protected List<TakeValueCallbackClass> m_TakeStore;
69 protected List<TakeValueCallbackClass> m_ReadStore;
70
71
72 // -----------------------------------------------------------------
73 /// <summary>
74 ///
75 /// </summary>
76 // -----------------------------------------------------------------
77 public JsonStore() : this("") {}
78
79 public JsonStore(string value)
80 {
81 m_TakeStore = new List<TakeValueCallbackClass>();
82 m_ReadStore = new List<TakeValueCallbackClass>();
83
84 if (String.IsNullOrEmpty(value))
85 m_ValueStore = new OSDMap();
86 else
87 m_ValueStore = OSDParser.DeserializeJson(value);
88 }
89
90 // -----------------------------------------------------------------
91 /// <summary>
92 ///
93 /// </summary>
94 // -----------------------------------------------------------------
95 public bool TestPath(string expr, bool useJson)
96 {
97 Stack<string> path = ParsePathExpression(expr);
98 OSD result = ProcessPathExpression(m_ValueStore,path);
99
100 if (result == null)
101 return false;
102
103 if (useJson || result.Type == OSDType.String)
104 return true;
105
106 return false;
107 }
108
109 // -----------------------------------------------------------------
110 /// <summary>
111 ///
112 /// </summary>
113 // -----------------------------------------------------------------
114 public bool GetValue(string expr, out string value, bool useJson)
115 {
116 Stack<string> path = ParsePathExpression(expr);
117 OSD result = ProcessPathExpression(m_ValueStore,path);
118 return ConvertOutputValue(result,out value,useJson);
119 }
120
121
122 // -----------------------------------------------------------------
123 /// <summary>
124 ///
125 /// </summary>
126 // -----------------------------------------------------------------
127 public bool RemoveValue(string expr)
128 {
129 return SetValueFromExpression(expr,null);
130 }
131
132 // -----------------------------------------------------------------
133 /// <summary>
134 ///
135 /// </summary>
136 // -----------------------------------------------------------------
137 public bool SetValue(string expr, string value, bool useJson)
138 {
139 OSD ovalue = useJson ? OSDParser.DeserializeJson(value) : new OSDString(value);
140 return SetValueFromExpression(expr,ovalue);
141 }
142
143 // -----------------------------------------------------------------
144 /// <summary>
145 ///
146 /// </summary>
147 // -----------------------------------------------------------------
148 public bool TakeValue(string expr, bool useJson, TakeValueCallback cback)
149 {
150 Stack<string> path = ParsePathExpression(expr);
151 string pexpr = PathExpressionToKey(path);
152
153 OSD result = ProcessPathExpression(m_ValueStore,path);
154 if (result == null)
155 {
156 m_TakeStore.Add(new TakeValueCallbackClass(pexpr,useJson,cback));
157 return false;
158 }
159
160 string value = String.Empty;
161 if (! ConvertOutputValue(result,out value,useJson))
162 {
163 // the structure does not match the request so i guess we'll wait
164 m_TakeStore.Add(new TakeValueCallbackClass(pexpr,useJson,cback));
165 return false;
166 }
167
168 SetValueFromExpression(expr,null);
169 cback(value);
170
171 return true;
172 }
173
174 // -----------------------------------------------------------------
175 /// <summary>
176 ///
177 /// </summary>
178 // -----------------------------------------------------------------
179 public bool ReadValue(string expr, bool useJson, TakeValueCallback cback)
180 {
181 Stack<string> path = ParsePathExpression(expr);
182 string pexpr = PathExpressionToKey(path);
183
184 OSD result = ProcessPathExpression(m_ValueStore,path);
185 if (result == null)
186 {
187 m_ReadStore.Add(new TakeValueCallbackClass(pexpr,useJson,cback));
188 return false;
189 }
190
191 string value = String.Empty;
192 if (! ConvertOutputValue(result,out value,useJson))
193 {
194 // the structure does not match the request so i guess we'll wait
195 m_ReadStore.Add(new TakeValueCallbackClass(pexpr,useJson,cback));
196 return false;
197 }
198
199 cback(value);
200
201 return true;
202 }
203
204 // -----------------------------------------------------------------
205 /// <summary>
206 ///
207 /// </summary>
208 // -----------------------------------------------------------------
209 protected bool SetValueFromExpression(string expr, OSD ovalue)
210 {
211 Stack<string> path = ParsePathExpression(expr);
212 if (path.Count == 0)
213 {
214 m_ValueStore = ovalue;
215 return true;
216 }
217
218 string pkey = path.Pop();
219 string pexpr = PathExpressionToKey(path);
220 if (pexpr != "")
221 pexpr += ".";
222
223 OSD result = ProcessPathExpression(m_ValueStore,path);
224 if (result == null)
225 return false;
226
227 Regex aPattern = new Regex("\\[([0-9]+|\\+)\\]");
228 MatchCollection amatches = aPattern.Matches(pkey,0);
229
230 if (amatches.Count > 0)
231 {
232 if (result.Type != OSDType.Array)
233 return false;
234
235 OSDArray amap = result as OSDArray;
236
237 Match match = amatches[0];
238 GroupCollection groups = match.Groups;
239 string akey = groups[1].Value;
240
241 if (akey == "+")
242 {
243 string npkey = String.Format("[{0}]",amap.Count);
244
245 amap.Add(ovalue);
246 InvokeNextCallback(pexpr + npkey);
247 return true;
248 }
249
250 int aval = Convert.ToInt32(akey);
251 if (0 <= aval && aval < amap.Count)
252 {
253 if (ovalue == null)
254 amap.RemoveAt(aval);
255 else
256 {
257 amap[aval] = ovalue;
258 InvokeNextCallback(pexpr + pkey);
259 }
260 return true;
261 }
262
263 return false;
264 }
265
266 Regex hPattern = new Regex("{([^}]+)}");
267 MatchCollection hmatches = hPattern.Matches(pkey,0);
268
269 if (hmatches.Count > 0)
270 {
271 Match match = hmatches[0];
272 GroupCollection groups = match.Groups;
273 string hkey = groups[1].Value;
274
275 if (result is OSDMap)
276 {
277 OSDMap hmap = result as OSDMap;
278 if (ovalue != null)
279 {
280 hmap[hkey] = ovalue;
281 InvokeNextCallback(pexpr + pkey);
282 }
283 else if (hmap.ContainsKey(hkey))
284 hmap.Remove(hkey);
285
286 return true;
287 }
288
289 return false;
290 }
291
292 // Shouldn't get here if the path was checked correctly
293 m_log.WarnFormat("[JsonStore] invalid path expression");
294 return false;
295 }
296
297 // -----------------------------------------------------------------
298 /// <summary>
299 ///
300 /// </summary>
301 // -----------------------------------------------------------------
302 protected bool InvokeNextCallback(string pexpr)
303 {
304 // Process all of the reads that match the expression first
305 List<TakeValueCallbackClass> reads =
306 m_ReadStore.FindAll(delegate(TakeValueCallbackClass tb) { return pexpr.StartsWith(tb.Path); });
307
308 foreach (TakeValueCallbackClass readcb in reads)
309 {
310 m_ReadStore.Remove(readcb);
311 ReadValue(readcb.Path,readcb.UseJson,readcb.Callback);
312 }
313
314 // Process one take next
315 TakeValueCallbackClass takecb =
316 m_TakeStore.Find(delegate(TakeValueCallbackClass tb) { return pexpr.StartsWith(tb.Path); });
317
318 if (takecb != null)
319 {
320 m_TakeStore.Remove(takecb);
321 TakeValue(takecb.Path,takecb.UseJson,takecb.Callback);
322
323 return true;
324 }
325
326 return false;
327 }
328
329 // -----------------------------------------------------------------
330 /// <summary>
331 /// Parse the path expression and put the components into a stack. We
332 /// use a stack because we process the path in inverse order later
333 /// </summary>
334 // -----------------------------------------------------------------
335 protected static Stack<string> ParsePathExpression(string path)
336 {
337 Stack<string> m_path = new Stack<string>();
338
339 // add front and rear separators
340 path = "." + path + ".";
341
342 // add separators for quoted paths
343 Regex pass1 = new Regex("{[^}]+}");
344 path = pass1.Replace(path,".$0.",-1,0);
345
346 // add separators for array references
347 Regex pass2 = new Regex("(\\[[0-9]+\\]|\\[\\+\\])");
348 path = pass2.Replace(path,".$0.",-1,0);
349
350 // add quotes to bare identifier
351 Regex pass3 = new Regex("\\.([a-zA-Z]+)");
352 path = pass3.Replace(path,".{$1}",-1,0);
353
354 // remove extra separators
355 Regex pass4 = new Regex("\\.+");
356 path = pass4.Replace(path,".",-1,0);
357
358 Regex validate = new Regex("^\\.(({[^}]+}|\\[[0-9]+\\]|\\[\\+\\])\\.)+$");
359 if (validate.IsMatch(path))
360 {
361 Regex parser = new Regex("\\.({[^}]+}|\\[[0-9]+\\]|\\[\\+\\]+)");
362 MatchCollection matches = parser.Matches(path,0);
363 foreach (Match match in matches)
364 m_path.Push(match.Groups[1].Value);
365 }
366
367 return m_path;
368 }
369
370 // -----------------------------------------------------------------
371 /// <summary>
372 ///
373 /// </summary>
374 /// <param>path is a stack where the top level of the path is at the bottom of the stack</param>
375 // -----------------------------------------------------------------
376 protected static OSD ProcessPathExpression(OSD map, Stack<string> path)
377 {
378 if (path.Count == 0)
379 return map;
380
381 string pkey = path.Pop();
382
383 OSD rmap = ProcessPathExpression(map,path);
384 if (rmap == null)
385 return null;
386
387 // ---------- Check for an array index ----------
388 Regex aPattern = new Regex("\\[([0-9]+)\\]");
389 MatchCollection amatches = aPattern.Matches(pkey,0);
390
391 if (amatches.Count > 0)
392 {
393 if (rmap.Type != OSDType.Array)
394 {
395 m_log.WarnFormat("[JsonStore] wrong type for key {2}, expecting {0}, got {1}",OSDType.Array,rmap.Type,pkey);
396 return null;
397 }
398
399 OSDArray amap = rmap as OSDArray;
400
401 Match match = amatches[0];
402 GroupCollection groups = match.Groups;
403 string akey = groups[1].Value;
404 int aval = Convert.ToInt32(akey);
405
406 if (aval < amap.Count)
407 return (OSD) amap[aval];
408
409 return null;
410 }
411
412 // ---------- Check for a hash index ----------
413 Regex hPattern = new Regex("{([^}]+)}");
414 MatchCollection hmatches = hPattern.Matches(pkey,0);
415
416 if (hmatches.Count > 0)
417 {
418 if (rmap.Type != OSDType.Map)
419 {
420 m_log.WarnFormat("[JsonStore] wrong type for key {2}, expecting {0}, got {1}",OSDType.Map,rmap.Type,pkey);
421 return null;
422 }
423
424 OSDMap hmap = rmap as OSDMap;
425
426 Match match = hmatches[0];
427 GroupCollection groups = match.Groups;
428 string hkey = groups[1].Value;
429
430 if (hmap.ContainsKey(hkey))
431 return (OSD) hmap[hkey];
432
433 return null;
434 }
435
436 // Shouldn't get here if the path was checked correctly
437 m_log.WarnFormat("[JsonStore] Path type (unknown) does not match the structure");
438 return null;
439 }
440
441 // -----------------------------------------------------------------
442 /// <summary>
443 ///
444 /// </summary>
445 // -----------------------------------------------------------------
446 protected static bool ConvertOutputValue(OSD result, out string value, bool useJson)
447 {
448 value = String.Empty;
449
450 // If we couldn't process the path
451 if (result == null)
452 return false;
453
454 if (useJson)
455 {
456 // The path pointed to an intermediate hash structure
457 if (result.Type == OSDType.Map)
458 {
459 value = OSDParser.SerializeJsonString(result as OSDMap);
460 return true;
461 }
462
463 // The path pointed to an intermediate hash structure
464 if (result.Type == OSDType.Array)
465 {
466 value = OSDParser.SerializeJsonString(result as OSDArray);
467 return true;
468 }
469
470 value = "'" + result.AsString() + "'";
471 return true;
472 }
473
474 if (result.Type == OSDType.String)
475 {
476 value = result.AsString();
477 return true;
478 }
479
480 return false;
481 }
482
483 // -----------------------------------------------------------------
484 /// <summary>
485 ///
486 /// </summary>
487 // -----------------------------------------------------------------
488 protected static string PathExpressionToKey(Stack<string> path)
489 {
490 if (path.Count == 0)
491 return "";
492
493 string pkey = "";
494 foreach (string k in path)
495 pkey = (pkey == "") ? k : (k + "." + pkey);
496
497 return pkey;
498 }
499 }
500}
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs
new file mode 100644
index 0000000..311531c
--- /dev/null
+++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs
@@ -0,0 +1,430 @@
1/*
2 * Copyright (c) Contributors
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using Mono.Addins;
28
29using System;
30using System.Reflection;
31using System.Threading;
32using System.Text;
33using System.Net;
34using System.Net.Sockets;
35using log4net;
36using Nini.Config;
37using OpenMetaverse;
38using OpenMetaverse.StructuredData;
39using OpenSim.Framework;
40using OpenSim.Region.Framework.Interfaces;
41using OpenSim.Region.Framework.Scenes;
42using System.Collections.Generic;
43using System.Text.RegularExpressions;
44
45
46namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
47{
48 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "JsonStoreModule")]
49
50 public class JsonStoreModule : INonSharedRegionModule, IJsonStoreModule
51 {
52 private static readonly ILog m_log =
53 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
54
55 private IConfig m_config = null;
56 private bool m_enabled = false;
57 private Scene m_scene = null;
58
59 private Dictionary<UUID,JsonStore> m_JsonValueStore;
60 private UUID m_sharedStore;
61
62#region IRegionModule Members
63
64 // -----------------------------------------------------------------
65 /// <summary>
66 /// Name of this shared module is it's class name
67 /// </summary>
68 // -----------------------------------------------------------------
69 public string Name
70 {
71 get { return this.GetType().Name; }
72 }
73
74 // -----------------------------------------------------------------
75 /// <summary>
76 /// Initialise this shared module
77 /// </summary>
78 /// <param name="scene">this region is getting initialised</param>
79 /// <param name="source">nini config, we are not using this</param>
80 // -----------------------------------------------------------------
81 public void Initialise(IConfigSource config)
82 {
83 try
84 {
85 if ((m_config = config.Configs["JsonStore"]) == null)
86 {
87 // There is no configuration, the module is disabled
88 // m_log.InfoFormat("[JsonStore] no configuration info");
89 return;
90 }
91
92 m_enabled = m_config.GetBoolean("Enabled", m_enabled);
93 }
94 catch (Exception e)
95 {
96 m_log.ErrorFormat("[JsonStore] initialization error: {0}",e.Message);
97 return;
98 }
99
100 if (m_enabled)
101 m_log.DebugFormat("[JsonStore] module is enabled");
102 }
103
104 // -----------------------------------------------------------------
105 /// <summary>
106 /// everything is loaded, perform post load configuration
107 /// </summary>
108 // -----------------------------------------------------------------
109 public void PostInitialise()
110 {
111 }
112
113 // -----------------------------------------------------------------
114 /// <summary>
115 /// Nothing to do on close
116 /// </summary>
117 // -----------------------------------------------------------------
118 public void Close()
119 {
120 }
121
122 // -----------------------------------------------------------------
123 /// <summary>
124 /// </summary>
125 // -----------------------------------------------------------------
126 public void AddRegion(Scene scene)
127 {
128 if (m_enabled)
129 {
130 m_scene = scene;
131 m_scene.RegisterModuleInterface<IJsonStoreModule>(this);
132
133 m_sharedStore = UUID.Zero;
134 m_JsonValueStore = new Dictionary<UUID,JsonStore>();
135 m_JsonValueStore.Add(m_sharedStore,new JsonStore(""));
136 }
137 }
138
139 // -----------------------------------------------------------------
140 /// <summary>
141 /// </summary>
142 // -----------------------------------------------------------------
143 public void RemoveRegion(Scene scene)
144 {
145 // need to remove all references to the scene in the subscription
146 // list to enable full garbage collection of the scene object
147 }
148
149 // -----------------------------------------------------------------
150 /// <summary>
151 /// Called when all modules have been added for a region. This is
152 /// where we hook up events
153 /// </summary>
154 // -----------------------------------------------------------------
155 public void RegionLoaded(Scene scene)
156 {
157 if (m_enabled) {}
158 }
159
160 /// -----------------------------------------------------------------
161 /// <summary>
162 /// </summary>
163 // -----------------------------------------------------------------
164 public Type ReplaceableInterface
165 {
166 get { return null; }
167 }
168
169#endregion
170
171#region ScriptInvocationInteface
172
173 // -----------------------------------------------------------------
174 /// <summary>
175 ///
176 /// </summary>
177 // -----------------------------------------------------------------
178 public bool CreateStore(string value, out UUID result)
179 {
180 result = UUID.Zero;
181
182 if (! m_enabled) return false;
183
184 UUID uuid = UUID.Random();
185 JsonStore map = null;
186
187 try
188 {
189 map = new JsonStore(value);
190 }
191 catch (Exception e)
192 {
193 m_log.InfoFormat("[JsonStore] Unable to initialize store from {0}; {1}",value,e.Message);
194 return false;
195 }
196
197 lock (m_JsonValueStore)
198 m_JsonValueStore.Add(uuid,map);
199
200 result = uuid;
201 return true;
202 }
203
204 // -----------------------------------------------------------------
205 /// <summary>
206 ///
207 /// </summary>
208 // -----------------------------------------------------------------
209 public bool DestroyStore(UUID storeID)
210 {
211 if (! m_enabled) return false;
212
213 lock (m_JsonValueStore)
214 m_JsonValueStore.Remove(storeID);
215
216 return true;
217 }
218
219 // -----------------------------------------------------------------
220 /// <summary>
221 ///
222 /// </summary>
223 // -----------------------------------------------------------------
224 public bool TestPath(UUID storeID, string path, bool useJson)
225 {
226 if (! m_enabled) return false;
227
228 JsonStore map = null;
229 lock (m_JsonValueStore)
230 {
231 if (! m_JsonValueStore.TryGetValue(storeID,out map))
232 {
233 m_log.InfoFormat("[JsonStore] Missing store {0}",storeID);
234 return true;
235 }
236 }
237
238 try
239 {
240 lock (map)
241 return map.TestPath(path,useJson);
242 }
243 catch (Exception e)
244 {
245 m_log.InfoFormat("[JsonStore] Path test failed for {0} in {1}; {2}",path,storeID,e.Message);
246 }
247
248 return false;
249 }
250
251 // -----------------------------------------------------------------
252 /// <summary>
253 ///
254 /// </summary>
255 // -----------------------------------------------------------------
256 public bool SetValue(UUID storeID, string path, string value, bool useJson)
257 {
258 if (! m_enabled) return false;
259
260 JsonStore map = null;
261 lock (m_JsonValueStore)
262 {
263 if (! m_JsonValueStore.TryGetValue(storeID,out map))
264 {
265 m_log.InfoFormat("[JsonStore] Missing store {0}",storeID);
266 return false;
267 }
268 }
269
270 try
271 {
272 lock (map)
273 if (map.SetValue(path,value,useJson))
274 return true;
275 }
276 catch (Exception e)
277 {
278 m_log.InfoFormat("[JsonStore] Unable to assign {0} to {1} in {2}; {3}",value,path,storeID,e.Message);
279 }
280
281 return false;
282 }
283
284 // -----------------------------------------------------------------
285 /// <summary>
286 ///
287 /// </summary>
288 // -----------------------------------------------------------------
289 public bool RemoveValue(UUID storeID, string path)
290 {
291 if (! m_enabled) return false;
292
293 JsonStore map = null;
294 lock (m_JsonValueStore)
295 {
296 if (! m_JsonValueStore.TryGetValue(storeID,out map))
297 {
298 m_log.InfoFormat("[JsonStore] Missing store {0}",storeID);
299 return false;
300 }
301 }
302
303 try
304 {
305 lock (map)
306 if (map.RemoveValue(path))
307 return true;
308 }
309 catch (Exception e)
310 {
311 m_log.InfoFormat("[JsonStore] Unable to remove {0} in {1}; {2}",path,storeID,e.Message);
312 }
313
314 return false;
315 }
316
317 // -----------------------------------------------------------------
318 /// <summary>
319 ///
320 /// </summary>
321 // -----------------------------------------------------------------
322 public bool GetValue(UUID storeID, string path, bool useJson, out string value)
323 {
324 value = String.Empty;
325
326 if (! m_enabled) return false;
327
328 JsonStore map = null;
329 lock (m_JsonValueStore)
330 {
331 if (! m_JsonValueStore.TryGetValue(storeID,out map))
332 return false;
333 }
334
335 try
336 {
337 lock (map)
338 {
339 return map.GetValue(path, out value, useJson);
340 }
341 }
342 catch (Exception e)
343 {
344 m_log.InfoFormat("[JsonStore] unable to retrieve value; {0}",e.Message);
345 }
346
347 return false;
348 }
349
350 // -----------------------------------------------------------------
351 /// <summary>
352 ///
353 /// </summary>
354 // -----------------------------------------------------------------
355 public void TakeValue(UUID storeID, string path, bool useJson, TakeValueCallback cback)
356 {
357 if (! m_enabled)
358 {
359 cback(String.Empty);
360 return;
361 }
362
363 JsonStore map = null;
364 lock (m_JsonValueStore)
365 {
366 if (! m_JsonValueStore.TryGetValue(storeID,out map))
367 {
368 cback(String.Empty);
369 return;
370 }
371 }
372
373 try
374 {
375 lock (map)
376 {
377 map.TakeValue(path, useJson, cback);
378 return;
379 }
380 }
381 catch (Exception e)
382 {
383 m_log.InfoFormat("[JsonStore] unable to retrieve value; {0}",e.ToString());
384 }
385
386 cback(String.Empty);
387 }
388
389 // -----------------------------------------------------------------
390 /// <summary>
391 ///
392 /// </summary>
393 // -----------------------------------------------------------------
394 public void ReadValue(UUID storeID, string path, bool useJson, TakeValueCallback cback)
395 {
396 if (! m_enabled)
397 {
398 cback(String.Empty);
399 return;
400 }
401
402 JsonStore map = null;
403 lock (m_JsonValueStore)
404 {
405 if (! m_JsonValueStore.TryGetValue(storeID,out map))
406 {
407 cback(String.Empty);
408 return;
409 }
410 }
411
412 try
413 {
414 lock (map)
415 {
416 map.ReadValue(path, useJson, cback);
417 return;
418 }
419 }
420 catch (Exception e)
421 {
422 m_log.InfoFormat("[JsonStore] unable to retrieve value; {0}",e.ToString());
423 }
424
425 cback(String.Empty);
426 }
427
428#endregion
429 }
430}
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs
new file mode 100644
index 0000000..eda2aef
--- /dev/null
+++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs
@@ -0,0 +1,490 @@
1/*
2 * Copyright (c) Contributors
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using Mono.Addins;
28
29using System;
30using System.Reflection;
31using System.Threading;
32using System.Text;
33using System.Net;
34using System.Net.Sockets;
35using log4net;
36using Nini.Config;
37using OpenMetaverse;
38using OpenMetaverse.StructuredData;
39using OpenSim.Framework;
40using OpenSim.Region.Framework.Interfaces;
41using OpenSim.Region.Framework.Scenes;
42using System.Collections.Generic;
43using System.Text.RegularExpressions;
44
45namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
46{
47 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "JsonStoreScriptModule")]
48
49 public class JsonStoreScriptModule : INonSharedRegionModule
50 {
51 private static readonly ILog m_log =
52 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53
54 private IConfig m_config = null;
55 private bool m_enabled = false;
56 private Scene m_scene = null;
57
58 private IScriptModuleComms m_comms;
59 private IJsonStoreModule m_store;
60
61#region IRegionModule Members
62
63 // -----------------------------------------------------------------
64 /// <summary>
65 /// Name of this shared module is it's class name
66 /// </summary>
67 // -----------------------------------------------------------------
68 public string Name
69 {
70 get { return this.GetType().Name; }
71 }
72
73 // -----------------------------------------------------------------
74 /// <summary>
75 /// Initialise this shared module
76 /// </summary>
77 /// <param name="scene">this region is getting initialised</param>
78 /// <param name="source">nini config, we are not using this</param>
79 // -----------------------------------------------------------------
80 public void Initialise(IConfigSource config)
81 {
82 try
83 {
84 if ((m_config = config.Configs["JsonStore"]) == null)
85 {
86 // There is no configuration, the module is disabled
87 // m_log.InfoFormat("[JsonStoreScripts] no configuration info");
88 return;
89 }
90
91 m_enabled = m_config.GetBoolean("Enabled", m_enabled);
92 }
93 catch (Exception e)
94 {
95 m_log.ErrorFormat("[JsonStoreScripts] initialization error: {0}",e.Message);
96 return;
97 }
98
99 if (m_enabled)
100 m_log.DebugFormat("[JsonStoreScripts] module is enabled");
101 }
102
103 // -----------------------------------------------------------------
104 /// <summary>
105 /// everything is loaded, perform post load configuration
106 /// </summary>
107 // -----------------------------------------------------------------
108 public void PostInitialise()
109 {
110 }
111
112 // -----------------------------------------------------------------
113 /// <summary>
114 /// Nothing to do on close
115 /// </summary>
116 // -----------------------------------------------------------------
117 public void Close()
118 {
119 }
120
121 // -----------------------------------------------------------------
122 /// <summary>
123 /// </summary>
124 // -----------------------------------------------------------------
125 public void AddRegion(Scene scene)
126 {
127 }
128
129 // -----------------------------------------------------------------
130 /// <summary>
131 /// </summary>
132 // -----------------------------------------------------------------
133 public void RemoveRegion(Scene scene)
134 {
135 // need to remove all references to the scene in the subscription
136 // list to enable full garbage collection of the scene object
137 }
138
139 // -----------------------------------------------------------------
140 /// <summary>
141 /// Called when all modules have been added for a region. This is
142 /// where we hook up events
143 /// </summary>
144 // -----------------------------------------------------------------
145 public void RegionLoaded(Scene scene)
146 {
147 if (m_enabled)
148 {
149 m_scene = scene;
150 m_comms = m_scene.RequestModuleInterface<IScriptModuleComms>();
151 if (m_comms == null)
152 {
153 m_log.ErrorFormat("[JsonStoreScripts] ScriptModuleComms interface not defined");
154 m_enabled = false;
155 return;
156 }
157
158 m_store = m_scene.RequestModuleInterface<IJsonStoreModule>();
159 if (m_store == null)
160 {
161 m_log.ErrorFormat("[JsonStoreScripts] JsonModule interface not defined");
162 m_enabled = false;
163 return;
164 }
165
166 m_comms.RegisterScriptInvocation(this,"JsonCreateStore");
167 m_comms.RegisterScriptInvocation(this,"JsonDestroyStore");
168
169 m_comms.RegisterScriptInvocation(this,"JsonReadNotecard");
170 m_comms.RegisterScriptInvocation(this,"JsonWriteNotecard");
171
172 m_comms.RegisterScriptInvocation(this,"JsonTestPath");
173 m_comms.RegisterScriptInvocation(this,"JsonTestPathJson");
174
175 m_comms.RegisterScriptInvocation(this,"JsonGetValue");
176 m_comms.RegisterScriptInvocation(this,"JsonGetValueJson");
177
178 m_comms.RegisterScriptInvocation(this,"JsonTakeValue");
179 m_comms.RegisterScriptInvocation(this,"JsonTakeValueJson");
180
181 m_comms.RegisterScriptInvocation(this,"JsonReadValue");
182 m_comms.RegisterScriptInvocation(this,"JsonReadValueJson");
183
184 m_comms.RegisterScriptInvocation(this,"JsonSetValue");
185 m_comms.RegisterScriptInvocation(this,"JsonSetValueJson");
186
187 m_comms.RegisterScriptInvocation(this,"JsonRemoveValue");
188 }
189 }
190
191 /// -----------------------------------------------------------------
192 /// <summary>
193 /// </summary>
194 // -----------------------------------------------------------------
195 public Type ReplaceableInterface
196 {
197 get { return null; }
198 }
199
200#endregion
201
202#region ScriptInvocationInteface
203 // -----------------------------------------------------------------
204 /// <summary>
205 ///
206 /// </summary>
207 // -----------------------------------------------------------------
208 protected void GenerateRuntimeError(string msg)
209 {
210 throw new Exception("JsonStore Runtime Error: " + msg);
211 }
212
213 // -----------------------------------------------------------------
214 /// <summary>
215 ///
216 /// </summary>
217 // -----------------------------------------------------------------
218 protected UUID JsonCreateStore(UUID hostID, UUID scriptID, string value)
219 {
220 UUID uuid = UUID.Zero;
221 if (! m_store.CreateStore(value, out uuid))
222 GenerateRuntimeError("Failed to create Json store");
223
224 return uuid;
225 }
226
227 // -----------------------------------------------------------------
228 /// <summary>
229 ///
230 /// </summary>
231 // -----------------------------------------------------------------
232 protected int JsonDestroyStore(UUID hostID, UUID scriptID, UUID storeID)
233 {
234 return m_store.DestroyStore(storeID) ? 1 : 0;
235 }
236
237 // -----------------------------------------------------------------
238 /// <summary>
239 ///
240 /// </summary>
241 // -----------------------------------------------------------------
242 protected UUID JsonReadNotecard(UUID hostID, UUID scriptID, UUID storeID, string path, UUID assetID)
243 {
244 UUID reqID = UUID.Random();
245 Util.FireAndForget(delegate(object o) { DoJsonReadNotecard(reqID,hostID,scriptID,storeID,path,assetID); });
246 return reqID;
247 }
248
249 // -----------------------------------------------------------------
250 /// <summary>
251 ///
252 /// </summary>
253 // -----------------------------------------------------------------
254 protected UUID JsonWriteNotecard(UUID hostID, UUID scriptID, UUID storeID, string path, string name)
255 {
256 UUID reqID = UUID.Random();
257 Util.FireAndForget(delegate(object o) { DoJsonWriteNotecard(reqID,hostID,scriptID,storeID,path,name); });
258 return reqID;
259 }
260
261 // -----------------------------------------------------------------
262 /// <summary>
263 ///
264 /// </summary>
265 // -----------------------------------------------------------------
266 protected int JsonTestPath(UUID hostID, UUID scriptID, UUID storeID, string path)
267 {
268 return m_store.TestPath(storeID,path,false) ? 1 : 0;
269 }
270
271 protected int JsonTestPathJson(UUID hostID, UUID scriptID, UUID storeID, string path)
272 {
273 return m_store.TestPath(storeID,path,true) ? 1 : 0;
274 }
275
276 // -----------------------------------------------------------------
277 /// <summary>
278 ///
279 /// </summary>
280 // -----------------------------------------------------------------
281 protected int JsonSetValue(UUID hostID, UUID scriptID, UUID storeID, string path, string value)
282 {
283 return m_store.SetValue(storeID,path,value,false) ? 1 : 0;
284 }
285
286 protected int JsonSetValueJson(UUID hostID, UUID scriptID, UUID storeID, string path, string value)
287 {
288 return m_store.SetValue(storeID,path,value,true) ? 1 : 0;
289 }
290
291 // -----------------------------------------------------------------
292 /// <summary>
293 ///
294 /// </summary>
295 // -----------------------------------------------------------------
296 protected int JsonRemoveValue(UUID hostID, UUID scriptID, UUID storeID, string path)
297 {
298 return m_store.RemoveValue(storeID,path) ? 1 : 0;
299 }
300
301 // -----------------------------------------------------------------
302 /// <summary>
303 ///
304 /// </summary>
305 // -----------------------------------------------------------------
306 protected string JsonGetValue(UUID hostID, UUID scriptID, UUID storeID, string path)
307 {
308 string value = String.Empty;
309 m_store.GetValue(storeID,path,false,out value);
310 return value;
311 }
312
313 protected string JsonGetValueJson(UUID hostID, UUID scriptID, UUID storeID, string path)
314 {
315 string value = String.Empty;
316 m_store.GetValue(storeID,path,true, out value);
317 return value;
318 }
319
320 // -----------------------------------------------------------------
321 /// <summary>
322 ///
323 /// </summary>
324 // -----------------------------------------------------------------
325 protected UUID JsonTakeValue(UUID hostID, UUID scriptID, UUID storeID, string path)
326 {
327 UUID reqID = UUID.Random();
328 Util.FireAndForget(delegate(object o) { DoJsonTakeValue(scriptID,reqID,storeID,path,false); });
329 return reqID;
330 }
331
332 protected UUID JsonTakeValueJson(UUID hostID, UUID scriptID, UUID storeID, string path)
333 {
334 UUID reqID = UUID.Random();
335 Util.FireAndForget(delegate(object o) { DoJsonTakeValue(scriptID,reqID,storeID,path,true); });
336 return reqID;
337 }
338
339 private void DoJsonTakeValue(UUID scriptID, UUID reqID, UUID storeID, string path, bool useJson)
340 {
341 try
342 {
343 m_store.TakeValue(storeID,path,useJson,delegate(string value) { DispatchValue(scriptID,reqID,value); });
344 return;
345 }
346 catch (Exception e)
347 {
348 m_log.InfoFormat("[JsonStoreScripts] unable to retrieve value; {0}",e.ToString());
349 }
350
351 DispatchValue(scriptID,reqID,String.Empty);
352 }
353
354
355 // -----------------------------------------------------------------
356 /// <summary>
357 ///
358 /// </summary>
359 // -----------------------------------------------------------------
360 protected UUID JsonReadValue(UUID hostID, UUID scriptID, UUID storeID, string path)
361 {
362 UUID reqID = UUID.Random();
363 Util.FireAndForget(delegate(object o) { DoJsonReadValue(scriptID,reqID,storeID,path,false); });
364 return reqID;
365 }
366
367 protected UUID JsonReadValueJson(UUID hostID, UUID scriptID, UUID storeID, string path)
368 {
369 UUID reqID = UUID.Random();
370 Util.FireAndForget(delegate(object o) { DoJsonReadValue(scriptID,reqID,storeID,path,true); });
371 return reqID;
372 }
373
374 private void DoJsonReadValue(UUID scriptID, UUID reqID, UUID storeID, string path, bool useJson)
375 {
376 try
377 {
378 m_store.ReadValue(storeID,path,useJson,delegate(string value) { DispatchValue(scriptID,reqID,value); });
379 return;
380 }
381 catch (Exception e)
382 {
383 m_log.InfoFormat("[JsonStoreScripts] unable to retrieve value; {0}",e.ToString());
384 }
385
386 DispatchValue(scriptID,reqID,String.Empty);
387 }
388
389#endregion
390
391 // -----------------------------------------------------------------
392 /// <summary>
393 ///
394 /// </summary>
395 // -----------------------------------------------------------------
396 protected void DispatchValue(UUID scriptID, UUID reqID, string value)
397 {
398 m_comms.DispatchReply(scriptID,1,value,reqID.ToString());
399 }
400
401 // -----------------------------------------------------------------
402 /// <summary>
403 ///
404 /// </summary>
405 // -----------------------------------------------------------------
406 private void DoJsonReadNotecard(UUID reqID, UUID hostID, UUID scriptID, UUID storeID, string path, UUID assetID)
407 {
408 AssetBase a = m_scene.AssetService.Get(assetID.ToString());
409 if (a == null)
410 GenerateRuntimeError(String.Format("Unable to find notecard asset {0}",assetID));
411
412 if (a.Type != (sbyte)AssetType.Notecard)
413 GenerateRuntimeError(String.Format("Invalid notecard asset {0}",assetID));
414
415 m_log.DebugFormat("[JsonStoreScripts] read notecard in context {0}",storeID);
416
417 try
418 {
419 System.Text.UTF8Encoding enc = new System.Text.UTF8Encoding();
420 string jsondata = SLUtil.ParseNotecardToString(enc.GetString(a.Data));
421 int result = m_store.SetValue(storeID,path,jsondata,true) ? 1 : 0;
422 m_comms.DispatchReply(scriptID,result,"",reqID.ToString());
423 return;
424 }
425 catch (Exception e)
426 {
427 m_log.WarnFormat("[JsonStoreScripts] Json parsing failed; {0}",e.Message);
428 }
429
430 GenerateRuntimeError(String.Format("Json parsing failed for {0}",assetID.ToString()));
431 m_comms.DispatchReply(scriptID,0,"",reqID.ToString());
432 }
433
434 // -----------------------------------------------------------------
435 /// <summary>
436 ///
437 /// </summary>
438 // -----------------------------------------------------------------
439 private void DoJsonWriteNotecard(UUID reqID, UUID hostID, UUID scriptID, UUID storeID, string path, string name)
440 {
441 string data;
442 if (! m_store.GetValue(storeID,path,true, out data))
443 {
444 m_comms.DispatchReply(scriptID,0,UUID.Zero.ToString(),reqID.ToString());
445 return;
446 }
447
448 SceneObjectPart host = m_scene.GetSceneObjectPart(hostID);
449
450 // Create new asset
451 UUID assetID = UUID.Random();
452 AssetBase asset = new AssetBase(assetID, name, (sbyte)AssetType.Notecard, host.OwnerID.ToString());
453 asset.Description = "Json store";
454
455 int textLength = data.Length;
456 data = "Linden text version 2\n{\nLLEmbeddedItems version 1\n{\ncount 0\n}\nText length "
457 + textLength.ToString() + "\n" + data + "}\n";
458
459 asset.Data = Util.UTF8.GetBytes(data);
460 m_scene.AssetService.Store(asset);
461
462 // Create Task Entry
463 TaskInventoryItem taskItem = new TaskInventoryItem();
464
465 taskItem.ResetIDs(host.UUID);
466 taskItem.ParentID = host.UUID;
467 taskItem.CreationDate = (uint)Util.UnixTimeSinceEpoch();
468 taskItem.Name = asset.Name;
469 taskItem.Description = asset.Description;
470 taskItem.Type = (int)AssetType.Notecard;
471 taskItem.InvType = (int)InventoryType.Notecard;
472 taskItem.OwnerID = host.OwnerID;
473 taskItem.CreatorID = host.OwnerID;
474 taskItem.BasePermissions = (uint)PermissionMask.All;
475 taskItem.CurrentPermissions = (uint)PermissionMask.All;
476 taskItem.EveryonePermissions = 0;
477 taskItem.NextPermissions = (uint)PermissionMask.All;
478 taskItem.GroupID = host.GroupID;
479 taskItem.GroupPermissions = 0;
480 taskItem.Flags = 0;
481 taskItem.PermsGranter = UUID.Zero;
482 taskItem.PermsMask = 0;
483 taskItem.AssetID = asset.FullID;
484
485 host.Inventory.AddInventoryItem(taskItem, false);
486
487 m_comms.DispatchReply(scriptID,1,assetID.ToString(),reqID.ToString());
488 }
489 }
490}
diff --git a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
index cab30de..74a85e2 100644
--- a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
@@ -38,7 +38,7 @@ using OpenMetaverse;
38using System.Linq; 38using System.Linq;
39using System.Linq.Expressions; 39using System.Linq.Expressions;
40 40
41namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms 41namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms
42{ 42{
43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ScriptModuleCommsModule")] 43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ScriptModuleCommsModule")]
44 class ScriptModuleCommsModule : INonSharedRegionModule, IScriptModuleComms 44 class ScriptModuleCommsModule : INonSharedRegionModule, IScriptModuleComms
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 8e73eb1..e9ec314 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -9990,7 +9990,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9990 // child agents have a mass of 1.0 9990 // child agents have a mass of 1.0
9991 return 1; 9991 return 1;
9992 else 9992 else
9993 return avatar.GetMass(); 9993 return (double)avatar.GetMass();
9994 } 9994 }
9995 catch (KeyNotFoundException) 9995 catch (KeyNotFoundException)
9996 { 9996 {
@@ -11182,19 +11182,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11182 break; 11182 break;
11183 // For the following 8 see the Object version below 11183 // For the following 8 see the Object version below
11184 case ScriptBaseClass.OBJECT_RUNNING_SCRIPT_COUNT: 11184 case ScriptBaseClass.OBJECT_RUNNING_SCRIPT_COUNT:
11185 ret.Add(new LSL_Integer(0)); 11185 ret.Add(new LSL_Integer(av.RunningScriptCount()));
11186 break; 11186 break;
11187 case ScriptBaseClass.OBJECT_TOTAL_SCRIPT_COUNT: 11187 case ScriptBaseClass.OBJECT_TOTAL_SCRIPT_COUNT:
11188 ret.Add(new LSL_Integer(0)); 11188 ret.Add(new LSL_Integer(av.ScriptCount()));
11189 break; 11189 break;
11190 case ScriptBaseClass.OBJECT_SCRIPT_MEMORY: 11190 case ScriptBaseClass.OBJECT_SCRIPT_MEMORY:
11191 ret.Add(new LSL_Integer(0)); 11191 ret.Add(new LSL_Integer(av.RunningScriptCount() * 16384));
11192 break; 11192 break;
11193 case ScriptBaseClass.OBJECT_SCRIPT_TIME: 11193 case ScriptBaseClass.OBJECT_SCRIPT_TIME:
11194 ret.Add(new LSL_Float(0)); 11194 ret.Add(new LSL_Float(av.ScriptExecutionTime() / 1000.0f));
11195 break; 11195 break;
11196 case ScriptBaseClass.OBJECT_PRIM_EQUIVALENCE: 11196 case ScriptBaseClass.OBJECT_PRIM_EQUIVALENCE:
11197 ret.Add(new LSL_Integer(0)); 11197 ret.Add(new LSL_Integer(1));
11198 break; 11198 break;
11199 case ScriptBaseClass.OBJECT_SERVER_COST: 11199 case ScriptBaseClass.OBJECT_SERVER_COST:
11200 ret.Add(new LSL_Float(0)); 11200 ret.Add(new LSL_Float(0));
@@ -11246,43 +11246,48 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11246 case ScriptBaseClass.OBJECT_CREATOR: 11246 case ScriptBaseClass.OBJECT_CREATOR:
11247 ret.Add(new LSL_String(obj.CreatorID.ToString())); 11247 ret.Add(new LSL_String(obj.CreatorID.ToString()));
11248 break; 11248 break;
11249 // The following 8 I have intentionaly coded to return zero. They are part of
11250 // "Land Impact" calculations. These calculations are probably not applicable
11251 // to OpenSim, required figures (cpu/memory usage) are not currently tracked
11252 // I have intentionally left these all at zero rather than return possibly
11253 // missleading numbers
11254 case ScriptBaseClass.OBJECT_RUNNING_SCRIPT_COUNT: 11249 case ScriptBaseClass.OBJECT_RUNNING_SCRIPT_COUNT:
11255 // in SL this currently includes crashed scripts 11250 ret.Add(new LSL_Integer(obj.ParentGroup.RunningScriptCount()));
11256 ret.Add(new LSL_Integer(0));
11257 break; 11251 break;
11258 case ScriptBaseClass.OBJECT_TOTAL_SCRIPT_COUNT: 11252 case ScriptBaseClass.OBJECT_TOTAL_SCRIPT_COUNT:
11259 ret.Add(new LSL_Integer(0)); 11253 ret.Add(new LSL_Integer(obj.ParentGroup.ScriptCount()));
11260 break; 11254 break;
11261 case ScriptBaseClass.OBJECT_SCRIPT_MEMORY: 11255 case ScriptBaseClass.OBJECT_SCRIPT_MEMORY:
11262 // The value returned in SL for mono scripts is 65536 * number of active scripts 11256 // The value returned in SL for mono scripts is 65536 * number of active scripts
11263 ret.Add(new LSL_Integer(0)); 11257 // and 16384 * number of active scripts for LSO. since llGetFreememory
11258 // is coded to give the LSO value use it here
11259 ret.Add(new LSL_Integer(obj.ParentGroup.RunningScriptCount() * 16384));
11264 break; 11260 break;
11265 case ScriptBaseClass.OBJECT_SCRIPT_TIME: 11261 case ScriptBaseClass.OBJECT_SCRIPT_TIME:
11266 // Average cpu time per simulator frame expended on all scripts in the objetc 11262 // Average cpu time in seconds per simulator frame expended on all scripts in the object
11267 ret.Add(new LSL_Float(0)); 11263 ret.Add(new LSL_Float(obj.ParentGroup.ScriptExecutionTime() / 1000.0f));
11268 break; 11264 break;
11269 case ScriptBaseClass.OBJECT_PRIM_EQUIVALENCE: 11265 case ScriptBaseClass.OBJECT_PRIM_EQUIVALENCE:
11270 // according to the SL wiki A prim or linkset will have prim 11266 // according to the SL wiki A prim or linkset will have prim
11271 // equivalent of the number of prims in a linkset if it does not 11267 // equivalent of the number of prims in a linkset if it does not
11272 // contain a mesh anywhere in the link set or is not a normal prim 11268 // contain a mesh anywhere in the link set or is not a normal prim
11273 // The value returned in SL for normal prims is prim count 11269 // The value returned in SL for normal prims is prim count
11274 ret.Add(new LSL_Integer(0)); 11270 ret.Add(new LSL_Integer(obj.ParentGroup.PrimCount));
11275 break; 11271 break;
11272 // The following 3 costs I have intentionaly coded to return zero. They are part of
11273 // "Land Impact" calculations. These calculations are probably not applicable
11274 // to OpenSim and are not yet complete in SL
11276 case ScriptBaseClass.OBJECT_SERVER_COST: 11275 case ScriptBaseClass.OBJECT_SERVER_COST:
11277 // The value returned in SL for normal prims is prim count 11276 // The linden calculation is here
11277 // http://wiki.secondlife.com/wiki/Mesh/Mesh_Server_Weight
11278 // The value returned in SL for normal prims looks like the prim count
11278 ret.Add(new LSL_Float(0)); 11279 ret.Add(new LSL_Float(0));
11279 break; 11280 break;
11280 case ScriptBaseClass.OBJECT_STREAMING_COST: 11281 case ScriptBaseClass.OBJECT_STREAMING_COST:
11281 // The value returned in SL for normal prims is prim count * 0.06 11282 // The linden calculation is here
11283 // http://wiki.secondlife.com/wiki/Mesh/Mesh_Streaming_Cost
11284 // The value returned in SL for normal prims looks like the prim count * 0.06
11282 ret.Add(new LSL_Float(0)); 11285 ret.Add(new LSL_Float(0));
11283 break; 11286 break;
11284 case ScriptBaseClass.OBJECT_PHYSICS_COST: 11287 case ScriptBaseClass.OBJECT_PHYSICS_COST:
11285 // The value returned in SL for normal prims is prim count 11288 // The linden calculation is here
11289 // http://wiki.secondlife.com/wiki/Mesh/Mesh_physics
11290 // The value returned in SL for normal prims looks like the prim count
11286 ret.Add(new LSL_Float(0)); 11291 ret.Add(new LSL_Float(0));
11287 break; 11292 break;
11288 default: 11293 default:
@@ -12037,7 +12042,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12037 bool isAccount = false; 12042 bool isAccount = false;
12038 bool isGroup = false; 12043 bool isGroup = false;
12039 12044
12040 if (!estate.IsEstateOwner(m_host.OwnerID) || !estate.IsEstateManager(m_host.OwnerID)) 12045 if (!estate.IsEstateOwner(m_host.OwnerID) || !estate.IsEstateManagerOrOwner(m_host.OwnerID))
12041 return 0; 12046 return 0;
12042 12047
12043 UUID id = new UUID(); 12048 UUID id = new UUID();
@@ -12099,35 +12104,50 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12099 return 1; 12104 return 1;
12100 } 12105 }
12101 12106
12102 #region Not Implemented 12107 public LSL_Integer llGetMemoryLimit()
12103 // 12108 {
12104 // Listing the unimplemented lsl functions here, please move 12109 m_host.AddScriptLPS(1);
12105 // them from this region as they are completed 12110 // The value returned for LSO scripts in SL
12106 // 12111 return 16384;
12112 }
12107 12113
12108 public void llGetEnv(LSL_String name) 12114 public LSL_Integer llSetMemoryLimit(LSL_Integer limit)
12109 { 12115 {
12110 m_host.AddScriptLPS(1); 12116 m_host.AddScriptLPS(1);
12111 NotImplemented("llGetEnv"); 12117 // Treat as an LSO script
12118 return ScriptBaseClass.FALSE;
12112 } 12119 }
12113 12120
12114 public void llGetSPMaxMemory() 12121 public LSL_Integer llGetSPMaxMemory()
12115 { 12122 {
12116 m_host.AddScriptLPS(1); 12123 m_host.AddScriptLPS(1);
12117 NotImplemented("llGetSPMaxMemory"); 12124 // The value returned for LSO scripts in SL
12125 return 16384;
12118 } 12126 }
12119 12127
12120 public virtual LSL_Integer llGetUsedMemory() 12128 public virtual LSL_Integer llGetUsedMemory()
12121 { 12129 {
12122 m_host.AddScriptLPS(1); 12130 m_host.AddScriptLPS(1);
12123 NotImplemented("llGetUsedMemory"); 12131 // The value returned for LSO scripts in SL
12124 return 0; 12132 return 16384;
12125 } 12133 }
12126 12134
12127 public void llScriptProfiler(LSL_Integer flags) 12135 public void llScriptProfiler(LSL_Integer flags)
12128 { 12136 {
12129 m_host.AddScriptLPS(1); 12137 m_host.AddScriptLPS(1);
12130 //NotImplemented("llScriptProfiler"); 12138 // This does nothing for LSO scripts in SL
12139 }
12140
12141 #region Not Implemented
12142 //
12143 // Listing the unimplemented lsl functions here, please move
12144 // them from this region as they are completed
12145 //
12146
12147 public void llGetEnv(LSL_String name)
12148 {
12149 m_host.AddScriptLPS(1);
12150 NotImplemented("llGetEnv");
12131 } 12151 }
12132 12152
12133 public void llSetSoundQueueing(int queue) 12153 public void llSetSoundQueueing(int queue)
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs
index 77a784d..df20126 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs
@@ -449,7 +449,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
449 LSShoutError("LightShare functions are not enabled."); 449 LSShoutError("LightShare functions are not enabled.");
450 return 0; 450 return 0;
451 } 451 }
452 if (!World.RegionInfo.EstateSettings.IsEstateManager(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200) 452 if (!World.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200)
453 { 453 {
454 LSShoutError("lsSetWindlightScene can only be used by estate managers or owners."); 454 LSShoutError("lsSetWindlightScene can only be used by estate managers or owners.");
455 return 0; 455 return 0;
@@ -477,7 +477,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
477 LSShoutError("LightShare functions are not enabled."); 477 LSShoutError("LightShare functions are not enabled.");
478 return; 478 return;
479 } 479 }
480 if (!World.RegionInfo.EstateSettings.IsEstateManager(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200) 480 if (!World.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200)
481 { 481 {
482 LSShoutError("lsSetWindlightScene can only be used by estate managers or owners."); 482 LSShoutError("lsSetWindlightScene can only be used by estate managers or owners.");
483 return; 483 return;
@@ -500,7 +500,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
500 LSShoutError("LightShare functions are not enabled."); 500 LSShoutError("LightShare functions are not enabled.");
501 return 0; 501 return 0;
502 } 502 }
503 if (!World.RegionInfo.EstateSettings.IsEstateManager(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200) 503 if (!World.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200)
504 { 504 {
505 LSShoutError("lsSetWindlightSceneTargeted can only be used by estate managers or owners."); 505 LSShoutError("lsSetWindlightSceneTargeted can only be used by estate managers or owners.");
506 return 0; 506 return 0;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index 0dc2aa2..89e85a0 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -378,7 +378,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
378 if (m_FunctionPerms[function].AllowedOwnerClasses.Contains("ESTATE_MANAGER")) 378 if (m_FunctionPerms[function].AllowedOwnerClasses.Contains("ESTATE_MANAGER"))
379 { 379 {
380 //Only Estate Managers may use the function 380 //Only Estate Managers may use the function
381 if (World.RegionInfo.EstateSettings.IsEstateManager(ownerID) && World.RegionInfo.EstateSettings.EstateOwner != ownerID) 381 if (World.RegionInfo.EstateSettings.IsEstateManagerOrOwner(ownerID) && World.RegionInfo.EstateSettings.EstateOwner != ownerID)
382 { 382 {
383 return; 383 return;
384 } 384 }
@@ -1186,12 +1186,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1186 CheckThreatLevel(ThreatLevel.High, "osSetRegionWaterHeight"); 1186 CheckThreatLevel(ThreatLevel.High, "osSetRegionWaterHeight");
1187 1187
1188 m_host.AddScriptLPS(1); 1188 m_host.AddScriptLPS(1);
1189 //Check to make sure that the script's owner is the estate manager/master 1189
1190 //World.Permissions.GenericEstatePermission( 1190 World.EventManager.TriggerRequestChangeWaterHeight((float)height);
1191 if (World.Permissions.IsGod(m_host.OwnerID))
1192 {
1193 World.EventManager.TriggerRequestChangeWaterHeight((float)height);
1194 }
1195 } 1191 }
1196 1192
1197 /// <summary> 1193 /// <summary>
@@ -1202,27 +1198,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1202 /// <param name="sunHour">The "Sun Hour" that is desired, 0...24, with 0 just after SunRise</param> 1198 /// <param name="sunHour">The "Sun Hour" that is desired, 0...24, with 0 just after SunRise</param>
1203 public void osSetRegionSunSettings(bool useEstateSun, bool sunFixed, double sunHour) 1199 public void osSetRegionSunSettings(bool useEstateSun, bool sunFixed, double sunHour)
1204 { 1200 {
1205 CheckThreatLevel(ThreatLevel.Nuisance, "osSetRegionSunSettings"); 1201 CheckThreatLevel(ThreatLevel.High, "osSetRegionSunSettings");
1206 1202
1207 m_host.AddScriptLPS(1); 1203 m_host.AddScriptLPS(1);
1208 //Check to make sure that the script's owner is the estate manager/master
1209 //World.Permissions.GenericEstatePermission(
1210 if (World.Permissions.IsGod(m_host.OwnerID))
1211 {
1212 while (sunHour > 24.0)
1213 sunHour -= 24.0;
1214 1204
1215 while (sunHour < 0) 1205 while (sunHour > 24.0)
1216 sunHour += 24.0; 1206 sunHour -= 24.0;
1217 1207
1208 while (sunHour < 0)
1209 sunHour += 24.0;
1218 1210
1219 World.RegionInfo.RegionSettings.UseEstateSun = useEstateSun; 1211 World.RegionInfo.RegionSettings.UseEstateSun = useEstateSun;
1220 World.RegionInfo.RegionSettings.SunPosition = sunHour + 6; // LL Region Sun Hour is 6 to 30 1212 World.RegionInfo.RegionSettings.SunPosition = sunHour + 6; // LL Region Sun Hour is 6 to 30
1221 World.RegionInfo.RegionSettings.FixedSun = sunFixed; 1213 World.RegionInfo.RegionSettings.FixedSun = sunFixed;
1222 World.RegionInfo.RegionSettings.Save(); 1214 World.RegionInfo.RegionSettings.Save();
1223 1215
1224 World.EventManager.TriggerEstateToolsSunUpdate(World.RegionInfo.RegionHandle, sunFixed, useEstateSun, (float)sunHour); 1216 World.EventManager.TriggerEstateToolsSunUpdate(
1225 } 1217 World.RegionInfo.RegionHandle, sunFixed, useEstateSun, (float)sunHour);
1226 } 1218 }
1227 1219
1228 /// <summary> 1220 /// <summary>
@@ -1232,26 +1224,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1232 /// <param name="sunHour">The "Sun Hour" that is desired, 0...24, with 0 just after SunRise</param> 1224 /// <param name="sunHour">The "Sun Hour" that is desired, 0...24, with 0 just after SunRise</param>
1233 public void osSetEstateSunSettings(bool sunFixed, double sunHour) 1225 public void osSetEstateSunSettings(bool sunFixed, double sunHour)
1234 { 1226 {
1235 CheckThreatLevel(ThreatLevel.Nuisance, "osSetEstateSunSettings"); 1227 CheckThreatLevel(ThreatLevel.High, "osSetEstateSunSettings");
1236 1228
1237 m_host.AddScriptLPS(1); 1229 m_host.AddScriptLPS(1);
1238 //Check to make sure that the script's owner is the estate manager/master
1239 //World.Permissions.GenericEstatePermission(
1240 if (World.Permissions.IsGod(m_host.OwnerID))
1241 {
1242 while (sunHour > 24.0)
1243 sunHour -= 24.0;
1244 1230
1245 while (sunHour < 0) 1231 while (sunHour > 24.0)
1246 sunHour += 24.0; 1232 sunHour -= 24.0;
1247 1233
1248 World.RegionInfo.EstateSettings.UseGlobalTime = !sunFixed; 1234 while (sunHour < 0)
1249 World.RegionInfo.EstateSettings.SunPosition = sunHour; 1235 sunHour += 24.0;
1250 World.RegionInfo.EstateSettings.FixedSun = sunFixed;
1251 World.RegionInfo.EstateSettings.Save();
1252 1236
1253 World.EventManager.TriggerEstateToolsSunUpdate(World.RegionInfo.RegionHandle, sunFixed, World.RegionInfo.RegionSettings.UseEstateSun, (float)sunHour); 1237 World.RegionInfo.EstateSettings.UseGlobalTime = !sunFixed;
1254 } 1238 World.RegionInfo.EstateSettings.SunPosition = sunHour;
1239 World.RegionInfo.EstateSettings.FixedSun = sunFixed;
1240 World.RegionInfo.EstateSettings.Save();
1241
1242 World.EventManager.TriggerEstateToolsSunUpdate(
1243 World.RegionInfo.RegionHandle, sunFixed, World.RegionInfo.RegionSettings.UseEstateSun, (float)sunHour);
1255 } 1244 }
1256 1245
1257 /// <summary> 1246 /// <summary>
@@ -2555,7 +2544,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2555 2544
2556 public void osNpcStopMoveToTarget(LSL_Key npc) 2545 public void osNpcStopMoveToTarget(LSL_Key npc)
2557 { 2546 {
2558 CheckThreatLevel(ThreatLevel.VeryLow, "osNpcStopMoveTo"); 2547 CheckThreatLevel(ThreatLevel.High, "osNpcStopMoveToTarget");
2559 m_host.AddScriptLPS(1); 2548 m_host.AddScriptLPS(1);
2560 2549
2561 INPCModule module = World.RequestModuleInterface<INPCModule>(); 2550 INPCModule module = World.RequestModuleInterface<INPCModule>();
@@ -3095,5 +3084,60 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3095 3084
3096 return ScriptBaseClass.TRUE; 3085 return ScriptBaseClass.TRUE;
3097 } 3086 }
3087
3088 /// <summary>
3089 /// Sets terrain estate texture
3090 /// </summary>
3091 /// <param name="level"></param>
3092 /// <param name="texture"></param>
3093 /// <returns></returns>
3094 public void osSetTerrainTexture(int level, LSL_Key texture)
3095 {
3096 CheckThreatLevel(ThreatLevel.High, "osSetTerrainTexture");
3097
3098 m_host.AddScriptLPS(1);
3099 //Check to make sure that the script's owner is the estate manager/master
3100 //World.Permissions.GenericEstatePermission(
3101 if (World.Permissions.IsGod(m_host.OwnerID))
3102 {
3103 if (level < 0 || level > 3)
3104 return;
3105
3106 UUID textureID = new UUID();
3107 if (!UUID.TryParse(texture, out textureID))
3108 return;
3109
3110 // estate module is required
3111 IEstateModule estate = World.RequestModuleInterface<IEstateModule>();
3112 if (estate != null)
3113 estate.setEstateTerrainBaseTexture(level, textureID);
3114 }
3115 }
3116
3117 /// <summary>
3118 /// Sets terrain heights of estate
3119 /// </summary>
3120 /// <param name="corner"></param>
3121 /// <param name="low"></param>
3122 /// <param name="high"></param>
3123 /// <returns></returns>
3124 public void osSetTerrainTextureHeight(int corner, double low, double high)
3125 {
3126 CheckThreatLevel(ThreatLevel.High, "osSetTerrainTextureHeight");
3127
3128 m_host.AddScriptLPS(1);
3129 //Check to make sure that the script's owner is the estate manager/master
3130 //World.Permissions.GenericEstatePermission(
3131 if (World.Permissions.IsGod(m_host.OwnerID))
3132 {
3133 if (corner < 0 || corner > 3)
3134 return;
3135
3136 // estate module is required
3137 IEstateModule estate = World.RequestModuleInterface<IEstateModule>();
3138 if (estate != null)
3139 estate.setEstateTerrainTextureHeights(corner, (float)low, (float)high);
3140 }
3141 }
3098 } 3142 }
3099} 3143}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
index 5c528977..eab6851 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
@@ -149,7 +149,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
149 LSL_Rotation llGetLocalRot(); 149 LSL_Rotation llGetLocalRot();
150 LSL_Float llGetMass(); 150 LSL_Float llGetMass();
151 LSL_Float llGetMassMKS(); 151 LSL_Float llGetMassMKS();
152 void llGetNextEmail(string address, string subject); 152 LSL_Integer llGetMemoryLimit();
153 void llGetNextEmail(string address, string subject);
153 LSL_String llGetNotecardLine(string name, int line); 154 LSL_String llGetNotecardLine(string name, int line);
154 LSL_Key llGetNumberOfNotecardLines(string name); 155 LSL_Key llGetNumberOfNotecardLines(string name);
155 LSL_Integer llGetNumberOfPrims(); 156 LSL_Integer llGetNumberOfPrims();
@@ -187,6 +188,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
187 LSL_String llGetScriptName(); 188 LSL_String llGetScriptName();
188 LSL_Integer llGetScriptState(string name); 189 LSL_Integer llGetScriptState(string name);
189 LSL_String llGetSimulatorHostname(); 190 LSL_String llGetSimulatorHostname();
191 LSL_Integer llGetSPMaxMemory();
190 LSL_Integer llGetStartParameter(); 192 LSL_Integer llGetStartParameter();
191 LSL_Integer llGetStatus(int status); 193 LSL_Integer llGetStatus(int status);
192 LSL_String llGetSubString(string src, int start, int end); 194 LSL_String llGetSubString(string src, int start, int end);
@@ -322,6 +324,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
322 void llSay(int channelID, string text); 324 void llSay(int channelID, string text);
323 void llScaleTexture(double u, double v, int face); 325 void llScaleTexture(double u, double v, int face);
324 LSL_Integer llScriptDanger(LSL_Vector pos); 326 LSL_Integer llScriptDanger(LSL_Vector pos);
327 void llScriptProfiler(LSL_Integer flag);
325 LSL_Key llSendRemoteData(string channel, string dest, int idata, string sdata); 328 LSL_Key llSendRemoteData(string channel, string dest, int idata, string sdata);
326 void llSensor(string name, string id, int type, double range, double arc); 329 void llSensor(string name, string id, int type, double range, double arc);
327 void llSensorRemove(); 330 void llSensorRemove();
@@ -345,6 +348,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
345 void llSetLinkTexture(int linknumber, string texture, int face); 348 void llSetLinkTexture(int linknumber, string texture, int face);
346 void llSetLinkTextureAnim(int linknum, int mode, int face, int sizex, int sizey, double start, double length, double rate); 349 void llSetLinkTextureAnim(int linknum, int mode, int face, int sizex, int sizey, double start, double length, double rate);
347 void llSetLocalRot(LSL_Rotation rot); 350 void llSetLocalRot(LSL_Rotation rot);
351 LSL_Integer llSetMemoryLimit(LSL_Integer limit);
348 void llSetObjectDesc(string desc); 352 void llSetObjectDesc(string desc);
349 void llSetObjectName(string name); 353 void llSetObjectName(string name);
350 void llSetObjectPermMask(int mask, int value); 354 void llSetObjectPermMask(int mask, int value);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
index 444a681..2fcc443 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
@@ -234,5 +234,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
234 234
235 LSL_Integer osInviteToGroup(LSL_Key agentId); 235 LSL_Integer osInviteToGroup(LSL_Key agentId);
236 LSL_Integer osEjectFromGroup(LSL_Key agentId); 236 LSL_Integer osEjectFromGroup(LSL_Key agentId);
237
238 void osSetTerrainTexture(int level, LSL_Key texture);
239 void osSetTerrainTextureHeight(int corner, double low, double high);
237 } 240 }
238} 241}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
index 6246b57..23b4336 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
@@ -383,6 +383,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
383 public const int PRIM_SCULPT_FLAG_INVERT = 64; 383 public const int PRIM_SCULPT_FLAG_INVERT = 64;
384 public const int PRIM_SCULPT_FLAG_MIRROR = 128; 384 public const int PRIM_SCULPT_FLAG_MIRROR = 128;
385 385
386 public const int PROFILE_NONE = 0;
387 public const int PROFILE_SCRIPT_MEMORY = 1;
388
386 public const int MASK_BASE = 0; 389 public const int MASK_BASE = 0;
387 public const int MASK_OWNER = 1; 390 public const int MASK_OWNER = 1;
388 public const int MASK_GROUP = 2; 391 public const int MASK_GROUP = 2;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
index 70c5fcd..9446099 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
@@ -586,6 +586,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
586 return m_LSL_Functions.llGetMassMKS(); 586 return m_LSL_Functions.llGetMassMKS();
587 } 587 }
588 588
589 public LSL_Integer llGetMemoryLimit()
590 {
591 return m_LSL_Functions.llGetMemoryLimit();
592 }
593
589 public void llGetNextEmail(string address, string subject) 594 public void llGetNextEmail(string address, string subject)
590 { 595 {
591 m_LSL_Functions.llGetNextEmail(address, subject); 596 m_LSL_Functions.llGetNextEmail(address, subject);
@@ -776,6 +781,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
776 return m_LSL_Functions.llGetSimulatorHostname(); 781 return m_LSL_Functions.llGetSimulatorHostname();
777 } 782 }
778 783
784 public LSL_Integer llGetSPMaxMemory()
785 {
786 return m_LSL_Functions.llGetSPMaxMemory();
787 }
788
779 public LSL_Integer llGetStartParameter() 789 public LSL_Integer llGetStartParameter()
780 { 790 {
781 return m_LSL_Functions.llGetStartParameter(); 791 return m_LSL_Functions.llGetStartParameter();
@@ -1445,6 +1455,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
1445 return m_LSL_Functions.llScriptDanger(pos); 1455 return m_LSL_Functions.llScriptDanger(pos);
1446 } 1456 }
1447 1457
1458 public void llScriptProfiler(LSL_Integer flags)
1459 {
1460 m_LSL_Functions.llScriptProfiler(flags);
1461 }
1462
1448 public LSL_Key llSendRemoteData(string channel, string dest, int idata, string sdata) 1463 public LSL_Key llSendRemoteData(string channel, string dest, int idata, string sdata)
1449 { 1464 {
1450 return m_LSL_Functions.llSendRemoteData(channel, dest, idata, sdata); 1465 return m_LSL_Functions.llSendRemoteData(channel, dest, idata, sdata);
@@ -1555,6 +1570,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
1555 m_LSL_Functions.llSetLocalRot(rot); 1570 m_LSL_Functions.llSetLocalRot(rot);
1556 } 1571 }
1557 1572
1573 public LSL_Integer llSetMemoryLimit(LSL_Integer limit)
1574 {
1575 return m_LSL_Functions.llSetMemoryLimit(limit);
1576 }
1577
1558 public void llSetObjectDesc(string desc) 1578 public void llSetObjectDesc(string desc)
1559 { 1579 {
1560 m_LSL_Functions.llSetObjectDesc(desc); 1580 m_LSL_Functions.llSetObjectDesc(desc);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
index 680cefb4..b94b9bf 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
@@ -878,5 +878,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
878 { 878 {
879 return m_OSSL_Functions.osEjectFromGroup(agentId); 879 return m_OSSL_Functions.osEjectFromGroup(agentId);
880 } 880 }
881
882 public void osSetTerrainTexture(int level, LSL_Key texture)
883 {
884 m_OSSL_Functions.osSetTerrainTexture(level, texture);
885 }
886
887 public void osSetTerrainTextureHeight(int corner, double low, double high)
888 {
889 m_OSSL_Functions.osSetTerrainTextureHeight(corner, low, high);
890 }
881 } 891 }
882} 892}
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index 1e0f01f..5a02d4c 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
@@ -1089,11 +1089,18 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1089 1089
1090 AppDomain sandbox; 1090 AppDomain sandbox;
1091 if (m_AppDomainLoading) 1091 if (m_AppDomainLoading)
1092 {
1092 sandbox = AppDomain.CreateDomain( 1093 sandbox = AppDomain.CreateDomain(
1093 m_Scene.RegionInfo.RegionID.ToString(), 1094 m_Scene.RegionInfo.RegionID.ToString(),
1094 evidence, appSetup); 1095 evidence, appSetup);
1096 m_AppDomains[appDomain].AssemblyResolve +=
1097 new ResolveEventHandler(
1098 AssemblyResolver.OnAssemblyResolve);
1099 }
1095 else 1100 else
1101 {
1096 sandbox = AppDomain.CurrentDomain; 1102 sandbox = AppDomain.CurrentDomain;
1103 }
1097 1104
1098 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel(); 1105 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
1099 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition(); 1106 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
@@ -1105,9 +1112,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1105 1112
1106 m_AppDomains[appDomain] = sandbox; 1113 m_AppDomains[appDomain] = sandbox;
1107 1114
1108 m_AppDomains[appDomain].AssemblyResolve +=
1109 new ResolveEventHandler(
1110 AssemblyResolver.OnAssemblyResolve);
1111 m_DomainScripts[appDomain] = new List<UUID>(); 1115 m_DomainScripts[appDomain] = new List<UUID>();
1112 } 1116 }
1113 catch (Exception e) 1117 catch (Exception e)
@@ -1997,45 +2001,59 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1997 if (!topScripts.ContainsKey(si.LocalID)) 2001 if (!topScripts.ContainsKey(si.LocalID))
1998 topScripts[si.RootLocalID] = 0; 2002 topScripts[si.RootLocalID] = 0;
1999 2003
2000// long ticksElapsed = tickNow - si.MeasurementPeriodTickStart; 2004 topScripts[si.RootLocalID] += CalculateAdjustedExectionTime(si, tickNow);
2001// float framesElapsed = ticksElapsed / (18.1818 * TimeSpan.TicksPerMillisecond); 2005 }
2002 2006 }
2003 // Execution time of the script adjusted by it's measurement period to make scripts started at
2004 // different times comparable.
2005// float adjustedExecutionTime
2006// = (float)si.MeasurementPeriodExecutionTime
2007// / ((float)(tickNow - si.MeasurementPeriodTickStart) / ScriptInstance.MaxMeasurementPeriod)
2008// / TimeSpan.TicksPerMillisecond;
2009
2010 long ticksElapsed = tickNow - si.MeasurementPeriodTickStart;
2011
2012 // Avoid divide by zerp
2013 if (ticksElapsed == 0)
2014 ticksElapsed = 1;
2015 2007
2016 // Scale execution time to the ideal 55 fps frame time for these reasons. 2008 return topScripts;
2017 // 2009 }
2018 // 1) XEngine does not execute scripts per frame, unlike other script engines. Hence, there is no
2019 // 'script execution time per frame', which is the original purpose of this value.
2020 //
2021 // 2) Giving the raw execution times is misleading since scripts start at different times, making
2022 // it impossible to compare scripts.
2023 //
2024 // 3) Scaling the raw execution time to the time that the script has been running is better but
2025 // is still misleading since a script that has just been rezzed may appear to have been running
2026 // for much longer.
2027 //
2028 // 4) Hence, we scale execution time to an idealised frame time (55 fps). This is also not perfect
2029 // since the figure does not represent actual execution time and very hard running scripts will
2030 // never exceed 18ms (though this is a very high number for script execution so is a warning sign).
2031 float adjustedExecutionTime
2032 = ((float)si.MeasurementPeriodExecutionTime / ticksElapsed) * 18.1818f;
2033 2010
2034 topScripts[si.RootLocalID] += adjustedExecutionTime; 2011 public float GetScriptExecutionTime(List<UUID> itemIDs)
2012 {
2013 if (itemIDs == null|| itemIDs.Count == 0)
2014 {
2015 return 0.0f;
2016 }
2017 float time = 0.0f;
2018 long tickNow = Util.EnvironmentTickCount();
2019 IScriptInstance si;
2020 // Calculate the time for all scripts that this engine is executing
2021 // Ignore any others
2022 foreach (UUID id in itemIDs)
2023 {
2024 si = GetInstance(id);
2025 if (si != null && si.Running)
2026 {
2027 time += CalculateAdjustedExectionTime(si, tickNow);
2035 } 2028 }
2036 } 2029 }
2030 return time;
2031 }
2037 2032
2038 return topScripts; 2033 private float CalculateAdjustedExectionTime(IScriptInstance si, long tickNow)
2034 {
2035 long ticksElapsed = tickNow - si.MeasurementPeriodTickStart;
2036
2037 // Avoid divide by zero
2038 if (ticksElapsed == 0)
2039 ticksElapsed = 1;
2040
2041 // Scale execution time to the ideal 55 fps frame time for these reasons.
2042 //
2043 // 1) XEngine does not execute scripts per frame, unlike other script engines. Hence, there is no
2044 // 'script execution time per frame', which is the original purpose of this value.
2045 //
2046 // 2) Giving the raw execution times is misleading since scripts start at different times, making
2047 // it impossible to compare scripts.
2048 //
2049 // 3) Scaling the raw execution time to the time that the script has been running is better but
2050 // is still misleading since a script that has just been rezzed may appear to have been running
2051 // for much longer.
2052 //
2053 // 4) Hence, we scale execution time to an idealised frame time (55 fps). This is also not perfect
2054 // since the figure does not represent actual execution time and very hard running scripts will
2055 // never exceed 18ms (though this is a very high number for script execution so is a warning sign).
2056 return ((float)si.MeasurementPeriodExecutionTime / ticksElapsed) * 18.1818f;
2039 } 2057 }
2040 2058
2041 public void SuspendScript(UUID itemID) 2059 public void SuspendScript(UUID itemID)
diff --git a/OpenSim/Region/UserStatistics/WebStatsModule.cs b/OpenSim/Region/UserStatistics/WebStatsModule.cs
index b9ba4bc..4248035 100644
--- a/OpenSim/Region/UserStatistics/WebStatsModule.cs
+++ b/OpenSim/Region/UserStatistics/WebStatsModule.cs
@@ -90,7 +90,7 @@ namespace OpenSim.Region.UserStatistics
90 90
91 dbConn = new SqliteConnection("URI=file:LocalUserStatistics.db,version=3"); 91 dbConn = new SqliteConnection("URI=file:LocalUserStatistics.db,version=3");
92 dbConn.Open(); 92 dbConn.Open();
93 CheckAndUpdateDatabase(dbConn); 93 CreateTables(dbConn);
94 94
95 Prototype_distributor protodep = new Prototype_distributor(); 95 Prototype_distributor protodep = new Prototype_distributor();
96 Updater_distributor updatedep = new Updater_distributor(); 96 Updater_distributor updatedep = new Updater_distributor();
@@ -131,7 +131,7 @@ namespace OpenSim.Region.UserStatistics
131 } 131 }
132 } 132 }
133 133
134 public void ReceiveClassicSimStatsPacket(SimStats stats) 134 private void ReceiveClassicSimStatsPacket(SimStats stats)
135 { 135 {
136 if (!enabled) 136 if (!enabled)
137 { 137 {
@@ -163,7 +163,7 @@ namespace OpenSim.Region.UserStatistics
163 } 163 }
164 } 164 }
165 165
166 public Hashtable HandleUnknownCAPSRequest(Hashtable request) 166 private Hashtable HandleUnknownCAPSRequest(Hashtable request)
167 { 167 {
168 //string regpath = request["uri"].ToString(); 168 //string regpath = request["uri"].ToString();
169 int response_code = 200; 169 int response_code = 200;
@@ -178,7 +178,7 @@ namespace OpenSim.Region.UserStatistics
178 return responsedata; 178 return responsedata;
179 } 179 }
180 180
181 public Hashtable HandleStatsRequest(Hashtable request) 181 private Hashtable HandleStatsRequest(Hashtable request)
182 { 182 {
183 lastHit = System.Environment.TickCount; 183 lastHit = System.Environment.TickCount;
184 Hashtable responsedata = new Hashtable(); 184 Hashtable responsedata = new Hashtable();
@@ -237,36 +237,12 @@ namespace OpenSim.Region.UserStatistics
237 237
238 return responsedata; 238 return responsedata;
239 } 239 }
240
241 public void CheckAndUpdateDatabase(SqliteConnection db)
242 {
243 lock (db)
244 {
245 // TODO: FIXME: implement stats migrations
246 const string SQL = @"SELECT * FROM migrations LIMIT 1";
247
248 using (SqliteCommand cmd = new SqliteCommand(SQL, db))
249 {
250 try
251 {
252 cmd.ExecuteNonQuery();
253 }
254 catch (SqliteSyntaxException)
255 {
256 CreateTables(db);
257 }
258 }
259 }
260 }
261 240
262 public void CreateTables(SqliteConnection db) 241 private void CreateTables(SqliteConnection db)
263 { 242 {
264 using (SqliteCommand createcmd = new SqliteCommand(SQL_STATS_TABLE_CREATE, db)) 243 using (SqliteCommand createcmd = new SqliteCommand(SQL_STATS_TABLE_CREATE, db))
265 { 244 {
266 createcmd.ExecuteNonQuery(); 245 createcmd.ExecuteNonQuery();
267
268 createcmd.CommandText = SQL_MIGRA_TABLE_CREATE;
269 createcmd.ExecuteNonQuery();
270 } 246 }
271 } 247 }
272 248
@@ -301,7 +277,7 @@ namespace OpenSim.Region.UserStatistics
301 get { return true; } 277 get { return true; }
302 } 278 }
303 279
304 public void OnRegisterCaps(UUID agentID, Caps caps) 280 private void OnRegisterCaps(UUID agentID, Caps caps)
305 { 281 {
306// m_log.DebugFormat("[WEB STATS MODULE]: OnRegisterCaps: agentID {0} caps {1}", agentID, caps); 282// m_log.DebugFormat("[WEB STATS MODULE]: OnRegisterCaps: agentID {0} caps {1}", agentID, caps);
307 283
@@ -316,7 +292,7 @@ namespace OpenSim.Region.UserStatistics
316 })); 292 }));
317 } 293 }
318 294
319 public void OnDeRegisterCaps(UUID agentID, Caps caps) 295 private void OnDeRegisterCaps(UUID agentID, Caps caps)
320 { 296 {
321 } 297 }
322 298
@@ -336,7 +312,7 @@ namespace OpenSim.Region.UserStatistics
336 } 312 }
337 } 313 }
338 314
339 public void OnMakeRootAgent(ScenePresence agent) 315 private void OnMakeRootAgent(ScenePresence agent)
340 { 316 {
341 UUID regionUUID = GetRegionUUIDFromHandle(agent.RegionHandle); 317 UUID regionUUID = GetRegionUUIDFromHandle(agent.RegionHandle);
342 318
@@ -365,11 +341,11 @@ namespace OpenSim.Region.UserStatistics
365 } 341 }
366 } 342 }
367 343
368 public void OnMakeChildAgent(ScenePresence agent) 344 private void OnMakeChildAgent(ScenePresence agent)
369 { 345 {
370 } 346 }
371 347
372 public void OnClientClosed(UUID agentID, Scene scene) 348 private void OnClientClosed(UUID agentID, Scene scene)
373 { 349 {
374 lock (m_sessions) 350 lock (m_sessions)
375 { 351 {
@@ -380,7 +356,7 @@ namespace OpenSim.Region.UserStatistics
380 } 356 }
381 } 357 }
382 358
383 public string readLogLines(int amount) 359 private string readLogLines(int amount)
384 { 360 {
385 Encoding encoding = Encoding.ASCII; 361 Encoding encoding = Encoding.ASCII;
386 int sizeOfChar = encoding.GetByteCount("\n"); 362 int sizeOfChar = encoding.GetByteCount("\n");
@@ -418,7 +394,7 @@ namespace OpenSim.Region.UserStatistics
418 return encoding.GetString(buffer); 394 return encoding.GetString(buffer);
419 } 395 }
420 396
421 public UUID GetRegionUUIDFromHandle(ulong regionhandle) 397 private UUID GetRegionUUIDFromHandle(ulong regionhandle)
422 { 398 {
423 lock (m_scenes) 399 lock (m_scenes)
424 { 400 {
@@ -441,17 +417,17 @@ namespace OpenSim.Region.UserStatistics
441 /// <param name="agentID"></param> 417 /// <param name="agentID"></param>
442 /// <param name="caps"></param> 418 /// <param name="caps"></param>
443 /// <returns></returns> 419 /// <returns></returns>
444 public string ViewerStatsReport(string request, string path, string param, 420 private string ViewerStatsReport(string request, string path, string param,
445 UUID agentID, Caps caps) 421 UUID agentID, Caps caps)
446 { 422 {
447// m_log.DebugFormat("[WEB STATS MODULE]: Received viewer starts report from {0}", agentID); 423// m_log.DebugFormat("[WEB STATS MODULE]: Received viewer starts report from {0}", agentID);
448 424
449 UpdateUserStats(ParseViewerStats(request,agentID), dbConn); 425 UpdateUserStats(ParseViewerStats(request, agentID), dbConn);
450 426
451 return String.Empty; 427 return String.Empty;
452 } 428 }
453 429
454 public UserSessionID ParseViewerStats(string request, UUID agentID) 430 private UserSessionID ParseViewerStats(string request, UUID agentID)
455 { 431 {
456 UserSessionID uid = new UserSessionID(); 432 UserSessionID uid = new UserSessionID();
457 UserSessionData usd; 433 UserSessionData usd;
@@ -592,14 +568,14 @@ namespace OpenSim.Region.UserStatistics
592 return uid; 568 return uid;
593 } 569 }
594 570
595 public void UpdateUserStats(UserSessionID uid, SqliteConnection db) 571 private void UpdateUserStats(UserSessionID uid, SqliteConnection db)
596 { 572 {
597 if (uid.session_id == UUID.Zero) 573 if (uid.session_id == UUID.Zero)
598 return; 574 return;
599 575
600 lock (db) 576 lock (db)
601 { 577 {
602 using (SqliteCommand updatecmd = new SqliteCommand(SQL_STATS_TABLE_UPDATE, db)) 578 using (SqliteCommand updatecmd = new SqliteCommand(SQL_STATS_TABLE_INSERT, db))
603 { 579 {
604 updatecmd.Parameters.Add(new SqliteParameter(":session_id", uid.session_data.session_id.ToString())); 580 updatecmd.Parameters.Add(new SqliteParameter(":session_id", uid.session_data.session_id.ToString()));
605 updatecmd.Parameters.Add(new SqliteParameter(":agent_id", uid.session_data.agent_id.ToString())); 581 updatecmd.Parameters.Add(new SqliteParameter(":agent_id", uid.session_data.agent_id.ToString()));
@@ -648,44 +624,26 @@ namespace OpenSim.Region.UserStatistics
648 updatecmd.Parameters.Add(new SqliteParameter(":f_dropped", uid.session_data.f_dropped)); 624 updatecmd.Parameters.Add(new SqliteParameter(":f_dropped", uid.session_data.f_dropped));
649 updatecmd.Parameters.Add(new SqliteParameter(":f_failed_resends", uid.session_data.f_failed_resends)); 625 updatecmd.Parameters.Add(new SqliteParameter(":f_failed_resends", uid.session_data.f_failed_resends));
650 updatecmd.Parameters.Add(new SqliteParameter(":f_invalid", uid.session_data.f_invalid)); 626 updatecmd.Parameters.Add(new SqliteParameter(":f_invalid", uid.session_data.f_invalid));
651
652 updatecmd.Parameters.Add(new SqliteParameter(":f_off_circuit", uid.session_data.f_off_circuit)); 627 updatecmd.Parameters.Add(new SqliteParameter(":f_off_circuit", uid.session_data.f_off_circuit));
653 updatecmd.Parameters.Add(new SqliteParameter(":f_resent", uid.session_data.f_resent)); 628 updatecmd.Parameters.Add(new SqliteParameter(":f_resent", uid.session_data.f_resent));
654 updatecmd.Parameters.Add(new SqliteParameter(":f_send_packet", uid.session_data.f_send_packet)); 629 updatecmd.Parameters.Add(new SqliteParameter(":f_send_packet", uid.session_data.f_send_packet));
655
656 updatecmd.Parameters.Add(new SqliteParameter(":session_key", uid.session_data.session_id.ToString()));
657 updatecmd.Parameters.Add(new SqliteParameter(":agent_key", uid.session_data.agent_id.ToString()));
658 updatecmd.Parameters.Add(new SqliteParameter(":region_key", uid.session_data.region_id.ToString()));
659 630
660// m_log.DebugFormat("[WEB STATS MODULE]: Database stats update for {0}", uid.session_data.agent_id); 631// StringBuilder parameters = new StringBuilder();
661 632// SqliteParameterCollection spc = updatecmd.Parameters;
662 int result = updatecmd.ExecuteNonQuery(); 633// foreach (SqliteParameter sp in spc)
663 634// parameters.AppendFormat("{0}={1},", sp.ParameterName, sp.Value);
664 if (result == 0) 635//
665 { 636// m_log.DebugFormat("[WEB STATS MODULE]: Parameters {0}", parameters);
666// m_log.DebugFormat("[WEB STATS MODULE]: Database stats insert for {0}", uid.session_data.agent_id);
667 637
668 updatecmd.CommandText = SQL_STATS_TABLE_INSERT; 638// m_log.DebugFormat("[WEB STATS MODULE]: Database stats update for {0}", uid.session_data.agent_id);
669 639
670 try 640 updatecmd.ExecuteNonQuery();
671 {
672 updatecmd.ExecuteNonQuery();
673 }
674 catch (Exception e)
675 {
676 m_log.WarnFormat(
677 "[WEB STATS MODULE]: failed to write stats for {0}, storage Execution Exception {1}{2}",
678 uid.session_data.agent_id, e.Message, e.StackTrace);
679 }
680 }
681 } 641 }
682 } 642 }
683 } 643 }
684 644
685 #region SQL 645 #region SQL
686 private const string SQL_MIGRA_TABLE_CREATE = @"create table migrations(name varchar(100), version int)"; 646 private const string SQL_STATS_TABLE_CREATE = @"CREATE TABLE IF NOT EXISTS stats_session_data (
687
688 private const string SQL_STATS_TABLE_CREATE = @"CREATE TABLE stats_session_data (
689 session_id VARCHAR(36) NOT NULL PRIMARY KEY, 647 session_id VARCHAR(36) NOT NULL PRIMARY KEY,
690 agent_id VARCHAR(36) NOT NULL DEFAULT '', 648 agent_id VARCHAR(36) NOT NULL DEFAULT '',
691 region_id VARCHAR(36) NOT NULL DEFAULT '', 649 region_id VARCHAR(36) NOT NULL DEFAULT '',
@@ -735,11 +693,11 @@ namespace OpenSim.Region.UserStatistics
735 f_send_packet INT NOT NULL DEFAULT '0' 693 f_send_packet INT NOT NULL DEFAULT '0'
736 );"; 694 );";
737 695
738 private const string SQL_STATS_TABLE_INSERT = @"INSERT INTO stats_session_data ( 696 private const string SQL_STATS_TABLE_INSERT = @"INSERT OR REPLACE INTO stats_session_data (
739session_id, agent_id, region_id, last_updated, remote_ip, name_f, name_l, avg_agents_in_view, min_agents_in_view, max_agents_in_view, 697session_id, agent_id, region_id, last_updated, remote_ip, name_f, name_l, avg_agents_in_view, min_agents_in_view, max_agents_in_view,
740mode_agents_in_view, avg_fps, min_fps, max_fps, mode_fps, a_language, mem_use, meters_traveled, avg_ping, min_ping, max_ping, mode_ping, 698mode_agents_in_view, avg_fps, min_fps, max_fps, mode_fps, a_language, mem_use, meters_traveled, avg_ping, min_ping, max_ping, mode_ping,
741regions_visited, run_time, avg_sim_fps, min_sim_fps, max_sim_fps, mode_sim_fps, start_time, client_version, s_cpu, s_gpu, s_os, s_ram, 699regions_visited, run_time, avg_sim_fps, min_sim_fps, max_sim_fps, mode_sim_fps, start_time, client_version, s_cpu, s_gpu, s_os, s_ram,
742d_object_kb, d_texture_kb, n_in_kb, n_in_pk, n_out_kb, n_out_pk, f_dropped, f_failed_resends, f_invalid, f_invalid, f_off_circuit, 700d_object_kb, d_texture_kb, d_world_kb, n_in_kb, n_in_pk, n_out_kb, n_out_pk, f_dropped, f_failed_resends, f_invalid, f_off_circuit,
743f_resent, f_send_packet 701f_resent, f_send_packet
744) 702)
745VALUES 703VALUES
@@ -747,62 +705,13 @@ VALUES
747:session_id, :agent_id, :region_id, :last_updated, :remote_ip, :name_f, :name_l, :avg_agents_in_view, :min_agents_in_view, :max_agents_in_view, 705:session_id, :agent_id, :region_id, :last_updated, :remote_ip, :name_f, :name_l, :avg_agents_in_view, :min_agents_in_view, :max_agents_in_view,
748:mode_agents_in_view, :avg_fps, :min_fps, :max_fps, :mode_fps, :a_language, :mem_use, :meters_traveled, :avg_ping, :min_ping, :max_ping, :mode_ping, 706:mode_agents_in_view, :avg_fps, :min_fps, :max_fps, :mode_fps, :a_language, :mem_use, :meters_traveled, :avg_ping, :min_ping, :max_ping, :mode_ping,
749:regions_visited, :run_time, :avg_sim_fps, :min_sim_fps, :max_sim_fps, :mode_sim_fps, :start_time, :client_version, :s_cpu, :s_gpu, :s_os, :s_ram, 707:regions_visited, :run_time, :avg_sim_fps, :min_sim_fps, :max_sim_fps, :mode_sim_fps, :start_time, :client_version, :s_cpu, :s_gpu, :s_os, :s_ram,
750:d_object_kb, :d_texture_kb, :n_in_kb, :n_in_pk, :n_out_kb, :n_out_pk, :f_dropped, :f_failed_resends, :f_invalid, :f_invalid, :f_off_circuit, 708:d_object_kb, :d_texture_kb, :d_world_kb, :n_in_kb, :n_in_pk, :n_out_kb, :n_out_pk, :f_dropped, :f_failed_resends, :f_invalid, :f_off_circuit,
751:f_resent, :f_send_packet 709:f_resent, :f_send_packet
752) 710)
753"; 711";
754 712
755 private const string SQL_STATS_TABLE_UPDATE = @" 713 #endregion
756UPDATE stats_session_data 714
757set session_id=:session_id,
758 agent_id=:agent_id,
759 region_id=:region_id,
760 last_updated=:last_updated,
761 remote_ip=:remote_ip,
762 name_f=:name_f,
763 name_l=:name_l,
764 avg_agents_in_view=:avg_agents_in_view,
765 min_agents_in_view=:min_agents_in_view,
766 max_agents_in_view=:max_agents_in_view,
767 mode_agents_in_view=:mode_agents_in_view,
768 avg_fps=:avg_fps,
769 min_fps=:min_fps,
770 max_fps=:max_fps,
771 mode_fps=:mode_fps,
772 a_language=:a_language,
773 mem_use=:mem_use,
774 meters_traveled=:meters_traveled,
775 avg_ping=:avg_ping,
776 min_ping=:min_ping,
777 max_ping=:max_ping,
778 mode_ping=:mode_ping,
779 regions_visited=:regions_visited,
780 run_time=:run_time,
781 avg_sim_fps=:avg_sim_fps,
782 min_sim_fps=:min_sim_fps,
783 max_sim_fps=:max_sim_fps,
784 mode_sim_fps=:mode_sim_fps,
785 start_time=:start_time,
786 client_version=:client_version,
787 s_cpu=:s_cpu,
788 s_gpu=:s_gpu,
789 s_os=:s_os,
790 s_ram=:s_ram,
791 d_object_kb=:d_object_kb,
792 d_texture_kb=:d_texture_kb,
793 d_world_kb=:d_world_kb,
794 n_in_kb=:n_in_kb,
795 n_in_pk=:n_in_pk,
796 n_out_kb=:n_out_kb,
797 n_out_pk=:n_out_pk,
798 f_dropped=:f_dropped,
799 f_failed_resends=:f_failed_resends,
800 f_invalid=:f_invalid,
801 f_off_circuit=:f_off_circuit,
802 f_resent=:f_resent,
803 f_send_packet=:f_send_packet
804WHERE session_id=:session_key AND agent_id=:agent_key AND region_id=:region_key";
805 #endregion
806 } 715 }
807 716
808 public static class UserSessionUtil 717 public static class UserSessionUtil
diff --git a/OpenSim/Services/Connectors/Grid/GridServiceConnector.cs b/OpenSim/Services/Connectors/Grid/GridServiceConnector.cs
index 7deaf95..f982cc1 100644
--- a/OpenSim/Services/Connectors/Grid/GridServiceConnector.cs
+++ b/OpenSim/Services/Connectors/Grid/GridServiceConnector.cs
@@ -116,29 +116,36 @@ namespace OpenSim.Services.Connectors
116 } 116 }
117 else if (replyData.ContainsKey("Result")&& (replyData["Result"].ToString().ToLower() == "failure")) 117 else if (replyData.ContainsKey("Result")&& (replyData["Result"].ToString().ToLower() == "failure"))
118 { 118 {
119 m_log.DebugFormat("[GRID CONNECTOR]: Registration failed: {0}", replyData["Message"].ToString()); 119 m_log.ErrorFormat(
120 "[GRID CONNECTOR]: Registration failed: {0} when contacting {1}", replyData["Message"], uri);
121
120 return replyData["Message"].ToString(); 122 return replyData["Message"].ToString();
121 } 123 }
122 else if (!replyData.ContainsKey("Result")) 124 else if (!replyData.ContainsKey("Result"))
123 { 125 {
124 m_log.DebugFormat("[GRID CONNECTOR]: reply data does not contain result field"); 126 m_log.ErrorFormat(
127 "[GRID CONNECTOR]: reply data does not contain result field when contacting {0}", uri);
125 } 128 }
126 else 129 else
127 { 130 {
128 m_log.DebugFormat("[GRID CONNECTOR]: unexpected result {0}", replyData["Result"].ToString()); 131 m_log.ErrorFormat(
129 return "Unexpected result "+replyData["Result"].ToString(); 132 "[GRID CONNECTOR]: unexpected result {0} when contacting {1}", replyData["Result"], uri);
133
134 return "Unexpected result " + replyData["Result"].ToString();
130 } 135 }
131
132 } 136 }
133 else 137 else
134 m_log.DebugFormat("[GRID CONNECTOR]: RegisterRegion received null reply"); 138 {
139 m_log.ErrorFormat(
140 "[GRID CONNECTOR]: RegisterRegion received null reply when contacting grid server at {0}", uri);
141 }
135 } 142 }
136 catch (Exception e) 143 catch (Exception e)
137 { 144 {
138 m_log.DebugFormat("[GRID CONNECTOR]: Exception when contacting grid server at {0}: {1}", uri, e.Message); 145 m_log.ErrorFormat("[GRID CONNECTOR]: Exception when contacting grid server at {0}: {1}", uri, e.Message);
139 } 146 }
140 147
141 return "Error communicating with grid service"; 148 return string.Format("Error communicating with the grid service at {0}", uri);
142 } 149 }
143 150
144 public bool DeregisterRegion(UUID regionID) 151 public bool DeregisterRegion(UUID regionID)
diff --git a/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs b/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs
index b6ec558..53fbea6 100644
--- a/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs
+++ b/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs
@@ -107,9 +107,8 @@ namespace OpenSim.Services.HypergridService
107 public override List<InventoryFolderBase> GetInventorySkeleton(UUID principalID) 107 public override List<InventoryFolderBase> GetInventorySkeleton(UUID principalID)
108 { 108 {
109 XInventoryFolder suitcase = GetSuitcaseXFolder(principalID); 109 XInventoryFolder suitcase = GetSuitcaseXFolder(principalID);
110 XInventoryFolder root = GetRootXFolder(principalID);
111 110
112 List<XInventoryFolder> tree = GetFolderTree(suitcase.folderID); 111 List<XInventoryFolder> tree = GetFolderTree(principalID, suitcase.folderID);
113 if (tree == null || (tree != null && tree.Count == 0)) 112 if (tree == null || (tree != null && tree.Count == 0))
114 return null; 113 return null;
115 114
@@ -119,7 +118,7 @@ namespace OpenSim.Services.HypergridService
119 folders.Add(ConvertToOpenSim(x)); 118 folders.Add(ConvertToOpenSim(x));
120 } 119 }
121 120
122 SetAsRootFolder(suitcase, root); 121 SetAsNormalFolder(suitcase);
123 folders.Add(ConvertToOpenSim(suitcase)); 122 folders.Add(ConvertToOpenSim(suitcase));
124 123
125 return folders; 124 return folders;
@@ -134,12 +133,11 @@ namespace OpenSim.Services.HypergridService
134 userInventory.Items = new List<InventoryItemBase>(); 133 userInventory.Items = new List<InventoryItemBase>();
135 134
136 XInventoryFolder suitcase = GetSuitcaseXFolder(userID); 135 XInventoryFolder suitcase = GetSuitcaseXFolder(userID);
137 XInventoryFolder root = GetRootXFolder(userID);
138 136
139 List<XInventoryFolder> tree = GetFolderTree(suitcase.folderID); 137 List<XInventoryFolder> tree = GetFolderTree(userID, suitcase.folderID);
140 if (tree == null || (tree != null && tree.Count == 0)) 138 if (tree == null || (tree != null && tree.Count == 0))
141 { 139 {
142 SetAsRootFolder(suitcase, root); 140 SetAsNormalFolder(suitcase);
143 userInventory.Folders.Add(ConvertToOpenSim(suitcase)); 141 userInventory.Folders.Add(ConvertToOpenSim(suitcase));
144 return userInventory; 142 return userInventory;
145 } 143 }
@@ -164,7 +162,7 @@ namespace OpenSim.Services.HypergridService
164 userInventory.Items.AddRange(items); 162 userInventory.Items.AddRange(items);
165 } 163 }
166 164
167 SetAsRootFolder(suitcase, root); 165 SetAsNormalFolder(suitcase);
168 userInventory.Folders.Add(ConvertToOpenSim(suitcase)); 166 userInventory.Folders.Add(ConvertToOpenSim(suitcase));
169 167
170 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: GetUserInventory for user {0} returning {1} folders and {2} items", 168 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: GetUserInventory for user {0} returning {1} folders and {2} items",
@@ -175,14 +173,13 @@ namespace OpenSim.Services.HypergridService
175 public override InventoryFolderBase GetRootFolder(UUID principalID) 173 public override InventoryFolderBase GetRootFolder(UUID principalID)
176 { 174 {
177 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: GetRootFolder for {0}", principalID); 175 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: GetRootFolder for {0}", principalID);
178 if (m_Database == null)
179 m_log.ErrorFormat("[XXX]: m_Database is NULL!");
180 176
181 // Let's find out the local root folder 177 // Let's find out the local root folder
182 XInventoryFolder root = GetRootXFolder(principalID); ; 178 XInventoryFolder root = GetRootXFolder(principalID); ;
183 if (root == null) 179 if (root == null)
184 { 180 {
185 m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: Unable to retrieve local root folder for user {0}", principalID); 181 m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: Unable to retrieve local root folder for user {0}", principalID);
182 return null;
186 } 183 }
187 184
188 // Warp! Root folder for travelers is the suitcase folder 185 // Warp! Root folder for travelers is the suitcase folder
@@ -202,7 +199,7 @@ namespace OpenSim.Services.HypergridService
202 CreateSystemFolders(principalID, suitcase.folderID); 199 CreateSystemFolders(principalID, suitcase.folderID);
203 } 200 }
204 201
205 SetAsRootFolder(suitcase, root); 202 SetAsNormalFolder(suitcase);
206 203
207 return ConvertToOpenSim(suitcase); 204 return ConvertToOpenSim(suitcase);
208 } 205 }
@@ -271,9 +268,8 @@ namespace OpenSim.Services.HypergridService
271 public override InventoryCollection GetFolderContent(UUID principalID, UUID folderID) 268 public override InventoryCollection GetFolderContent(UUID principalID, UUID folderID)
272 { 269 {
273 InventoryCollection coll = null; 270 InventoryCollection coll = null;
274 XInventoryFolder suitcase = GetSuitcaseXFolder(principalID);
275 271
276 if (!IsWithinSuitcaseTree(folderID, suitcase)) 272 if (!IsWithinSuitcaseTree(principalID, folderID))
277 return new InventoryCollection(); 273 return new InventoryCollection();
278 274
279 coll = base.GetFolderContent(principalID, folderID); 275 coll = base.GetFolderContent(principalID, folderID);
@@ -290,9 +286,7 @@ namespace OpenSim.Services.HypergridService
290 { 286 {
291 // Let's do a bit of sanity checking, more than the base service does 287 // Let's do a bit of sanity checking, more than the base service does
292 // make sure the given folder exists under the suitcase tree of this user 288 // make sure the given folder exists under the suitcase tree of this user
293 XInventoryFolder suitcase = GetSuitcaseXFolder(principalID); 289 if (!IsWithinSuitcaseTree(principalID, folderID))
294
295 if (!IsWithinSuitcaseTree(folderID, suitcase))
296 return new List<InventoryItemBase>(); 290 return new List<InventoryItemBase>();
297 291
298 return base.GetFolderItems(principalID, folderID); 292 return base.GetFolderItems(principalID, folderID);
@@ -303,21 +297,27 @@ namespace OpenSim.Services.HypergridService
303 m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: AddFolder {0} {1}", folder.Name, folder.ParentID); 297 m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: AddFolder {0} {1}", folder.Name, folder.ParentID);
304 // Let's do a bit of sanity checking, more than the base service does 298 // Let's do a bit of sanity checking, more than the base service does
305 // make sure the given folder's parent folder exists under the suitcase tree of this user 299 // make sure the given folder's parent folder exists under the suitcase tree of this user
306 XInventoryFolder suitcase = GetSuitcaseXFolder(folder.Owner);
307 300
308 if (!IsWithinSuitcaseTree(folder.ParentID, suitcase)) 301 if (!IsWithinSuitcaseTree(folder.Owner, folder.ParentID))
309 return false; 302 return false;
310 303
311 // OK, it's legit 304 // OK, it's legit
312 return base.AddFolder(folder); 305 if (base.AddFolder(folder))
306 {
307 List<XInventoryFolder> tree;
308 if (m_SuitcaseTrees.TryGetValue(folder.Owner, out tree))
309 tree.Add(ConvertFromOpenSim(folder));
310
311 return true;
312 }
313
314 return false;
313 } 315 }
314 316
315 public override bool UpdateFolder(InventoryFolderBase folder) 317 public override bool UpdateFolder(InventoryFolderBase folder)
316 { 318 {
317 XInventoryFolder suitcase = GetSuitcaseXFolder(folder.Owner);
318
319 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Update folder {0}, version {1}", folder.ID, folder.Version); 319 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Update folder {0}, version {1}", folder.ID, folder.Version);
320 if (!IsWithinSuitcaseTree(folder.ID, suitcase)) 320 if (!IsWithinSuitcaseTree(folder.Owner, folder.ID))
321 { 321 {
322 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: folder {0} not within Suitcase tree", folder.Name); 322 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: folder {0} not within Suitcase tree", folder.Name);
323 return false; 323 return false;
@@ -329,9 +329,8 @@ namespace OpenSim.Services.HypergridService
329 329
330 public override bool MoveFolder(InventoryFolderBase folder) 330 public override bool MoveFolder(InventoryFolderBase folder)
331 { 331 {
332 XInventoryFolder suitcase = GetSuitcaseXFolder(folder.Owner); 332 if (!IsWithinSuitcaseTree(folder.Owner, folder.ID) ||
333 333 !IsWithinSuitcaseTree(folder.Owner, folder.ParentID))
334 if (!IsWithinSuitcaseTree(folder.ID, suitcase) || !IsWithinSuitcaseTree(folder.ParentID, suitcase))
335 return false; 334 return false;
336 335
337 return base.MoveFolder(folder); 336 return base.MoveFolder(folder);
@@ -353,9 +352,7 @@ namespace OpenSim.Services.HypergridService
353 { 352 {
354 // Let's do a bit of sanity checking, more than the base service does 353 // Let's do a bit of sanity checking, more than the base service does
355 // make sure the given folder's parent folder exists under the suitcase tree of this user 354 // make sure the given folder's parent folder exists under the suitcase tree of this user
356 XInventoryFolder suitcase = GetSuitcaseXFolder(item.Owner); 355 if (!IsWithinSuitcaseTree(item.Owner, item.Folder))
357
358 if (!IsWithinSuitcaseTree(item.Folder, suitcase))
359 return false; 356 return false;
360 357
361 // OK, it's legit 358 // OK, it's legit
@@ -365,9 +362,7 @@ namespace OpenSim.Services.HypergridService
365 362
366 public override bool UpdateItem(InventoryItemBase item) 363 public override bool UpdateItem(InventoryItemBase item)
367 { 364 {
368 XInventoryFolder suitcase = GetSuitcaseXFolder(item.Owner); 365 if (!IsWithinSuitcaseTree(item.Owner, item.Folder))
369
370 if (!IsWithinSuitcaseTree(item.Folder, suitcase))
371 return false; 366 return false;
372 367
373 return base.UpdateItem(item); 368 return base.UpdateItem(item);
@@ -377,9 +372,7 @@ namespace OpenSim.Services.HypergridService
377 { 372 {
378 // Principal is b0rked. *sigh* 373 // Principal is b0rked. *sigh*
379 374
380 XInventoryFolder suitcase = GetSuitcaseXFolder(items[0].Owner); 375 if (!IsWithinSuitcaseTree(items[0].Owner, items[0].Folder))
381
382 if (!IsWithinSuitcaseTree(items[0].Folder, suitcase))
383 return false; 376 return false;
384 377
385 return base.MoveItems(principalID, items); 378 return base.MoveItems(principalID, items);
@@ -400,15 +393,8 @@ namespace OpenSim.Services.HypergridService
400 item.Name, item.ID, item.Folder); 393 item.Name, item.ID, item.Folder);
401 return null; 394 return null;
402 } 395 }
403 XInventoryFolder suitcase = GetSuitcaseXFolder(it.Owner);
404 if (suitcase == null)
405 {
406 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Root or Suitcase are null for user {0}",
407 it.Owner);
408 return null;
409 }
410 396
411 if (!IsWithinSuitcaseTree(it.Folder, suitcase)) 397 if (!IsWithinSuitcaseTree(it.Owner, it.Folder))
412 { 398 {
413 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Item {0} (folder {1}) is not within Suitcase", 399 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Item {0} (folder {1}) is not within Suitcase",
414 it.Name, it.Folder); 400 it.Name, it.Folder);
@@ -431,9 +417,7 @@ namespace OpenSim.Services.HypergridService
431 417
432 if (f != null) 418 if (f != null)
433 { 419 {
434 XInventoryFolder suitcase = GetSuitcaseXFolder(f.Owner); 420 if (!IsWithinSuitcaseTree(f.Owner, f.ID))
435
436 if (!IsWithinSuitcaseTree(f.ID, suitcase))
437 return null; 421 return null;
438 } 422 }
439 423
@@ -481,22 +465,37 @@ namespace OpenSim.Services.HypergridService
481 465
482 if (folders != null && folders.Length > 0) 466 if (folders != null && folders.Length > 0)
483 return folders[0]; 467 return folders[0];
468
469 // check to see if we have the old Suitcase folder
470 folders = m_Database.GetFolders(
471 new string[] { "agentID", "folderName", "parentFolderID" },
472 new string[] { principalID.ToString(), "My Suitcase", UUID.Zero.ToString() });
473 if (folders != null && folders.Length > 0)
474 {
475 // Move it to under the root folder
476 XInventoryFolder root = GetRootXFolder(principalID);
477 folders[0].parentFolderID = root.folderID;
478 folders[0].type = 100;
479 m_Database.StoreFolder(folders[0]);
480 return folders[0];
481 }
482
484 return null; 483 return null;
485 } 484 }
486 485
487 private void SetAsRootFolder(XInventoryFolder suitcase, XInventoryFolder root) 486 private void SetAsNormalFolder(XInventoryFolder suitcase)
488 { 487 {
489 suitcase.type = (short)AssetType.Folder; 488 suitcase.type = (short)AssetType.Folder;
490 } 489 }
491 490
492 private List<XInventoryFolder> GetFolderTree(UUID folder) 491 private List<XInventoryFolder> GetFolderTree(UUID principalID, UUID folder)
493 { 492 {
494 List<XInventoryFolder> t = null; 493 List<XInventoryFolder> t = null;
495 if (m_SuitcaseTrees.TryGetValue(folder, out t)) 494 if (m_SuitcaseTrees.TryGetValue(principalID, out t))
496 return t; 495 return t;
497 496
498 t = GetFolderTreeRecursive(folder); 497 t = GetFolderTreeRecursive(folder);
499 m_SuitcaseTrees.AddOrUpdate(folder, t, 120); 498 m_SuitcaseTrees.AddOrUpdate(principalID, t, 5*60); // 5minutes
500 return t; 499 return t;
501 } 500 }
502 501
@@ -528,11 +527,18 @@ namespace OpenSim.Services.HypergridService
528 /// <param name="root"></param> 527 /// <param name="root"></param>
529 /// <param name="suitcase"></param> 528 /// <param name="suitcase"></param>
530 /// <returns></returns> 529 /// <returns></returns>
531 private bool IsWithinSuitcaseTree(UUID folderID, XInventoryFolder suitcase) 530 private bool IsWithinSuitcaseTree(UUID principalID, UUID folderID)
532 { 531 {
532 XInventoryFolder suitcase = GetSuitcaseXFolder(principalID);
533 if (suitcase == null)
534 {
535 m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: User {0} does not have a Suitcase folder", principalID);
536 return false;
537 }
538
533 List<XInventoryFolder> tree = new List<XInventoryFolder>(); 539 List<XInventoryFolder> tree = new List<XInventoryFolder>();
534 tree.Add(suitcase); // Warp! the tree is the real root folder plus the children of the suitcase folder 540 tree.Add(suitcase); // Warp! the tree is the real root folder plus the children of the suitcase folder
535 tree.AddRange(GetFolderTree(suitcase.folderID)); 541 tree.AddRange(GetFolderTree(principalID, suitcase.folderID));
536 XInventoryFolder f = tree.Find(delegate(XInventoryFolder fl) 542 XInventoryFolder f = tree.Find(delegate(XInventoryFolder fl)
537 { 543 {
538 if (fl.folderID == folderID) return true; 544 if (fl.folderID == folderID) return true;