MoapModule.cs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671
  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. using System;
  28. using System.Collections;
  29. using System.Collections.Generic;
  30. using System.Collections.Specialized;
  31. using System.Reflection;
  32. using System.IO;
  33. using System.Web;
  34. using System.Xml;
  35. using log4net;
  36. using Mono.Addins;
  37. using Nini.Config;
  38. using OpenMetaverse;
  39. using OpenMetaverse.Messages.Linden;
  40. using OpenMetaverse.StructuredData;
  41. using OpenSim.Framework;
  42. using OpenSim.Framework.Capabilities;
  43. using OpenSim.Framework.Servers;
  44. using OpenSim.Framework.Servers.HttpServer;
  45. using OpenSim.Region.Framework.Interfaces;
  46. using OpenSim.Region.Framework.Scenes;
  47. using OpenSim.Services.Interfaces;
  48. using Caps = OpenSim.Framework.Capabilities.Caps;
  49. using OSDArray = OpenMetaverse.StructuredData.OSDArray;
  50. using OSDMap = OpenMetaverse.StructuredData.OSDMap;
  51. namespace OpenSim.Region.CoreModules.World.Media.Moap
  52. {
  53. [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "MoapModule")]
  54. public class MoapModule : INonSharedRegionModule, IMoapModule
  55. {
  56. private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  57. public string Name { get { return "MoapModule"; } }
  58. public Type ReplaceableInterface { get { return null; } }
  59. /// <summary>
  60. /// Is this module enabled?
  61. /// </summary>
  62. protected bool m_isEnabled = true;
  63. /// <summary>
  64. /// The scene to which this module is attached
  65. /// </summary>
  66. protected Scene m_scene;
  67. /// <summary>
  68. /// Track the ObjectMedia capabilities given to users keyed by path
  69. /// </summary>
  70. protected Dictionary<string, UUID> m_omCapUsers = new Dictionary<string, UUID>();
  71. /// <summary>
  72. /// Track the ObjectMedia capabilities given to users keyed by agent. Lock m_omCapUsers to manipulate.
  73. /// </summary>
  74. protected Dictionary<UUID, string> m_omCapUrls = new Dictionary<UUID, string>();
  75. /// <summary>
  76. /// Track the ObjectMediaUpdate capabilities given to users keyed by path
  77. /// </summary>
  78. protected Dictionary<string, UUID> m_omuCapUsers = new Dictionary<string, UUID>();
  79. /// <summary>
  80. /// Track the ObjectMediaUpdate capabilities given to users keyed by agent. Lock m_omuCapUsers to manipulate
  81. /// </summary>
  82. protected Dictionary<UUID, string> m_omuCapUrls = new Dictionary<UUID, string>();
  83. public void Initialise(IConfigSource configSource)
  84. {
  85. IConfig config = configSource.Configs["MediaOnAPrim"];
  86. if (config != null && !config.GetBoolean("Enabled", false))
  87. m_isEnabled = false;
  88. // else
  89. // m_log.Debug("[MOAP]: Initialised module.")l
  90. }
  91. public void AddRegion(Scene scene)
  92. {
  93. if (!m_isEnabled)
  94. return;
  95. m_scene = scene;
  96. m_scene.RegisterModuleInterface<IMoapModule>(this);
  97. }
  98. public void RemoveRegion(Scene scene) {}
  99. public void RegionLoaded(Scene scene)
  100. {
  101. if (!m_isEnabled)
  102. return;
  103. m_scene.EventManager.OnRegisterCaps += OnRegisterCaps;
  104. m_scene.EventManager.OnDeregisterCaps += OnDeregisterCaps;
  105. m_scene.EventManager.OnSceneObjectPartCopy += OnSceneObjectPartCopy;
  106. }
  107. public void Close()
  108. {
  109. if (!m_isEnabled)
  110. return;
  111. m_scene.EventManager.OnRegisterCaps -= OnRegisterCaps;
  112. m_scene.EventManager.OnDeregisterCaps -= OnDeregisterCaps;
  113. m_scene.EventManager.OnSceneObjectPartCopy -= OnSceneObjectPartCopy;
  114. }
  115. public void OnRegisterCaps(UUID agentID, Caps caps)
  116. {
  117. // m_log.DebugFormat(
  118. // "[MOAP]: Registering ObjectMedia and ObjectMediaNavigate capabilities for agent {0}", agentID);
  119. string omCapUrl = "/CAPS/" + UUID.Random();
  120. lock (m_omCapUsers)
  121. {
  122. m_omCapUsers[omCapUrl] = agentID;
  123. m_omCapUrls[agentID] = omCapUrl;
  124. // Even though we're registering for POST we're going to get GETS and UPDATES too
  125. caps.RegisterHandler(
  126. "ObjectMedia",
  127. new RestStreamHandler(
  128. "POST", omCapUrl, HandleObjectMediaMessage, "ObjectMedia", agentID.ToString()));
  129. }
  130. string omuCapUrl = "/CAPS/" + UUID.Random();
  131. lock (m_omuCapUsers)
  132. {
  133. m_omuCapUsers[omuCapUrl] = agentID;
  134. m_omuCapUrls[agentID] = omuCapUrl;
  135. // Even though we're registering for POST we're going to get GETS and UPDATES too
  136. caps.RegisterHandler(
  137. "ObjectMediaNavigate",
  138. new RestStreamHandler(
  139. "POST", omuCapUrl, HandleObjectMediaNavigateMessage, "ObjectMediaNavigate", agentID.ToString()));
  140. }
  141. }
  142. public void OnDeregisterCaps(UUID agentID, Caps caps)
  143. {
  144. lock (m_omCapUsers)
  145. {
  146. string path = m_omCapUrls[agentID];
  147. m_omCapUrls.Remove(agentID);
  148. m_omCapUsers.Remove(path);
  149. }
  150. lock (m_omuCapUsers)
  151. {
  152. string path = m_omuCapUrls[agentID];
  153. m_omuCapUrls.Remove(agentID);
  154. m_omuCapUsers.Remove(path);
  155. }
  156. }
  157. protected void OnSceneObjectPartCopy(SceneObjectPart copy, SceneObjectPart original, bool userExposed)
  158. {
  159. if (original.Shape.Media != null)
  160. {
  161. PrimitiveBaseShape.MediaList dupeMedia = new PrimitiveBaseShape.MediaList();
  162. lock (original.Shape.Media)
  163. {
  164. foreach (MediaEntry me in original.Shape.Media)
  165. {
  166. if (me != null)
  167. dupeMedia.Add(MediaEntry.FromOSD(me.GetOSD()));
  168. else
  169. dupeMedia.Add(null);
  170. }
  171. }
  172. copy.Shape.Media = dupeMedia;
  173. }
  174. }
  175. public MediaEntry GetMediaEntry(SceneObjectPart part, int face)
  176. {
  177. MediaEntry me = null;
  178. CheckFaceParam(part, face);
  179. List<MediaEntry> media = part.Shape.Media;
  180. if (null == media)
  181. {
  182. me = null;
  183. }
  184. else
  185. {
  186. lock (media)
  187. me = media[face];
  188. if (me != null)
  189. {
  190. Primitive.TextureEntry te = part.Shape.Textures;
  191. Primitive.TextureEntryFace teFace = te.GetFace((uint)face);
  192. if (teFace != null && teFace.MediaFlags)
  193. me = MediaEntry.FromOSD(me.GetOSD());
  194. }
  195. }
  196. // m_log.DebugFormat("[MOAP]: GetMediaEntry for {0} face {1} found {2}", part.Name, face, me);
  197. return me;
  198. }
  199. /// <summary>
  200. /// Set the media entry on the face of the given part.
  201. /// </summary>
  202. /// <param name="part">/param>
  203. /// <param name="face"></param>
  204. /// <param name="me">If null, then the media entry is cleared.</param>
  205. public void SetMediaEntry(SceneObjectPart part, int face, MediaEntry me)
  206. {
  207. // m_log.DebugFormat("[MOAP]: SetMediaEntry for {0}, face {1}", part.Name, face);
  208. CheckFaceParam(part, face);
  209. if (null == part.Shape.Media)
  210. {
  211. if (me == null)
  212. return;
  213. else
  214. part.Shape.Media = new PrimitiveBaseShape.MediaList(new MediaEntry[part.GetNumberOfSides()]);
  215. }
  216. lock (part.Shape.Media)
  217. part.Shape.Media[face] = me;
  218. UpdateMediaUrl(part, UUID.Zero);
  219. SetPartMediaFlags(part, face, me != null);
  220. part.ParentGroup.HasGroupChanged = true;
  221. part.ScheduleFullUpdate();
  222. part.TriggerScriptChangedEvent(Changed.MEDIA);
  223. }
  224. /// <summary>
  225. /// Clear the media entry from the face of the given part.
  226. /// </summary>
  227. /// <param name="part"></param>
  228. /// <param name="face"></param>
  229. public void ClearMediaEntry(SceneObjectPart part, int face)
  230. {
  231. SetMediaEntry(part, face, null);
  232. }
  233. /// <summary>
  234. /// Set the media flags on the texture face of the given part.
  235. /// </summary>
  236. /// <remarks>
  237. /// The fact that we need a separate function to do what should be a simple one line operation is BUTT UGLY.
  238. /// </remarks>
  239. /// <param name="part"></param>
  240. /// <param name="face"></param>
  241. /// <param name="flag"></param>
  242. protected void SetPartMediaFlags(SceneObjectPart part, int face, bool flag)
  243. {
  244. Primitive.TextureEntry te = part.Shape.Textures;
  245. Primitive.TextureEntryFace teFace = te.GetFace((uint)face);
  246. teFace.MediaFlags = flag;
  247. part.Shape.Textures = te;
  248. }
  249. /// <summary>
  250. /// Sets or gets per face media textures.
  251. /// </summary>
  252. /// <param name="request"></param>
  253. /// <param name="path"></param>
  254. /// <param name="param"></param>
  255. /// <param name="httpRequest"></param>
  256. /// <param name="httpResponse"></param>
  257. /// <returns></returns>
  258. protected string HandleObjectMediaMessage(
  259. string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
  260. {
  261. // m_log.DebugFormat("[MOAP]: Got ObjectMedia path [{0}], raw request [{1}]", path, request);
  262. OSDMap osd = (OSDMap)OSDParser.DeserializeLLSDXml(request);
  263. ObjectMediaMessage omm = new ObjectMediaMessage();
  264. omm.Deserialize(osd);
  265. if (omm.Request is ObjectMediaRequest)
  266. return HandleObjectMediaRequest(omm.Request as ObjectMediaRequest);
  267. else if (omm.Request is ObjectMediaUpdate)
  268. return HandleObjectMediaUpdate(path, omm.Request as ObjectMediaUpdate);
  269. throw new Exception(
  270. string.Format(
  271. "[MOAP]: ObjectMediaMessage has unrecognized ObjectMediaBlock of {0}",
  272. omm.Request.GetType()));
  273. }
  274. /// <summary>
  275. /// Handle a fetch request for media textures
  276. /// </summary>
  277. /// <param name="omr"></param>
  278. /// <returns></returns>
  279. protected string HandleObjectMediaRequest(ObjectMediaRequest omr)
  280. {
  281. UUID primId = omr.PrimID;
  282. SceneObjectPart part = m_scene.GetSceneObjectPart(primId);
  283. if (null == part)
  284. {
  285. m_log.WarnFormat(
  286. "[MOAP]: Received a GET ObjectMediaRequest for prim {0} but this doesn't exist in region {1}",
  287. primId, m_scene.RegionInfo.RegionName);
  288. return string.Empty;
  289. }
  290. if (part.Shape.Media == null)
  291. return string.Empty;
  292. MediaEntry[] currentML = part.Shape.Media.ToArray();
  293. int nentries = currentML.Length;
  294. int nsides = part.GetNumberOfSides();
  295. if(nentries > nsides)
  296. nentries = nsides;
  297. Primitive.TextureEntry te = part.Shape.Textures;
  298. bool isnull = true;
  299. for(int face = 0; face < nentries; ++face)
  300. {
  301. Primitive.TextureEntryFace teFace = te.GetFace((uint)face);
  302. if(!teFace.MediaFlags)
  303. currentML[face] = null;
  304. else
  305. isnull = false;
  306. }
  307. if(isnull)
  308. {
  309. //remove the damm thing
  310. part.Shape.Media = null;
  311. part.MediaUrl = null;
  312. return string.Empty;
  313. }
  314. ObjectMediaResponse resp = new ObjectMediaResponse();
  315. resp.PrimID = primId;
  316. resp.FaceMedia = currentML;
  317. resp.Version = part.MediaUrl;
  318. string rawResp = OSDParser.SerializeLLSDXmlString(resp.Serialize());
  319. // m_log.DebugFormat("[MOAP]: Got HandleObjectMediaRequestGet raw response is [{0}]", rawResp);
  320. return rawResp;
  321. }
  322. /// <summary>
  323. /// Handle an update of media textures.
  324. /// </summary>
  325. /// <param name="path">Path on which this request was made</param>
  326. /// <param name="omu">/param>
  327. /// <returns></returns>
  328. protected string HandleObjectMediaUpdate(string path, ObjectMediaUpdate omu)
  329. {
  330. UUID primId = omu.PrimID;
  331. SceneObjectPart part = m_scene.GetSceneObjectPart(primId);
  332. if (null == part)
  333. {
  334. m_log.WarnFormat(
  335. "[MOAP]: Received an UPDATE ObjectMediaRequest for prim {0} but this doesn't exist in region {1}",
  336. primId, m_scene.RegionInfo.RegionName);
  337. return string.Empty;
  338. }
  339. // m_log.DebugFormat("[MOAP]: Received {0} media entries for prim {1}", omu.FaceMedia.Length, primId);
  340. //
  341. // for (int i = 0; i < omu.FaceMedia.Length; i++)
  342. // {
  343. // MediaEntry me = omu.FaceMedia[i];
  344. // string v = (null == me ? "null": OSDParser.SerializeLLSDXmlString(me.GetOSD()));
  345. // m_log.DebugFormat("[MOAP]: Face {0} [{1}]", i, v);
  346. // }
  347. if (omu.FaceMedia.Length > part.GetNumberOfSides())
  348. {
  349. m_log.WarnFormat(
  350. "[MOAP]: Received {0} media entries from client for prim {1} {2} but this prim has only {3} faces. Dropping request.",
  351. omu.FaceMedia.Length, part.Name, part.UUID, part.GetNumberOfSides());
  352. return string.Empty;
  353. }
  354. UUID agentId = default(UUID);
  355. lock (m_omCapUsers)
  356. agentId = m_omCapUsers[path];
  357. List<MediaEntry> media = part.Shape.Media;
  358. if (null == media)
  359. {
  360. // m_log.DebugFormat("[MOAP]: Setting all new media list for {0}", part.Name);
  361. part.Shape.Media = new PrimitiveBaseShape.MediaList(omu.FaceMedia);
  362. for (int i = 0; i < omu.FaceMedia.Length; i++)
  363. {
  364. if (omu.FaceMedia[i] != null)
  365. {
  366. // FIXME: Race condition here since some other texture entry manipulator may overwrite/get
  367. // overwritten. Unfortunately, PrimitiveBaseShape does not allow us to change texture entry
  368. // directly.
  369. SetPartMediaFlags(part, i, true);
  370. // m_log.DebugFormat(
  371. // "[MOAP]: Media flags for face {0} is {1}",
  372. // i, part.Shape.Textures.FaceTextures[i].MediaFlags);
  373. }
  374. }
  375. }
  376. else
  377. {
  378. // m_log.DebugFormat("[MOAP]: Setting existing media list for {0}", part.Name);
  379. // We need to go through the media textures one at a time to make sure that we have permission
  380. // to change them
  381. // FIXME: Race condition here since some other texture entry manipulator may overwrite/get
  382. // overwritten. Unfortunately, PrimitiveBaseShape does not allow us to change texture entry
  383. // directly.
  384. Primitive.TextureEntry te = part.Shape.Textures;
  385. lock (media)
  386. {
  387. for (int i = 0; i < media.Count; i++)
  388. {
  389. if (m_scene.Permissions.CanControlPrimMedia(agentId, part.UUID, i))
  390. {
  391. media[i] = omu.FaceMedia[i];
  392. // When a face is cleared this is done by setting the MediaFlags in the TextureEntry via a normal
  393. // texture update, so we don't need to worry about clearing MediaFlags here.
  394. if (null == media[i])
  395. continue;
  396. SetPartMediaFlags(part, i, true);
  397. // m_log.DebugFormat(
  398. // "[MOAP]: Media flags for face {0} is {1}",
  399. // i, face.MediaFlags);
  400. // m_log.DebugFormat("[MOAP]: Set media entry for face {0} on {1}", i, part.Name);
  401. }
  402. }
  403. }
  404. part.Shape.Textures = te;
  405. // for (int i2 = 0; i2 < part.Shape.Textures.FaceTextures.Length; i2++)
  406. // m_log.DebugFormat("[MOAP]: FaceTexture[{0}] is {1}", i2, part.Shape.Textures.FaceTextures[i2]);
  407. }
  408. UpdateMediaUrl(part, agentId);
  409. // Arguably, we could avoid sending a full update to the avatar that just changed the texture.
  410. part.ParentGroup.HasGroupChanged = true;
  411. part.ScheduleFullUpdate();
  412. part.TriggerScriptChangedEvent(Changed.MEDIA);
  413. return string.Empty;
  414. }
  415. /// <summary>
  416. /// Received from the viewer if a user has changed the url of a media texture.
  417. /// </summary>
  418. /// <param name="request"></param>
  419. /// <param name="path"></param>
  420. /// <param name="param"></param>
  421. /// <param name="httpRequest">/param>
  422. /// <param name="httpResponse">/param>
  423. /// <returns></returns>
  424. protected string HandleObjectMediaNavigateMessage(
  425. string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
  426. {
  427. // m_log.DebugFormat("[MOAP]: Got ObjectMediaNavigate request [{0}]", request);
  428. OSDMap osd = (OSDMap)OSDParser.DeserializeLLSDXml(request);
  429. ObjectMediaNavigateMessage omn = new ObjectMediaNavigateMessage();
  430. omn.Deserialize(osd);
  431. UUID primId = omn.PrimID;
  432. SceneObjectPart part = m_scene.GetSceneObjectPart(primId);
  433. if (null == part)
  434. {
  435. m_log.WarnFormat(
  436. "[MOAP]: Received an ObjectMediaNavigateMessage for prim {0} but this doesn't exist in region {1}",
  437. primId, m_scene.RegionInfo.RegionName);
  438. return string.Empty;
  439. }
  440. UUID agentId = default(UUID);
  441. lock (m_omuCapUsers)
  442. agentId = m_omuCapUsers[path];
  443. if (!m_scene.Permissions.CanInteractWithPrimMedia(agentId, part.UUID, omn.Face))
  444. return string.Empty;
  445. // m_log.DebugFormat(
  446. // "[MOAP]: Received request to update media entry for face {0} on prim {1} {2} to {3}",
  447. // omn.Face, part.Name, part.UUID, omn.URL);
  448. // If media has never been set for this prim, then just return.
  449. if (null == part.Shape.Media)
  450. return string.Empty;
  451. MediaEntry me = null;
  452. lock (part.Shape.Media)
  453. me = part.Shape.Media[omn.Face];
  454. // Do the same if media has not been set up for a specific face
  455. if (null == me)
  456. return string.Empty;
  457. if (me.EnableWhiteList)
  458. {
  459. if (!CheckUrlAgainstWhitelist(omn.URL, me.WhiteList))
  460. {
  461. // m_log.DebugFormat(
  462. // "[MOAP]: Blocking change of face {0} on prim {1} {2} to {3} since it's not on the enabled whitelist",
  463. // omn.Face, part.Name, part.UUID, omn.URL);
  464. return string.Empty;
  465. }
  466. }
  467. me.CurrentURL = omn.URL;
  468. UpdateMediaUrl(part, agentId);
  469. part.ParentGroup.HasGroupChanged = true;
  470. part.ScheduleFullUpdate();
  471. part.TriggerScriptChangedEvent(Changed.MEDIA);
  472. return OSDParser.SerializeLLSDXmlString(new OSD());
  473. }
  474. /// <summary>
  475. /// Check that the face number is valid for the given prim.
  476. /// </summary>
  477. /// <param name="part"></param>
  478. /// <param name="face"></param>
  479. protected void CheckFaceParam(SceneObjectPart part, int face)
  480. {
  481. if (face < 0)
  482. throw new ArgumentException("Face cannot be less than zero");
  483. int maxFaces = part.GetNumberOfSides() - 1;
  484. if (face > maxFaces)
  485. throw new ArgumentException(
  486. string.Format("Face argument was {0} but max is {1}", face, maxFaces));
  487. }
  488. /// <summary>
  489. /// Update the media url of the given part
  490. /// </summary>
  491. /// <param name="part"></param>
  492. /// <param name="updateId">
  493. /// The id to attach to this update. Normally, this is the user that changed the
  494. /// texture
  495. /// </param>
  496. protected void UpdateMediaUrl(SceneObjectPart part, UUID updateId)
  497. {
  498. if (null == part.MediaUrl)
  499. {
  500. // TODO: We can't set the last changer until we start tracking which cap we give to which agent id
  501. part.MediaUrl = "x-mv:0000000000/" + updateId;
  502. }
  503. else
  504. {
  505. string rawVersion = part.MediaUrl.Substring(5, 10);
  506. int version = int.Parse(rawVersion);
  507. part.MediaUrl = string.Format("x-mv:{0:D10}/{1}", ++version, updateId);
  508. }
  509. // m_log.DebugFormat("[MOAP]: Storing media url [{0}] in prim {1} {2}", part.MediaUrl, part.Name, part.UUID);
  510. }
  511. /// <summary>
  512. /// Check the given url against the given whitelist.
  513. /// </summary>
  514. /// <param name="rawUrl"></param>
  515. /// <param name="whitelist"></param>
  516. /// <returns>true if the url matches an entry on the whitelist, false otherwise</returns>
  517. protected bool CheckUrlAgainstWhitelist(string rawUrl, string[] whitelist)
  518. {
  519. if (whitelist == null)
  520. return false;
  521. Uri url = new Uri(rawUrl);
  522. foreach (string origWlUrl in whitelist)
  523. {
  524. string wlUrl = origWlUrl;
  525. // Deal with a line-ending wildcard
  526. if (wlUrl.EndsWith("*"))
  527. wlUrl = wlUrl.Remove(wlUrl.Length - 1);
  528. // m_log.DebugFormat("[MOAP]: Checking whitelist URL pattern {0}", origWlUrl);
  529. // Handle a line starting wildcard slightly differently since this can only match the domain, not the path
  530. if (wlUrl.StartsWith("*"))
  531. {
  532. wlUrl = wlUrl.Substring(1);
  533. if (url.Host.Contains(wlUrl))
  534. {
  535. // m_log.DebugFormat("[MOAP]: Whitelist URL {0} matches {1}", origWlUrl, rawUrl);
  536. return true;
  537. }
  538. }
  539. else
  540. {
  541. string urlToMatch = url.Authority + url.AbsolutePath;
  542. if (urlToMatch.StartsWith(wlUrl))
  543. {
  544. // m_log.DebugFormat("[MOAP]: Whitelist URL {0} matches {1}", origWlUrl, rawUrl);
  545. return true;
  546. }
  547. }
  548. }
  549. return false;
  550. }
  551. }
  552. }