aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs3
-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/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs235
-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
13 files changed, 1213 insertions, 12 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index 0aec01a..c59eedf 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -4288,8 +4288,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4288 4288
4289 public void SendLandObjectOwners(LandData land, List<UUID> groups, Dictionary<UUID, int> ownersAndCount) 4289 public void SendLandObjectOwners(LandData land, List<UUID> groups, Dictionary<UUID, int> ownersAndCount)
4290 { 4290 {
4291
4292
4293 int notifyCount = ownersAndCount.Count; 4291 int notifyCount = ownersAndCount.Count;
4294 ParcelObjectOwnersReplyPacket pack = (ParcelObjectOwnersReplyPacket)PacketPool.Instance.GetPacket(PacketType.ParcelObjectOwnersReply); 4292 ParcelObjectOwnersReplyPacket pack = (ParcelObjectOwnersReplyPacket)PacketPool.Instance.GetPacket(PacketType.ParcelObjectOwnersReply);
4295 4293
@@ -4561,6 +4559,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4561 update.TextureEntry = data.Shape.TextureEntry ?? Utils.EmptyBytes; 4559 update.TextureEntry = data.Shape.TextureEntry ?? Utils.EmptyBytes;
4562 update.Scale = data.Shape.Scale; 4560 update.Scale = data.Shape.Scale;
4563 update.Text = Util.StringToBytes256(data.Text); 4561 update.Text = Util.StringToBytes256(data.Text);
4562 update.MediaURL = Util.StringToBytes256(data.MediaUrl);
4564 4563
4565 #region PrimFlags 4564 #region PrimFlags
4566 4565
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 1d70546..bc54997 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 9db2e41..0ae3146 100644
--- a/OpenSim/Region/Framework/Scenes/EventManager.cs
+++ b/OpenSim/Region/Framework/Scenes/EventManager.cs
@@ -330,10 +330,38 @@ namespace OpenSim.Region.Framework.Scenes
330 /// If the object is being attached, then the avatarID will be present. If the object is being detached then 330 /// If the object is being attached, then the avatarID will be present. If the object is being detached then
331 /// the avatarID is UUID.Zero (I know, this doesn't make much sense but now it's historical). 331 /// the avatarID is UUID.Zero (I know, this doesn't make much sense but now it's historical).
332 public delegate void Attach(uint localID, UUID itemID, UUID avatarID); 332 public delegate void Attach(uint localID, UUID itemID, UUID avatarID);
333 public event Attach OnAttach; 333 public event Attach OnAttach;
334
335 /// <summary>
336 /// Called immediately after an object is loaded from storage.
337 /// </summary>
338 public event SceneObjectDelegate OnSceneObjectLoaded;
339 public delegate void SceneObjectDelegate(SceneObjectGroup so);
340
341 /// <summary>
342 /// Called immediately before an object is saved to storage.
343 /// </summary>
344 /// <param name="persistingSo">
345 /// The scene object being persisted.
346 /// 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.
347 /// </param>
348 /// <param name="originalSo">
349 /// The original scene object being persisted. Changes here will stay in memory but will not be saved to storage on this save.
350 /// </param>
351 public event SceneObjectPreSaveDelegate OnSceneObjectPreSave;
352 public delegate void SceneObjectPreSaveDelegate(SceneObjectGroup persistingSo, SceneObjectGroup originalSo);
353
354 /// <summary>
355 /// Called when a scene object part is cloned within the region.
356 /// </summary>
357 /// <param name="copy"></param>
358 /// <param name="original"></param>
359 /// <param name="userExposed">True if the duplicate will immediately be in the scene, false otherwise</param>
360 public event SceneObjectPartCopyDelegate OnSceneObjectPartCopy;
361 public delegate void SceneObjectPartCopyDelegate(SceneObjectPart copy, SceneObjectPart original, bool userExposed);
334 362
335 public delegate void RegionUp(GridRegion region); 363 public delegate void RegionUp(GridRegion region);
336 public event RegionUp OnRegionUp; 364 public event RegionUp OnRegionUp;
337 365
338 public class MoneyTransferArgs : EventArgs 366 public class MoneyTransferArgs : EventArgs
339 { 367 {
@@ -2013,5 +2041,68 @@ namespace OpenSim.Region.Framework.Scenes
2013 } 2041 }
2014 } 2042 }
2015 } 2043 }
2044
2045 public void TriggerOnSceneObjectLoaded(SceneObjectGroup so)
2046 {
2047 SceneObjectDelegate handler = OnSceneObjectLoaded;
2048 if (handler != null)
2049 {
2050 foreach (SceneObjectDelegate d in handler.GetInvocationList())
2051 {
2052 try
2053 {
2054 d(so);
2055 }
2056 catch (Exception e)
2057 {
2058 m_log.ErrorFormat(
2059 "[EVENT MANAGER]: Delegate for TriggerOnSceneObjectLoaded failed - continuing. {0} {1}",
2060 e.Message, e.StackTrace);
2061 }
2062 }
2063 }
2064 }
2065
2066 public void TriggerOnSceneObjectPreSave(SceneObjectGroup persistingSo, SceneObjectGroup originalSo)
2067 {
2068 SceneObjectPreSaveDelegate handler = OnSceneObjectPreSave;
2069 if (handler != null)
2070 {
2071 foreach (SceneObjectPreSaveDelegate d in handler.GetInvocationList())
2072 {
2073 try
2074 {
2075 d(persistingSo, originalSo);
2076 }
2077 catch (Exception e)
2078 {
2079 m_log.ErrorFormat(
2080 "[EVENT MANAGER]: Delegate for TriggerOnSceneObjectPreSave failed - continuing. {0} {1}",
2081 e.Message, e.StackTrace);
2082 }
2083 }
2084 }
2085 }
2086
2087 public void TriggerOnSceneObjectPartCopy(SceneObjectPart copy, SceneObjectPart original, bool userExposed)
2088 {
2089 SceneObjectPartCopyDelegate handler = OnSceneObjectPartCopy;
2090 if (handler != null)
2091 {
2092 foreach (SceneObjectPartCopyDelegate d in handler.GetInvocationList())
2093 {
2094 try
2095 {
2096 d(copy, original, userExposed);
2097 }
2098 catch (Exception e)
2099 {
2100 m_log.ErrorFormat(
2101 "[EVENT MANAGER]: Delegate for TriggerOnSceneObjectPartCopy failed - continuing. {0} {1}",
2102 e.Message, e.StackTrace);
2103 }
2104 }
2105 }
2106 }
2016 } 2107 }
2017} 2108} \ 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 93f684c..dcd7f3d 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -1887,9 +1887,11 @@ namespace OpenSim.Region.Framework.Scenes
1887 1887
1888 foreach (SceneObjectGroup group in PrimsFromDB) 1888 foreach (SceneObjectGroup group in PrimsFromDB)
1889 { 1889 {
1890 EventManager.TriggerOnSceneObjectLoaded(group);
1891
1890 if (group.RootPart == null) 1892 if (group.RootPart == null)
1891 { 1893 {
1892 m_log.ErrorFormat("[SCENE] Found a SceneObjectGroup with m_rootPart == null and {0} children", 1894 m_log.ErrorFormat("[SCENE]: Found a SceneObjectGroup with m_rootPart == null and {0} children",
1893 group.Children == null ? 0 : group.Children.Count); 1895 group.Children == null ? 0 : group.Children.Count);
1894 } 1896 }
1895 1897
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 17275d0..e26e4ae 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -1479,6 +1479,7 @@ namespace OpenSim.Region.Framework.Scenes
1479 backup_group.RootPart.ParticleSystem = RootPart.ParticleSystem; 1479 backup_group.RootPart.ParticleSystem = RootPart.ParticleSystem;
1480 HasGroupChanged = false; 1480 HasGroupChanged = false;
1481 1481
1482 m_scene.EventManager.TriggerOnSceneObjectPreSave(backup_group, this);
1482 datastore.StoreObject(backup_group, m_scene.RegionInfo.RegionID); 1483 datastore.StoreObject(backup_group, m_scene.RegionInfo.RegionID);
1483 1484
1484 backup_group.ForEachPart(delegate(SceneObjectPart part) 1485 backup_group.ForEachPart(delegate(SceneObjectPart part)
@@ -1527,6 +1528,7 @@ namespace OpenSim.Region.Framework.Scenes
1527 /// <summary> 1528 /// <summary>
1528 /// Duplicates this object, including operations such as physics set up and attaching to the backup event. 1529 /// Duplicates this object, including operations such as physics set up and attaching to the backup event.
1529 /// </summary> 1530 /// </summary>
1531 /// <param name="userExposed">True if the duplicate will immediately be in the scene, false otherwise</param>
1530 /// <returns></returns> 1532 /// <returns></returns>
1531 public SceneObjectGroup Copy(bool userExposed) 1533 public SceneObjectGroup Copy(bool userExposed)
1532 { 1534 {
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 69f9627..3dac0ad 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
@@ -321,6 +322,11 @@ namespace OpenSim.Region.Framework.Scenes
321 protected Vector3 m_lastAcceleration; 322 protected Vector3 m_lastAcceleration;
322 protected Vector3 m_lastAngularVelocity; 323 protected Vector3 m_lastAngularVelocity;
323 protected int m_lastTerseSent; 324 protected int m_lastTerseSent;
325
326 /// <summary>
327 /// Stores media texture data
328 /// </summary>
329 protected string m_mediaUrl;
324 330
325 // TODO: Those have to be changed into persistent properties at some later point, 331 // TODO: Those have to be changed into persistent properties at some later point,
326 // or sit-camera on vehicles will break on sim-crossing. 332 // or sit-camera on vehicles will break on sim-crossing.
@@ -965,18 +971,39 @@ namespace OpenSim.Region.Framework.Scenes
965 TriggerScriptChangedEvent(Changed.SCALE); 971 TriggerScriptChangedEvent(Changed.SCALE);
966 } 972 }
967 } 973 }
974
968 public byte UpdateFlag 975 public byte UpdateFlag
969 { 976 {
970 get { return m_updateFlag; } 977 get { return m_updateFlag; }
971 set { m_updateFlag = value; } 978 set { m_updateFlag = value; }
972 } 979 }
980
981 /// <summary>
982 /// Used for media on a prim.
983 /// </summary>
984 /// Do not change this value directly - always do it through an IMoapModule.
985 public string MediaUrl
986 {
987 get
988 {
989 return m_mediaUrl;
990 }
991
992 set
993 {
994 m_mediaUrl = value;
995
996 if (ParentGroup != null)
997 ParentGroup.HasGroupChanged = true;
998 }
999 }
973 1000
974 [XmlIgnore] 1001 [XmlIgnore]
975 public bool CreateSelected 1002 public bool CreateSelected
976 { 1003 {
977 get { return m_createSelected; } 1004 get { return m_createSelected; }
978 set { m_createSelected = value; } 1005 set { m_createSelected = value; }
979 } 1006 }
980 1007
981 #endregion 1008 #endregion
982 1009
@@ -1527,6 +1554,11 @@ namespace OpenSim.Region.Framework.Scenes
1527 /// <summary> 1554 /// <summary>
1528 /// Duplicates this part. 1555 /// Duplicates this part.
1529 /// </summary> 1556 /// </summary>
1557 /// <param name="localID"></param>
1558 /// <param name="AgentID"></param>
1559 /// <param name="GroupID"></param>
1560 /// <param name="linkNum"></param>
1561 /// <param name="userExposed">True if the duplicate will immediately be in the scene, false otherwise</param>
1530 /// <returns></returns> 1562 /// <returns></returns>
1531 public SceneObjectPart Copy(uint localID, UUID AgentID, UUID GroupID, int linkNum, bool userExposed) 1563 public SceneObjectPart Copy(uint localID, UUID AgentID, UUID GroupID, int linkNum, bool userExposed)
1532 { 1564 {
@@ -1590,7 +1622,11 @@ namespace OpenSim.Region.Framework.Scenes
1590 dupe.DoPhysicsPropertyUpdate(UsePhysics, true); 1622 dupe.DoPhysicsPropertyUpdate(UsePhysics, true);
1591 } 1623 }
1592 1624
1593 return dupe; 1625 ParentGroup.Scene.EventManager.TriggerOnSceneObjectPartCopy(dupe, this, userExposed);
1626
1627// m_log.DebugFormat("[SCENE OBJECT PART]: Clone of {0} {1} finished", Name, UUID);
1628
1629 return dupe;
1594 } 1630 }
1595 1631
1596 protected void AssetReceived(string id, Object sender, AssetBase asset) 1632 protected void AssetReceived(string id, Object sender, AssetBase asset)
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 50ea489..ba1a5f1 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -7848,6 +7848,241 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7848 return res; 7848 return res;
7849 } 7849 }
7850 7850
7851 public LSL_List llGetPrimMediaParams(int face, LSL_List rules)
7852 {
7853 m_host.AddScriptLPS(1);
7854 ScriptSleep(1000);
7855
7856 // LSL Spec http://wiki.secondlife.com/wiki/LlGetPrimMediaParams says to fail silently if face is invalid
7857 // TODO: Need to correctly handle case where a face has no media (which gives back an empty list).
7858 // Assuming silently fail means give back an empty list. Ideally, need to check this.
7859 if (face < 0 || face > m_host.GetNumberOfSides() - 1)
7860 return new LSL_List();
7861
7862 return GetPrimMediaParams(face, rules);
7863 }
7864
7865 private LSL_List GetPrimMediaParams(int face, LSL_List rules)
7866 {
7867 IMoapModule module = m_ScriptEngine.World.RequestModuleInterface<IMoapModule>();
7868 if (null == module)
7869 throw new Exception("Media on a prim functions not available");
7870
7871 MediaEntry me = module.GetMediaEntry(m_host, face);
7872
7873 // As per http://wiki.secondlife.com/wiki/LlGetPrimMediaParams
7874 if (null == me)
7875 return new LSL_List();
7876
7877 LSL_List res = new LSL_List();
7878
7879 for (int i = 0; i < rules.Length; i++)
7880 {
7881 int code = (int)rules.GetLSLIntegerItem(i);
7882
7883 switch (code)
7884 {
7885 case ScriptBaseClass.PRIM_MEDIA_ALT_IMAGE_ENABLE:
7886 // Not implemented
7887 res.Add(new LSL_Integer(0));
7888 break;
7889
7890 case ScriptBaseClass.PRIM_MEDIA_CONTROLS:
7891 if (me.Controls == MediaControls.Standard)
7892 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_MEDIA_CONTROLS_STANDARD));
7893 else
7894 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_MEDIA_CONTROLS_MINI));
7895 break;
7896
7897 case ScriptBaseClass.PRIM_MEDIA_CURRENT_URL:
7898 res.Add(new LSL_String(me.CurrentURL));
7899 break;
7900
7901 case ScriptBaseClass.PRIM_MEDIA_HOME_URL:
7902 res.Add(new LSL_String(me.HomeURL));
7903 break;
7904
7905 case ScriptBaseClass.PRIM_MEDIA_AUTO_LOOP:
7906 res.Add(me.AutoLoop ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE);
7907 break;
7908
7909 case ScriptBaseClass.PRIM_MEDIA_AUTO_PLAY:
7910 res.Add(me.AutoPlay ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE);
7911 break;
7912
7913 case ScriptBaseClass.PRIM_MEDIA_AUTO_SCALE:
7914 res.Add(me.AutoScale ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE);
7915 break;
7916
7917 case ScriptBaseClass.PRIM_MEDIA_AUTO_ZOOM:
7918 res.Add(me.AutoZoom ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE);
7919 break;
7920
7921 case ScriptBaseClass.PRIM_MEDIA_FIRST_CLICK_INTERACT:
7922 res.Add(me.InteractOnFirstClick ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE);
7923 break;
7924
7925 case ScriptBaseClass.PRIM_MEDIA_WIDTH_PIXELS:
7926 res.Add(new LSL_Integer(me.Width));
7927 break;
7928
7929 case ScriptBaseClass.PRIM_MEDIA_HEIGHT_PIXELS:
7930 res.Add(new LSL_Integer(me.Height));
7931 break;
7932
7933 case ScriptBaseClass.PRIM_MEDIA_WHITELIST_ENABLE:
7934 res.Add(me.EnableWhiteList ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE);
7935 break;
7936
7937 case ScriptBaseClass.PRIM_MEDIA_WHITELIST:
7938 string[] urls = (string[])me.WhiteList.Clone();
7939
7940 for (int j = 0; j < urls.Length; j++)
7941 urls[j] = Uri.EscapeDataString(urls[j]);
7942
7943 res.Add(new LSL_String(string.Join(", ", urls)));
7944 break;
7945
7946 case ScriptBaseClass.PRIM_MEDIA_PERMS_INTERACT:
7947 res.Add(new LSL_Integer((int)me.InteractPermissions));
7948 break;
7949
7950 case ScriptBaseClass.PRIM_MEDIA_PERMS_CONTROL:
7951 res.Add(new LSL_Integer((int)me.ControlPermissions));
7952 break;
7953 }
7954 }
7955
7956 return res;
7957 }
7958
7959 public LSL_Integer llSetPrimMediaParams(int face, LSL_List rules)
7960 {
7961 m_host.AddScriptLPS(1);
7962 ScriptSleep(1000);
7963
7964 // LSL Spec http://wiki.secondlife.com/wiki/LlSetPrimMediaParams says to fail silently if face is invalid
7965 // Assuming silently fail means sending back LSL_STATUS_OK. Ideally, need to check this.
7966 // Don't perform the media check directly
7967 if (face < 0 || face > m_host.GetNumberOfSides() - 1)
7968 return ScriptBaseClass.LSL_STATUS_OK;
7969
7970 return SetPrimMediaParams(face, rules);
7971 }
7972
7973 private LSL_Integer SetPrimMediaParams(int face, LSL_List rules)
7974 {
7975 IMoapModule module = m_ScriptEngine.World.RequestModuleInterface<IMoapModule>();
7976 if (null == module)
7977 throw new Exception("Media on a prim functions not available");
7978
7979 MediaEntry me = module.GetMediaEntry(m_host, face);
7980 if (null == me)
7981 me = new MediaEntry();
7982
7983 int i = 0;
7984
7985 while (i < rules.Length - 1)
7986 {
7987 int code = rules.GetLSLIntegerItem(i++);
7988
7989 switch (code)
7990 {
7991 case ScriptBaseClass.PRIM_MEDIA_ALT_IMAGE_ENABLE:
7992 me.EnableAlterntiveImage = (rules.GetLSLIntegerItem(i++) != 0 ? true : false);
7993 break;
7994
7995 case ScriptBaseClass.PRIM_MEDIA_CONTROLS:
7996 int v = rules.GetLSLIntegerItem(i++);
7997 if (ScriptBaseClass.PRIM_MEDIA_CONTROLS_STANDARD == v)
7998 me.Controls = MediaControls.Standard;
7999 else
8000 me.Controls = MediaControls.Mini;
8001 break;
8002
8003 case ScriptBaseClass.PRIM_MEDIA_CURRENT_URL:
8004 me.CurrentURL = rules.GetLSLStringItem(i++);
8005 break;
8006
8007 case ScriptBaseClass.PRIM_MEDIA_HOME_URL:
8008 me.HomeURL = rules.GetLSLStringItem(i++);
8009 break;
8010
8011 case ScriptBaseClass.PRIM_MEDIA_AUTO_LOOP:
8012 me.AutoLoop = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false);
8013 break;
8014
8015 case ScriptBaseClass.PRIM_MEDIA_AUTO_PLAY:
8016 me.AutoPlay = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false);
8017 break;
8018
8019 case ScriptBaseClass.PRIM_MEDIA_AUTO_SCALE:
8020 me.AutoScale = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false);
8021 break;
8022
8023 case ScriptBaseClass.PRIM_MEDIA_AUTO_ZOOM:
8024 me.AutoZoom = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false);
8025 break;
8026
8027 case ScriptBaseClass.PRIM_MEDIA_FIRST_CLICK_INTERACT:
8028 me.InteractOnFirstClick = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false);
8029 break;
8030
8031 case ScriptBaseClass.PRIM_MEDIA_WIDTH_PIXELS:
8032 me.Width = (int)rules.GetLSLIntegerItem(i++);
8033 break;
8034
8035 case ScriptBaseClass.PRIM_MEDIA_HEIGHT_PIXELS:
8036 me.Height = (int)rules.GetLSLIntegerItem(i++);
8037 break;
8038
8039 case ScriptBaseClass.PRIM_MEDIA_WHITELIST_ENABLE:
8040 me.EnableWhiteList = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false);
8041 break;
8042
8043 case ScriptBaseClass.PRIM_MEDIA_WHITELIST:
8044 string[] rawWhiteListUrls = rules.GetLSLStringItem(i++).ToString().Split(new char[] { ',' });
8045 List<string> whiteListUrls = new List<string>();
8046 Array.ForEach(
8047 rawWhiteListUrls, delegate(string rawUrl) { whiteListUrls.Add(rawUrl.Trim()); });
8048 me.WhiteList = whiteListUrls.ToArray();
8049 break;
8050
8051 case ScriptBaseClass.PRIM_MEDIA_PERMS_INTERACT:
8052 me.InteractPermissions = (MediaPermission)(byte)(int)rules.GetLSLIntegerItem(i++);
8053 break;
8054
8055 case ScriptBaseClass.PRIM_MEDIA_PERMS_CONTROL:
8056 me.ControlPermissions = (MediaPermission)(byte)(int)rules.GetLSLIntegerItem(i++);
8057 break;
8058 }
8059 }
8060
8061 module.SetMediaEntry(m_host, face, me);
8062
8063 return ScriptBaseClass.LSL_STATUS_OK;
8064 }
8065
8066 public LSL_Integer llClearPrimMedia(LSL_Integer face)
8067 {
8068 m_host.AddScriptLPS(1);
8069 ScriptSleep(1000);
8070
8071 // LSL Spec http://wiki.secondlife.com/wiki/LlClearPrimMedia says to fail silently if face is invalid
8072 // Assuming silently fail means sending back LSL_STATUS_OK. Ideally, need to check this.
8073 // FIXME: Don't perform the media check directly
8074 if (face < 0 || face > m_host.GetNumberOfSides() - 1)
8075 return ScriptBaseClass.LSL_STATUS_OK;
8076
8077 IMoapModule module = m_ScriptEngine.World.RequestModuleInterface<IMoapModule>();
8078 if (null == module)
8079 throw new Exception("Media on a prim functions not available");
8080
8081 module.ClearMediaEntry(m_host, face);
8082
8083 return ScriptBaseClass.LSL_STATUS_OK;
8084 }
8085
7851 // <remarks> 8086 // <remarks>
7852 // <para> 8087 // <para>
7853 // The .NET definition of base 64 is: 8088 // The .NET definition of base 64 is:
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 3339995..451163f 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
@@ -1832,5 +1832,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
1832 { 1832 {
1833 return m_LSL_Functions.llXorBase64StringsCorrect(str1, str2); 1833 return m_LSL_Functions.llXorBase64StringsCorrect(str1, str2);
1834 } 1834 }
1835
1836 public LSL_List llGetPrimMediaParams(int face, LSL_List rules)
1837 {
1838 return m_LSL_Functions.llGetPrimMediaParams(face, rules);
1839 }
1840
1841 public LSL_Integer llSetPrimMediaParams(int face, LSL_List rules)
1842 {
1843 return m_LSL_Functions.llSetPrimMediaParams(face, rules);
1844 }
1845
1846 public LSL_Integer llClearPrimMedia(LSL_Integer face)
1847 {
1848 return m_LSL_Functions.llClearPrimMedia(face);
1849 }
1835 } 1850 }
1836} 1851}