diff options
Diffstat (limited to '')
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 | |||
28 | using System; | ||
29 | using System.Collections; | ||
30 | using System.Collections.Generic; | ||
31 | using System.Collections.Specialized; | ||
32 | using System.Reflection; | ||
33 | using System.IO; | ||
34 | using System.Web; | ||
35 | using System.Xml; | ||
36 | using log4net; | ||
37 | using Mono.Addins; | ||
38 | using Nini.Config; | ||
39 | using OpenMetaverse; | ||
40 | using OpenMetaverse.Messages.Linden; | ||
41 | using OpenMetaverse.StructuredData; | ||
42 | using OpenSim.Framework; | ||
43 | using OpenSim.Framework.Capabilities; | ||
44 | using OpenSim.Framework.Servers; | ||
45 | using OpenSim.Framework.Servers.HttpServer; | ||
46 | using OpenSim.Region.Framework.Interfaces; | ||
47 | using OpenSim.Region.Framework.Scenes; | ||
48 | using OpenSim.Services.Interfaces; | ||
49 | using Caps = OpenSim.Framework.Capabilities.Caps; | ||
50 | using OSDArray = OpenMetaverse.StructuredData.OSDArray; | ||
51 | using OSDMap = OpenMetaverse.StructuredData.OSDMap; | ||
52 | |||
53 | namespace 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 | |||
28 | using System; | ||
29 | using OpenMetaverse; | ||
30 | using OpenSim.Region.Framework.Scenes; | ||
31 | |||
32 | namespace 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 | } |