aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
authorTom2010-08-06 11:44:57 -0700
committerTom2010-08-06 11:44:57 -0700
commitf9f776e4071dd983b8d9f52ecb75bc361a2b62ce (patch)
treec202070adf22e071541732c35c90347839a3af36 /OpenSim/Region
parentImplement CreateNewOutfitAttachments. This addresses mantis #199. (diff)
parentMerge branch 'master' into careminster-presence-refactor (diff)
downloadopensim-SC_OLD-f9f776e4071dd983b8d9f52ecb75bc361a2b62ce.zip
opensim-SC_OLD-f9f776e4071dd983b8d9f52ecb75bc361a2b62ce.tar.gz
opensim-SC_OLD-f9f776e4071dd983b8d9f52ecb75bc361a2b62ce.tar.bz2
opensim-SC_OLD-f9f776e4071dd983b8d9f52ecb75bc361a2b62ce.tar.xz
Merge branch 'careminster-presence-refactor' of ssh://3dhosting.de/var/git/careminster into careminster-presence-refactor
Diffstat (limited to 'OpenSim/Region')
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs3
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs110
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs54
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs50
-rw-r--r--OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs8
-rw-r--r--OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs596
-rw-r--r--OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs89
-rw-r--r--OpenSim/Region/Framework/Interfaces/IMoapModule.cs67
-rw-r--r--OpenSim/Region/Framework/Scenes/EventManager.cs97
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Permissions.cs38
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs40
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs7
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs271
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs3
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs36
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs15
19 files changed, 1371 insertions, 121 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index cd7c11b..d2d1e8f 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -4328,8 +4328,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4328 4328
4329 public void SendLandObjectOwners(LandData land, List<UUID> groups, Dictionary<UUID, int> ownersAndCount) 4329 public void SendLandObjectOwners(LandData land, List<UUID> groups, Dictionary<UUID, int> ownersAndCount)
4330 { 4330 {
4331
4332
4333 int notifyCount = ownersAndCount.Count; 4331 int notifyCount = ownersAndCount.Count;
4334 ParcelObjectOwnersReplyPacket pack = (ParcelObjectOwnersReplyPacket)PacketPool.Instance.GetPacket(PacketType.ParcelObjectOwnersReply); 4332 ParcelObjectOwnersReplyPacket pack = (ParcelObjectOwnersReplyPacket)PacketPool.Instance.GetPacket(PacketType.ParcelObjectOwnersReply);
4335 4333
@@ -4601,6 +4599,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4601 update.TextureEntry = data.Shape.TextureEntry ?? Utils.EmptyBytes; 4599 update.TextureEntry = data.Shape.TextureEntry ?? Utils.EmptyBytes;
4602 update.Scale = data.Shape.Scale; 4600 update.Scale = data.Shape.Scale;
4603 update.Text = Util.StringToBytes256(data.Text); 4601 update.Text = Util.StringToBytes256(data.Text);
4602 update.MediaURL = Util.StringToBytes256(data.MediaUrl);
4604 4603
4605 #region PrimFlags 4604 #region PrimFlags
4606 4605
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
index 31dfe14..7683288 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
@@ -54,6 +54,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
54 54
55 private UserAccount m_userInfo; 55 private UserAccount m_userInfo;
56 private string m_invPath; 56 private string m_invPath;
57
58 /// <summary>
59 /// Do we want to merge this load with existing inventory?
60 /// </summary>
61 protected bool m_merge;
57 62
58 /// <value> 63 /// <value>
59 /// We only use this to request modules 64 /// We only use this to request modules
@@ -66,19 +71,21 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
66 private Stream m_loadStream; 71 private Stream m_loadStream;
67 72
68 public InventoryArchiveReadRequest( 73 public InventoryArchiveReadRequest(
69 Scene scene, UserAccount userInfo, string invPath, string loadPath) 74 Scene scene, UserAccount userInfo, string invPath, string loadPath, bool merge)
70 : this( 75 : this(
71 scene, 76 scene,
72 userInfo, 77 userInfo,
73 invPath, 78 invPath,
74 new GZipStream(ArchiveHelpers.GetStream(loadPath), CompressionMode.Decompress)) 79 new GZipStream(ArchiveHelpers.GetStream(loadPath), CompressionMode.Decompress),
80 merge)
75 { 81 {
76 } 82 }
77 83
78 public InventoryArchiveReadRequest( 84 public InventoryArchiveReadRequest(
79 Scene scene, UserAccount userInfo, string invPath, Stream loadStream) 85 Scene scene, UserAccount userInfo, string invPath, Stream loadStream, bool merge)
80 { 86 {
81 m_scene = scene; 87 m_scene = scene;
88 m_merge = merge;
82 m_userInfo = userInfo; 89 m_userInfo = userInfo;
83 m_invPath = invPath; 90 m_invPath = invPath;
84 m_loadStream = loadStream; 91 m_loadStream = loadStream;
@@ -91,7 +98,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
91 /// A list of the inventory nodes loaded. If folders were loaded then only the root folders are 98 /// A list of the inventory nodes loaded. If folders were loaded then only the root folders are
92 /// returned 99 /// returned
93 /// </returns> 100 /// </returns>
94 public List<InventoryNodeBase> Execute() 101 public HashSet<InventoryNodeBase> Execute()
95 { 102 {
96 try 103 try
97 { 104 {
@@ -100,7 +107,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
100 int failedAssetRestores = 0; 107 int failedAssetRestores = 0;
101 int successfulItemRestores = 0; 108 int successfulItemRestores = 0;
102 109
103 List<InventoryNodeBase> loadedNodes = new List<InventoryNodeBase>(); 110 HashSet<InventoryNodeBase> loadedNodes = new HashSet<InventoryNodeBase>();
104 111
105 List<InventoryFolderBase> folderCandidates 112 List<InventoryFolderBase> folderCandidates
106 = InventoryArchiveUtils.FindFolderByPath( 113 = InventoryArchiveUtils.FindFolderByPath(
@@ -158,9 +165,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
158 { 165 {
159 successfulItemRestores++; 166 successfulItemRestores++;
160 167
161 // If we're loading an item directly into the given destination folder then we need to record 168 // If we aren't loading the folder containing the item then well need to update the
162 // it separately from any loaded root folders 169 // viewer separately for that item.
163 if (rootDestinationFolder == foundFolder) 170 if (!loadedNodes.Contains(foundFolder))
164 loadedNodes.Add(item); 171 loadedNodes.Add(item);
165 } 172 }
166 } 173 }
@@ -205,14 +212,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
205 string iarPath, 212 string iarPath,
206 InventoryFolderBase rootDestFolder, 213 InventoryFolderBase rootDestFolder,
207 Dictionary <string, InventoryFolderBase> resolvedFolders, 214 Dictionary <string, InventoryFolderBase> resolvedFolders,
208 List<InventoryNodeBase> loadedNodes) 215 HashSet<InventoryNodeBase> loadedNodes)
209 { 216 {
210 string iarPathExisting = iarPath; 217 string iarPathExisting = iarPath;
211 218
212// m_log.DebugFormat( 219// m_log.DebugFormat(
213// "[INVENTORY ARCHIVER]: Loading folder {0} {1}", rootDestFolder.Name, rootDestFolder.ID); 220// "[INVENTORY ARCHIVER]: Loading folder {0} {1}", rootDestFolder.Name, rootDestFolder.ID);
214 221
215 InventoryFolderBase destFolder = ResolveDestinationFolder(rootDestFolder, ref iarPathExisting, resolvedFolders); 222 InventoryFolderBase destFolder
223 = ResolveDestinationFolder(rootDestFolder, ref iarPathExisting, resolvedFolders);
216 224
217// m_log.DebugFormat( 225// m_log.DebugFormat(
218// "[INVENTORY ARCHIVER]: originalArchivePath [{0}], section already loaded [{1}]", 226// "[INVENTORY ARCHIVER]: originalArchivePath [{0}], section already loaded [{1}]",
@@ -251,46 +259,55 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
251 { 259 {
252// string originalArchivePath = archivePath; 260// string originalArchivePath = archivePath;
253 261
254 InventoryFolderBase destFolder = null; 262 while (archivePath.Length > 0)
255
256 if (archivePath.Length > 0)
257 { 263 {
258 while (null == destFolder && archivePath.Length > 0) 264 m_log.DebugFormat("[INVENTORY ARCHIVER]: Trying to resolve destination folder {0}", archivePath);
265
266 if (resolvedFolders.ContainsKey(archivePath))
267 {
268// m_log.DebugFormat(
269// "[INVENTORY ARCHIVER]: Found previously created folder from archive path {0}", archivePath);
270 return resolvedFolders[archivePath];
271 }
272 else
259 { 273 {
260// m_log.DebugFormat("[INVENTORY ARCHIVER]: Trying to resolve destination folder {0}", archivePath); 274 if (m_merge)
275 {
276 // TODO: Using m_invPath is totally wrong - what we need to do is strip the uuid from the
277 // iar name and try to find that instead.
278 string plainPath = ArchiveConstants.ExtractPlainPathFromIarPath(archivePath);
279 List<InventoryFolderBase> folderCandidates
280 = InventoryArchiveUtils.FindFolderByPath(
281 m_scene.InventoryService, m_userInfo.PrincipalID, plainPath);
282
283 if (folderCandidates.Count != 0)
284 {
285 InventoryFolderBase destFolder = folderCandidates[0];
286 resolvedFolders[archivePath] = destFolder;
287 return destFolder;
288 }
289 }
261 290
262 if (resolvedFolders.ContainsKey(archivePath)) 291 // Don't include the last slash so find the penultimate one
292 int penultimateSlashIndex = archivePath.LastIndexOf("/", archivePath.Length - 2);
293
294 if (penultimateSlashIndex >= 0)
263 { 295 {
264// m_log.DebugFormat( 296 // Remove the last section of path so that we can see if we've already resolved the parent
265// "[INVENTORY ARCHIVER]: Found previously created folder from archive path {0}", archivePath); 297 archivePath = archivePath.Remove(penultimateSlashIndex + 1);
266 destFolder = resolvedFolders[archivePath];
267 } 298 }
268 else 299 else
269 { 300 {
270 // Don't include the last slash so find the penultimate one 301// m_log.DebugFormat(
271 int penultimateSlashIndex = archivePath.LastIndexOf("/", archivePath.Length - 2); 302// "[INVENTORY ARCHIVER]: Found no previously created folder for archive path {0}",
272 303// originalArchivePath);
273 if (penultimateSlashIndex >= 0) 304 archivePath = string.Empty;
274 { 305 return rootDestFolder;
275 // Remove the last section of path so that we can see if we've already resolved the parent
276 archivePath = archivePath.Remove(penultimateSlashIndex + 1);
277 }
278 else
279 {
280// m_log.DebugFormat(
281// "[INVENTORY ARCHIVER]: Found no previously created folder for archive path {0}",
282// originalArchivePath);
283 archivePath = string.Empty;
284 destFolder = rootDestFolder;
285 }
286 } 306 }
287 } 307 }
288 } 308 }
289 309
290 if (null == destFolder) 310 return rootDestFolder;
291 destFolder = rootDestFolder;
292
293 return destFolder;
294 } 311 }
295 312
296 /// <summary> 313 /// <summary>
@@ -316,24 +333,21 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
316 string iarPathExisting, 333 string iarPathExisting,
317 string iarPathToReplicate, 334 string iarPathToReplicate,
318 Dictionary <string, InventoryFolderBase> resolvedFolders, 335 Dictionary <string, InventoryFolderBase> resolvedFolders,
319 List<InventoryNodeBase> loadedNodes) 336 HashSet<InventoryNodeBase> loadedNodes)
320 { 337 {
321 string[] rawDirsToCreate = iarPathToReplicate.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries); 338 string[] rawDirsToCreate = iarPathToReplicate.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
322 int i = 0;
323 339
324 while (i < rawDirsToCreate.Length) 340 for (int i = 0; i < rawDirsToCreate.Length; i++)
325 { 341 {
326// m_log.DebugFormat("[INVENTORY ARCHIVER]: Creating folder {0} from IAR", rawDirsToCreate[i]); 342// m_log.DebugFormat("[INVENTORY ARCHIVER]: Creating folder {0} from IAR", rawDirsToCreate[i]);
327 343
344 if (!rawDirsToCreate[i].Contains(ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR))
345 continue;
346
328 int identicalNameIdentifierIndex 347 int identicalNameIdentifierIndex
329 = rawDirsToCreate[i].LastIndexOf( 348 = rawDirsToCreate[i].LastIndexOf(
330 ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR); 349 ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR);
331 350
332 if (identicalNameIdentifierIndex < 0)
333 {
334 i++;
335 continue;
336 }
337 string newFolderName = rawDirsToCreate[i].Remove(identicalNameIdentifierIndex); 351 string newFolderName = rawDirsToCreate[i].Remove(identicalNameIdentifierIndex);
338 352
339 newFolderName = InventoryArchiveUtils.UnescapeArchivePath(newFolderName); 353 newFolderName = InventoryArchiveUtils.UnescapeArchivePath(newFolderName);
@@ -356,8 +370,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
356 370
357 if (0 == i) 371 if (0 == i)
358 loadedNodes.Add(destFolder); 372 loadedNodes.Add(destFolder);
359
360 i++;
361 } 373 }
362 } 374 }
363 375
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
index f7a2b09..f03f2a1 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
@@ -91,12 +91,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
91 91
92 scene.AddCommand( 92 scene.AddCommand(
93 this, "load iar", 93 this, "load iar",
94 "load iar <first> <last> <inventory path> <password> [<IAR path>]", 94 "load iar <first> <last> <inventory path> <password> [<IAR path>]",
95 //"load iar [--merge] <first> <last> <inventory path> <password> [<IAR path>]", 95 //"load iar [--merge] <first> <last> <inventory path> <password> [<IAR path>]",
96 "Load user inventory archive (IAR).", 96 "Load user inventory archive (IAR).",
97 //"--merge is an option which merges the loaded IAR with existing inventory folders where possible, rather than always creating new ones" 97 //"--merge is an option which merges the loaded IAR with existing inventory folders where possible, rather than always creating new ones"
98 //+ "<first> is user's first name." + Environment.NewLine 98 //+ "<first> is user's first name." + Environment.NewLine
99 "<first> is user's first name." + Environment.NewLine 99 "<first> is user's first name." + Environment.NewLine
100 + "<last> is user's last name." + Environment.NewLine 100 + "<last> is user's last name." + Environment.NewLine
101 + "<inventory path> is the path inside the user's inventory where the IAR should be loaded." + Environment.NewLine 101 + "<inventory path> is the path inside the user's inventory where the IAR should be loaded." + Environment.NewLine
102 + "<password> is the user's password." + Environment.NewLine 102 + "<password> is the user's password." + Environment.NewLine
@@ -136,16 +136,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
136 if (handlerInventoryArchiveSaved != null) 136 if (handlerInventoryArchiveSaved != null)
137 handlerInventoryArchiveSaved(id, succeeded, userInfo, invPath, saveStream, reportedException); 137 handlerInventoryArchiveSaved(id, succeeded, userInfo, invPath, saveStream, reportedException);
138 } 138 }
139 139
140 public bool ArchiveInventory( 140 public bool ArchiveInventory(
141 Guid id, string firstName, string lastName, string invPath, string pass, Stream saveStream) 141 Guid id, string firstName, string lastName, string invPath, string pass, Stream saveStream)
142 { 142 {
143 return ArchiveInventory(id, firstName, lastName, invPath, pass, saveStream, new Dictionary<string, object>()); 143 return ArchiveInventory(id, firstName, lastName, invPath, pass, saveStream, new Dictionary<string, object>());
144 } 144 }
145 145
146 public bool ArchiveInventory( 146 public bool ArchiveInventory(
147 Guid id, string firstName, string lastName, string invPath, string pass, Stream saveStream, 147 Guid id, string firstName, string lastName, string invPath, string pass, Stream saveStream,
148 Dictionary<string, object> options) 148 Dictionary<string, object> options)
149 { 149 {
150 if (m_scenes.Count > 0) 150 if (m_scenes.Count > 0)
151 { 151 {
@@ -184,8 +184,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
184 } 184 }
185 185
186 public bool ArchiveInventory( 186 public bool ArchiveInventory(
187 Guid id, string firstName, string lastName, string invPath, string pass, string savePath, 187 Guid id, string firstName, string lastName, string invPath, string pass, string savePath,
188 Dictionary<string, object> options) 188 Dictionary<string, object> options)
189 { 189 {
190 if (m_scenes.Count > 0) 190 if (m_scenes.Count > 0)
191 { 191 {
@@ -224,13 +224,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
224 } 224 }
225 225
226 public bool DearchiveInventory(string firstName, string lastName, string invPath, string pass, Stream loadStream) 226 public bool DearchiveInventory(string firstName, string lastName, string invPath, string pass, Stream loadStream)
227 { 227 {
228 return DearchiveInventory(firstName, lastName, invPath, pass, loadStream, new Dictionary<string, object>()); 228 return DearchiveInventory(firstName, lastName, invPath, pass, loadStream, new Dictionary<string, object>());
229 } 229 }
230 230
231 public bool DearchiveInventory( 231 public bool DearchiveInventory(
232 string firstName, string lastName, string invPath, string pass, Stream loadStream, 232 string firstName, string lastName, string invPath, string pass, Stream loadStream,
233 Dictionary<string, object> options) 233 Dictionary<string, object> options)
234 { 234 {
235 if (m_scenes.Count > 0) 235 if (m_scenes.Count > 0)
236 { 236 {
@@ -241,10 +241,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
241 if (CheckPresence(userInfo.PrincipalID)) 241 if (CheckPresence(userInfo.PrincipalID))
242 { 242 {
243 InventoryArchiveReadRequest request; 243 InventoryArchiveReadRequest request;
244 bool merge = (options.ContainsKey("merge") ? (bool)options["merge"] : false);
244 245
245 try 246 try
246 { 247 {
247 request = new InventoryArchiveReadRequest(m_aScene, userInfo, invPath, loadStream); 248 request = new InventoryArchiveReadRequest(m_aScene, userInfo, invPath, loadStream, merge);
248 } 249 }
249 catch (EntryPointNotFoundException e) 250 catch (EntryPointNotFoundException e)
250 { 251 {
@@ -273,8 +274,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
273 } 274 }
274 275
275 public bool DearchiveInventory( 276 public bool DearchiveInventory(
276 string firstName, string lastName, string invPath, string pass, string loadPath, 277 string firstName, string lastName, string invPath, string pass, string loadPath,
277 Dictionary<string, object> options) 278 Dictionary<string, object> options)
278 { 279 {
279 if (m_scenes.Count > 0) 280 if (m_scenes.Count > 0)
280 { 281 {
@@ -285,10 +286,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
285 if (CheckPresence(userInfo.PrincipalID)) 286 if (CheckPresence(userInfo.PrincipalID))
286 { 287 {
287 InventoryArchiveReadRequest request; 288 InventoryArchiveReadRequest request;
289 bool merge = (options.ContainsKey("merge") ? (bool)options["merge"] : false);
288 290
289 try 291 try
290 { 292 {
291 request = new InventoryArchiveReadRequest(m_aScene, userInfo, invPath, loadPath); 293 request = new InventoryArchiveReadRequest(m_aScene, userInfo, invPath, loadPath, merge);
292 } 294 }
293 catch (EntryPointNotFoundException e) 295 catch (EntryPointNotFoundException e)
294 { 296 {
@@ -334,7 +336,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
334 if (mainParams.Count < 6) 336 if (mainParams.Count < 6)
335 { 337 {
336 m_log.Error( 338 m_log.Error(
337 "[INVENTORY ARCHIVER]: usage is load iar <first name> <last name> <inventory path> <user password> [<load file path>]"); 339 "[INVENTORY ARCHIVER]: usage is load iar [--merge] <first name> <last name> <inventory path> <user password> [<load file path>]");
338 return; 340 return;
339 } 341 }
340 342
@@ -356,7 +358,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
356 catch (InventoryArchiverException e) 358 catch (InventoryArchiverException e)
357 { 359 {
358 m_log.ErrorFormat("[INVENTORY ARCHIVER]: {0}", e.Message); 360 m_log.ErrorFormat("[INVENTORY ARCHIVER]: {0}", e.Message);
359 } 361 }
360 } 362 }
361 363
362 /// <summary> 364 /// <summary>
@@ -469,7 +471,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
469 /// Notify the client of loaded nodes if they are logged in 471 /// Notify the client of loaded nodes if they are logged in
470 /// </summary> 472 /// </summary>
471 /// <param name="loadedNodes">Can be empty. In which case, nothing happens</param> 473 /// <param name="loadedNodes">Can be empty. In which case, nothing happens</param>
472 private void UpdateClientWithLoadedNodes(UserAccount userInfo, List<InventoryNodeBase> loadedNodes) 474 private void UpdateClientWithLoadedNodes(UserAccount userInfo, HashSet<InventoryNodeBase> loadedNodes)
473 { 475 {
474 if (loadedNodes.Count == 0) 476 if (loadedNodes.Count == 0)
475 return; 477 return;
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs
index 4531bfd..2d80382 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs
@@ -629,7 +629,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
629 UserAccount ua1 = UserProfileTestUtils.CreateUserWithInventory(scene); 629 UserAccount ua1 = UserProfileTestUtils.CreateUserWithInventory(scene);
630 630
631 Dictionary <string, InventoryFolderBase> foldersCreated = new Dictionary<string, InventoryFolderBase>(); 631 Dictionary <string, InventoryFolderBase> foldersCreated = new Dictionary<string, InventoryFolderBase>();
632 List<InventoryNodeBase> nodesLoaded = new List<InventoryNodeBase>(); 632 HashSet<InventoryNodeBase> nodesLoaded = new HashSet<InventoryNodeBase>();
633 633
634 string folder1Name = "1"; 634 string folder1Name = "1";
635 string folder2aName = "2a"; 635 string folder2aName = "2a";
@@ -644,7 +644,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
644 644
645 { 645 {
646 // Test replication of path1 646 // Test replication of path1
647 new InventoryArchiveReadRequest(scene, ua1, null, (Stream)null) 647 new InventoryArchiveReadRequest(scene, ua1, null, (Stream)null, false)
648 .ReplicateArchivePathToUserInventory( 648 .ReplicateArchivePathToUserInventory(
649 iarPath1, scene.InventoryService.GetRootFolder(ua1.PrincipalID), 649 iarPath1, scene.InventoryService.GetRootFolder(ua1.PrincipalID),
650 foldersCreated, nodesLoaded); 650 foldersCreated, nodesLoaded);
@@ -661,7 +661,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
661 661
662 { 662 {
663 // Test replication of path2 663 // Test replication of path2
664 new InventoryArchiveReadRequest(scene, ua1, null, (Stream)null) 664 new InventoryArchiveReadRequest(scene, ua1, null, (Stream)null, false)
665 .ReplicateArchivePathToUserInventory( 665 .ReplicateArchivePathToUserInventory(
666 iarPath2, scene.InventoryService.GetRootFolder(ua1.PrincipalID), 666 iarPath2, scene.InventoryService.GetRootFolder(ua1.PrincipalID),
667 foldersCreated, nodesLoaded); 667 foldersCreated, nodesLoaded);
@@ -707,10 +707,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
707 707
708 string itemArchivePath = string.Join("", new string[] { folder1ArchiveName, folder2ArchiveName }); 708 string itemArchivePath = string.Join("", new string[] { folder1ArchiveName, folder2ArchiveName });
709 709
710 new InventoryArchiveReadRequest(scene, ua1, null, (Stream)null) 710 new InventoryArchiveReadRequest(scene, ua1, null, (Stream)null, false)
711 .ReplicateArchivePathToUserInventory( 711 .ReplicateArchivePathToUserInventory(
712 itemArchivePath, scene.InventoryService.GetRootFolder(ua1.PrincipalID), 712 itemArchivePath, scene.InventoryService.GetRootFolder(ua1.PrincipalID),
713 new Dictionary<string, InventoryFolderBase>(), new List<InventoryNodeBase>()); 713 new Dictionary<string, InventoryFolderBase>(), new HashSet<InventoryNodeBase>());
714 714
715 List<InventoryFolderBase> folder1PostCandidates 715 List<InventoryFolderBase> folder1PostCandidates
716 = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, ua1.PrincipalID, folder1ExistingName); 716 = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, ua1.PrincipalID, folder1ExistingName);
@@ -732,5 +732,45 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
732 = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, folder1Post, "b"); 732 = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, folder1Post, "b");
733 Assert.That(folder2PostCandidates.Count, Is.EqualTo(1)); 733 Assert.That(folder2PostCandidates.Count, Is.EqualTo(1));
734 } 734 }
735
736 /// <summary>
737 /// Test replication of a partly existing archive path to the user's inventory. This should create
738 /// a merged path.
739 /// </summary>
740 [Test]
741 public void TestMergeIarPath()
742 {
743 TestHelper.InMethod();
744 log4net.Config.XmlConfigurator.Configure();
745
746 Scene scene = SceneSetupHelpers.SetupScene("inventory");
747 UserAccount ua1 = UserProfileTestUtils.CreateUserWithInventory(scene);
748
749 string folder1ExistingName = "a";
750 string folder2Name = "b";
751
752 InventoryFolderBase folder1
753 = UserInventoryTestUtils.CreateInventoryFolder(
754 scene.InventoryService, ua1.PrincipalID, folder1ExistingName);
755
756 string folder1ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder1ExistingName, UUID.Random());
757 string folder2ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2Name, UUID.Random());
758
759 string itemArchivePath = string.Join("", new string[] { folder1ArchiveName, folder2ArchiveName });
760
761 new InventoryArchiveReadRequest(scene, ua1, folder1ExistingName, (Stream)null, true)
762 .ReplicateArchivePathToUserInventory(
763 itemArchivePath, scene.InventoryService.GetRootFolder(ua1.PrincipalID),
764 new Dictionary<string, InventoryFolderBase>(), new HashSet<InventoryNodeBase>());
765
766 List<InventoryFolderBase> folder1PostCandidates
767 = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, ua1.PrincipalID, folder1ExistingName);
768 Assert.That(folder1PostCandidates.Count, Is.EqualTo(1));
769 Assert.That(folder1PostCandidates[0].ID, Is.EqualTo(folder1.ID));
770
771 List<InventoryFolderBase> folder2PostCandidates
772 = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, folder1PostCandidates[0], "b");
773 Assert.That(folder2PostCandidates.Count, Is.EqualTo(1));
774 }
735 } 775 }
736} \ No newline at end of file 776} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs b/OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs
index 36dae6b..9c20d68 100644
--- a/OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
@@ -173,16 +173,16 @@ namespace OpenSim.Region.CoreModules.Framework.Library
173 m_log.InfoFormat("[LIBRARY MODULE]: Loading library archive {0} ({1})...", iarFileName, simpleName); 173 m_log.InfoFormat("[LIBRARY MODULE]: Loading library archive {0} ({1})...", iarFileName, simpleName);
174 simpleName = GetInventoryPathFromName(simpleName); 174 simpleName = GetInventoryPathFromName(simpleName);
175 175
176 InventoryArchiveReadRequest archread = new InventoryArchiveReadRequest(m_MockScene, uinfo, simpleName, iarFileName); 176 InventoryArchiveReadRequest archread = new InventoryArchiveReadRequest(m_MockScene, uinfo, simpleName, iarFileName, false);
177 try 177 try
178 { 178 {
179 List<InventoryNodeBase> nodes = archread.Execute(); 179 HashSet<InventoryNodeBase> nodes = archread.Execute();
180 if (nodes != null && nodes.Count == 0) 180 if (nodes != null && nodes.Count == 0)
181 { 181 {
182 // didn't find the subfolder with the given name; place it on the top 182 // didn't find the subfolder with the given name; place it on the top
183 m_log.InfoFormat("[LIBRARY MODULE]: Didn't find {0} in library. Placing archive on the top level", simpleName); 183 m_log.InfoFormat("[LIBRARY MODULE]: Didn't find {0} in library. Placing archive on the top level", simpleName);
184 archread.Close(); 184 archread.Close();
185 archread = new InventoryArchiveReadRequest(m_MockScene, uinfo, "/", iarFileName); 185 archread = new InventoryArchiveReadRequest(m_MockScene, uinfo, "/", iarFileName, false);
186 archread.Execute(); 186 archread.Execute();
187 } 187 }
188 foreach (InventoryNodeBase node in nodes) 188 foreach (InventoryNodeBase node in nodes)
diff --git a/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs b/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs
new file mode 100644
index 0000000..82ad109
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs
@@ -0,0 +1,596 @@
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.Collections;
30using System.Collections.Generic;
31using System.Collections.Specialized;
32using System.Reflection;
33using System.IO;
34using System.Web;
35using System.Xml;
36using log4net;
37using Mono.Addins;
38using Nini.Config;
39using OpenMetaverse;
40using OpenMetaverse.Messages.Linden;
41using OpenMetaverse.StructuredData;
42using OpenSim.Framework;
43using OpenSim.Framework.Capabilities;
44using OpenSim.Framework.Servers;
45using OpenSim.Framework.Servers.HttpServer;
46using OpenSim.Region.Framework.Interfaces;
47using OpenSim.Region.Framework.Scenes;
48using OpenSim.Services.Interfaces;
49using Caps = OpenSim.Framework.Capabilities.Caps;
50using OSDArray = OpenMetaverse.StructuredData.OSDArray;
51using OSDMap = OpenMetaverse.StructuredData.OSDMap;
52
53namespace OpenSim.Region.CoreModules.Media.Moap
54{
55 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "MoapModule")]
56 public class MoapModule : INonSharedRegionModule, IMoapModule
57 {
58 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
59
60 public string Name { get { return "MoapModule"; } }
61 public Type ReplaceableInterface { get { return null; } }
62
63 /// <summary>
64 /// Is this module enabled?
65 /// </summary>
66 protected bool m_isEnabled = true;
67
68 /// <summary>
69 /// The scene to which this module is attached
70 /// </summary>
71 protected Scene m_scene;
72
73 /// <summary>
74 /// Track the ObjectMedia capabilities given to users keyed by path
75 /// </summary>
76 protected Dictionary<string, UUID> m_omCapUsers = new Dictionary<string, UUID>();
77
78 /// <summary>
79 /// Track the ObjectMedia capabilities given to users keyed by agent. Lock m_omCapUsers to manipulate.
80 /// </summary>
81 protected Dictionary<UUID, string> m_omCapUrls = new Dictionary<UUID, string>();
82
83 /// <summary>
84 /// Track the ObjectMediaUpdate capabilities given to users keyed by path
85 /// </summary>
86 protected Dictionary<string, UUID> m_omuCapUsers = new Dictionary<string, UUID>();
87
88 /// <summary>
89 /// Track the ObjectMediaUpdate capabilities given to users keyed by agent. Lock m_omuCapUsers to manipulate
90 /// </summary>
91 protected Dictionary<UUID, string> m_omuCapUrls = new Dictionary<UUID, string>();
92
93 public void Initialise(IConfigSource configSource)
94 {
95 IConfig config = configSource.Configs["MediaOnAPrim"];
96
97 if (config != null && !config.GetBoolean("Enabled", false))
98 m_isEnabled = false;
99// else
100// m_log.Debug("[MOAP]: Initialised module.")l
101 }
102
103 public void AddRegion(Scene scene)
104 {
105 if (!m_isEnabled)
106 return;
107
108 m_scene = scene;
109 m_scene.RegisterModuleInterface<IMoapModule>(this);
110 }
111
112 public void RemoveRegion(Scene scene) {}
113
114 public void RegionLoaded(Scene scene)
115 {
116 if (!m_isEnabled)
117 return;
118
119 m_scene.EventManager.OnRegisterCaps += OnRegisterCaps;
120 m_scene.EventManager.OnDeregisterCaps += OnDeregisterCaps;
121 m_scene.EventManager.OnSceneObjectPartCopy += OnSceneObjectPartCopy;
122 }
123
124 public void Close()
125 {
126 if (!m_isEnabled)
127 return;
128
129 m_scene.EventManager.OnRegisterCaps -= OnRegisterCaps;
130 m_scene.EventManager.OnDeregisterCaps -= OnDeregisterCaps;
131 m_scene.EventManager.OnSceneObjectPartCopy -= OnSceneObjectPartCopy;
132 }
133
134 public void OnRegisterCaps(UUID agentID, Caps caps)
135 {
136// m_log.DebugFormat(
137// "[MOAP]: Registering ObjectMedia and ObjectMediaNavigate capabilities for agent {0}", agentID);
138
139 string omCapUrl = "/CAPS/" + UUID.Random();
140
141 lock (m_omCapUsers)
142 {
143 m_omCapUsers[omCapUrl] = agentID;
144 m_omCapUrls[agentID] = omCapUrl;
145
146 // Even though we're registering for POST we're going to get GETS and UPDATES too
147 caps.RegisterHandler(
148 "ObjectMedia", new RestStreamHandler("POST", omCapUrl, HandleObjectMediaMessage));
149 }
150
151 string omuCapUrl = "/CAPS/" + UUID.Random();
152
153 lock (m_omuCapUsers)
154 {
155 m_omuCapUsers[omuCapUrl] = agentID;
156 m_omuCapUrls[agentID] = omuCapUrl;
157
158 // Even though we're registering for POST we're going to get GETS and UPDATES too
159 caps.RegisterHandler(
160 "ObjectMediaNavigate", new RestStreamHandler("POST", omuCapUrl, HandleObjectMediaNavigateMessage));
161 }
162 }
163
164 public void OnDeregisterCaps(UUID agentID, Caps caps)
165 {
166 lock (m_omCapUsers)
167 {
168 string path = m_omCapUrls[agentID];
169 m_omCapUrls.Remove(agentID);
170 m_omCapUsers.Remove(path);
171 }
172
173 lock (m_omuCapUsers)
174 {
175 string path = m_omuCapUrls[agentID];
176 m_omuCapUrls.Remove(agentID);
177 m_omuCapUsers.Remove(path);
178 }
179 }
180
181 protected void OnSceneObjectPartCopy(SceneObjectPart copy, SceneObjectPart original, bool userExposed)
182 {
183 if (original.Shape.Media != null)
184 {
185 PrimitiveBaseShape.MediaList dupeMedia = new PrimitiveBaseShape.MediaList();
186 lock (original.Shape.Media)
187 {
188 foreach (MediaEntry me in original.Shape.Media)
189 {
190 if (me != null)
191 dupeMedia.Add(MediaEntry.FromOSD(me.GetOSD()));
192 else
193 dupeMedia.Add(null);
194 }
195 }
196
197 copy.Shape.Media = dupeMedia;
198 }
199 }
200
201 public MediaEntry GetMediaEntry(SceneObjectPart part, int face)
202 {
203 MediaEntry me = null;
204
205 CheckFaceParam(part, face);
206
207 List<MediaEntry> media = part.Shape.Media;
208
209 if (null == media)
210 {
211 me = null;
212 }
213 else
214 {
215 lock (media)
216 me = media[face];
217
218 // TODO: Really need a proper copy constructor down in libopenmetaverse
219 if (me != null)
220 me = MediaEntry.FromOSD(me.GetOSD());
221 }
222
223// m_log.DebugFormat("[MOAP]: GetMediaEntry for {0} face {1} found {2}", part.Name, face, me);
224
225 return me;
226 }
227
228 public void SetMediaEntry(SceneObjectPart part, int face, MediaEntry me)
229 {
230 CheckFaceParam(part, face);
231
232 if (null == part.Shape.Media)
233 part.Shape.Media = new PrimitiveBaseShape.MediaList(new MediaEntry[part.GetNumberOfSides()]);
234
235 lock (part.Shape.Media)
236 part.Shape.Media[face] = me;
237
238 UpdateMediaUrl(part, UUID.Zero);
239 part.ScheduleFullUpdate();
240 part.TriggerScriptChangedEvent(Changed.MEDIA);
241 }
242
243 public void ClearMediaEntry(SceneObjectPart part, int face)
244 {
245 SetMediaEntry(part, face, null);
246 }
247
248 /// <summary>
249 /// Sets or gets per face media textures.
250 /// </summary>
251 /// <param name="request"></param>
252 /// <param name="path"></param>
253 /// <param name="param"></param>
254 /// <param name="httpRequest"></param>
255 /// <param name="httpResponse"></param>
256 /// <returns></returns>
257 protected string HandleObjectMediaMessage(
258 string request, string path, string param, OSHttpRequest httpRequest, OSHttpResponse httpResponse)
259 {
260// m_log.DebugFormat("[MOAP]: Got ObjectMedia path [{0}], raw request [{1}]", path, request);
261
262 OSDMap osd = (OSDMap)OSDParser.DeserializeLLSDXml(request);
263 ObjectMediaMessage omm = new ObjectMediaMessage();
264 omm.Deserialize(osd);
265
266 if (omm.Request is ObjectMediaRequest)
267 return HandleObjectMediaRequest(omm.Request as ObjectMediaRequest);
268 else if (omm.Request is ObjectMediaUpdate)
269 return HandleObjectMediaUpdate(path, omm.Request as ObjectMediaUpdate);
270
271 throw new Exception(
272 string.Format(
273 "[MOAP]: ObjectMediaMessage has unrecognized ObjectMediaBlock of {0}",
274 omm.Request.GetType()));
275 }
276
277 /// <summary>
278 /// Handle a fetch request for media textures
279 /// </summary>
280 /// <param name="omr"></param>
281 /// <returns></returns>
282 protected string HandleObjectMediaRequest(ObjectMediaRequest omr)
283 {
284 UUID primId = omr.PrimID;
285
286 SceneObjectPart part = m_scene.GetSceneObjectPart(primId);
287
288 if (null == part)
289 {
290 m_log.WarnFormat(
291 "[MOAP]: Received a GET ObjectMediaRequest for prim {0} but this doesn't exist in region {1}",
292 primId, m_scene.RegionInfo.RegionName);
293 return string.Empty;
294 }
295
296 if (null == part.Shape.Media)
297 return string.Empty;
298
299 ObjectMediaResponse resp = new ObjectMediaResponse();
300
301 resp.PrimID = primId;
302
303 lock (part.Shape.Media)
304 resp.FaceMedia = part.Shape.Media.ToArray();
305
306 resp.Version = part.MediaUrl;
307
308 string rawResp = OSDParser.SerializeLLSDXmlString(resp.Serialize());
309
310// m_log.DebugFormat("[MOAP]: Got HandleObjectMediaRequestGet raw response is [{0}]", rawResp);
311
312 return rawResp;
313 }
314
315 /// <summary>
316 /// Handle an update of media textures.
317 /// </summary>
318 /// <param name="path">Path on which this request was made</param>
319 /// <param name="omu">/param>
320 /// <returns></returns>
321 protected string HandleObjectMediaUpdate(string path, ObjectMediaUpdate omu)
322 {
323 UUID primId = omu.PrimID;
324
325 SceneObjectPart part = m_scene.GetSceneObjectPart(primId);
326
327 if (null == part)
328 {
329 m_log.WarnFormat(
330 "[MOAP]: Received an UPDATE ObjectMediaRequest for prim {0} but this doesn't exist in region {1}",
331 primId, m_scene.RegionInfo.RegionName);
332 return string.Empty;
333 }
334
335// m_log.DebugFormat("[MOAP]: Received {0} media entries for prim {1}", omu.FaceMedia.Length, primId);
336
337// for (int i = 0; i < omu.FaceMedia.Length; i++)
338// {
339// MediaEntry me = omu.FaceMedia[i];
340// string v = (null == me ? "null": OSDParser.SerializeLLSDXmlString(me.GetOSD()));
341// m_log.DebugFormat("[MOAP]: Face {0} [{1}]", i, v);
342// }
343
344 if (omu.FaceMedia.Length > part.GetNumberOfSides())
345 {
346 m_log.WarnFormat(
347 "[MOAP]: Received {0} media entries from client for prim {1} {2} but this prim has only {3} faces. Dropping request.",
348 omu.FaceMedia.Length, part.Name, part.UUID, part.GetNumberOfSides());
349 return string.Empty;
350 }
351
352 UUID agentId = default(UUID);
353
354 lock (m_omCapUsers)
355 agentId = m_omCapUsers[path];
356
357 List<MediaEntry> media = part.Shape.Media;
358
359 if (null == media)
360 {
361// m_log.DebugFormat("[MOAP]: Setting all new media list for {0}", part.Name);
362 part.Shape.Media = new PrimitiveBaseShape.MediaList(omu.FaceMedia);
363
364 for (int i = 0; i < omu.FaceMedia.Length; i++)
365 {
366 if (omu.FaceMedia[i] != null)
367 {
368 // FIXME: Race condition here since some other texture entry manipulator may overwrite/get
369 // overwritten. Unfortunately, PrimitiveBaseShape does not allow us to change texture entry
370 // directly.
371 Primitive.TextureEntry te = part.Shape.Textures;
372 Primitive.TextureEntryFace face = te.CreateFace((uint)i);
373 face.MediaFlags = true;
374 part.Shape.Textures = te;
375// m_log.DebugFormat(
376// "[MOAP]: Media flags for face {0} is {1}",
377// i, part.Shape.Textures.FaceTextures[i].MediaFlags);
378 }
379 }
380 }
381 else
382 {
383 // We need to go through the media textures one at a time to make sure that we have permission
384 // to change them
385
386 // FIXME: Race condition here since some other texture entry manipulator may overwrite/get
387 // overwritten. Unfortunately, PrimitiveBaseShape does not allow us to change texture entry
388 // directly.
389 Primitive.TextureEntry te = part.Shape.Textures;
390
391 lock (media)
392 {
393 for (int i = 0; i < media.Count; i++)
394 {
395 if (m_scene.Permissions.CanControlPrimMedia(agentId, part.UUID, i))
396 {
397 media[i] = omu.FaceMedia[i];
398
399 // When a face is cleared this is done by setting the MediaFlags in the TextureEntry via a normal
400 // texture update, so we don't need to worry about clearing MediaFlags here.
401 if (null == media[i])
402 continue;
403
404 Primitive.TextureEntryFace face = te.CreateFace((uint)i);
405 face.MediaFlags = true;
406
407 // m_log.DebugFormat(
408 // "[MOAP]: Media flags for face {0} is {1}",
409 // i, face.MediaFlags);
410 // m_log.DebugFormat("[MOAP]: Set media entry for face {0} on {1}", i, part.Name);
411 }
412 }
413 }
414
415 part.Shape.Textures = te;
416
417// for (int i2 = 0; i2 < part.Shape.Textures.FaceTextures.Length; i2++)
418// m_log.DebugFormat("[MOAP]: FaceTexture[{0}] is {1}", i2, part.Shape.Textures.FaceTextures[i2]);
419 }
420
421 UpdateMediaUrl(part, agentId);
422
423 // Arguably, we could avoid sending a full update to the avatar that just changed the texture.
424 part.ScheduleFullUpdate();
425
426 part.TriggerScriptChangedEvent(Changed.MEDIA);
427
428 return string.Empty;
429 }
430
431 /// <summary>
432 /// Received from the viewer if a user has changed the url of a media texture.
433 /// </summary>
434 /// <param name="request"></param>
435 /// <param name="path"></param>
436 /// <param name="param"></param>
437 /// <param name="httpRequest">/param>
438 /// <param name="httpResponse">/param>
439 /// <returns></returns>
440 protected string HandleObjectMediaNavigateMessage(
441 string request, string path, string param, OSHttpRequest httpRequest, OSHttpResponse httpResponse)
442 {
443// m_log.DebugFormat("[MOAP]: Got ObjectMediaNavigate request [{0}]", request);
444
445 OSDMap osd = (OSDMap)OSDParser.DeserializeLLSDXml(request);
446 ObjectMediaNavigateMessage omn = new ObjectMediaNavigateMessage();
447 omn.Deserialize(osd);
448
449 UUID primId = omn.PrimID;
450
451 SceneObjectPart part = m_scene.GetSceneObjectPart(primId);
452
453 if (null == part)
454 {
455 m_log.WarnFormat(
456 "[MOAP]: Received an ObjectMediaNavigateMessage for prim {0} but this doesn't exist in region {1}",
457 primId, m_scene.RegionInfo.RegionName);
458 return string.Empty;
459 }
460
461 UUID agentId = default(UUID);
462
463 lock (m_omuCapUsers)
464 agentId = m_omuCapUsers[path];
465
466 if (!m_scene.Permissions.CanInteractWithPrimMedia(agentId, part.UUID, omn.Face))
467 return string.Empty;
468
469// m_log.DebugFormat(
470// "[MOAP]: Received request to update media entry for face {0} on prim {1} {2} to {3}",
471// omn.Face, part.Name, part.UUID, omn.URL);
472
473 // If media has never been set for this prim, then just return.
474 if (null == part.Shape.Media)
475 return string.Empty;
476
477 MediaEntry me = null;
478
479 lock (part.Shape.Media)
480 me = part.Shape.Media[omn.Face];
481
482 // Do the same if media has not been set up for a specific face
483 if (null == me)
484 return string.Empty;
485
486 if (me.EnableWhiteList)
487 {
488 if (!CheckUrlAgainstWhitelist(omn.URL, me.WhiteList))
489 {
490// m_log.DebugFormat(
491// "[MOAP]: Blocking change of face {0} on prim {1} {2} to {3} since it's not on the enabled whitelist",
492// omn.Face, part.Name, part.UUID, omn.URL);
493
494 return string.Empty;
495 }
496 }
497
498 me.CurrentURL = omn.URL;
499
500 UpdateMediaUrl(part, agentId);
501
502 part.ScheduleFullUpdate();
503
504 part.TriggerScriptChangedEvent(Changed.MEDIA);
505
506 return OSDParser.SerializeLLSDXmlString(new OSD());
507 }
508
509 /// <summary>
510 /// Check that the face number is valid for the given prim.
511 /// </summary>
512 /// <param name="part"></param>
513 /// <param name="face"></param>
514 protected void CheckFaceParam(SceneObjectPart part, int face)
515 {
516 if (face < 0)
517 throw new ArgumentException("Face cannot be less than zero");
518
519 int maxFaces = part.GetNumberOfSides() - 1;
520 if (face > maxFaces)
521 throw new ArgumentException(
522 string.Format("Face argument was {0} but max is {1}", face, maxFaces));
523 }
524
525 /// <summary>
526 /// Update the media url of the given part
527 /// </summary>
528 /// <param name="part"></param>
529 /// <param name="updateId">
530 /// The id to attach to this update. Normally, this is the user that changed the
531 /// texture
532 /// </param>
533 protected void UpdateMediaUrl(SceneObjectPart part, UUID updateId)
534 {
535 if (null == part.MediaUrl)
536 {
537 // TODO: We can't set the last changer until we start tracking which cap we give to which agent id
538 part.MediaUrl = "x-mv:0000000000/" + updateId;
539 }
540 else
541 {
542 string rawVersion = part.MediaUrl.Substring(5, 10);
543 int version = int.Parse(rawVersion);
544 part.MediaUrl = string.Format("x-mv:{0:D10}/{1}", ++version, updateId);
545 }
546
547// m_log.DebugFormat("[MOAP]: Storing media url [{0}] in prim {1} {2}", part.MediaUrl, part.Name, part.UUID);
548 }
549
550 /// <summary>
551 /// Check the given url against the given whitelist.
552 /// </summary>
553 /// <param name="rawUrl"></param>
554 /// <param name="whitelist"></param>
555 /// <returns>true if the url matches an entry on the whitelist, false otherwise</returns>
556 protected bool CheckUrlAgainstWhitelist(string rawUrl, string[] whitelist)
557 {
558 Uri url = new Uri(rawUrl);
559
560 foreach (string origWlUrl in whitelist)
561 {
562 string wlUrl = origWlUrl;
563
564 // Deal with a line-ending wildcard
565 if (wlUrl.EndsWith("*"))
566 wlUrl = wlUrl.Remove(wlUrl.Length - 1);
567
568// m_log.DebugFormat("[MOAP]: Checking whitelist URL pattern {0}", origWlUrl);
569
570 // Handle a line starting wildcard slightly differently since this can only match the domain, not the path
571 if (wlUrl.StartsWith("*"))
572 {
573 wlUrl = wlUrl.Substring(1);
574
575 if (url.Host.Contains(wlUrl))
576 {
577// m_log.DebugFormat("[MOAP]: Whitelist URL {0} matches {1}", origWlUrl, rawUrl);
578 return true;
579 }
580 }
581 else
582 {
583 string urlToMatch = url.Authority + url.AbsolutePath;
584
585 if (urlToMatch.StartsWith(wlUrl))
586 {
587// m_log.DebugFormat("[MOAP]: Whitelist URL {0} matches {1}", origWlUrl, rawUrl);
588 return true;
589 }
590 }
591 }
592
593 return false;
594 }
595 }
596} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
index 8223f12..b1747ef 100644
--- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
+++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
@@ -164,6 +164,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
164 private Dictionary<string, bool> GrantYP = new Dictionary<string, bool>(); 164 private Dictionary<string, bool> GrantYP = new Dictionary<string, bool>();
165 private IFriendsModule m_friendsModule; 165 private IFriendsModule m_friendsModule;
166 private IGroupsModule m_groupsModule; 166 private IGroupsModule m_groupsModule;
167 private IMoapModule m_moapModule;
167 168
168 #endregion 169 #endregion
169 170
@@ -177,7 +178,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
177 178
178 string permissionModules = myConfig.GetString("permissionmodules", "DefaultPermissionsModule"); 179 string permissionModules = myConfig.GetString("permissionmodules", "DefaultPermissionsModule");
179 180
180 List<string> modules=new List<string>(permissionModules.Split(',')); 181 List<string> modules = new List<string>(permissionModules.Split(','));
181 182
182 if (!modules.Contains("DefaultPermissionsModule")) 183 if (!modules.Contains("DefaultPermissionsModule"))
183 return; 184 return;
@@ -249,6 +250,9 @@ namespace OpenSim.Region.CoreModules.World.Permissions
249 m_scene.Permissions.OnDeleteUserInventory += CanDeleteUserInventory; //NOT YET IMPLEMENTED 250 m_scene.Permissions.OnDeleteUserInventory += CanDeleteUserInventory; //NOT YET IMPLEMENTED
250 251
251 m_scene.Permissions.OnTeleport += CanTeleport; //NOT YET IMPLEMENTED 252 m_scene.Permissions.OnTeleport += CanTeleport; //NOT YET IMPLEMENTED
253
254 m_scene.Permissions.OnControlPrimMedia += CanControlPrimMedia;
255 m_scene.Permissions.OnInteractWithPrimMedia += CanInteractWithPrimMedia;
252 256
253 m_scene.AddCommand(this, "bypass permissions", 257 m_scene.AddCommand(this, "bypass permissions",
254 "bypass permissions <true / false>", 258 "bypass permissions <true / false>",
@@ -394,6 +398,12 @@ namespace OpenSim.Region.CoreModules.World.Permissions
394 398
395 if (m_groupsModule == null) 399 if (m_groupsModule == null)
396 m_log.Warn("[PERMISSIONS]: Groups module not found, group permissions will not work"); 400 m_log.Warn("[PERMISSIONS]: Groups module not found, group permissions will not work");
401
402 m_moapModule = m_scene.RequestModuleInterface<IMoapModule>();
403
404 // This log line will be commented out when no longer required for debugging
405// if (m_moapModule == null)
406// m_log.Warn("[PERMISSIONS]: Media on a prim module not found, media on a prim permissions will not work");
397 } 407 }
398 408
399 public void Close() 409 public void Close()
@@ -1894,5 +1904,80 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1894 } 1904 }
1895 return(false); 1905 return(false);
1896 } 1906 }
1907
1908 private bool CanControlPrimMedia(UUID agentID, UUID primID, int face)
1909 {
1910// m_log.DebugFormat(
1911// "[PERMISSONS]: Performing CanControlPrimMedia check with agentID {0}, primID {1}, face {2}",
1912// agentID, primID, face);
1913
1914 if (null == m_moapModule)
1915 return false;
1916
1917 SceneObjectPart part = m_scene.GetSceneObjectPart(primID);
1918 if (null == part)
1919 return false;
1920
1921 MediaEntry me = m_moapModule.GetMediaEntry(part, face);
1922
1923 // If there is no existing media entry then it can be controlled (in this context, created).
1924 if (null == me)
1925 return true;
1926
1927// m_log.DebugFormat(
1928// "[PERMISSIONS]: Checking CanControlPrimMedia for {0} on {1} face {2} with control permissions {3}",
1929// agentID, primID, face, me.ControlPermissions);
1930
1931 return GenericPrimMediaPermission(part, agentID, me.ControlPermissions);
1932 }
1933
1934 private bool CanInteractWithPrimMedia(UUID agentID, UUID primID, int face)
1935 {
1936// m_log.DebugFormat(
1937// "[PERMISSONS]: Performing CanInteractWithPrimMedia check with agentID {0}, primID {1}, face {2}",
1938// agentID, primID, face);
1939
1940 if (null == m_moapModule)
1941 return false;
1942
1943 SceneObjectPart part = m_scene.GetSceneObjectPart(primID);
1944 if (null == part)
1945 return false;
1946
1947 MediaEntry me = m_moapModule.GetMediaEntry(part, face);
1948
1949 // If there is no existing media entry then it can be controlled (in this context, created).
1950 if (null == me)
1951 return true;
1952
1953// m_log.DebugFormat(
1954// "[PERMISSIONS]: Checking CanInteractWithPrimMedia for {0} on {1} face {2} with interact permissions {3}",
1955// agentID, primID, face, me.InteractPermissions);
1956
1957 return GenericPrimMediaPermission(part, agentID, me.InteractPermissions);
1958 }
1959
1960 private bool GenericPrimMediaPermission(SceneObjectPart part, UUID agentID, MediaPermission perms)
1961 {
1962// if (IsAdministrator(agentID))
1963// return true;
1964
1965 if ((perms & MediaPermission.Anyone) == MediaPermission.Anyone)
1966 return true;
1967
1968 if ((perms & MediaPermission.Owner) == MediaPermission.Owner)
1969 {
1970 if (agentID == part.OwnerID)
1971 return true;
1972 }
1973
1974 if ((perms & MediaPermission.Group) == MediaPermission.Group)
1975 {
1976 if (IsGroupMember(part.GroupID, agentID, 0))
1977 return true;
1978 }
1979
1980 return false;
1981 }
1897 } 1982 }
1898} 1983} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Interfaces/IMoapModule.cs b/OpenSim/Region/Framework/Interfaces/IMoapModule.cs
new file mode 100644
index 0000000..24b6860
--- /dev/null
+++ b/OpenSim/Region/Framework/Interfaces/IMoapModule.cs
@@ -0,0 +1,67 @@
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 OpenMetaverse;
30using OpenSim.Region.Framework.Scenes;
31
32namespace OpenSim.Region.Framework.Interfaces
33{
34 /// <summary>
35 /// Provides methods from manipulating media-on-a-prim
36 /// </summary>
37 public interface IMoapModule
38 {
39 /// <summary>
40 /// Get the media entry for a given prim face.
41 /// </summary>
42 /// A copy of the media entry is returned rather than the original, so this can be altered at will without
43 /// affecting the original settings.
44 /// <param name="part"></param>
45 /// <param name="face"></param>
46 /// <returns></returns>
47 MediaEntry GetMediaEntry(SceneObjectPart part, int face);
48
49 /// <summary>
50 /// Set the media entry for a given prim face.
51 /// </summary>
52 /// <param name="SceneObjectPart"></param>
53 /// <param name="face"></param>
54 /// <param name="me"></param>
55 void SetMediaEntry(SceneObjectPart part, int face, MediaEntry me);
56
57 /// <summary>
58 /// Clear the media entry for a given prim face.
59 /// </summary>
60 ///
61 /// This is the equivalent of setting a media entry of null
62 ///
63 /// <param name="part"></param>
64 /// <param name="face">/param>
65 void ClearMediaEntry(SceneObjectPart part, int face);
66 }
67} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs
index e060c05..52e6e92 100644
--- a/OpenSim/Region/Framework/Scenes/EventManager.cs
+++ b/OpenSim/Region/Framework/Scenes/EventManager.cs
@@ -334,10 +334,38 @@ namespace OpenSim.Region.Framework.Scenes
334 /// If the object is being attached, then the avatarID will be present. If the object is being detached then 334 /// If the object is being attached, then the avatarID will be present. If the object is being detached then
335 /// the avatarID is UUID.Zero (I know, this doesn't make much sense but now it's historical). 335 /// the avatarID is UUID.Zero (I know, this doesn't make much sense but now it's historical).
336 public delegate void Attach(uint localID, UUID itemID, UUID avatarID); 336 public delegate void Attach(uint localID, UUID itemID, UUID avatarID);
337 public event Attach OnAttach; 337 public event Attach OnAttach;
338
339 /// <summary>
340 /// Called immediately after an object is loaded from storage.
341 /// </summary>
342 public event SceneObjectDelegate OnSceneObjectLoaded;
343 public delegate void SceneObjectDelegate(SceneObjectGroup so);
344
345 /// <summary>
346 /// Called immediately before an object is saved to storage.
347 /// </summary>
348 /// <param name="persistingSo">
349 /// The scene object being persisted.
350 /// This is actually a copy of the original scene object so changes made here will be saved to storage but will not be kept in memory.
351 /// </param>
352 /// <param name="originalSo">
353 /// The original scene object being persisted. Changes here will stay in memory but will not be saved to storage on this save.
354 /// </param>
355 public event SceneObjectPreSaveDelegate OnSceneObjectPreSave;
356 public delegate void SceneObjectPreSaveDelegate(SceneObjectGroup persistingSo, SceneObjectGroup originalSo);
357
358 /// <summary>
359 /// Called when a scene object part is cloned within the region.
360 /// </summary>
361 /// <param name="copy"></param>
362 /// <param name="original"></param>
363 /// <param name="userExposed">True if the duplicate will immediately be in the scene, false otherwise</param>
364 public event SceneObjectPartCopyDelegate OnSceneObjectPartCopy;
365 public delegate void SceneObjectPartCopyDelegate(SceneObjectPart copy, SceneObjectPart original, bool userExposed);
338 366
339 public delegate void RegionUp(GridRegion region); 367 public delegate void RegionUp(GridRegion region);
340 public event RegionUp OnRegionUp; 368 public event RegionUp OnRegionUp;
341 369
342 public class MoneyTransferArgs : EventArgs 370 public class MoneyTransferArgs : EventArgs
343 { 371 {
@@ -2037,5 +2065,68 @@ namespace OpenSim.Region.Framework.Scenes
2037 } 2065 }
2038 } 2066 }
2039 } 2067 }
2068
2069 public void TriggerOnSceneObjectLoaded(SceneObjectGroup so)
2070 {
2071 SceneObjectDelegate handler = OnSceneObjectLoaded;
2072 if (handler != null)
2073 {
2074 foreach (SceneObjectDelegate d in handler.GetInvocationList())
2075 {
2076 try
2077 {
2078 d(so);
2079 }
2080 catch (Exception e)
2081 {
2082 m_log.ErrorFormat(
2083 "[EVENT MANAGER]: Delegate for TriggerOnSceneObjectLoaded failed - continuing. {0} {1}",
2084 e.Message, e.StackTrace);
2085 }
2086 }
2087 }
2088 }
2089
2090 public void TriggerOnSceneObjectPreSave(SceneObjectGroup persistingSo, SceneObjectGroup originalSo)
2091 {
2092 SceneObjectPreSaveDelegate handler = OnSceneObjectPreSave;
2093 if (handler != null)
2094 {
2095 foreach (SceneObjectPreSaveDelegate d in handler.GetInvocationList())
2096 {
2097 try
2098 {
2099 d(persistingSo, originalSo);
2100 }
2101 catch (Exception e)
2102 {
2103 m_log.ErrorFormat(
2104 "[EVENT MANAGER]: Delegate for TriggerOnSceneObjectPreSave failed - continuing. {0} {1}",
2105 e.Message, e.StackTrace);
2106 }
2107 }
2108 }
2109 }
2110
2111 public void TriggerOnSceneObjectPartCopy(SceneObjectPart copy, SceneObjectPart original, bool userExposed)
2112 {
2113 SceneObjectPartCopyDelegate handler = OnSceneObjectPartCopy;
2114 if (handler != null)
2115 {
2116 foreach (SceneObjectPartCopyDelegate d in handler.GetInvocationList())
2117 {
2118 try
2119 {
2120 d(copy, original, userExposed);
2121 }
2122 catch (Exception e)
2123 {
2124 m_log.ErrorFormat(
2125 "[EVENT MANAGER]: Delegate for TriggerOnSceneObjectPartCopy failed - continuing. {0} {1}",
2126 e.Message, e.StackTrace);
2127 }
2128 }
2129 }
2130 }
2040 } 2131 }
2041} 2132} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs b/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs
index a523351..4e80bf2 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
@@ -82,6 +82,8 @@ namespace OpenSim.Region.Framework.Scenes
82 public delegate bool CopyUserInventoryHandler(UUID itemID, UUID userID); 82 public delegate bool CopyUserInventoryHandler(UUID itemID, UUID userID);
83 public delegate bool DeleteUserInventoryHandler(UUID itemID, UUID userID); 83 public delegate bool DeleteUserInventoryHandler(UUID itemID, UUID userID);
84 public delegate bool TeleportHandler(UUID userID, Scene scene); 84 public delegate bool TeleportHandler(UUID userID, Scene scene);
85 public delegate bool ControlPrimMediaHandler(UUID userID, UUID primID, int face);
86 public delegate bool InteractWithPrimMediaHandler(UUID userID, UUID primID, int face);
85 #endregion 87 #endregion
86 88
87 public class ScenePermissions 89 public class ScenePermissions
@@ -141,6 +143,8 @@ namespace OpenSim.Region.Framework.Scenes
141 public event CopyUserInventoryHandler OnCopyUserInventory; 143 public event CopyUserInventoryHandler OnCopyUserInventory;
142 public event DeleteUserInventoryHandler OnDeleteUserInventory; 144 public event DeleteUserInventoryHandler OnDeleteUserInventory;
143 public event TeleportHandler OnTeleport; 145 public event TeleportHandler OnTeleport;
146 public event ControlPrimMediaHandler OnControlPrimMedia;
147 public event InteractWithPrimMediaHandler OnInteractWithPrimMedia;
144 #endregion 148 #endregion
145 149
146 #region Object Permission Checks 150 #region Object Permission Checks
@@ -964,5 +968,35 @@ namespace OpenSim.Region.Framework.Scenes
964 } 968 }
965 return true; 969 return true;
966 } 970 }
971
972 public bool CanControlPrimMedia(UUID userID, UUID primID, int face)
973 {
974 ControlPrimMediaHandler handler = OnControlPrimMedia;
975 if (handler != null)
976 {
977 Delegate[] list = handler.GetInvocationList();
978 foreach (ControlPrimMediaHandler h in list)
979 {
980 if (h(userID, primID, face) == false)
981 return false;
982 }
983 }
984 return true;
985 }
986
987 public bool CanInteractWithPrimMedia(UUID userID, UUID primID, int face)
988 {
989 InteractWithPrimMediaHandler handler = OnInteractWithPrimMedia;
990 if (handler != null)
991 {
992 Delegate[] list = handler.GetInvocationList();
993 foreach (InteractWithPrimMediaHandler h in list)
994 {
995 if (h(userID, primID, face) == false)
996 return false;
997 }
998 }
999 return true;
1000 }
967 } 1001 }
968} 1002} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index ea52ffb..6c17be8 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -1918,9 +1918,11 @@ namespace OpenSim.Region.Framework.Scenes
1918 1918
1919 foreach (SceneObjectGroup group in PrimsFromDB) 1919 foreach (SceneObjectGroup group in PrimsFromDB)
1920 { 1920 {
1921 EventManager.TriggerOnSceneObjectLoaded(group);
1922
1921 if (group.RootPart == null) 1923 if (group.RootPart == null)
1922 { 1924 {
1923 m_log.ErrorFormat("[SCENE] Found a SceneObjectGroup with m_rootPart == null and {0} children", 1925 m_log.ErrorFormat("[SCENE]: Found a SceneObjectGroup with m_rootPart == null and {0} children",
1924 group.Children == null ? 0 : group.Children.Count); 1926 group.Children == null ? 0 : group.Children.Count);
1925 } 1927 }
1926 1928
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 5a3dc20..8ce79a2 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -1745,6 +1745,7 @@ namespace OpenSim.Region.Framework.Scenes
1745 backup_group.RootPart.ParticleSystem = RootPart.ParticleSystem; 1745 backup_group.RootPart.ParticleSystem = RootPart.ParticleSystem;
1746 HasGroupChanged = false; 1746 HasGroupChanged = false;
1747 1747
1748 m_scene.EventManager.TriggerOnSceneObjectPreSave(backup_group, this);
1748 datastore.StoreObject(backup_group, m_scene.RegionInfo.RegionID); 1749 datastore.StoreObject(backup_group, m_scene.RegionInfo.RegionID);
1749 1750
1750 backup_group.ForEachPart(delegate(SceneObjectPart part) 1751 backup_group.ForEachPart(delegate(SceneObjectPart part)
@@ -1795,6 +1796,7 @@ namespace OpenSim.Region.Framework.Scenes
1795 /// <summary> 1796 /// <summary>
1796 /// Duplicates this object, including operations such as physics set up and attaching to the backup event. 1797 /// Duplicates this object, including operations such as physics set up and attaching to the backup event.
1797 /// </summary> 1798 /// </summary>
1799 /// <param name="userExposed">True if the duplicate will immediately be in the scene, false otherwise</param>
1798 /// <returns></returns> 1800 /// <returns></returns>
1799 public SceneObjectGroup Copy(bool userExposed) 1801 public SceneObjectGroup Copy(bool userExposed)
1800 { 1802 {
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index badd357..efdc19c 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -59,6 +59,7 @@ namespace OpenSim.Region.Framework.Scenes
59 REGION = 256, 59 REGION = 256,
60 TELEPORT = 512, 60 TELEPORT = 512,
61 REGION_RESTART = 1024, 61 REGION_RESTART = 1024,
62 MEDIA = 2048,
62 ANIMATION = 16384 63 ANIMATION = 16384
63 } 64 }
64 65
@@ -330,6 +331,11 @@ namespace OpenSim.Region.Framework.Scenes
330 protected Vector3 m_lastAcceleration; 331 protected Vector3 m_lastAcceleration;
331 protected Vector3 m_lastAngularVelocity; 332 protected Vector3 m_lastAngularVelocity;
332 protected int m_lastTerseSent; 333 protected int m_lastTerseSent;
334
335 /// <summary>
336 /// Stores media texture data
337 /// </summary>
338 protected string m_mediaUrl;
333 339
334 // TODO: Those have to be changed into persistent properties at some later point, 340 // TODO: Those have to be changed into persistent properties at some later point,
335 // or sit-camera on vehicles will break on sim-crossing. 341 // or sit-camera on vehicles will break on sim-crossing.
@@ -984,18 +990,39 @@ namespace OpenSim.Region.Framework.Scenes
984 TriggerScriptChangedEvent(Changed.SCALE); 990 TriggerScriptChangedEvent(Changed.SCALE);
985 } 991 }
986 } 992 }
993
987 public byte UpdateFlag 994 public byte UpdateFlag
988 { 995 {
989 get { return m_updateFlag; } 996 get { return m_updateFlag; }
990 set { m_updateFlag = value; } 997 set { m_updateFlag = value; }
991 } 998 }
999
1000 /// <summary>
1001 /// Used for media on a prim.
1002 /// </summary>
1003 /// Do not change this value directly - always do it through an IMoapModule.
1004 public string MediaUrl
1005 {
1006 get
1007 {
1008 return m_mediaUrl;
1009 }
1010
1011 set
1012 {
1013 m_mediaUrl = value;
1014
1015 if (ParentGroup != null)
1016 ParentGroup.HasGroupChanged = true;
1017 }
1018 }
992 1019
993 [XmlIgnore] 1020 [XmlIgnore]
994 public bool CreateSelected 1021 public bool CreateSelected
995 { 1022 {
996 get { return m_createSelected; } 1023 get { return m_createSelected; }
997 set { m_createSelected = value; } 1024 set { m_createSelected = value; }
998 } 1025 }
999 1026
1000 #endregion 1027 #endregion
1001 1028
@@ -1553,6 +1580,11 @@ namespace OpenSim.Region.Framework.Scenes
1553 /// <summary> 1580 /// <summary>
1554 /// Duplicates this part. 1581 /// Duplicates this part.
1555 /// </summary> 1582 /// </summary>
1583 /// <param name="localID"></param>
1584 /// <param name="AgentID"></param>
1585 /// <param name="GroupID"></param>
1586 /// <param name="linkNum"></param>
1587 /// <param name="userExposed">True if the duplicate will immediately be in the scene, false otherwise</param>
1556 /// <returns></returns> 1588 /// <returns></returns>
1557 public SceneObjectPart Copy(uint localID, UUID AgentID, UUID GroupID, int linkNum, bool userExposed) 1589 public SceneObjectPart Copy(uint localID, UUID AgentID, UUID GroupID, int linkNum, bool userExposed)
1558 { 1590 {
@@ -1616,7 +1648,11 @@ namespace OpenSim.Region.Framework.Scenes
1616 dupe.DoPhysicsPropertyUpdate(UsePhysics, true); 1648 dupe.DoPhysicsPropertyUpdate(UsePhysics, true);
1617 } 1649 }
1618 1650
1619 return dupe; 1651 ParentGroup.Scene.EventManager.TriggerOnSceneObjectPartCopy(dupe, this, userExposed);
1652
1653// m_log.DebugFormat("[SCENE OBJECT PART]: Clone of {0} {1} finished", Name, UUID);
1654
1655 return dupe;
1620 } 1656 }
1621 1657
1622 protected void AssetReceived(string id, Object sender, AssetBase asset) 1658 protected void AssetReceived(string id, Object sender, AssetBase asset)
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 44c3d12..b3fa2f4 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -1059,7 +1059,12 @@ namespace OpenSim.Region.Framework.Scenes
1059 /// </summary> 1059 /// </summary>
1060 public void MakeChildAgent() 1060 public void MakeChildAgent()
1061 { 1061 {
1062 Animator.ResetAnimations(); 1062 // It looks like m_animator is set to null somewhere, and MakeChild
1063 // is called after that. Probably in aborted teleports.
1064 if (m_animator == null)
1065 m_animator = new ScenePresenceAnimator(this);
1066 else
1067 Animator.ResetAnimations();
1063 1068
1064// m_log.DebugFormat( 1069// m_log.DebugFormat(
1065// "[SCENEPRESENCE]: Downgrading root agent {0}, {1} to a child agent in {2}", 1070// "[SCENEPRESENCE]: Downgrading root agent {0}, {1} to a child agent in {2}",
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 236458c..a711ebf 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -2111,7 +2111,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2111 return; 2111 return;
2112 2112
2113 // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos) 2113 // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos)
2114 LSL_Vector currentPos = llGetLocalPos(); 2114 LSL_Vector currentPos = GetPartLocalPos(part);
2115 2115
2116 float ground = World.GetGroundHeight((float)targetPos.x, (float)targetPos.y); 2116 float ground = World.GetGroundHeight((float)targetPos.x, (float)targetPos.y);
2117 bool disable_underground_movement = m_ScriptEngine.Config.GetBoolean("DisableUndergroundMovement", true); 2117 bool disable_underground_movement = m_ScriptEngine.Config.GetBoolean("DisableUndergroundMovement", true);
@@ -2144,33 +2144,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2144 public LSL_Vector llGetLocalPos() 2144 public LSL_Vector llGetLocalPos()
2145 { 2145 {
2146 m_host.AddScriptLPS(1); 2146 m_host.AddScriptLPS(1);
2147 if (m_host.IsAttachment == true) { 2147 return GetPartLocalPos(m_host);
2148 if (m_host.IsRoot == true) 2148 }
2149 {
2150 return new LSL_Vector(m_host.AbsolutePosition.X,
2151 m_host.AbsolutePosition.Y,
2152 m_host.AbsolutePosition.Z);
2153
2154 }
2155 else
2156 {
2157 return new LSL_Vector(m_host.OffsetPosition.X,
2158 m_host.OffsetPosition.Y,
2159 m_host.OffsetPosition.Z);
2160 }
2161 }
2162 2149
2163 if (m_host.ParentID != 0) 2150 protected LSL_Vector GetPartLocalPos(SceneObjectPart part)
2151 {
2152 m_host.AddScriptLPS(1);
2153 if (part.ParentID != 0)
2164 { 2154 {
2165 return new LSL_Vector(m_host.OffsetPosition.X, 2155 return new LSL_Vector(part.OffsetPosition.X,
2166 m_host.OffsetPosition.Y, 2156 part.OffsetPosition.Y,
2167 m_host.OffsetPosition.Z); 2157 part.OffsetPosition.Z);
2168 } 2158 }
2169 else 2159 else
2170 { 2160 {
2171 return new LSL_Vector(m_host.AbsolutePosition.X, 2161 return new LSL_Vector(part.AbsolutePosition.X,
2172 m_host.AbsolutePosition.Y, 2162 part.AbsolutePosition.Y,
2173 m_host.AbsolutePosition.Z); 2163 part.AbsolutePosition.Z);
2174 } 2164 }
2175 } 2165 }
2176 2166
@@ -8300,6 +8290,241 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8300 return res; 8290 return res;
8301 } 8291 }
8302 8292
8293 public LSL_List llGetPrimMediaParams(int face, LSL_List rules)
8294 {
8295 m_host.AddScriptLPS(1);
8296 ScriptSleep(1000);
8297
8298 // LSL Spec http://wiki.secondlife.com/wiki/LlGetPrimMediaParams says to fail silently if face is invalid
8299 // TODO: Need to correctly handle case where a face has no media (which gives back an empty list).
8300 // Assuming silently fail means give back an empty list. Ideally, need to check this.
8301 if (face < 0 || face > m_host.GetNumberOfSides() - 1)
8302 return new LSL_List();
8303
8304 return GetPrimMediaParams(face, rules);
8305 }
8306
8307 private LSL_List GetPrimMediaParams(int face, LSL_List rules)
8308 {
8309 IMoapModule module = m_ScriptEngine.World.RequestModuleInterface<IMoapModule>();
8310 if (null == module)
8311 throw new Exception("Media on a prim functions not available");
8312
8313 MediaEntry me = module.GetMediaEntry(m_host, face);
8314
8315 // As per http://wiki.secondlife.com/wiki/LlGetPrimMediaParams
8316 if (null == me)
8317 return new LSL_List();
8318
8319 LSL_List res = new LSL_List();
8320
8321 for (int i = 0; i < rules.Length; i++)
8322 {
8323 int code = (int)rules.GetLSLIntegerItem(i);
8324
8325 switch (code)
8326 {
8327 case ScriptBaseClass.PRIM_MEDIA_ALT_IMAGE_ENABLE:
8328 // Not implemented
8329 res.Add(new LSL_Integer(0));
8330 break;
8331
8332 case ScriptBaseClass.PRIM_MEDIA_CONTROLS:
8333 if (me.Controls == MediaControls.Standard)
8334 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_MEDIA_CONTROLS_STANDARD));
8335 else
8336 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_MEDIA_CONTROLS_MINI));
8337 break;
8338
8339 case ScriptBaseClass.PRIM_MEDIA_CURRENT_URL:
8340 res.Add(new LSL_String(me.CurrentURL));
8341 break;
8342
8343 case ScriptBaseClass.PRIM_MEDIA_HOME_URL:
8344 res.Add(new LSL_String(me.HomeURL));
8345 break;
8346
8347 case ScriptBaseClass.PRIM_MEDIA_AUTO_LOOP:
8348 res.Add(me.AutoLoop ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE);
8349 break;
8350
8351 case ScriptBaseClass.PRIM_MEDIA_AUTO_PLAY:
8352 res.Add(me.AutoPlay ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE);
8353 break;
8354
8355 case ScriptBaseClass.PRIM_MEDIA_AUTO_SCALE:
8356 res.Add(me.AutoScale ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE);
8357 break;
8358
8359 case ScriptBaseClass.PRIM_MEDIA_AUTO_ZOOM:
8360 res.Add(me.AutoZoom ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE);
8361 break;
8362
8363 case ScriptBaseClass.PRIM_MEDIA_FIRST_CLICK_INTERACT:
8364 res.Add(me.InteractOnFirstClick ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE);
8365 break;
8366
8367 case ScriptBaseClass.PRIM_MEDIA_WIDTH_PIXELS:
8368 res.Add(new LSL_Integer(me.Width));
8369 break;
8370
8371 case ScriptBaseClass.PRIM_MEDIA_HEIGHT_PIXELS:
8372 res.Add(new LSL_Integer(me.Height));
8373 break;
8374
8375 case ScriptBaseClass.PRIM_MEDIA_WHITELIST_ENABLE:
8376 res.Add(me.EnableWhiteList ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE);
8377 break;
8378
8379 case ScriptBaseClass.PRIM_MEDIA_WHITELIST:
8380 string[] urls = (string[])me.WhiteList.Clone();
8381
8382 for (int j = 0; j < urls.Length; j++)
8383 urls[j] = Uri.EscapeDataString(urls[j]);
8384
8385 res.Add(new LSL_String(string.Join(", ", urls)));
8386 break;
8387
8388 case ScriptBaseClass.PRIM_MEDIA_PERMS_INTERACT:
8389 res.Add(new LSL_Integer((int)me.InteractPermissions));
8390 break;
8391
8392 case ScriptBaseClass.PRIM_MEDIA_PERMS_CONTROL:
8393 res.Add(new LSL_Integer((int)me.ControlPermissions));
8394 break;
8395 }
8396 }
8397
8398 return res;
8399 }
8400
8401 public LSL_Integer llSetPrimMediaParams(int face, LSL_List rules)
8402 {
8403 m_host.AddScriptLPS(1);
8404 ScriptSleep(1000);
8405
8406 // LSL Spec http://wiki.secondlife.com/wiki/LlSetPrimMediaParams says to fail silently if face is invalid
8407 // Assuming silently fail means sending back LSL_STATUS_OK. Ideally, need to check this.
8408 // Don't perform the media check directly
8409 if (face < 0 || face > m_host.GetNumberOfSides() - 1)
8410 return ScriptBaseClass.LSL_STATUS_OK;
8411
8412 return SetPrimMediaParams(face, rules);
8413 }
8414
8415 private LSL_Integer SetPrimMediaParams(int face, LSL_List rules)
8416 {
8417 IMoapModule module = m_ScriptEngine.World.RequestModuleInterface<IMoapModule>();
8418 if (null == module)
8419 throw new Exception("Media on a prim functions not available");
8420
8421 MediaEntry me = module.GetMediaEntry(m_host, face);
8422 if (null == me)
8423 me = new MediaEntry();
8424
8425 int i = 0;
8426
8427 while (i < rules.Length - 1)
8428 {
8429 int code = rules.GetLSLIntegerItem(i++);
8430
8431 switch (code)
8432 {
8433 case ScriptBaseClass.PRIM_MEDIA_ALT_IMAGE_ENABLE:
8434 me.EnableAlterntiveImage = (rules.GetLSLIntegerItem(i++) != 0 ? true : false);
8435 break;
8436
8437 case ScriptBaseClass.PRIM_MEDIA_CONTROLS:
8438 int v = rules.GetLSLIntegerItem(i++);
8439 if (ScriptBaseClass.PRIM_MEDIA_CONTROLS_STANDARD == v)
8440 me.Controls = MediaControls.Standard;
8441 else
8442 me.Controls = MediaControls.Mini;
8443 break;
8444
8445 case ScriptBaseClass.PRIM_MEDIA_CURRENT_URL:
8446 me.CurrentURL = rules.GetLSLStringItem(i++);
8447 break;
8448
8449 case ScriptBaseClass.PRIM_MEDIA_HOME_URL:
8450 me.HomeURL = rules.GetLSLStringItem(i++);
8451 break;
8452
8453 case ScriptBaseClass.PRIM_MEDIA_AUTO_LOOP:
8454 me.AutoLoop = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false);
8455 break;
8456
8457 case ScriptBaseClass.PRIM_MEDIA_AUTO_PLAY:
8458 me.AutoPlay = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false);
8459 break;
8460
8461 case ScriptBaseClass.PRIM_MEDIA_AUTO_SCALE:
8462 me.AutoScale = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false);
8463 break;
8464
8465 case ScriptBaseClass.PRIM_MEDIA_AUTO_ZOOM:
8466 me.AutoZoom = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false);
8467 break;
8468
8469 case ScriptBaseClass.PRIM_MEDIA_FIRST_CLICK_INTERACT:
8470 me.InteractOnFirstClick = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false);
8471 break;
8472
8473 case ScriptBaseClass.PRIM_MEDIA_WIDTH_PIXELS:
8474 me.Width = (int)rules.GetLSLIntegerItem(i++);
8475 break;
8476
8477 case ScriptBaseClass.PRIM_MEDIA_HEIGHT_PIXELS:
8478 me.Height = (int)rules.GetLSLIntegerItem(i++);
8479 break;
8480
8481 case ScriptBaseClass.PRIM_MEDIA_WHITELIST_ENABLE:
8482 me.EnableWhiteList = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false);
8483 break;
8484
8485 case ScriptBaseClass.PRIM_MEDIA_WHITELIST:
8486 string[] rawWhiteListUrls = rules.GetLSLStringItem(i++).ToString().Split(new char[] { ',' });
8487 List<string> whiteListUrls = new List<string>();
8488 Array.ForEach(
8489 rawWhiteListUrls, delegate(string rawUrl) { whiteListUrls.Add(rawUrl.Trim()); });
8490 me.WhiteList = whiteListUrls.ToArray();
8491 break;
8492
8493 case ScriptBaseClass.PRIM_MEDIA_PERMS_INTERACT:
8494 me.InteractPermissions = (MediaPermission)(byte)(int)rules.GetLSLIntegerItem(i++);
8495 break;
8496
8497 case ScriptBaseClass.PRIM_MEDIA_PERMS_CONTROL:
8498 me.ControlPermissions = (MediaPermission)(byte)(int)rules.GetLSLIntegerItem(i++);
8499 break;
8500 }
8501 }
8502
8503 module.SetMediaEntry(m_host, face, me);
8504
8505 return ScriptBaseClass.LSL_STATUS_OK;
8506 }
8507
8508 public LSL_Integer llClearPrimMedia(LSL_Integer face)
8509 {
8510 m_host.AddScriptLPS(1);
8511 ScriptSleep(1000);
8512
8513 // LSL Spec http://wiki.secondlife.com/wiki/LlClearPrimMedia says to fail silently if face is invalid
8514 // Assuming silently fail means sending back LSL_STATUS_OK. Ideally, need to check this.
8515 // FIXME: Don't perform the media check directly
8516 if (face < 0 || face > m_host.GetNumberOfSides() - 1)
8517 return ScriptBaseClass.LSL_STATUS_OK;
8518
8519 IMoapModule module = m_ScriptEngine.World.RequestModuleInterface<IMoapModule>();
8520 if (null == module)
8521 throw new Exception("Media on a prim functions not available");
8522
8523 module.ClearMediaEntry(m_host, face);
8524
8525 return ScriptBaseClass.LSL_STATUS_OK;
8526 }
8527
8303 // <remarks> 8528 // <remarks>
8304 // <para> 8529 // <para>
8305 // The .NET definition of base 64 is: 8530 // The .NET definition of base 64 is:
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs
index 1fa8c30..fffe65c 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
index cba46a3..561e3b3 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
@@ -62,6 +62,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
62 void llBreakLink(int linknum); 62 void llBreakLink(int linknum);
63 LSL_Integer llCeil(double f); 63 LSL_Integer llCeil(double f);
64 void llClearCameraParams(); 64 void llClearCameraParams();
65 LSL_Integer llClearPrimMedia(LSL_Integer face);
65 void llCloseRemoteDataChannel(string channel); 66 void llCloseRemoteDataChannel(string channel);
66 LSL_Float llCloud(LSL_Vector offset); 67 LSL_Float llCloud(LSL_Vector offset);
67 void llCollisionFilter(string name, string id, int accept); 68 void llCollisionFilter(string name, string id, int accept);
@@ -162,6 +163,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
162 LSL_List llGetParcelPrimOwners(LSL_Vector pos); 163 LSL_List llGetParcelPrimOwners(LSL_Vector pos);
163 LSL_Integer llGetPermissions(); 164 LSL_Integer llGetPermissions();
164 LSL_Key llGetPermissionsKey(); 165 LSL_Key llGetPermissionsKey();
166 LSL_List llGetPrimMediaParams(int face, LSL_List rules);
165 LSL_Vector llGetPos(); 167 LSL_Vector llGetPos();
166 LSL_List llGetPrimitiveParams(LSL_List rules); 168 LSL_List llGetPrimitiveParams(LSL_List rules);
167 LSL_Integer llGetRegionAgentCount(); 169 LSL_Integer llGetRegionAgentCount();
@@ -332,6 +334,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
332 void llSetParcelMusicURL(string url); 334 void llSetParcelMusicURL(string url);
333 void llSetPayPrice(int price, LSL_List quick_pay_buttons); 335 void llSetPayPrice(int price, LSL_List quick_pay_buttons);
334 void llSetPos(LSL_Vector pos); 336 void llSetPos(LSL_Vector pos);
337 LSL_Integer llSetPrimMediaParams(int face, LSL_List rules);
335 void llSetPrimitiveParams(LSL_List rules); 338 void llSetPrimitiveParams(LSL_List rules);
336 void llSetLinkPrimitiveParamsFast(int linknum, LSL_List rules); 339 void llSetLinkPrimitiveParamsFast(int linknum, LSL_List rules);
337 void llSetPrimURL(string url); 340 void llSetPrimURL(string url);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
index 69f48c9..5da6bb9 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
@@ -277,6 +277,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
277 public const int CHANGED_TELEPORT = 512; 277 public const int CHANGED_TELEPORT = 512;
278 public const int CHANGED_REGION_RESTART = 1024; 278 public const int CHANGED_REGION_RESTART = 1024;
279 public const int CHANGED_REGION_START = 1024; //LL Changed the constant from CHANGED_REGION_RESTART 279 public const int CHANGED_REGION_START = 1024; //LL Changed the constant from CHANGED_REGION_RESTART
280 public const int CHANGED_MEDIA = 2048;
280 public const int CHANGED_ANIMATION = 16384; 281 public const int CHANGED_ANIMATION = 16384;
281 public const int TYPE_INVALID = 0; 282 public const int TYPE_INVALID = 0;
282 public const int TYPE_INTEGER = 1; 283 public const int TYPE_INTEGER = 1;
@@ -518,6 +519,41 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
518 public const int TOUCH_INVALID_FACE = -1; 519 public const int TOUCH_INVALID_FACE = -1;
519 public static readonly vector TOUCH_INVALID_TEXCOORD = new vector(-1.0, -1.0, 0.0); 520 public static readonly vector TOUCH_INVALID_TEXCOORD = new vector(-1.0, -1.0, 0.0);
520 public static readonly vector TOUCH_INVALID_VECTOR = ZERO_VECTOR; 521 public static readonly vector TOUCH_INVALID_VECTOR = ZERO_VECTOR;
522
523 // constants for llGetPrimMediaParams/llSetPrimMediaParams
524 public const int PRIM_MEDIA_ALT_IMAGE_ENABLE = 0;
525 public const int PRIM_MEDIA_CONTROLS = 1;
526 public const int PRIM_MEDIA_CURRENT_URL = 2;
527 public const int PRIM_MEDIA_HOME_URL = 3;
528 public const int PRIM_MEDIA_AUTO_LOOP = 4;
529 public const int PRIM_MEDIA_AUTO_PLAY = 5;
530 public const int PRIM_MEDIA_AUTO_SCALE = 6;
531 public const int PRIM_MEDIA_AUTO_ZOOM = 7;
532 public const int PRIM_MEDIA_FIRST_CLICK_INTERACT = 8;
533 public const int PRIM_MEDIA_WIDTH_PIXELS = 9;
534 public const int PRIM_MEDIA_HEIGHT_PIXELS = 10;
535 public const int PRIM_MEDIA_WHITELIST_ENABLE = 11;
536 public const int PRIM_MEDIA_WHITELIST = 12;
537 public const int PRIM_MEDIA_PERMS_INTERACT = 13;
538 public const int PRIM_MEDIA_PERMS_CONTROL = 14;
539
540 public const int PRIM_MEDIA_CONTROLS_STANDARD = 0;
541 public const int PRIM_MEDIA_CONTROLS_MINI = 1;
542
543 public const int PRIM_MEDIA_PERM_NONE = 0;
544 public const int PRIM_MEDIA_PERM_OWNER = 1;
545 public const int PRIM_MEDIA_PERM_GROUP = 2;
546 public const int PRIM_MEDIA_PERM_ANYONE = 4;
547
548 // extra constants for llSetPrimMediaParams
549 public static readonly LSLInteger LSL_STATUS_OK = new LSLInteger(0);
550 public static readonly LSLInteger LSL_STATUS_MALFORMED_PARAMS = new LSLInteger(1000);
551 public static readonly LSLInteger LSL_STATUS_TYPE_MISMATCH = new LSLInteger(1001);
552 public static readonly LSLInteger LSL_STATUS_BOUNDS_ERROR = new LSLInteger(1002);
553 public static readonly LSLInteger LSL_STATUS_NOT_FOUND = new LSLInteger(1003);
554 public static readonly LSLInteger LSL_STATUS_NOT_SUPPORTED = new LSLInteger(1004);
555 public static readonly LSLInteger LSL_STATUS_INTERNAL_ERROR = new LSLInteger(1999);
556 public static readonly LSLInteger LSL_STATUS_WHITELIST_FAILED = new LSLInteger(2001);
521 557
522 // Constants for default textures 558 // Constants for default textures
523 public const string TEXTURE_BLANK = "5748decc-f629-461c-9a36-a35a221fe21f"; 559 public const string TEXTURE_BLANK = "5748decc-f629-461c-9a36-a35a221fe21f";
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
index e86d08c..f14967e 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
@@ -1834,5 +1834,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
1834 { 1834 {
1835 return m_LSL_Functions.llXorBase64StringsCorrect(str1, str2); 1835 return m_LSL_Functions.llXorBase64StringsCorrect(str1, str2);
1836 } 1836 }
1837
1838 public LSL_List llGetPrimMediaParams(int face, LSL_List rules)
1839 {
1840 return m_LSL_Functions.llGetPrimMediaParams(face, rules);
1841 }
1842
1843 public LSL_Integer llSetPrimMediaParams(int face, LSL_List rules)
1844 {
1845 return m_LSL_Functions.llSetPrimMediaParams(face, rules);
1846 }
1847
1848 public LSL_Integer llClearPrimMedia(LSL_Integer face)
1849 {
1850 return m_LSL_Functions.llClearPrimMedia(face);
1851 }
1837 } 1852 }
1838} 1853}