/* * Copyright (c) Contributors, http://opensimulator.org/ * See CONTRIBUTORS.TXT for a full list of copyright holders. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the OpenSimulator Project nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ using System; using System.Collections.Generic; using System.IO; using System.Reflection; using System.Net; using Nini.Config; using log4net; using OpenMetaverse; using OpenSim.Server.Base; using OpenSim.Services.Interfaces; using OpenSim.Framework; using OpenSim.Framework.ServiceAuth; using OpenSim.Framework.Servers.HttpServer; using OpenSim.Server.Handlers.Base; namespace OpenSim.Server.Handlers { public class EstateDataRobustConnector : ServiceConnector { private string m_ConfigName = "EstateService"; public EstateDataRobustConnector(IConfigSource config, IHttpServer server, string configName) : base(config, server, configName) { IConfig serverConfig = config.Configs[m_ConfigName]; if (serverConfig == null) throw new Exception(String.Format("No section {0} in config file", m_ConfigName)); string service = serverConfig.GetString("LocalServiceModule", String.Empty); if (service.Length == 0) throw new Exception("No LocalServiceModule in config file"); Object[] args = new Object[] { config }; IEstateDataService e_service = ServerUtils.LoadPlugin(service, args); IServiceAuth auth = ServiceAuth.Create(config, m_ConfigName); server.AddStreamHandler(new EstateServerGetHandler(e_service, auth)); server.AddStreamHandler(new EstateServerPostHandler(e_service, auth)); } } public class EstateServerGetHandler : BaseStreamHandler { // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); IEstateDataService m_EstateService; // Possibilities // /estates/estate/?region=uuid&create=[t|f] // /estates/estate/?eid=int // /estates/?name=string // /estates/?owner=uuid // /estates/ (all) // /estates/regions/?eid=int public EstateServerGetHandler(IEstateDataService service, IServiceAuth auth) : base("GET", "/estates", auth) { m_EstateService = service; } protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { Dictionary data = null; string[] p = SplitParams(path); // /estates/ (all) // /estates/?name=string // /estates/?owner=uuid if (p.Length == 0) data = GetEstates(httpRequest, httpResponse); else { string resource = p[0]; // /estates/estate/?region=uuid&create=[t|f] // /estates/estate/?eid=int if ("estate".Equals(resource)) data = GetEstate(httpRequest, httpResponse); // /estates/regions/?eid=int else if ("regions".Equals(resource)) data = GetRegions(httpRequest, httpResponse); } if (data == null) data = new Dictionary(); string xmlString = ServerUtils.BuildXmlResponse(data); return Util.UTF8NoBomEncoding.GetBytes(xmlString); } private Dictionary GetEstates(IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { // /estates/ (all) // /estates/?name=string // /estates/?owner=uuid Dictionary data = null; string name = (string)httpRequest.Query["name"]; string owner = (string)httpRequest.Query["owner"]; if (!string.IsNullOrEmpty(name) || !string.IsNullOrEmpty(owner)) { List estateIDs = null; if (!string.IsNullOrEmpty(name)) { estateIDs = m_EstateService.GetEstates(name); } else if (!string.IsNullOrEmpty(owner)) { UUID ownerID = UUID.Zero; if (UUID.TryParse(owner, out ownerID)) estateIDs = m_EstateService.GetEstatesByOwner(ownerID); } if (estateIDs == null || (estateIDs != null && estateIDs.Count == 0)) httpResponse.StatusCode = (int)HttpStatusCode.NotFound; else { httpResponse.StatusCode = (int)HttpStatusCode.OK; httpResponse.ContentType = "text/xml"; data = new Dictionary(); int i = 0; foreach (int id in estateIDs) data["estate" + i++] = id; } } else { List estates = m_EstateService.LoadEstateSettingsAll(); if (estates == null || estates.Count == 0) { httpResponse.StatusCode = (int)HttpStatusCode.NotFound; } else { httpResponse.StatusCode = (int)HttpStatusCode.OK; httpResponse.ContentType = "text/xml"; data = new Dictionary(); int i = 0; foreach (EstateSettings es in estates) data["estate" + i++] = es.ToMap(); } } return data; } private Dictionary GetEstate(IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { // /estates/estate/?region=uuid&create=[t|f] // /estates/estate/?eid=int Dictionary data = null; string region = (string)httpRequest.Query["region"]; string eid = (string)httpRequest.Query["eid"]; EstateSettings estate = null; if (!string.IsNullOrEmpty(region)) { if (UUID.TryParse(region, out UUID regionID)) { string create = (string)httpRequest.Query["create"]; bool.TryParse(create, out bool createYN); estate = m_EstateService.LoadEstateSettings(regionID, createYN); } } else if (!string.IsNullOrEmpty(eid)) { if (int.TryParse(eid, out int id)) estate = m_EstateService.LoadEstateSettings(id); } if (estate != null) { httpResponse.StatusCode = (int)HttpStatusCode.OK; httpResponse.ContentType = "text/xml"; data = estate.ToMap(); } else httpResponse.StatusCode = (int)HttpStatusCode.NotFound; return data; } private Dictionary GetRegions(IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { // /estates/regions/?eid=int Dictionary data = null; string eid = (string)httpRequest.Query["eid"]; httpResponse.StatusCode = (int)HttpStatusCode.NotFound; if (!string.IsNullOrEmpty(eid)) { int id = 0; if (Int32.TryParse(eid, out id)) { List regions = m_EstateService.GetRegions(id); if (regions != null && regions.Count > 0) { data = new Dictionary(); int i = 0; foreach (UUID uuid in regions) data["region" + i++] = uuid.ToString(); httpResponse.StatusCode = (int)HttpStatusCode.OK; httpResponse.ContentType = "text/xml"; } } } return data; } } public class EstateServerPostHandler : BaseStreamHandler { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); IEstateDataService m_EstateService; // Possibilities // /estates/estate/ (post an estate) // /estates/estate/?eid=int®ion=uuid (link a region to an estate) public EstateServerPostHandler(IEstateDataService service, IServiceAuth auth) : base("POST", "/estates", auth) { m_EstateService = service; } protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { Dictionary data = null; string[] p = SplitParams(path); if (p.Length > 0) { string resource = p[0]; // /estates/estate/ // /estates/estate/?eid=int®ion=uuid if ("estate".Equals(resource)) { string body; using(StreamReader sr = new StreamReader(request)) body = sr.ReadToEnd(); body = body.Trim(); Dictionary requestData = ServerUtils.ParseQueryString(body); data = UpdateEstate(requestData, httpRequest, httpResponse); } } if (data == null) data = new Dictionary(); string xmlString = ServerUtils.BuildXmlResponse(data); return Util.UTF8NoBomEncoding.GetBytes(xmlString); } private Dictionary UpdateEstate(Dictionary requestData, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { // /estates/estate/ // /estates/estate/?eid=int®ion=uuid Dictionary result = new Dictionary(); string eid = (string)httpRequest.Query["eid"]; string region = (string)httpRequest.Query["region"]; httpResponse.StatusCode = (int)HttpStatusCode.NotFound; if (string.IsNullOrEmpty(eid) && string.IsNullOrEmpty(region) && requestData.ContainsKey("OP") && requestData["OP"] != null && "STORE".Equals(requestData["OP"])) { // /estates/estate/ EstateSettings es = new EstateSettings(requestData); m_EstateService.StoreEstateSettings(es); //m_log.DebugFormat("[EstateServerPostHandler]: Store estate {0}", es.ToString()); httpResponse.StatusCode = (int)HttpStatusCode.OK; result["Result"] = true; } else if (!string.IsNullOrEmpty(region) && !string.IsNullOrEmpty(eid) && requestData.ContainsKey("OP") && requestData["OP"] != null && "LINK".Equals(requestData["OP"])) { int id = 0; UUID regionID = UUID.Zero; if (UUID.TryParse(region, out regionID) && Int32.TryParse(eid, out id)) { m_log.DebugFormat("[EstateServerPostHandler]: Link region {0} to estate {1}", regionID, id); httpResponse.StatusCode = (int)HttpStatusCode.OK; result["Result"] = m_EstateService.LinkRegion(regionID, id); } } else m_log.WarnFormat("[EstateServerPostHandler]: something wrong with POST request {0}", httpRequest.RawUrl); return result; } } }