change MoapModule
parent
27ea249194
commit
5929e43c2c
|
@ -26,11 +26,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Specialized;
|
using System.Net;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.IO;
|
|
||||||
using System.Web;
|
using System.Web;
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
using log4net;
|
using log4net;
|
||||||
|
@ -40,14 +38,11 @@ using OpenMetaverse;
|
||||||
using OpenMetaverse.Messages.Linden;
|
using OpenMetaverse.Messages.Linden;
|
||||||
using OpenMetaverse.StructuredData;
|
using OpenMetaverse.StructuredData;
|
||||||
using OpenSim.Framework;
|
using OpenSim.Framework;
|
||||||
using OpenSim.Framework.Capabilities;
|
|
||||||
using OpenSim.Framework.Servers;
|
|
||||||
using OpenSim.Framework.Servers.HttpServer;
|
using OpenSim.Framework.Servers.HttpServer;
|
||||||
using OpenSim.Region.Framework.Interfaces;
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
using OpenSim.Region.Framework.Scenes;
|
using OpenSim.Region.Framework.Scenes;
|
||||||
using OpenSim.Services.Interfaces;
|
|
||||||
using Caps = OpenSim.Framework.Capabilities.Caps;
|
using Caps = OpenSim.Framework.Capabilities.Caps;
|
||||||
using OSDArray = OpenMetaverse.StructuredData.OSDArray;
|
|
||||||
using OSDMap = OpenMetaverse.StructuredData.OSDMap;
|
using OSDMap = OpenMetaverse.StructuredData.OSDMap;
|
||||||
|
|
||||||
namespace OpenSim.Region.CoreModules.World.Media.Moap
|
namespace OpenSim.Region.CoreModules.World.Media.Moap
|
||||||
|
@ -70,26 +65,6 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected Scene m_scene;
|
protected Scene m_scene;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Track the ObjectMedia capabilities given to users keyed by path
|
|
||||||
/// </summary>
|
|
||||||
protected Dictionary<string, UUID> m_omCapUsers = new Dictionary<string, UUID>();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Track the ObjectMedia capabilities given to users keyed by agent. Lock m_omCapUsers to manipulate.
|
|
||||||
/// </summary>
|
|
||||||
protected Dictionary<UUID, string> m_omCapUrls = new Dictionary<UUID, string>();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Track the ObjectMediaUpdate capabilities given to users keyed by path
|
|
||||||
/// </summary>
|
|
||||||
protected Dictionary<string, UUID> m_omuCapUsers = new Dictionary<string, UUID>();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Track the ObjectMediaUpdate capabilities given to users keyed by agent. Lock m_omuCapUsers to manipulate
|
|
||||||
/// </summary>
|
|
||||||
protected Dictionary<UUID, string> m_omuCapUrls = new Dictionary<UUID, string>();
|
|
||||||
|
|
||||||
public void Initialise(IConfigSource configSource)
|
public void Initialise(IConfigSource configSource)
|
||||||
{
|
{
|
||||||
IConfig config = configSource.Configs["MediaOnAPrim"];
|
IConfig config = configSource.Configs["MediaOnAPrim"];
|
||||||
|
@ -117,7 +92,6 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_scene.EventManager.OnRegisterCaps += OnRegisterCaps;
|
m_scene.EventManager.OnRegisterCaps += OnRegisterCaps;
|
||||||
m_scene.EventManager.OnDeregisterCaps += OnDeregisterCaps;
|
|
||||||
m_scene.EventManager.OnSceneObjectPartCopy += OnSceneObjectPartCopy;
|
m_scene.EventManager.OnSceneObjectPartCopy += OnSceneObjectPartCopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,7 +101,6 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_scene.EventManager.OnRegisterCaps -= OnRegisterCaps;
|
m_scene.EventManager.OnRegisterCaps -= OnRegisterCaps;
|
||||||
m_scene.EventManager.OnDeregisterCaps -= OnDeregisterCaps;
|
|
||||||
m_scene.EventManager.OnSceneObjectPartCopy -= OnSceneObjectPartCopy;
|
m_scene.EventManager.OnSceneObjectPartCopy -= OnSceneObjectPartCopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,50 +109,18 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
|
||||||
// m_log.DebugFormat(
|
// m_log.DebugFormat(
|
||||||
// "[MOAP]: Registering ObjectMedia and ObjectMediaNavigate capabilities for agent {0}", agentID);
|
// "[MOAP]: Registering ObjectMedia and ObjectMediaNavigate capabilities for agent {0}", agentID);
|
||||||
|
|
||||||
string omCapUrl = "/CAPS/" + UUID.Random();
|
|
||||||
|
|
||||||
lock (m_omCapUsers)
|
caps.RegisterSimpleHandler("ObjectMedia",
|
||||||
{
|
new SimpleStreamHandler("/" + UUID.Random() + "/", delegate (IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
|
||||||
m_omCapUsers[omCapUrl] = agentID;
|
{
|
||||||
m_omCapUrls[agentID] = omCapUrl;
|
HandleObjectMediaMessage(httpRequest, httpResponse, agentID);
|
||||||
|
}));
|
||||||
|
|
||||||
// Even though we're registering for POST we're going to get GETS and UPDATES too
|
caps.RegisterSimpleHandler("ObjectMediaNavigate",
|
||||||
caps.RegisterHandler(
|
new SimpleStreamHandler("/" + UUID.Random() + "/", delegate (IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
|
||||||
"ObjectMedia",
|
{
|
||||||
new RestStreamHandler(
|
HandleObjectMediaNavigateMessage(httpRequest, httpResponse, agentID);
|
||||||
"POST", omCapUrl, HandleObjectMediaMessage, "ObjectMedia", agentID.ToString()));
|
}));
|
||||||
}
|
|
||||||
|
|
||||||
string omuCapUrl = "/CAPS/" + UUID.Random();
|
|
||||||
|
|
||||||
lock (m_omuCapUsers)
|
|
||||||
{
|
|
||||||
m_omuCapUsers[omuCapUrl] = agentID;
|
|
||||||
m_omuCapUrls[agentID] = omuCapUrl;
|
|
||||||
|
|
||||||
// Even though we're registering for POST we're going to get GETS and UPDATES too
|
|
||||||
caps.RegisterHandler(
|
|
||||||
"ObjectMediaNavigate",
|
|
||||||
new RestStreamHandler(
|
|
||||||
"POST", omuCapUrl, HandleObjectMediaNavigateMessage, "ObjectMediaNavigate", agentID.ToString()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnDeregisterCaps(UUID agentID, Caps caps)
|
|
||||||
{
|
|
||||||
lock (m_omCapUsers)
|
|
||||||
{
|
|
||||||
string path = m_omCapUrls[agentID];
|
|
||||||
m_omCapUrls.Remove(agentID);
|
|
||||||
m_omCapUsers.Remove(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
lock (m_omuCapUsers)
|
|
||||||
{
|
|
||||||
string path = m_omuCapUrls[agentID];
|
|
||||||
m_omuCapUrls.Remove(agentID);
|
|
||||||
m_omuCapUsers.Remove(path);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void OnSceneObjectPartCopy(SceneObjectPart copy, SceneObjectPart original, bool userExposed)
|
protected void OnSceneObjectPartCopy(SceneObjectPart copy, SceneObjectPart original, bool userExposed)
|
||||||
|
@ -295,30 +236,46 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets or gets per face media textures.
|
/// Sets or gets per face media textures.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request"></param>
|
protected void HandleObjectMediaMessage(IOSHttpRequest httpRequest, IOSHttpResponse httpResponse, UUID agentID)
|
||||||
/// <param name="path"></param>
|
|
||||||
/// <param name="param"></param>
|
|
||||||
/// <param name="httpRequest"></param>
|
|
||||||
/// <param name="httpResponse"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
protected string HandleObjectMediaMessage(
|
|
||||||
string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
|
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat("[MOAP]: Got ObjectMedia path [{0}], raw request [{1}]", path, request);
|
// m_log.DebugFormat("[MOAP]: Got ObjectMedia path [{0}], raw request [{1}]", path, request);
|
||||||
|
|
||||||
OSDMap osd = (OSDMap)OSDParser.DeserializeLLSDXml(request);
|
try
|
||||||
ObjectMediaMessage omm = new ObjectMediaMessage();
|
{
|
||||||
omm.Deserialize(osd);
|
OSDMap osd = (OSDMap)OSDParser.DeserializeLLSDXml(httpRequest.InputStream);
|
||||||
|
ObjectMediaMessage omm = new ObjectMediaMessage();
|
||||||
|
omm.Deserialize(osd);
|
||||||
|
|
||||||
if (omm.Request is ObjectMediaRequest)
|
if (omm.Request is ObjectMediaRequest)
|
||||||
return HandleObjectMediaRequest(omm.Request as ObjectMediaRequest);
|
{
|
||||||
else if (omm.Request is ObjectMediaUpdate)
|
string ret = HandleObjectMediaRequest(omm.Request as ObjectMediaRequest);
|
||||||
return HandleObjectMediaUpdate(path, omm.Request as ObjectMediaUpdate);
|
if(!string.IsNullOrEmpty(ret))
|
||||||
|
{
|
||||||
throw new Exception(
|
httpResponse.RawBuffer = Util.UTF8.GetBytes(ret);
|
||||||
string.Format(
|
httpResponse.StatusCode = (int)HttpStatusCode.OK;
|
||||||
"[MOAP]: ObjectMediaMessage has unrecognized ObjectMediaBlock of {0}",
|
return;
|
||||||
omm.Request.GetType()));
|
}
|
||||||
|
}
|
||||||
|
else if (omm.Request is ObjectMediaUpdate)
|
||||||
|
{
|
||||||
|
if(HandleObjectMediaUpdate(omm.Request as ObjectMediaUpdate, agentID))
|
||||||
|
{
|
||||||
|
httpResponse.StatusCode = (int)HttpStatusCode.OK;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat(
|
||||||
|
"[MOAP]: ObjectMediaMessage has unrecognized ObjectMediaBlock of {0}",
|
||||||
|
omm.Request.GetType());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
}
|
||||||
|
httpResponse.StatusCode = (int)HttpStatusCode.BadRequest;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -387,10 +344,9 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle an update of media textures.
|
/// Handle an update of media textures.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="path">Path on which this request was made</param>
|
|
||||||
/// <param name="omu">/param>
|
/// <param name="omu">/param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
protected string HandleObjectMediaUpdate(string path, ObjectMediaUpdate omu)
|
protected bool HandleObjectMediaUpdate(ObjectMediaUpdate omu, UUID agentId)
|
||||||
{
|
{
|
||||||
UUID primId = omu.PrimID;
|
UUID primId = omu.PrimID;
|
||||||
|
|
||||||
|
@ -401,7 +357,7 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
|
||||||
m_log.WarnFormat(
|
m_log.WarnFormat(
|
||||||
"[MOAP]: Received an UPDATE ObjectMediaRequest for prim {0} but this doesn't exist in region {1}",
|
"[MOAP]: Received an UPDATE ObjectMediaRequest for prim {0} but this doesn't exist in region {1}",
|
||||||
primId, m_scene.RegionInfo.RegionName);
|
primId, m_scene.RegionInfo.RegionName);
|
||||||
return string.Empty;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// m_log.DebugFormat("[MOAP]: Received {0} media entries for prim {1}", omu.FaceMedia.Length, primId);
|
// m_log.DebugFormat("[MOAP]: Received {0} media entries for prim {1}", omu.FaceMedia.Length, primId);
|
||||||
|
@ -418,14 +374,9 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
|
||||||
m_log.WarnFormat(
|
m_log.WarnFormat(
|
||||||
"[MOAP]: Received {0} media entries from client for prim {1} {2} but this prim has only {3} faces. Dropping request.",
|
"[MOAP]: Received {0} media entries from client for prim {1} {2} but this prim has only {3} faces. Dropping request.",
|
||||||
omu.FaceMedia.Length, part.Name, part.UUID, part.GetNumberOfSides());
|
omu.FaceMedia.Length, part.Name, part.UUID, part.GetNumberOfSides());
|
||||||
return string.Empty;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
UUID agentId = default(UUID);
|
|
||||||
|
|
||||||
lock (m_omCapUsers)
|
|
||||||
agentId = m_omCapUsers[path];
|
|
||||||
|
|
||||||
List<MediaEntry> media = part.Shape.Media;
|
List<MediaEntry> media = part.Shape.Media;
|
||||||
|
|
||||||
if (null == media)
|
if (null == media)
|
||||||
|
@ -496,7 +447,7 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
|
||||||
|
|
||||||
part.TriggerScriptChangedEvent(Changed.MEDIA);
|
part.TriggerScriptChangedEvent(Changed.MEDIA);
|
||||||
|
|
||||||
return string.Empty;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -508,74 +459,87 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
|
||||||
/// <param name="httpRequest">/param>
|
/// <param name="httpRequest">/param>
|
||||||
/// <param name="httpResponse">/param>
|
/// <param name="httpResponse">/param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
protected string HandleObjectMediaNavigateMessage(
|
protected void HandleObjectMediaNavigateMessage(IOSHttpRequest httpRequest, IOSHttpResponse httpResponse, UUID agentId)
|
||||||
string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
|
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat("[MOAP]: Got ObjectMediaNavigate request [{0}]", request);
|
// m_log.DebugFormat("[MOAP]: Got ObjectMediaNavigate request [{0}]", request);
|
||||||
|
|
||||||
OSDMap osd = (OSDMap)OSDParser.DeserializeLLSDXml(request);
|
try
|
||||||
ObjectMediaNavigateMessage omn = new ObjectMediaNavigateMessage();
|
|
||||||
omn.Deserialize(osd);
|
|
||||||
|
|
||||||
UUID primId = omn.PrimID;
|
|
||||||
|
|
||||||
SceneObjectPart part = m_scene.GetSceneObjectPart(primId);
|
|
||||||
|
|
||||||
if (null == part)
|
|
||||||
{
|
{
|
||||||
m_log.WarnFormat(
|
OSDMap osd = (OSDMap)OSDParser.DeserializeLLSDXml(httpRequest.InputStream);
|
||||||
"[MOAP]: Received an ObjectMediaNavigateMessage for prim {0} but this doesn't exist in region {1}",
|
ObjectMediaNavigateMessage omn = new ObjectMediaNavigateMessage();
|
||||||
primId, m_scene.RegionInfo.RegionName);
|
omn.Deserialize(osd);
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
UUID agentId = default(UUID);
|
UUID primId = omn.PrimID;
|
||||||
|
|
||||||
lock (m_omuCapUsers)
|
SceneObjectPart part = m_scene.GetSceneObjectPart(primId);
|
||||||
agentId = m_omuCapUsers[path];
|
|
||||||
|
|
||||||
if (!m_scene.Permissions.CanInteractWithPrimMedia(agentId, part.UUID, omn.Face))
|
bool bad = true;
|
||||||
return string.Empty;
|
MediaEntry me = null;
|
||||||
|
|
||||||
// m_log.DebugFormat(
|
while (true)
|
||||||
// "[MOAP]: Received request to update media entry for face {0} on prim {1} {2} to {3}",
|
|
||||||
// omn.Face, part.Name, part.UUID, omn.URL);
|
|
||||||
|
|
||||||
// If media has never been set for this prim, then just return.
|
|
||||||
if (null == part.Shape.Media)
|
|
||||||
return string.Empty;
|
|
||||||
|
|
||||||
MediaEntry me = null;
|
|
||||||
|
|
||||||
lock (part.Shape.Media)
|
|
||||||
me = part.Shape.Media[omn.Face];
|
|
||||||
|
|
||||||
// Do the same if media has not been set up for a specific face
|
|
||||||
if (null == me)
|
|
||||||
return string.Empty;
|
|
||||||
|
|
||||||
if (me.EnableWhiteList)
|
|
||||||
{
|
|
||||||
if (!CheckUrlAgainstWhitelist(omn.URL, me.WhiteList))
|
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat(
|
if (null == part)
|
||||||
// "[MOAP]: Blocking change of face {0} on prim {1} {2} to {3} since it's not on the enabled whitelist",
|
{
|
||||||
// omn.Face, part.Name, part.UUID, omn.URL);
|
m_log.WarnFormat(
|
||||||
|
"[MOAP]: Received an ObjectMediaNavigateMessage for prim {0} but this doesn't exist in region {1}",
|
||||||
|
primId, m_scene.RegionInfo.RegionName);
|
||||||
|
}
|
||||||
|
|
||||||
return string.Empty;
|
if (!m_scene.Permissions.CanInteractWithPrimMedia(agentId, part.UUID, omn.Face))
|
||||||
|
break;
|
||||||
|
|
||||||
|
//m_log.DebugFormat(
|
||||||
|
// "[MOAP]: Received request to update media entry for face {0} on prim {1} {2} to {3}",
|
||||||
|
// omn.Face, part.Name, part.UUID, omn.URL);
|
||||||
|
|
||||||
|
// If media has never been set for this prim, then just return.
|
||||||
|
if (null == part.Shape.Media)
|
||||||
|
break;
|
||||||
|
|
||||||
|
lock (part.Shape.Media)
|
||||||
|
me = part.Shape.Media[omn.Face];
|
||||||
|
|
||||||
|
// Do the same if media has not been set up for a specific face
|
||||||
|
if (null == me)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (me.EnableWhiteList)
|
||||||
|
{
|
||||||
|
if (!CheckUrlAgainstWhitelist(omn.URL, me.WhiteList))
|
||||||
|
{
|
||||||
|
//m_log.DebugFormat(
|
||||||
|
// "[MOAP]: Blocking change of face {0} on prim {1} {2} to {3} since it's not on the enabled whitelist",
|
||||||
|
// omn.Face, part.Name, part.UUID, omn.URL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bad = false;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(bad)
|
||||||
|
{
|
||||||
|
httpResponse.StatusCode = (int)HttpStatusCode.BadRequest;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
me.CurrentURL = omn.URL;
|
||||||
|
|
||||||
|
UpdateMediaUrl(part, agentId);
|
||||||
|
|
||||||
|
part.ParentGroup.HasGroupChanged = true;
|
||||||
|
part.ScheduleFullUpdate();
|
||||||
|
|
||||||
|
part.TriggerScriptChangedEvent(Changed.MEDIA);
|
||||||
|
|
||||||
|
httpResponse.RawBuffer = Util.UTF8.GetBytes(OSDParser.SerializeLLSDXmlString(new OSD()));
|
||||||
|
httpResponse.StatusCode = (int)HttpStatusCode.OK;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
httpResponse.StatusCode = (int)HttpStatusCode.BadRequest;
|
||||||
|
httpResponse.RawBuffer = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
me.CurrentURL = omn.URL;
|
|
||||||
|
|
||||||
UpdateMediaUrl(part, agentId);
|
|
||||||
|
|
||||||
part.ParentGroup.HasGroupChanged = true;
|
|
||||||
part.ScheduleFullUpdate();
|
|
||||||
|
|
||||||
part.TriggerScriptChangedEvent(Changed.MEDIA);
|
|
||||||
|
|
||||||
return OSDParser.SerializeLLSDXmlString(new OSD());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -616,7 +580,7 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
|
||||||
part.MediaUrl = string.Format("x-mv:{0:D10}/{1}", ++version, updateId);
|
part.MediaUrl = string.Format("x-mv:{0:D10}/{1}", ++version, updateId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// m_log.DebugFormat("[MOAP]: Storing media url [{0}] in prim {1} {2}", part.MediaUrl, part.Name, part.UUID);
|
//m_log.DebugFormat("[MOAP]: Storing media url [{0}] in prim {1} {2}", part.MediaUrl, part.Name, part.UUID);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -236,7 +236,7 @@ namespace OpenSim.Region.OptionalModules.Materials
|
||||||
|
|
||||||
private void preprocess(IOSHttpRequest request, IOSHttpResponse response, UUID agentID)
|
private void preprocess(IOSHttpRequest request, IOSHttpResponse response, UUID agentID)
|
||||||
{
|
{
|
||||||
switch(request.HttpMethod)
|
switch (request.HttpMethod)
|
||||||
{
|
{
|
||||||
case "GET":
|
case "GET":
|
||||||
RenderMaterialsGetCap(request, response);
|
RenderMaterialsGetCap(request, response);
|
||||||
|
|
Loading…
Reference in New Issue