From 5e709b087ccf380749c6a6da8a8293c23f211efd Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Mon, 18 Feb 2013 15:44:00 -0800 Subject: Donating Diva OfflineIM as an addon in a single dll, OpenSim.Addons.OpenSim.dll --- OpenSim/Addons/OfflineIM/Data/IOfflineIMData.cs | 49 ++++ .../Addons/OfflineIM/Data/MySQLOfflineIMData.cs | 68 ++++++ OpenSim/Addons/OfflineIM/OfflineIMRegionModule.cs | 267 +++++++++++++++++++++ .../Addons/OfflineIM/Properties/AssemblyInfo.cs | 37 +++ .../Remote/OfflineIMServiceRemoteConnector.cs | 143 +++++++++++ .../Remote/OfflineIMServiceRobustConnector.cs | 215 +++++++++++++++++ .../Addons/OfflineIM/Resources/IM_Store.migrations | 23 ++ .../Addons/OfflineIM/Service/OfflineIMService.cs | 131 ++++++++++ .../OfflineIM/Service/OfflineIMServiceBase.cs | 83 +++++++ 9 files changed, 1016 insertions(+) create mode 100644 OpenSim/Addons/OfflineIM/Data/IOfflineIMData.cs create mode 100644 OpenSim/Addons/OfflineIM/Data/MySQLOfflineIMData.cs create mode 100644 OpenSim/Addons/OfflineIM/OfflineIMRegionModule.cs create mode 100644 OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs create mode 100644 OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRemoteConnector.cs create mode 100644 OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRobustConnector.cs create mode 100644 OpenSim/Addons/OfflineIM/Resources/IM_Store.migrations create mode 100644 OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs create mode 100644 OpenSim/Addons/OfflineIM/Service/OfflineIMServiceBase.cs (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/OfflineIM/Data/IOfflineIMData.cs b/OpenSim/Addons/OfflineIM/Data/IOfflineIMData.cs new file mode 100644 index 0000000..a507f7d --- /dev/null +++ b/OpenSim/Addons/OfflineIM/Data/IOfflineIMData.cs @@ -0,0 +1,49 @@ +/* + * 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.Collections.Generic; +using OpenSim.Data; +using OpenMetaverse; + +namespace OpenSim.OfflineIM +{ + public class OfflineIMData + { + public UUID PrincipalID; + public Dictionary Data; + } + + + public interface IOfflineIMData + { + OfflineIMData[] Get(string field, string val); + long GetCount(string field, string key); + bool Store(OfflineIMData data); + bool Delete(string field, string val); + void DeleteOld(); + } +} diff --git a/OpenSim/Addons/OfflineIM/Data/MySQLOfflineIMData.cs b/OpenSim/Addons/OfflineIM/Data/MySQLOfflineIMData.cs new file mode 100644 index 0000000..0a61cd2 --- /dev/null +++ b/OpenSim/Addons/OfflineIM/Data/MySQLOfflineIMData.cs @@ -0,0 +1,68 @@ +/* + * 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; +using System.Collections.Generic; +using System.Reflection; + +using OpenSim.Framework; +using OpenSim.Data.MySQL; + +using OpenMetaverse; +using MySql.Data.MySqlClient; + +namespace OpenSim.OfflineIM +{ + public class MySQLOfflineIMData : MySQLGenericTableHandler, IOfflineIMData + { + protected override Assembly Assembly + { + // WARNING! Moving migrations to this assembly!!! + get { return GetType().Assembly; } + } + + public MySQLOfflineIMData(string connectionString, string realm) + : base(connectionString, realm, "IM_Store") + { + } + + public void DeleteOld() + { + uint now = (uint)Util.UnixTimeSinceEpoch(); + + using (MySqlCommand cmd = new MySqlCommand()) + { + cmd.CommandText = String.Format("delete from {0} where TMStamp < ?tstamp", m_Realm); + cmd.Parameters.AddWithValue("?tstamp", now - 14 * 24 * 60 * 60); // > 2 weeks old + + ExecuteNonQuery(cmd); + } + + } + } +} diff --git a/OpenSim/Addons/OfflineIM/OfflineIMRegionModule.cs b/OpenSim/Addons/OfflineIM/OfflineIMRegionModule.cs new file mode 100644 index 0000000..050ebd2 --- /dev/null +++ b/OpenSim/Addons/OfflineIM/OfflineIMRegionModule.cs @@ -0,0 +1,267 @@ +/* + * 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.Reflection; +using log4net; +using Mono.Addins; +using Nini.Config; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Framework.Servers; +using OpenSim.Framework.Client; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; + +namespace OpenSim.OfflineIM +{ + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "OfflineIMConnectorModule")] + public class OfflineIMRegionModule : ISharedRegionModule, IOfflineIMService + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private bool m_Enabled = false; + private List m_SceneList = new List(); + IMessageTransferModule m_TransferModule = null; + private bool m_ForwardOfflineGroupMessages = true; + + private IOfflineIMService m_OfflineIMService; + + public void Initialise(IConfigSource config) + { + IConfig cnf = config.Configs["Messaging"]; + if (cnf == null) + return; + if (cnf != null && cnf.GetString("OfflineMessageModule", string.Empty) != Name) + return; + + m_Enabled = true; + + string serviceLocation = cnf.GetString("OfflineMessageURL", string.Empty); + if (serviceLocation == string.Empty) + m_OfflineIMService = new OfflineIMService(config); + else + m_OfflineIMService = new OfflineIMServiceRemoteConnector(serviceLocation); + + m_ForwardOfflineGroupMessages = cnf.GetBoolean("ForwardOfflineGroupMessages", m_ForwardOfflineGroupMessages); + m_log.DebugFormat("[OfflineIM.V2]: Offline messages enabled by {0}", Name); + } + + public void AddRegion(Scene scene) + { + if (!m_Enabled) + return; + + scene.RegisterModuleInterface(this); + m_SceneList.Add(scene); + scene.EventManager.OnNewClient += OnNewClient; + } + + public void RegionLoaded(Scene scene) + { + if (!m_Enabled) + return; + + if (m_TransferModule == null) + { + m_TransferModule = scene.RequestModuleInterface(); + if (m_TransferModule == null) + { + scene.EventManager.OnNewClient -= OnNewClient; + + m_SceneList.Clear(); + + m_log.Error("[OfflineIM.V2]: No message transfer module is enabled. Disabling offline messages"); + } + m_TransferModule.OnUndeliveredMessage += UndeliveredMessage; + } + } + + public void RemoveRegion(Scene scene) + { + if (!m_Enabled) + return; + + m_SceneList.Remove(scene); + scene.EventManager.OnNewClient -= OnNewClient; + m_TransferModule.OnUndeliveredMessage -= UndeliveredMessage; + + scene.ForEachClient(delegate(IClientAPI client) + { + client.OnRetrieveInstantMessages -= RetrieveInstantMessages; + client.OnMuteListRequest -= OnMuteListRequest; + }); + } + + public void PostInitialise() + { + } + + public string Name + { + get { return "Offline Message Module V2"; } + } + + public Type ReplaceableInterface + { + get { return null; } + } + + public void Close() + { + m_SceneList.Clear(); + } + + private Scene FindScene(UUID agentID) + { + foreach (Scene s in m_SceneList) + { + ScenePresence presence = s.GetScenePresence(agentID); + if (presence != null && !presence.IsChildAgent) + return s; + } + return null; + } + + private IClientAPI FindClient(UUID agentID) + { + foreach (Scene s in m_SceneList) + { + ScenePresence presence = s.GetScenePresence(agentID); + if (presence != null && !presence.IsChildAgent) + return presence.ControllingClient; + } + return null; + } + + private void OnNewClient(IClientAPI client) + { + client.OnRetrieveInstantMessages += RetrieveInstantMessages; + client.OnMuteListRequest += OnMuteListRequest; + } + + private void RetrieveInstantMessages(IClientAPI client) + { + m_log.DebugFormat("[OfflineIM.V2]: Retrieving stored messages for {0}", client.AgentId); + + List msglist = m_OfflineIMService.GetMessages(client.AgentId); + + if (msglist == null) + m_log.DebugFormat("[OfflineIM.V2]: WARNING null message list."); + + foreach (GridInstantMessage im in msglist) + { + if (im.dialog == (byte)InstantMessageDialog.InventoryOffered) + // send it directly or else the item will be given twice + client.SendInstantMessage(im); + else + { + // Send through scene event manager so all modules get a chance + // to look at this message before it gets delivered. + // + // Needed for proper state management for stored group + // invitations + // + Scene s = FindScene(client.AgentId); + if (s != null) + s.EventManager.TriggerIncomingInstantMessage(im); + } + } + } + + // Apparently this is needed in order for the viewer to request the IMs. + private void OnMuteListRequest(IClientAPI client, uint crc) + { + m_log.DebugFormat("[OfflineIM.V2] Got mute list request for crc {0}", crc); + string filename = "mutes" + client.AgentId.ToString(); + + IXfer xfer = client.Scene.RequestModuleInterface(); + if (xfer != null) + { + xfer.AddNewFile(filename, new Byte[0]); + client.SendMuteListUpdate(filename); + } + } + + private void UndeliveredMessage(GridInstantMessage im) + { + if (im.dialog != (byte)InstantMessageDialog.MessageFromObject && + im.dialog != (byte)InstantMessageDialog.MessageFromAgent && + im.dialog != (byte)InstantMessageDialog.GroupNotice && + im.dialog != (byte)InstantMessageDialog.GroupInvitation && + im.dialog != (byte)InstantMessageDialog.InventoryOffered) + { + return; + } + + if (!m_ForwardOfflineGroupMessages) + { + if (im.dialog == (byte)InstantMessageDialog.GroupNotice || + im.dialog == (byte)InstantMessageDialog.GroupInvitation) + return; + } + + Scene scene = FindScene(new UUID(im.fromAgentID)); + if (scene == null) + scene = m_SceneList[0]; + + string reason = string.Empty; + bool success = m_OfflineIMService.StoreMessage(im, out reason); + + if (im.dialog == (byte)InstantMessageDialog.MessageFromAgent) + { + IClientAPI client = FindClient(new UUID(im.fromAgentID)); + if (client == null) + return; + + client.SendInstantMessage(new GridInstantMessage( + null, new UUID(im.toAgentID), + "System", new UUID(im.fromAgentID), + (byte)InstantMessageDialog.MessageFromAgent, + "User is not logged in. " + + (success ? "Message saved." : "Message not saved: " + reason), + false, new Vector3())); + } + } + + #region IOfflineIM + + public List GetMessages(UUID principalID) + { + return m_OfflineIMService.GetMessages(principalID); + } + + public bool StoreMessage(GridInstantMessage im, out string reason) + { + return m_OfflineIMService.StoreMessage(im, out reason); + } + + #endregion + } +} + diff --git a/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs b/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..31667eb --- /dev/null +++ b/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs @@ -0,0 +1,37 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using Mono.Addins; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("OpenSim.Addons.OfflineIM")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("http://opensimulator.org")] +[assembly: AssemblyProduct("OpenSim.Addons.OfflineIM")] +[assembly: AssemblyCopyright("Copyright (c) OpenSimulator.org Developers")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("a16a9905-4393-4872-9fca-4c81bedbd9f2")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +[assembly: AssemblyVersion("0.7.5.*")] +[assembly: AssemblyFileVersion("1.0.0.0")] + +[assembly: Addin("OpenSim.OfflineIM", "0.1")] +[assembly: AddinDependency("OpenSim", "0.5")] diff --git a/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRemoteConnector.cs b/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRemoteConnector.cs new file mode 100644 index 0000000..69feb76 --- /dev/null +++ b/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRemoteConnector.cs @@ -0,0 +1,143 @@ +/* + * 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.Linq; +using System.Reflection; +using System.Text; + +using OpenSim.Framework; +using OpenSim.Server.Base; +using OpenSim.Services.Interfaces; + +using OpenMetaverse; +using log4net; +using Nini.Config; + +namespace OpenSim.OfflineIM +{ + public class OfflineIMServiceRemoteConnector : IOfflineIMService + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private string m_ServerURI = string.Empty; + private object m_Lock = new object(); + + public OfflineIMServiceRemoteConnector(string url) + { + m_ServerURI = url; + m_log.DebugFormat("[OfflineIM.V2.RemoteConnector]: Offline IM server at {0}", m_ServerURI); + } + + public OfflineIMServiceRemoteConnector(IConfigSource config) + { + IConfig cnf = config.Configs["Messaging"]; + if (cnf == null) + { + m_log.WarnFormat("[OfflineIM.V2.RemoteConnector]: Missing Messaging configuration"); + return; + } + + m_ServerURI = cnf.GetString("OfflineMessageURL", string.Empty); + + } + + #region IOfflineIMService + public List GetMessages(UUID principalID) + { + List ims = new List(); + + Dictionary sendData = new Dictionary(); + sendData["PrincipalID"] = principalID; + Dictionary ret = MakeRequest("GET", sendData); + + if (ret == null) + return ims; + + if (!ret.ContainsKey("RESULT")) + return ims; + + if (ret["RESULT"].ToString() == "NULL") + return ims; + + foreach (object v in ((Dictionary)ret["RESULT"]).Values) + { + GridInstantMessage m = OfflineIMDataUtils.GridInstantMessage((Dictionary)v); + ims.Add(m); + } + + return ims; + } + + public bool StoreMessage(GridInstantMessage im, out string reason) + { + reason = string.Empty; + Dictionary sendData = OfflineIMDataUtils.GridInstantMessage(im); + + Dictionary ret = MakeRequest("STORE", sendData); + + if (ret == null) + { + reason = "Bad response from server"; + return false; + } + + string result = ret["RESULT"].ToString(); + if (result == "NULL" || result.ToLower() == "false") + { + reason = ret["REASON"].ToString(); + return false; + } + + return true; + } + + #endregion + + + #region Make Request + + private Dictionary MakeRequest(string method, Dictionary sendData) + { + sendData["METHOD"] = method; + + string reply = string.Empty; + lock (m_Lock) + reply = SynchronousRestFormsRequester.MakeRequest("POST", + m_ServerURI + "/offlineim", + ServerUtils.BuildQueryString(sendData)); + + Dictionary replyData = ServerUtils.ParseXmlResponse( + reply); + + return replyData; + } + #endregion + + } +} diff --git a/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRobustConnector.cs b/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRobustConnector.cs new file mode 100644 index 0000000..2b3a01d --- /dev/null +++ b/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRobustConnector.cs @@ -0,0 +1,215 @@ +/* + * 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.Reflection; +using System.Text; +using System.Xml; +using System.Collections.Generic; +using System.IO; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Server.Base; +using OpenSim.Services.Interfaces; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Server.Handlers.Base; +using log4net; +using OpenMetaverse; + +namespace OpenSim.OfflineIM +{ + public class OfflineIMServiceRobustConnector : ServiceConnector + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private IOfflineIMService m_OfflineIMService; + private string m_ConfigName = "Messaging"; + + public OfflineIMServiceRobustConnector(IConfigSource config, IHttpServer server, string configName) : + base(config, server, configName) + { + if (configName != String.Empty) + m_ConfigName = configName; + + m_log.DebugFormat("[OfflineIM.V2.RobustConnector]: Starting with config name {0}", m_ConfigName); + + m_OfflineIMService = new OfflineIMService(config); + + server.AddStreamHandler(new OfflineIMServicePostHandler(m_OfflineIMService)); + } + } + + public class OfflineIMServicePostHandler : BaseStreamHandler + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private IOfflineIMService m_OfflineIMService; + + public OfflineIMServicePostHandler(IOfflineIMService service) : + base("POST", "/offlineim") + { + m_OfflineIMService = service; + } + + public override byte[] Handle(string path, Stream requestData, + IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) + { + StreamReader sr = new StreamReader(requestData); + string body = sr.ReadToEnd(); + sr.Close(); + body = body.Trim(); + + //m_log.DebugFormat("[XXX]: query String: {0}", body); + + try + { + Dictionary request = + ServerUtils.ParseQueryString(body); + + if (!request.ContainsKey("METHOD")) + return FailureResult(); + + string method = request["METHOD"].ToString(); + request.Remove("METHOD"); + + m_log.DebugFormat("[OfflineIM.V2.Handler]: {0}", method); + switch (method) + { + case "GET": + return HandleGet(request); + case "STORE": + return HandleStore(request); + } + m_log.DebugFormat("[OFFLINE IM HANDLER]: unknown method request: {0}", method); + } + catch (Exception e) + { + m_log.DebugFormat("[OFFLINE IM HANDLER]: Exception {0}", e.StackTrace); + } + + return FailureResult(); + } + + byte[] HandleStore(Dictionary request) + { + Dictionary result = new Dictionary(); + + GridInstantMessage im = OfflineIMDataUtils.GridInstantMessage(request); + + string reason = string.Empty; + + bool success = m_OfflineIMService.StoreMessage(im, out reason); + + result["RESULT"] = success.ToString(); + if (!success) + result["REASON"] = reason; + + string xmlString = ServerUtils.BuildXmlResponse(result); + + //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString); + return Util.UTF8NoBomEncoding.GetBytes(xmlString); + } + + byte[] HandleGet(Dictionary request) + { + Dictionary result = new Dictionary(); + + if (!request.ContainsKey("PrincipalID")) + NullResult(result, "Bad network data"); + else + { + UUID principalID = new UUID(request["PrincipalID"].ToString()); + List ims = m_OfflineIMService.GetMessages(principalID); + + Dictionary dict = new Dictionary(); + int i = 0; + foreach (GridInstantMessage m in ims) + dict["im-" + i++] = OfflineIMDataUtils.GridInstantMessage(m); + + result["RESULT"] = dict; + } + + string xmlString = ServerUtils.BuildXmlResponse(result); + + //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString); + return Util.UTF8NoBomEncoding.GetBytes(xmlString); + } + + #region Helpers + + private void NullResult(Dictionary result, string reason) + { + result["RESULT"] = "NULL"; + result["REASON"] = reason; + } + + private byte[] FailureResult() + { + return BoolResult(false); + } + + private byte[] SuccessResult() + { + return BoolResult(true); + } + + private byte[] BoolResult(bool value) + { + XmlDocument doc = new XmlDocument(); + + XmlNode xmlnode = doc.CreateNode(XmlNodeType.XmlDeclaration, + "", ""); + + doc.AppendChild(xmlnode); + + XmlElement rootElement = doc.CreateElement("", "ServerResponse", + ""); + + doc.AppendChild(rootElement); + + XmlElement result = doc.CreateElement("", "RESULT", ""); + result.AppendChild(doc.CreateTextNode(value.ToString())); + + rootElement.AppendChild(result); + + return DocToBytes(doc); + } + + private byte[] DocToBytes(XmlDocument doc) + { + MemoryStream ms = new MemoryStream(); + XmlTextWriter xw = new XmlTextWriter(ms, null); + xw.Formatting = Formatting.Indented; + doc.WriteTo(xw); + xw.Flush(); + + return ms.ToArray(); + } + + #endregion + } +} diff --git a/OpenSim/Addons/OfflineIM/Resources/IM_Store.migrations b/OpenSim/Addons/OfflineIM/Resources/IM_Store.migrations new file mode 100644 index 0000000..d1cff8e --- /dev/null +++ b/OpenSim/Addons/OfflineIM/Resources/IM_Store.migrations @@ -0,0 +1,23 @@ +:VERSION 1 # -------------------------- + +BEGIN; + +CREATE TABLE `im_offline` ( + `ID` MEDIUMINT NOT NULL AUTO_INCREMENT, + `PrincipalID` char(36) NOT NULL default '', + `Message` text NOT NULL, + `TMStamp` timestamp NOT NULL, + PRIMARY KEY (`ID`), + KEY `PrincipalID` (`PrincipalID`) +) ENGINE=MyISAM; + +COMMIT; + +:VERSION 2 # -------------------------- + +BEGIN; + +INSERT INTO `im_offline` SELECT * from `diva_im_offline`; +DROP TABLE `diva_im_offline`; + +COMMIT; \ No newline at end of file diff --git a/OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs b/OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs new file mode 100644 index 0000000..6ba022c --- /dev/null +++ b/OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs @@ -0,0 +1,131 @@ +/* + * 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.Runtime.Serialization; +using System.Text; +using System.Timers; +using System.Xml; +using System.Xml.Serialization; +using log4net; +using Nini.Config; + +using OpenMetaverse; +using OpenSim.Data; +using OpenSim.Framework; +using OpenSim.Services.Interfaces; + +namespace OpenSim.OfflineIM +{ + public class OfflineIMService : OfflineIMServiceBase, IOfflineIMService + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private const int MAX_IM = 25; + + private XmlSerializer m_serializer; + private static bool m_Initialized = false; + + public OfflineIMService(IConfigSource config) + : base(config) + { + m_serializer = new XmlSerializer(typeof(GridInstantMessage)); + if (!m_Initialized) + { + m_Database.DeleteOld(); + m_Initialized = true; + } + } + + public List GetMessages(UUID principalID) + { + List ims = new List(); + + OfflineIMData[] messages = m_Database.Get("PrincipalID", principalID.ToString()); + + if (messages == null || (messages != null && messages.Length == 0)) + return ims; + + foreach (OfflineIMData m in messages) + { + using (MemoryStream mstream = new MemoryStream(Encoding.UTF8.GetBytes(m.Data["Message"]))) + { + GridInstantMessage im = (GridInstantMessage)m_serializer.Deserialize(mstream); + ims.Add(im); + } + } + + // Then, delete them + m_Database.Delete("PrincipalID", principalID.ToString()); + + return ims; + } + + public bool StoreMessage(GridInstantMessage im, out string reason) + { + reason = string.Empty; + + // TODO Check limits + UUID principalID = new UUID(im.toAgentID); + long count = m_Database.GetCount("PrincipalID", principalID.ToString()); + if (count >= MAX_IM) + { + reason = "Number of offline IMs has maxed out"; + return false; + } + + string imXml = string.Empty; + using (MemoryStream mstream = new MemoryStream()) + { + XmlWriterSettings settings = new XmlWriterSettings(); + settings.Encoding = Encoding.UTF8; + + using (XmlWriter writer = XmlWriter.Create(mstream, settings)) + { + m_serializer.Serialize(writer, im); + writer.Flush(); + + mstream.Position = 0; + using (StreamReader sreader = new StreamReader(mstream)) + { + imXml = sreader.ReadToEnd(); + } + } + } + + OfflineIMData data = new OfflineIMData(); + data.PrincipalID = principalID; + data.Data = new Dictionary(); + data.Data["Message"] = imXml; + + return m_Database.Store(data); + + } + } +} diff --git a/OpenSim/Addons/OfflineIM/Service/OfflineIMServiceBase.cs b/OpenSim/Addons/OfflineIM/Service/OfflineIMServiceBase.cs new file mode 100644 index 0000000..3376be4 --- /dev/null +++ b/OpenSim/Addons/OfflineIM/Service/OfflineIMServiceBase.cs @@ -0,0 +1,83 @@ +/* + * 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.Reflection; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Data; +using OpenSim.Services.Interfaces; +using OpenSim.Services.Base; + +namespace OpenSim.OfflineIM +{ + public class OfflineIMServiceBase : ServiceBase + { + protected IOfflineIMData m_Database = null; + + public OfflineIMServiceBase(IConfigSource config) + : base(config) + { + string dllName = String.Empty; + string connString = String.Empty; + string realm = "im_offline"; + + // + // Try reading the [DatabaseService] section, if it exists + // + IConfig dbConfig = config.Configs["DatabaseService"]; + if (dbConfig != null) + { + if (dllName == String.Empty) + dllName = dbConfig.GetString("StorageProvider", String.Empty); + if (connString == String.Empty) + connString = dbConfig.GetString("ConnectionString", String.Empty); + } + + // + // [Messaging] section overrides [DatabaseService], if it exists + // + IConfig imConfig = config.Configs["Messaging"]; + if (imConfig != null) + { + dllName = imConfig.GetString("StorageProvider", dllName); + connString = imConfig.GetString("ConnectionString", connString); + realm = imConfig.GetString("Realm", realm); + } + + // + // We tried, but this doesn't exist. We can't proceed. + // + if (dllName.Equals(String.Empty)) + throw new Exception("No StorageProvider configured"); + + m_Database = LoadPlugin(dllName, new Object[] { connString, realm }); + if (m_Database == null) + throw new Exception("Could not find a storage interface in the given module " + dllName); + } + } +} -- cgit v1.1 From 9e460f2af8cb012a9cd333ed6683f409ce1bede8 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Mon, 18 Feb 2013 19:54:18 -0800 Subject: One more sql statement on migration #2 for offline im, to really clean up things. --- OpenSim/Addons/OfflineIM/Resources/IM_Store.migrations | 1 + 1 file changed, 1 insertion(+) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/OfflineIM/Resources/IM_Store.migrations b/OpenSim/Addons/OfflineIM/Resources/IM_Store.migrations index d1cff8e..7cfcd43 100644 --- a/OpenSim/Addons/OfflineIM/Resources/IM_Store.migrations +++ b/OpenSim/Addons/OfflineIM/Resources/IM_Store.migrations @@ -19,5 +19,6 @@ BEGIN; INSERT INTO `im_offline` SELECT * from `diva_im_offline`; DROP TABLE `diva_im_offline`; +DELETE FROM `migrations` WHERE name='diva_im_Store'; COMMIT; \ No newline at end of file -- cgit v1.1 From 46e182dbf546dcb58d088c043a0baa2dcfed9125 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Tue, 19 Feb 2013 06:37:20 -0800 Subject: Offline IM: moved the Data and MySQL bits to the corresponding places in core, so that it will be easier to plugin a SQLite backend, if anyone is interested in doing that. --- OpenSim/Addons/OfflineIM/Data/IOfflineIMData.cs | 49 ---------------- .../Addons/OfflineIM/Data/MySQLOfflineIMData.cs | 68 ---------------------- .../Addons/OfflineIM/Resources/IM_Store.migrations | 24 -------- 3 files changed, 141 deletions(-) delete mode 100644 OpenSim/Addons/OfflineIM/Data/IOfflineIMData.cs delete mode 100644 OpenSim/Addons/OfflineIM/Data/MySQLOfflineIMData.cs delete mode 100644 OpenSim/Addons/OfflineIM/Resources/IM_Store.migrations (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/OfflineIM/Data/IOfflineIMData.cs b/OpenSim/Addons/OfflineIM/Data/IOfflineIMData.cs deleted file mode 100644 index a507f7d..0000000 --- a/OpenSim/Addons/OfflineIM/Data/IOfflineIMData.cs +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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.Collections.Generic; -using OpenSim.Data; -using OpenMetaverse; - -namespace OpenSim.OfflineIM -{ - public class OfflineIMData - { - public UUID PrincipalID; - public Dictionary Data; - } - - - public interface IOfflineIMData - { - OfflineIMData[] Get(string field, string val); - long GetCount(string field, string key); - bool Store(OfflineIMData data); - bool Delete(string field, string val); - void DeleteOld(); - } -} diff --git a/OpenSim/Addons/OfflineIM/Data/MySQLOfflineIMData.cs b/OpenSim/Addons/OfflineIM/Data/MySQLOfflineIMData.cs deleted file mode 100644 index 0a61cd2..0000000 --- a/OpenSim/Addons/OfflineIM/Data/MySQLOfflineIMData.cs +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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; -using System.Collections.Generic; -using System.Reflection; - -using OpenSim.Framework; -using OpenSim.Data.MySQL; - -using OpenMetaverse; -using MySql.Data.MySqlClient; - -namespace OpenSim.OfflineIM -{ - public class MySQLOfflineIMData : MySQLGenericTableHandler, IOfflineIMData - { - protected override Assembly Assembly - { - // WARNING! Moving migrations to this assembly!!! - get { return GetType().Assembly; } - } - - public MySQLOfflineIMData(string connectionString, string realm) - : base(connectionString, realm, "IM_Store") - { - } - - public void DeleteOld() - { - uint now = (uint)Util.UnixTimeSinceEpoch(); - - using (MySqlCommand cmd = new MySqlCommand()) - { - cmd.CommandText = String.Format("delete from {0} where TMStamp < ?tstamp", m_Realm); - cmd.Parameters.AddWithValue("?tstamp", now - 14 * 24 * 60 * 60); // > 2 weeks old - - ExecuteNonQuery(cmd); - } - - } - } -} diff --git a/OpenSim/Addons/OfflineIM/Resources/IM_Store.migrations b/OpenSim/Addons/OfflineIM/Resources/IM_Store.migrations deleted file mode 100644 index 7cfcd43..0000000 --- a/OpenSim/Addons/OfflineIM/Resources/IM_Store.migrations +++ /dev/null @@ -1,24 +0,0 @@ -:VERSION 1 # -------------------------- - -BEGIN; - -CREATE TABLE `im_offline` ( - `ID` MEDIUMINT NOT NULL AUTO_INCREMENT, - `PrincipalID` char(36) NOT NULL default '', - `Message` text NOT NULL, - `TMStamp` timestamp NOT NULL, - PRIMARY KEY (`ID`), - KEY `PrincipalID` (`PrincipalID`) -) ENGINE=MyISAM; - -COMMIT; - -:VERSION 2 # -------------------------- - -BEGIN; - -INSERT INTO `im_offline` SELECT * from `diva_im_offline`; -DROP TABLE `diva_im_offline`; -DELETE FROM `migrations` WHERE name='diva_im_Store'; - -COMMIT; \ No newline at end of file -- cgit v1.1 From 9380d01976726885bd993573aa649f2cb0992909 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Tue, 19 Feb 2013 07:26:40 -0800 Subject: First commit of Diva Groups. The Data bits went to OpenSim.Data core, the rest to Addons.Groups.dll. --- OpenSim/Addons/Groups/ForeignImporter.cs | 77 + OpenSim/Addons/Groups/GroupsExtendedData.cs | 509 +++++++ OpenSim/Addons/Groups/GroupsMessagingModule.cs | 594 ++++++++ OpenSim/Addons/Groups/GroupsModule.cs | 1467 ++++++++++++++++++++ .../Groups/Hypergrid/GroupsServiceHGConnector.cs | 289 ++++ .../Hypergrid/GroupsServiceHGConnectorModule.cs | 717 ++++++++++ .../Hypergrid/HGGroupsServiceRobustConnector.cs | 443 ++++++ OpenSim/Addons/Groups/IGroupsServicesConnector.cs | 118 ++ .../Local/GroupsServiceLocalConnectorModule.cs | 347 +++++ OpenSim/Addons/Groups/Properties/AssemblyInfo.cs | 37 + .../Groups/Remote/GroupsServiceRemoteConnector.cs | 642 +++++++++ .../Remote/GroupsServiceRemoteConnectorModule.cs | 437 ++++++ .../Groups/Remote/GroupsServiceRobustConnector.cs | 760 ++++++++++ .../Addons/Groups/RemoteConnectorCacheWrapper.cs | 824 +++++++++++ OpenSim/Addons/Groups/Service/GroupsService.cs | 1014 ++++++++++++++ OpenSim/Addons/Groups/Service/GroupsServiceBase.cs | 84 ++ OpenSim/Addons/Groups/Service/HGGroupsService.cs | 353 +++++ 17 files changed, 8712 insertions(+) create mode 100644 OpenSim/Addons/Groups/ForeignImporter.cs create mode 100644 OpenSim/Addons/Groups/GroupsExtendedData.cs create mode 100644 OpenSim/Addons/Groups/GroupsMessagingModule.cs create mode 100644 OpenSim/Addons/Groups/GroupsModule.cs create mode 100644 OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnector.cs create mode 100644 OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs create mode 100644 OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs create mode 100644 OpenSim/Addons/Groups/IGroupsServicesConnector.cs create mode 100644 OpenSim/Addons/Groups/Local/GroupsServiceLocalConnectorModule.cs create mode 100644 OpenSim/Addons/Groups/Properties/AssemblyInfo.cs create mode 100644 OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnector.cs create mode 100644 OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnectorModule.cs create mode 100644 OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs create mode 100644 OpenSim/Addons/Groups/RemoteConnectorCacheWrapper.cs create mode 100644 OpenSim/Addons/Groups/Service/GroupsService.cs create mode 100644 OpenSim/Addons/Groups/Service/GroupsServiceBase.cs create mode 100644 OpenSim/Addons/Groups/Service/HGGroupsService.cs (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/ForeignImporter.cs b/OpenSim/Addons/Groups/ForeignImporter.cs new file mode 100644 index 0000000..788d21d --- /dev/null +++ b/OpenSim/Addons/Groups/ForeignImporter.cs @@ -0,0 +1,77 @@ +/* + * 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 OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; + +namespace OpenSim.Groups +{ + public class ForeignImporter + { + IUserManagement m_UserManagement; + public ForeignImporter(IUserManagement uman) + { + m_UserManagement = uman; + } + + public GroupMembersData ConvertGroupMembersData(ExtendedGroupMembersData _m) + { + GroupMembersData m = new GroupMembersData(); + m.AcceptNotices = _m.AcceptNotices; + m.AgentPowers = _m.AgentPowers; + m.Contribution = _m.Contribution; + m.IsOwner = _m.IsOwner; + m.ListInProfile = _m.ListInProfile; + m.OnlineStatus = _m.OnlineStatus; + m.Title = _m.Title; + + string url = string.Empty, first = string.Empty, last = string.Empty, tmp = string.Empty; + Util.ParseUniversalUserIdentifier(_m.AgentID, out m.AgentID, out url, out first, out last, out tmp); + if (url != string.Empty) + m_UserManagement.AddUser(m.AgentID, first, last, url); + + return m; + } + + public GroupRoleMembersData ConvertGroupRoleMembersData(ExtendedGroupRoleMembersData _rm) + { + GroupRoleMembersData rm = new GroupRoleMembersData(); + rm.RoleID = _rm.RoleID; + + string url = string.Empty, first = string.Empty, last = string.Empty, tmp = string.Empty; + Util.ParseUniversalUserIdentifier(_rm.MemberID, out rm.MemberID, out url, out first, out last, out tmp); + if (url != string.Empty) + m_UserManagement.AddUser(rm.MemberID, first, last, url); + + return rm; + } + + } +} diff --git a/OpenSim/Addons/Groups/GroupsExtendedData.cs b/OpenSim/Addons/Groups/GroupsExtendedData.cs new file mode 100644 index 0000000..6f4db28 --- /dev/null +++ b/OpenSim/Addons/Groups/GroupsExtendedData.cs @@ -0,0 +1,509 @@ +/* + * 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 OpenSim.Framework; +using OpenMetaverse; + +namespace OpenSim.Groups +{ + public class ExtendedGroupRecord : GroupRecord + { + public int MemberCount; + public int RoleCount; + public string ServiceLocation; + public string FounderUUI; + } + + public class ExtendedGroupMembershipData : GroupMembershipData + { + public string AccessToken; + } + + public class ExtendedGroupMembersData + { + // This is the only difference: this is a string + public string AgentID; + public int Contribution; + public string OnlineStatus; + public ulong AgentPowers; + public string Title; + public bool IsOwner; + public bool ListInProfile; + public bool AcceptNotices; + public string AccessToken; + } + + public class ExtendedGroupRoleMembersData + { + public UUID RoleID; + // This is the only difference: this is a string + public string MemberID; + + } + + public struct ExtendedGroupNoticeData + { + public UUID NoticeID; + public uint Timestamp; + public string FromName; + public string Subject; + public bool HasAttachment; + public byte AttachmentType; + public string AttachmentName; + public UUID AttachmentItemID; + public string AttachmentOwnerID; + + public GroupNoticeData ToGroupNoticeData() + { + GroupNoticeData n = new GroupNoticeData(); + n.FromName = this.FromName; + n.AssetType = this.AttachmentType; + n.HasAttachment = this.HasAttachment; + n.NoticeID = this.NoticeID; + n.Subject = this.Subject; + n.Timestamp = this.Timestamp; + + return n; + } + } + + public class GroupsDataUtils + { + public static string Sanitize(string s) + { + return s == null ? string.Empty : s; + } + + public static Dictionary GroupRecord(ExtendedGroupRecord grec) + { + Dictionary dict = new Dictionary(); + if (grec == null) + return dict; + + dict["AllowPublish"] = grec.AllowPublish.ToString(); + dict["Charter"] = Sanitize(grec.Charter); + dict["FounderID"] = grec.FounderID.ToString(); + dict["FounderUUI"] = Sanitize(grec.FounderUUI); + dict["GroupID"] = grec.GroupID.ToString(); + dict["GroupName"] = Sanitize(grec.GroupName); + dict["InsigniaID"] = grec.GroupPicture.ToString(); + dict["MaturePublish"] = grec.MaturePublish.ToString(); + dict["MembershipFee"] = grec.MembershipFee.ToString(); + dict["OpenEnrollment"] = grec.OpenEnrollment.ToString(); + dict["OwnerRoleID"] = grec.OwnerRoleID.ToString(); + dict["ServiceLocation"] = Sanitize(grec.ServiceLocation); + dict["ShownInList"] = grec.ShowInList.ToString(); + dict["MemberCount"] = grec.MemberCount.ToString(); + dict["RoleCount"] = grec.RoleCount.ToString(); + + return dict; + } + + public static ExtendedGroupRecord GroupRecord(Dictionary dict) + { + if (dict == null) + return null; + + ExtendedGroupRecord grec = new ExtendedGroupRecord(); + if (dict.ContainsKey("AllowPublish") && dict["AllowPublish"] != null) + grec.AllowPublish = bool.Parse(dict["AllowPublish"].ToString()); + + if (dict.ContainsKey("Charter") && dict["Charter"] != null) + grec.Charter = dict["Charter"].ToString(); + else + grec.Charter = string.Empty; + + if (dict.ContainsKey("FounderID") && dict["FounderID"] != null) + grec.FounderID = UUID.Parse(dict["FounderID"].ToString()); + + if (dict.ContainsKey("FounderUUI") && dict["FounderUUI"] != null) + grec.FounderUUI = dict["FounderUUI"].ToString(); + else + grec.FounderUUI = string.Empty; + + if (dict.ContainsKey("GroupID") && dict["GroupID"] != null) + grec.GroupID = UUID.Parse(dict["GroupID"].ToString()); + + if (dict.ContainsKey("GroupName") && dict["GroupName"] != null) + grec.GroupName = dict["GroupName"].ToString(); + else + grec.GroupName = string.Empty; + + if (dict.ContainsKey("InsigniaID") && dict["InsigniaID"] != null) + grec.GroupPicture = UUID.Parse(dict["InsigniaID"].ToString()); + + if (dict.ContainsKey("MaturePublish") && dict["MaturePublish"] != null) + grec.MaturePublish = bool.Parse(dict["MaturePublish"].ToString()); + + if (dict.ContainsKey("MembershipFee") && dict["MembershipFee"] != null) + grec.MembershipFee = Int32.Parse(dict["MembershipFee"].ToString()); + + if (dict.ContainsKey("OpenEnrollment") && dict["OpenEnrollment"] != null) + grec.OpenEnrollment = bool.Parse(dict["OpenEnrollment"].ToString()); + + if (dict.ContainsKey("OwnerRoleID") && dict["OwnerRoleID"] != null) + grec.OwnerRoleID = UUID.Parse(dict["OwnerRoleID"].ToString()); + + if (dict.ContainsKey("ServiceLocation") && dict["ServiceLocation"] != null) + grec.ServiceLocation = dict["ServiceLocation"].ToString(); + else + grec.GroupName = string.Empty; + + if (dict.ContainsKey("ShownInList") && dict["ShownInList"] != null) + grec.ShowInList = bool.Parse(dict["ShownInList"].ToString()); + + if (dict.ContainsKey("MemberCount") && dict["MemberCount"] != null) + grec.MemberCount = Int32.Parse(dict["MemberCount"].ToString()); + + if (dict.ContainsKey("RoleCount") && dict["RoleCount"] != null) + grec.RoleCount = Int32.Parse(dict["RoleCount"].ToString()); + + return grec; + } + + public static Dictionary GroupMembershipData(ExtendedGroupMembershipData membership) + { + Dictionary dict = new Dictionary(); + if (membership == null) + return dict; + + dict["AcceptNotices"] = membership.AcceptNotices.ToString(); + dict["AccessToken"] = Sanitize(membership.AccessToken); + dict["Active"] = membership.Active.ToString(); + dict["ActiveRole"] = membership.ActiveRole.ToString(); + dict["AllowPublish"] = membership.AllowPublish.ToString(); + dict["Charter"] = Sanitize(membership.Charter); + dict["Contribution"] = membership.Contribution.ToString(); + dict["FounderID"] = membership.FounderID.ToString(); + dict["GroupID"] = membership.GroupID.ToString(); + dict["GroupName"] = Sanitize(membership.GroupName); + dict["GroupPicture"] = membership.GroupPicture.ToString(); + dict["GroupPowers"] = membership.GroupPowers.ToString(); + dict["GroupTitle"] = Sanitize(membership.GroupTitle); + dict["ListInProfile"] = membership.ListInProfile.ToString(); + dict["MaturePublish"] = membership.MaturePublish.ToString(); + dict["MembershipFee"] = membership.MembershipFee.ToString(); + dict["OpenEnrollment"] = membership.OpenEnrollment.ToString(); + dict["ShowInList"] = membership.ShowInList.ToString(); + + return dict; + } + + public static ExtendedGroupMembershipData GroupMembershipData(Dictionary dict) + { + if (dict == null) + return null; + + ExtendedGroupMembershipData membership = new ExtendedGroupMembershipData(); + + if (dict.ContainsKey("AcceptNotices") && dict["AcceptNotices"] != null) + membership.AcceptNotices = bool.Parse(dict["AcceptNotices"].ToString()); + + if (dict.ContainsKey("AccessToken") && dict["AccessToken"] != null) + membership.AccessToken = dict["AccessToken"].ToString(); + else + membership.AccessToken = string.Empty; + + if (dict.ContainsKey("Active") && dict["Active"] != null) + membership.Active = bool.Parse(dict["Active"].ToString()); + + if (dict.ContainsKey("ActiveRole") && dict["ActiveRole"] != null) + membership.ActiveRole = UUID.Parse(dict["ActiveRole"].ToString()); + + if (dict.ContainsKey("AllowPublish") && dict["AllowPublish"] != null) + membership.AllowPublish = bool.Parse(dict["AllowPublish"].ToString()); + + if (dict.ContainsKey("Charter") && dict["Charter"] != null) + membership.Charter = dict["Charter"].ToString(); + else + membership.Charter = string.Empty; + + if (dict.ContainsKey("Contribution") && dict["Contribution"] != null) + membership.Contribution = Int32.Parse(dict["Contribution"].ToString()); + + if (dict.ContainsKey("FounderID") && dict["FounderID"] != null) + membership.FounderID = UUID.Parse(dict["FounderID"].ToString()); + + if (dict.ContainsKey("GroupID") && dict["GroupID"] != null) + membership.GroupID = UUID.Parse(dict["GroupID"].ToString()); + + if (dict.ContainsKey("GroupName") && dict["GroupName"] != null) + membership.GroupName = dict["GroupName"].ToString(); + else + membership.GroupName = string.Empty; + + if (dict.ContainsKey("GroupPicture") && dict["GroupPicture"] != null) + membership.GroupPicture = UUID.Parse(dict["GroupPicture"].ToString()); + + if (dict.ContainsKey("GroupPowers") && dict["GroupPowers"] != null) + membership.GroupPowers = UInt64.Parse(dict["GroupPowers"].ToString()); + + if (dict.ContainsKey("GroupTitle") && dict["GroupTitle"] != null) + membership.GroupTitle = dict["GroupTitle"].ToString(); + else + membership.GroupTitle = string.Empty; + + if (dict.ContainsKey("ListInProfile") && dict["ListInProfile"] != null) + membership.ListInProfile = bool.Parse(dict["ListInProfile"].ToString()); + + if (dict.ContainsKey("MaturePublish") && dict["MaturePublish"] != null) + membership.MaturePublish = bool.Parse(dict["MaturePublish"].ToString()); + + if (dict.ContainsKey("MembershipFee") && dict["MembershipFee"] != null) + membership.MembershipFee = Int32.Parse(dict["MembershipFee"].ToString()); + + if (dict.ContainsKey("OpenEnrollment") && dict["OpenEnrollment"] != null) + membership.OpenEnrollment = bool.Parse(dict["OpenEnrollment"].ToString()); + + if (dict.ContainsKey("ShowInList") && dict["ShowInList"] != null) + membership.ShowInList = bool.Parse(dict["ShowInList"].ToString()); + + return membership; + } + + public static Dictionary GroupMembersData(ExtendedGroupMembersData member) + { + Dictionary dict = new Dictionary(); + + dict["AcceptNotices"] = member.AcceptNotices.ToString(); + dict["AccessToken"] = Sanitize(member.AccessToken); + dict["AgentID"] = Sanitize(member.AgentID); + dict["AgentPowers"] = member.AgentPowers.ToString(); + dict["Contribution"] = member.Contribution.ToString(); + dict["IsOwner"] = member.IsOwner.ToString(); + dict["ListInProfile"] = member.ListInProfile.ToString(); + dict["OnlineStatus"] = Sanitize(member.OnlineStatus); + dict["Title"] = Sanitize(member.Title); + + return dict; + } + + public static ExtendedGroupMembersData GroupMembersData(Dictionary dict) + { + ExtendedGroupMembersData member = new ExtendedGroupMembersData(); + + if (dict == null) + return member; + + if (dict.ContainsKey("AcceptNotices") && dict["AcceptNotices"] != null) + member.AcceptNotices = bool.Parse(dict["AcceptNotices"].ToString()); + + if (dict.ContainsKey("AccessToken") && dict["AccessToken"] != null) + member.AccessToken = Sanitize(dict["AccessToken"].ToString()); + else + member.AccessToken = string.Empty; + + if (dict.ContainsKey("AgentID") && dict["AgentID"] != null) + member.AgentID = Sanitize(dict["AgentID"].ToString()); + else + member.AgentID = UUID.Zero.ToString(); + + if (dict.ContainsKey("AgentPowers") && dict["AgentPowers"] != null) + member.AgentPowers = UInt64.Parse(dict["AgentPowers"].ToString()); + + if (dict.ContainsKey("Contribution") && dict["Contribution"] != null) + member.Contribution = Int32.Parse(dict["Contribution"].ToString()); + + if (dict.ContainsKey("IsOwner") && dict["IsOwner"] != null) + member.IsOwner = bool.Parse(dict["IsOwner"].ToString()); + + if (dict.ContainsKey("ListInProfile") && dict["ListInProfile"] != null) + member.ListInProfile = bool.Parse(dict["ListInProfile"].ToString()); + + if (dict.ContainsKey("OnlineStatus") && dict["OnlineStatus"] != null) + member.OnlineStatus = Sanitize(dict["OnlineStatus"].ToString()); + else + member.OnlineStatus = string.Empty; + + if (dict.ContainsKey("Title") && dict["Title"] != null) + member.Title = Sanitize(dict["Title"].ToString()); + else + member.Title = string.Empty; + + return member; + } + + public static Dictionary GroupRolesData(GroupRolesData role) + { + Dictionary dict = new Dictionary(); + + dict["Description"] = Sanitize(role.Description); + dict["Members"] = role.Members.ToString(); + dict["Name"] = Sanitize(role.Name); + dict["Powers"] = role.Powers.ToString(); + dict["RoleID"] = role.RoleID.ToString(); + dict["Title"] = Sanitize(role.Title); + + return dict; + } + + public static GroupRolesData GroupRolesData(Dictionary dict) + { + GroupRolesData role = new GroupRolesData(); + + if (dict == null) + return role; + + if (dict.ContainsKey("Description") && dict["Description"] != null) + role.Description = Sanitize(dict["Description"].ToString()); + else + role.Description = string.Empty; + + if (dict.ContainsKey("Members") && dict["Members"] != null) + role.Members = Int32.Parse(dict["Members"].ToString()); + + if (dict.ContainsKey("Name") && dict["Name"] != null) + role.Name = Sanitize(dict["Name"].ToString()); + else + role.Name = string.Empty; + + if (dict.ContainsKey("Powers") && dict["Powers"] != null) + role.Powers = UInt64.Parse(dict["Powers"].ToString()); + + if (dict.ContainsKey("Title") && dict["Title"] != null) + role.Title = Sanitize(dict["Title"].ToString()); + else + role.Title = string.Empty; + + if (dict.ContainsKey("RoleID") && dict["RoleID"] != null) + role.RoleID = UUID.Parse(dict["RoleID"].ToString()); + + return role; + } + + public static Dictionary GroupRoleMembersData(ExtendedGroupRoleMembersData rmember) + { + Dictionary dict = new Dictionary(); + + dict["RoleID"] = rmember.RoleID.ToString(); + dict["MemberID"] = rmember.MemberID; + return dict; + } + + public static ExtendedGroupRoleMembersData GroupRoleMembersData(Dictionary dict) + { + ExtendedGroupRoleMembersData rmember = new ExtendedGroupRoleMembersData(); + + if (dict.ContainsKey("RoleID") && dict["RoleID"] != null) + rmember.RoleID = new UUID(dict["RoleID"].ToString()); + + if (dict.ContainsKey("MemberID") && dict["MemberID"] != null) + rmember.MemberID = dict["MemberID"].ToString(); + + return rmember; + } + + public static Dictionary GroupInviteInfo(GroupInviteInfo invite) + { + Dictionary dict = new Dictionary(); + + dict["InviteID"] = invite.InviteID.ToString(); + dict["GroupID"] = invite.GroupID.ToString(); + dict["RoleID"] = invite.RoleID.ToString(); + dict["AgentID"] = invite.AgentID; + + return dict; + } + + public static GroupInviteInfo GroupInviteInfo(Dictionary dict) + { + if (dict == null) + return null; + + GroupInviteInfo invite = new GroupInviteInfo(); + + invite.InviteID = new UUID(dict["InviteID"].ToString()); + invite.GroupID = new UUID(dict["GroupID"].ToString()); + invite.RoleID = new UUID(dict["RoleID"].ToString()); + invite.AgentID = Sanitize(dict["AgentID"].ToString()); + + return invite; + } + + public static Dictionary GroupNoticeData(ExtendedGroupNoticeData notice) + { + Dictionary dict = new Dictionary(); + + dict["NoticeID"] = notice.NoticeID.ToString(); + dict["Timestamp"] = notice.Timestamp.ToString(); + dict["FromName"] = Sanitize(notice.FromName); + dict["Subject"] = Sanitize(notice.Subject); + dict["HasAttachment"] = notice.HasAttachment.ToString(); + dict["AttachmentItemID"] = notice.AttachmentItemID.ToString(); + dict["AttachmentName"] = Sanitize(notice.AttachmentName); + dict["AttachmentType"] = notice.AttachmentType.ToString(); + dict["AttachmentOwnerID"] = Sanitize(notice.AttachmentOwnerID); + + return dict; + } + + public static ExtendedGroupNoticeData GroupNoticeData(Dictionary dict) + { + ExtendedGroupNoticeData notice = new ExtendedGroupNoticeData(); + + if (dict == null) + return notice; + + notice.NoticeID = new UUID(dict["NoticeID"].ToString()); + notice.Timestamp = UInt32.Parse(dict["Timestamp"].ToString()); + notice.FromName = Sanitize(dict["FromName"].ToString()); + notice.Subject = Sanitize(dict["Subject"].ToString()); + notice.HasAttachment = bool.Parse(dict["HasAttachment"].ToString()); + notice.AttachmentItemID = new UUID(dict["AttachmentItemID"].ToString()); + notice.AttachmentName = dict["AttachmentName"].ToString(); + notice.AttachmentType = byte.Parse(dict["AttachmentType"].ToString()); + notice.AttachmentOwnerID = dict["AttachmentOwnerID"].ToString(); + + return notice; + } + + public static Dictionary GroupNoticeInfo(GroupNoticeInfo notice) + { + Dictionary dict = GroupNoticeData(notice.noticeData); + + dict["GroupID"] = notice.GroupID.ToString(); + dict["Message"] = Sanitize(notice.Message); + + return dict; + } + + public static GroupNoticeInfo GroupNoticeInfo(Dictionary dict) + { + GroupNoticeInfo notice = new GroupNoticeInfo(); + + notice.noticeData = GroupNoticeData(dict); + notice.GroupID = new UUID(dict["GroupID"].ToString()); + notice.Message = Sanitize(dict["Message"].ToString()); + + return notice; + } + } + +} diff --git a/OpenSim/Addons/Groups/GroupsMessagingModule.cs b/OpenSim/Addons/Groups/GroupsMessagingModule.cs new file mode 100644 index 0000000..d172d48 --- /dev/null +++ b/OpenSim/Addons/Groups/GroupsMessagingModule.cs @@ -0,0 +1,594 @@ +/* + * 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.Linq; +using System.Reflection; +using log4net; +using Mono.Addins; +using Nini.Config; +using OpenMetaverse; +using OpenMetaverse.StructuredData; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; +using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo; + +namespace OpenSim.Groups +{ + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GroupsMessagingModule")] + public class GroupsMessagingModule : ISharedRegionModule, IGroupsMessagingModule + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private List m_sceneList = new List(); + private IPresenceService m_presenceService; + + private IMessageTransferModule m_msgTransferModule = null; + + private IGroupsServicesConnector m_groupData = null; + + // Config Options + private bool m_groupMessagingEnabled = false; + private bool m_debugEnabled = true; + + /// + /// If enabled, module only tries to send group IMs to online users by querying cached presence information. + /// + private bool m_messageOnlineAgentsOnly; + + /// + /// Cache for online users. + /// + /// + /// Group ID is key, presence information for online members is value. + /// Will only be non-null if m_messageOnlineAgentsOnly = true + /// We cache here so that group messages don't constantly have to re-request the online user list to avoid + /// attempted expensive sending of messages to offline users. + /// The tradeoff is that a user that comes online will not receive messages consistently from all other users + /// until caches have updated. + /// Therefore, we set the cache expiry to just 20 seconds. + /// + private ExpiringCache m_usersOnlineCache; + + private int m_usersOnlineCacheExpirySeconds = 20; + + #region Region Module interfaceBase Members + + public void Initialise(IConfigSource config) + { + IConfig groupsConfig = config.Configs["Groups"]; + + if (groupsConfig == null) + // Do not run this module by default. + return; + + // if groups aren't enabled, we're not needed. + // if we're not specified as the connector to use, then we're not wanted + if ((groupsConfig.GetBoolean("Enabled", false) == false) + || (groupsConfig.GetString("MessagingModule", "") != Name)) + { + m_groupMessagingEnabled = false; + return; + } + + m_groupMessagingEnabled = groupsConfig.GetBoolean("MessagingEnabled", true); + + if (!m_groupMessagingEnabled) + return; + + m_messageOnlineAgentsOnly = groupsConfig.GetBoolean("MessageOnlineUsersOnly", false); + + if (m_messageOnlineAgentsOnly) + m_usersOnlineCache = new ExpiringCache(); + + m_debugEnabled = groupsConfig.GetBoolean("DebugEnabled", true); + + m_log.InfoFormat( + "[Groups.Messaging]: GroupsMessagingModule enabled with MessageOnlineOnly = {0}, DebugEnabled = {1}", + m_messageOnlineAgentsOnly, m_debugEnabled); + } + + public void AddRegion(Scene scene) + { + if (!m_groupMessagingEnabled) + return; + + scene.RegisterModuleInterface(this); + m_sceneList.Add(scene); + + scene.EventManager.OnNewClient += OnNewClient; + scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; + scene.EventManager.OnClientLogin += OnClientLogin; + } + + public void RegionLoaded(Scene scene) + { + if (!m_groupMessagingEnabled) + return; + + if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + m_groupData = scene.RequestModuleInterface(); + + // No groups module, no groups messaging + if (m_groupData == null) + { + m_log.Error("[Groups.Messaging]: Could not get IGroupsServicesConnector, GroupsMessagingModule is now disabled."); + RemoveRegion(scene); + return; + } + + m_msgTransferModule = scene.RequestModuleInterface(); + + // No message transfer module, no groups messaging + if (m_msgTransferModule == null) + { + m_log.Error("[Groups.Messaging]: Could not get MessageTransferModule"); + RemoveRegion(scene); + return; + } + + if (m_presenceService == null) + m_presenceService = scene.PresenceService; + + } + + public void RemoveRegion(Scene scene) + { + if (!m_groupMessagingEnabled) + return; + + if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + m_sceneList.Remove(scene); + scene.EventManager.OnNewClient -= OnNewClient; + scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage; + scene.EventManager.OnClientLogin -= OnClientLogin; + scene.UnregisterModuleInterface(this); + } + + public void Close() + { + if (!m_groupMessagingEnabled) + return; + + if (m_debugEnabled) m_log.Debug("[Groups.Messaging]: Shutting down GroupsMessagingModule module."); + + m_sceneList.Clear(); + + m_groupData = null; + m_msgTransferModule = null; + } + + public Type ReplaceableInterface + { + get { return null; } + } + + public string Name + { + get { return "Groups Messaging Module V2"; } + } + + public void PostInitialise() + { + // NoOp + } + + #endregion + + + /// + /// Not really needed, but does confirm that the group exists. + /// + public bool StartGroupChatSession(UUID agentID, UUID groupID) + { + if (m_debugEnabled) + m_log.DebugFormat("[Groups.Messaging]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + GroupRecord groupInfo = m_groupData.GetGroupRecord(agentID.ToString(), groupID, null); + + if (groupInfo != null) + { + return true; + } + else + { + return false; + } + } + + public void SendMessageToGroup(GridInstantMessage im, UUID groupID) + { + List groupMembers = m_groupData.GetGroupMembers(new UUID(im.fromAgentID).ToString(), groupID); + int groupMembersCount = groupMembers.Count; + + if (m_messageOnlineAgentsOnly) + { + string[] t1 = groupMembers.ConvertAll(gmd => gmd.AgentID.ToString()).ToArray(); + + // We cache in order not to overwhlem the presence service on large grids with many groups. This does + // mean that members coming online will not see all group members until after m_usersOnlineCacheExpirySeconds has elapsed. + // (assuming this is the same across all grid simulators). + PresenceInfo[] onlineAgents; + if (!m_usersOnlineCache.TryGetValue(groupID, out onlineAgents)) + { + onlineAgents = m_presenceService.GetAgents(t1); + m_usersOnlineCache.Add(groupID, onlineAgents, m_usersOnlineCacheExpirySeconds); + } + + HashSet onlineAgentsUuidSet = new HashSet(); + Array.ForEach(onlineAgents, pi => onlineAgentsUuidSet.Add(pi.UserID)); + + groupMembers = groupMembers.Where(gmd => onlineAgentsUuidSet.Contains(gmd.AgentID.ToString())).ToList(); + + // if (m_debugEnabled) +// m_log.DebugFormat( +// "[Groups.Messaging]: SendMessageToGroup called for group {0} with {1} visible members, {2} online", +// groupID, groupMembersCount, groupMembers.Count()); + } + else + { + if (m_debugEnabled) + m_log.DebugFormat( + "[Groups.Messaging]: SendMessageToGroup called for group {0} with {1} visible members", + groupID, groupMembers.Count); + } + + int requestStartTick = Environment.TickCount; + + foreach (GroupMembersData member in groupMembers) + { + if (m_groupData.hasAgentDroppedGroupChatSession(member.AgentID.ToString(), groupID)) + { + // Don't deliver messages to people who have dropped this session + if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: {0} has dropped session, not delivering to them", member.AgentID); + continue; + } + + // Copy Message + GridInstantMessage msg = new GridInstantMessage(); + msg.imSessionID = groupID.Guid; + msg.fromAgentName = im.fromAgentName; + msg.message = im.message; + msg.dialog = im.dialog; + msg.offline = im.offline; + msg.ParentEstateID = im.ParentEstateID; + msg.Position = im.Position; + msg.RegionID = im.RegionID; + msg.binaryBucket = im.binaryBucket; + msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); + + msg.fromAgentID = im.fromAgentID; + msg.fromGroup = true; + + msg.toAgentID = member.AgentID.Guid; + + IClientAPI client = GetActiveClient(member.AgentID); + if (client == null) + { + // If they're not local, forward across the grid + if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Delivering to {0} via Grid", member.AgentID); + m_msgTransferModule.SendInstantMessage(msg, delegate(bool success) { }); + } + else + { + // Deliver locally, directly + if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Passing to ProcessMessageFromGroupSession to deliver to {0} locally", client.Name); + ProcessMessageFromGroupSession(msg); + } + } + + // Temporary for assessing how long it still takes to send messages to large online groups. + if (m_messageOnlineAgentsOnly) + m_log.DebugFormat( + "[Groups.Messaging]: SendMessageToGroup for group {0} with {1} visible members, {2} online took {3}ms", + groupID, groupMembersCount, groupMembers.Count(), Environment.TickCount - requestStartTick); + } + + #region SimGridEventHandlers + + void OnClientLogin(IClientAPI client) + { + if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: OnInstantMessage registered for {0}", client.Name); + } + + private void OnNewClient(IClientAPI client) + { + if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: OnInstantMessage registered for {0}", client.Name); + + client.OnInstantMessage += OnInstantMessage; + } + + private void OnGridInstantMessage(GridInstantMessage msg) + { + // The instant message module will only deliver messages of dialog types: + // MessageFromAgent, StartTyping, StopTyping, MessageFromObject + // + // Any other message type will not be delivered to a client by the + // Instant Message Module + + + if (m_debugEnabled) + { + m_log.DebugFormat("[Groups.Messaging]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + DebugGridInstantMessage(msg); + } + + // Incoming message from a group + if ((msg.fromGroup == true) && + ((msg.dialog == (byte)InstantMessageDialog.SessionSend) + || (msg.dialog == (byte)InstantMessageDialog.SessionAdd) + || (msg.dialog == (byte)InstantMessageDialog.SessionDrop))) + { + ProcessMessageFromGroupSession(msg); + } + } + + private void ProcessMessageFromGroupSession(GridInstantMessage msg) + { + if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Session message from {0} going to agent {1}", msg.fromAgentName, msg.toAgentID); + + UUID AgentID = new UUID(msg.fromAgentID); + UUID GroupID = new UUID(msg.imSessionID); + + switch (msg.dialog) + { + case (byte)InstantMessageDialog.SessionAdd: + m_groupData.AgentInvitedToGroupChatSession(AgentID.ToString(), GroupID); + break; + + case (byte)InstantMessageDialog.SessionDrop: + m_groupData.AgentDroppedFromGroupChatSession(AgentID.ToString(), GroupID); + break; + + case (byte)InstantMessageDialog.SessionSend: + if (!m_groupData.hasAgentDroppedGroupChatSession(AgentID.ToString(), GroupID) + && !m_groupData.hasAgentBeenInvitedToGroupChatSession(AgentID.ToString(), GroupID) + ) + { + // Agent not in session and hasn't dropped from session + // Add them to the session for now, and Invite them + m_groupData.AgentInvitedToGroupChatSession(AgentID.ToString(), GroupID); + + UUID toAgentID = new UUID(msg.toAgentID); + IClientAPI activeClient = GetActiveClient(toAgentID); + if (activeClient != null) + { + GroupRecord groupInfo = m_groupData.GetGroupRecord(UUID.Zero.ToString(), GroupID, null); + if (groupInfo != null) + { + if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Sending chatterbox invite instant message"); + + // Force? open the group session dialog??? + // and simultanously deliver the message, so we don't need to do a seperate client.SendInstantMessage(msg); + IEventQueue eq = activeClient.Scene.RequestModuleInterface(); + eq.ChatterboxInvitation( + GroupID + , groupInfo.GroupName + , new UUID(msg.fromAgentID) + , msg.message + , new UUID(msg.toAgentID) + , msg.fromAgentName + , msg.dialog + , msg.timestamp + , msg.offline == 1 + , (int)msg.ParentEstateID + , msg.Position + , 1 + , new UUID(msg.imSessionID) + , msg.fromGroup + , OpenMetaverse.Utils.StringToBytes(groupInfo.GroupName) + ); + + eq.ChatterBoxSessionAgentListUpdates( + new UUID(GroupID) + , new UUID(msg.fromAgentID) + , new UUID(msg.toAgentID) + , false //canVoiceChat + , false //isModerator + , false //text mute + ); + } + } + } + else if (!m_groupData.hasAgentDroppedGroupChatSession(AgentID.ToString(), GroupID)) + { + // User hasn't dropped, so they're in the session, + // maybe we should deliver it. + IClientAPI client = GetActiveClient(new UUID(msg.toAgentID)); + if (client != null) + { + // Deliver locally, directly + if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Delivering to {0} locally", client.Name); + client.SendInstantMessage(msg); + } + else + { + m_log.WarnFormat("[Groups.Messaging]: Received a message over the grid for a client that isn't here: {0}", msg.toAgentID); + } + } + break; + + default: + m_log.WarnFormat("[Groups.Messaging]: I don't know how to proccess a {0} message.", ((InstantMessageDialog)msg.dialog).ToString()); + break; + } + } + + #endregion + + + #region ClientEvents + private void OnInstantMessage(IClientAPI remoteClient, GridInstantMessage im) + { + if (m_debugEnabled) + { + m_log.DebugFormat("[Groups.Messaging]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + DebugGridInstantMessage(im); + } + + // Start group IM session + if ((im.dialog == (byte)InstantMessageDialog.SessionGroupStart)) + { + if (m_debugEnabled) m_log.InfoFormat("[Groups.Messaging]: imSessionID({0}) toAgentID({1})", im.imSessionID, im.toAgentID); + + UUID GroupID = new UUID(im.imSessionID); + UUID AgentID = new UUID(im.fromAgentID); + + GroupRecord groupInfo = m_groupData.GetGroupRecord(UUID.Zero.ToString(), GroupID, null); + + if (groupInfo != null) + { + m_groupData.AgentInvitedToGroupChatSession(AgentID.ToString(), GroupID); + + ChatterBoxSessionStartReplyViaCaps(remoteClient, groupInfo.GroupName, GroupID); + + IEventQueue queue = remoteClient.Scene.RequestModuleInterface(); + queue.ChatterBoxSessionAgentListUpdates( + GroupID + , AgentID + , new UUID(im.toAgentID) + , false //canVoiceChat + , false //isModerator + , false //text mute + ); + } + } + + // Send a message from locally connected client to a group + if ((im.dialog == (byte)InstantMessageDialog.SessionSend)) + { + UUID GroupID = new UUID(im.imSessionID); + UUID AgentID = new UUID(im.fromAgentID); + + if (m_debugEnabled) + m_log.DebugFormat("[Groups.Messaging]: Send message to session for group {0} with session ID {1}", GroupID, im.imSessionID.ToString()); + + //If this agent is sending a message, then they want to be in the session + m_groupData.AgentInvitedToGroupChatSession(AgentID.ToString(), GroupID); + + SendMessageToGroup(im, GroupID); + } + } + + #endregion + + void ChatterBoxSessionStartReplyViaCaps(IClientAPI remoteClient, string groupName, UUID groupID) + { + if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + OSDMap moderatedMap = new OSDMap(4); + moderatedMap.Add("voice", OSD.FromBoolean(false)); + + OSDMap sessionMap = new OSDMap(4); + sessionMap.Add("moderated_mode", moderatedMap); + sessionMap.Add("session_name", OSD.FromString(groupName)); + sessionMap.Add("type", OSD.FromInteger(0)); + sessionMap.Add("voice_enabled", OSD.FromBoolean(false)); + + OSDMap bodyMap = new OSDMap(4); + bodyMap.Add("session_id", OSD.FromUUID(groupID)); + bodyMap.Add("temp_session_id", OSD.FromUUID(groupID)); + bodyMap.Add("success", OSD.FromBoolean(true)); + bodyMap.Add("session_info", sessionMap); + + IEventQueue queue = remoteClient.Scene.RequestModuleInterface(); + + if (queue != null) + { + queue.Enqueue(queue.BuildEvent("ChatterBoxSessionStartReply", bodyMap), remoteClient.AgentId); + } + } + + private void DebugGridInstantMessage(GridInstantMessage im) + { + // Don't log any normal IMs (privacy!) + if (m_debugEnabled && im.dialog != (byte)InstantMessageDialog.MessageFromAgent) + { + m_log.WarnFormat("[Groups.Messaging]: IM: fromGroup({0})", im.fromGroup ? "True" : "False"); + m_log.WarnFormat("[Groups.Messaging]: IM: Dialog({0})", ((InstantMessageDialog)im.dialog).ToString()); + m_log.WarnFormat("[Groups.Messaging]: IM: fromAgentID({0})", im.fromAgentID.ToString()); + m_log.WarnFormat("[Groups.Messaging]: IM: fromAgentName({0})", im.fromAgentName.ToString()); + m_log.WarnFormat("[Groups.Messaging]: IM: imSessionID({0})", im.imSessionID.ToString()); + m_log.WarnFormat("[Groups.Messaging]: IM: message({0})", im.message.ToString()); + m_log.WarnFormat("[Groups.Messaging]: IM: offline({0})", im.offline.ToString()); + m_log.WarnFormat("[Groups.Messaging]: IM: toAgentID({0})", im.toAgentID.ToString()); + m_log.WarnFormat("[Groups.Messaging]: IM: binaryBucket({0})", OpenMetaverse.Utils.BytesToHexString(im.binaryBucket, "BinaryBucket")); + } + } + + #region Client Tools + + /// + /// Try to find an active IClientAPI reference for agentID giving preference to root connections + /// + private IClientAPI GetActiveClient(UUID agentID) + { + if (m_debugEnabled) m_log.WarnFormat("[Groups.Messaging]: Looking for local client {0}", agentID); + + IClientAPI child = null; + + // Try root avatar first + foreach (Scene scene in m_sceneList) + { + ScenePresence sp = scene.GetScenePresence(agentID); + if (sp != null) + { + if (!sp.IsChildAgent) + { + if (m_debugEnabled) m_log.WarnFormat("[Groups.Messaging]: Found root agent for client : {0}", sp.ControllingClient.Name); + return sp.ControllingClient; + } + else + { + if (m_debugEnabled) m_log.WarnFormat("[Groups.Messaging]: Found child agent for client : {0}", sp.ControllingClient.Name); + child = sp.ControllingClient; + } + } + } + + // If we didn't find a root, then just return whichever child we found, or null if none + if (child == null) + { + if (m_debugEnabled) m_log.WarnFormat("[Groups.Messaging]: Could not find local client for agent : {0}", agentID); + } + else + { + if (m_debugEnabled) m_log.WarnFormat("[Groups.Messaging]: Returning child agent for client : {0}", child.Name); + } + return child; + } + + #endregion + } +} diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs new file mode 100644 index 0000000..10bfa8f --- /dev/null +++ b/OpenSim/Addons/Groups/GroupsModule.cs @@ -0,0 +1,1467 @@ +/* + * 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.Reflection; +using System.Timers; +using log4net; +using Mono.Addins; +using Nini.Config; +using OpenMetaverse; +using OpenMetaverse.StructuredData; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; +using DirFindFlags = OpenMetaverse.DirectoryManager.DirFindFlags; + +namespace OpenSim.Groups +{ + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GroupsModule")] + public class GroupsModule : ISharedRegionModule, IGroupsModule + { + /// + /// + + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private List m_sceneList = new List(); + + private IMessageTransferModule m_msgTransferModule = null; + + private IGroupsServicesConnector m_groupData = null; + private IUserManagement m_UserManagement; + + // Configuration settings + private bool m_groupsEnabled = false; + private bool m_groupNoticesEnabled = true; + private bool m_debugEnabled = false; + private int m_levelGroupCreate = 0; + + #region Region Module interfaceBase Members + + public void Initialise(IConfigSource config) + { + IConfig groupsConfig = config.Configs["Groups"]; + + if (groupsConfig == null) + { + // Do not run this module by default. + return; + } + else + { + m_groupsEnabled = groupsConfig.GetBoolean("Enabled", false); + if (!m_groupsEnabled) + { + return; + } + + if (groupsConfig.GetString("Module", "Default") != Name) + { + m_groupsEnabled = false; + + return; + } + + m_log.InfoFormat("[Groups]: Initializing {0}", this.Name); + + m_groupNoticesEnabled = groupsConfig.GetBoolean("NoticesEnabled", true); + m_debugEnabled = groupsConfig.GetBoolean("DebugEnabled", false); + m_levelGroupCreate = groupsConfig.GetInt("LevelGroupCreate", 0); + } + } + + public void AddRegion(Scene scene) + { + if (m_groupsEnabled) + { + scene.RegisterModuleInterface(this); + scene.AddCommand( + "debug", + this, + "debug groups verbose", + "debug groups verbose ", + "This setting turns on very verbose groups debugging", + HandleDebugGroupsVerbose); + } + } + + private void HandleDebugGroupsVerbose(object modules, string[] args) + { + if (args.Length < 4) + { + MainConsole.Instance.Output("Usage: debug groups verbose "); + return; + } + + bool verbose = false; + if (!bool.TryParse(args[3], out verbose)) + { + MainConsole.Instance.Output("Usage: debug groups verbose "); + return; + } + + m_debugEnabled = verbose; + + MainConsole.Instance.OutputFormat("{0} verbose logging set to {1}", Name, m_debugEnabled); + } + + public void RegionLoaded(Scene scene) + { + if (!m_groupsEnabled) + return; + + if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + scene.EventManager.OnNewClient += OnNewClient; + scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; + // The InstantMessageModule itself doesn't do this, + // so lets see if things explode if we don't do it + // scene.EventManager.OnClientClosed += OnClientClosed; + + if (m_groupData == null) + { + m_groupData = scene.RequestModuleInterface(); + + // No Groups Service Connector, then nothing works... + if (m_groupData == null) + { + m_groupsEnabled = false; + m_log.Error("[Groups]: Could not get IGroupsServicesConnector"); + RemoveRegion(scene); + return; + } + } + + if (m_msgTransferModule == null) + { + m_msgTransferModule = scene.RequestModuleInterface(); + + // No message transfer module, no notices, group invites, rejects, ejects, etc + if (m_msgTransferModule == null) + { + m_log.Warn("[Groups]: Could not get MessageTransferModule"); + } + } + + if (m_UserManagement == null) + { + m_UserManagement = scene.RequestModuleInterface(); + if (m_UserManagement == null) + m_log.Warn("[Groups]: Could not get UserManagementModule"); + } + + lock (m_sceneList) + { + m_sceneList.Add(scene); + } + + + } + + public void RemoveRegion(Scene scene) + { + if (!m_groupsEnabled) + return; + + if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + scene.EventManager.OnNewClient -= OnNewClient; + scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage; + + lock (m_sceneList) + { + m_sceneList.Remove(scene); + } + } + + public void Close() + { + if (!m_groupsEnabled) + return; + + if (m_debugEnabled) m_log.Debug("[Groups]: Shutting down Groups module."); + } + + public Type ReplaceableInterface + { + get { return null; } + } + + public string Name + { + get { return "Groups Module V2"; } + } + + public void PostInitialise() + { + // NoOp + } + + #endregion + + #region EventHandlers + private void OnNewClient(IClientAPI client) + { + if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + client.OnUUIDGroupNameRequest += HandleUUIDGroupNameRequest; + client.OnAgentDataUpdateRequest += OnAgentDataUpdateRequest; + client.OnDirFindQuery += OnDirFindQuery; + client.OnRequestAvatarProperties += OnRequestAvatarProperties; + + // Used for Notices and Group Invites/Accept/Reject + client.OnInstantMessage += OnInstantMessage; + + // Send client their groups information. + SendAgentGroupDataUpdate(client, client.AgentId); + } + + private void OnRequestAvatarProperties(IClientAPI remoteClient, UUID avatarID) + { + if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + //GroupMembershipData[] avatarGroups = m_groupData.GetAgentGroupMemberships(GetRequestingAgentID(remoteClient), avatarID).ToArray(); + GroupMembershipData[] avatarGroups = GetProfileListedGroupMemberships(remoteClient, avatarID); + remoteClient.SendAvatarGroupsReply(avatarID, avatarGroups); + } + + /* + * This becomes very problematic in a shared module. In a shared module you may have more then one + * reference to IClientAPI's, one for 0 or 1 root connections, and 0 or more child connections. + * The OnClientClosed event does not provide anything to indicate which one of those should be closed + * nor does it provide what scene it was from so that the specific reference can be looked up. + * The InstantMessageModule.cs does not currently worry about unregistering the handles, + * and it should be an issue, since it's the client that references us not the other way around + * , so as long as we don't keep a reference to the client laying around, the client can still be GC'ed + private void OnClientClosed(UUID AgentId) + { + if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + lock (m_ActiveClients) + { + if (m_ActiveClients.ContainsKey(AgentId)) + { + IClientAPI client = m_ActiveClients[AgentId]; + client.OnUUIDGroupNameRequest -= HandleUUIDGroupNameRequest; + client.OnAgentDataUpdateRequest -= OnAgentDataUpdateRequest; + client.OnDirFindQuery -= OnDirFindQuery; + client.OnInstantMessage -= OnInstantMessage; + + m_ActiveClients.Remove(AgentId); + } + else + { + if (m_debugEnabled) m_log.WarnFormat("[Groups]: Client closed that wasn't registered here."); + } + + + } + } + */ + + void OnDirFindQuery(IClientAPI remoteClient, UUID queryID, string queryText, uint queryFlags, int queryStart) + { + if (((DirFindFlags)queryFlags & DirFindFlags.Groups) == DirFindFlags.Groups) + { + if (m_debugEnabled) + m_log.DebugFormat( + "[Groups]: {0} called with queryText({1}) queryFlags({2}) queryStart({3})", + System.Reflection.MethodBase.GetCurrentMethod().Name, queryText, (DirFindFlags)queryFlags, queryStart); + + // TODO: This currently ignores pretty much all the query flags including Mature and sort order + remoteClient.SendDirGroupsReply(queryID, m_groupData.FindGroups(GetRequestingAgentIDStr(remoteClient), queryText).ToArray()); + } + + } + + private void OnAgentDataUpdateRequest(IClientAPI remoteClient, UUID dataForAgentID, UUID sessionID) + { + if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + UUID activeGroupID = UUID.Zero; + string activeGroupTitle = string.Empty; + string activeGroupName = string.Empty; + ulong activeGroupPowers = (ulong)GroupPowers.None; + + GroupMembershipData membership = m_groupData.GetAgentActiveMembership(GetRequestingAgentIDStr(remoteClient), dataForAgentID.ToString()); + if (membership != null) + { + activeGroupID = membership.GroupID; + activeGroupTitle = membership.GroupTitle; + activeGroupPowers = membership.GroupPowers; + } + + SendAgentDataUpdate(remoteClient, dataForAgentID, activeGroupID, activeGroupName, activeGroupPowers, activeGroupTitle); + + SendScenePresenceUpdate(dataForAgentID, activeGroupTitle); + } + + private void HandleUUIDGroupNameRequest(UUID GroupID, IClientAPI remoteClient) + { + if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + string GroupName; + + GroupRecord group = m_groupData.GetGroupRecord(GetRequestingAgentIDStr(remoteClient), GroupID, null); + if (group != null) + { + GroupName = group.GroupName; + } + else + { + GroupName = "Unknown"; + } + + remoteClient.SendGroupNameReply(GroupID, GroupName); + } + + private void OnInstantMessage(IClientAPI remoteClient, GridInstantMessage im) + { + if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + m_log.DebugFormat("[Groups]: IM From {0} to {1} msg {2} type {3}", im.fromAgentID, im.toAgentID, im.message, (InstantMessageDialog)im.dialog); + // Group invitations + if ((im.dialog == (byte)InstantMessageDialog.GroupInvitationAccept) || (im.dialog == (byte)InstantMessageDialog.GroupInvitationDecline)) + { + UUID inviteID = new UUID(im.imSessionID); + GroupInviteInfo inviteInfo = m_groupData.GetAgentToGroupInvite(GetRequestingAgentIDStr(remoteClient), inviteID); + + if (inviteInfo == null) + { + if (m_debugEnabled) m_log.WarnFormat("[Groups]: Received an Invite IM for an invite that does not exist {0}.", inviteID); + return; + } + + //m_log.DebugFormat("[XXX]: Invite is for Agent {0} to Group {1}.", inviteInfo.AgentID, inviteInfo.GroupID); + + UUID fromAgentID = new UUID(im.fromAgentID); + UUID invitee = UUID.Zero; + string tmp = string.Empty; + Util.ParseUniversalUserIdentifier(inviteInfo.AgentID, out invitee, out tmp, out tmp, out tmp, out tmp); + if ((inviteInfo != null) && (fromAgentID == invitee)) + { + // Accept + if (im.dialog == (byte)InstantMessageDialog.GroupInvitationAccept) + { + //m_log.DebugFormat("[XXX]: Received an accept invite notice."); + + // and the sessionid is the role + string reason = string.Empty; + if (!m_groupData.AddAgentToGroup(GetRequestingAgentIDStr(remoteClient), invitee.ToString(), inviteInfo.GroupID, inviteInfo.RoleID, string.Empty, out reason)) + remoteClient.SendAgentAlertMessage("Unable to add you to the group: " + reason, false); + else + { + GridInstantMessage msg = new GridInstantMessage(); + msg.imSessionID = UUID.Zero.Guid; + msg.fromAgentID = UUID.Zero.Guid; + msg.toAgentID = invitee.Guid; + msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); + msg.fromAgentName = "Groups"; + msg.message = string.Format("You have been added to the group."); + msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.MessageBox; + msg.fromGroup = false; + msg.offline = (byte)0; + msg.ParentEstateID = 0; + msg.Position = Vector3.Zero; + msg.RegionID = UUID.Zero.Guid; + msg.binaryBucket = new byte[0]; + + OutgoingInstantMessage(msg, invitee); + + UpdateAllClientsWithGroupInfo(invitee); + } + + m_groupData.RemoveAgentToGroupInvite(GetRequestingAgentIDStr(remoteClient), inviteID); + + } + + // Reject + if (im.dialog == (byte)InstantMessageDialog.GroupInvitationDecline) + { + if (m_debugEnabled) m_log.DebugFormat("[Groups]: Received a reject invite notice."); + m_groupData.RemoveAgentToGroupInvite(GetRequestingAgentIDStr(remoteClient), inviteID); + + m_groupData.RemoveAgentFromGroup(GetRequestingAgentIDStr(remoteClient), inviteInfo.AgentID, inviteInfo.GroupID); + } + } + } + + // Group notices + if ((im.dialog == (byte)InstantMessageDialog.GroupNotice)) + { + if (!m_groupNoticesEnabled) + { + return; + } + + UUID GroupID = new UUID(im.toAgentID); + if (m_groupData.GetGroupRecord(GetRequestingAgentIDStr(remoteClient), GroupID, null) != null) + { + UUID NoticeID = UUID.Random(); + string Subject = im.message.Substring(0, im.message.IndexOf('|')); + string Message = im.message.Substring(Subject.Length + 1); + + InventoryItemBase item = null; + bool hasAttachment = false; + + if (im.binaryBucket.Length >= 1 && im.binaryBucket[0] > 0) + { + hasAttachment = true; + string binBucket = OpenMetaverse.Utils.BytesToString(im.binaryBucket); + binBucket = binBucket.Remove(0, 14).Trim(); + + OSD binBucketOSD = OSDParser.DeserializeLLSDXml(binBucket); + if (binBucketOSD is OSDMap) + { + OSDMap binBucketMap = (OSDMap)binBucketOSD; + + UUID itemID = binBucketMap["item_id"].AsUUID(); + UUID ownerID = binBucketMap["owner_id"].AsUUID(); + item = new InventoryItemBase(itemID, ownerID); + item = m_sceneList[0].InventoryService.GetItem(item); + } + else + m_log.DebugFormat("[Groups]: Received OSD with unexpected type: {0}", binBucketOSD.GetType()); + } + + if (m_groupData.AddGroupNotice(GetRequestingAgentIDStr(remoteClient), GroupID, NoticeID, im.fromAgentName, Subject, Message, + hasAttachment, + (byte)(item == null ? 0 : item.AssetType), + item == null ? null : item.Name, + item == null ? UUID.Zero : item.ID, + item == null ? UUID.Zero.ToString() : item.Owner.ToString())) + { + if (OnNewGroupNotice != null) + { + OnNewGroupNotice(GroupID, NoticeID); + } + + // Send notice out to everyone that wants notices + // Build notice IIM + GridInstantMessage msg = CreateGroupNoticeIM(UUID.Zero, NoticeID, (byte)OpenMetaverse.InstantMessageDialog.GroupNotice); + foreach (GroupMembersData member in m_groupData.GetGroupMembers(GetRequestingAgentIDStr(remoteClient), GroupID)) + { + if (member.AcceptNotices) + { + msg.toAgentID = member.AgentID.Guid; + OutgoingInstantMessage(msg, member.AgentID); + } + } + } + } + } + + if (im.dialog == (byte)InstantMessageDialog.GroupNoticeInventoryAccepted) + { + if (im.binaryBucket.Length < 16) // Invalid + return; + + //// 16 bytes are the UUID. Maybe. + UUID folderID = new UUID(im.binaryBucket, 0); + UUID noticeID = new UUID(im.imSessionID); + + GroupNoticeInfo notice = m_groupData.GetGroupNotice(remoteClient.AgentId.ToString(), noticeID); + if (notice != null) + { + UUID giver = new UUID(im.toAgentID); + string tmp = string.Empty; + Util.ParseUniversalUserIdentifier(notice.noticeData.AttachmentOwnerID, out giver, out tmp, out tmp, out tmp, out tmp); + + m_log.DebugFormat("[Groups]: Giving inventory from {0} to {1}", giver, remoteClient.AgentId); + InventoryItemBase itemCopy = ((Scene)(remoteClient.Scene)).GiveInventoryItem(remoteClient.AgentId, + giver, notice.noticeData.AttachmentItemID); + + if (itemCopy == null) + { + remoteClient.SendAgentAlertMessage("Can't find item to give. Nothing given.", false); + return; + } + + remoteClient.SendInventoryItemCreateUpdate(itemCopy, 0); + } + + } + + // Interop, received special 210 code for ejecting a group member + // this only works within the comms servers domain, and won't work hypergrid + // TODO:FIXME: Use a presense server of some kind to find out where the + // client actually is, and try contacting that region directly to notify them, + // or provide the notification via xmlrpc update queue + if ((im.dialog == 210)) + { + // This is sent from the region that the ejectee was ejected from + // if it's being delivered here, then the ejectee is here + // so we need to send local updates to the agent. + + UUID ejecteeID = new UUID(im.toAgentID); + + im.dialog = (byte)InstantMessageDialog.MessageFromAgent; + OutgoingInstantMessage(im, ejecteeID); + + IClientAPI ejectee = GetActiveClient(ejecteeID); + if (ejectee != null) + { + UUID groupID = new UUID(im.imSessionID); + ejectee.SendAgentDropGroup(groupID); + } + } + } + + private void OnGridInstantMessage(GridInstantMessage msg) + { + if (m_debugEnabled) m_log.InfoFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + // Trigger the above event handler + OnInstantMessage(null, msg); + + // If a message from a group arrives here, it may need to be forwarded to a local client + if (msg.fromGroup == true) + { + switch (msg.dialog) + { + case (byte)InstantMessageDialog.GroupInvitation: + case (byte)InstantMessageDialog.GroupNotice: + UUID toAgentID = new UUID(msg.toAgentID); + IClientAPI localClient = GetActiveClient(toAgentID); + if (localClient != null) + { + localClient.SendInstantMessage(msg); + } + break; + } + } + } + + #endregion + + #region IGroupsModule Members + + public event NewGroupNotice OnNewGroupNotice; + + public GroupRecord GetGroupRecord(UUID GroupID) + { + return m_groupData.GetGroupRecord(UUID.Zero.ToString(), GroupID, null); + } + + public GroupRecord GetGroupRecord(string name) + { + return m_groupData.GetGroupRecord(UUID.Zero.ToString(), UUID.Zero, name); + } + + public void ActivateGroup(IClientAPI remoteClient, UUID groupID) + { + if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + m_groupData.SetAgentActiveGroup(GetRequestingAgentIDStr(remoteClient), GetRequestingAgentIDStr(remoteClient), groupID); + + // Changing active group changes title, active powers, all kinds of things + // anyone who is in any region that can see this client, should probably be + // updated with new group info. At a minimum, they should get ScenePresence + // updated with new title. + UpdateAllClientsWithGroupInfo(remoteClient.AgentId); + } + + /// + /// Get the Role Titles for an Agent, for a specific group + /// + public List GroupTitlesRequest(IClientAPI remoteClient, UUID groupID) + { + if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + List agentRoles = m_groupData.GetAgentGroupRoles(GetRequestingAgentIDStr(remoteClient), GetRequestingAgentIDStr(remoteClient), groupID); + GroupMembershipData agentMembership = m_groupData.GetAgentGroupMembership(GetRequestingAgentIDStr(remoteClient), GetRequestingAgentIDStr(remoteClient), groupID); + + List titles = new List(); + foreach (GroupRolesData role in agentRoles) + { + GroupTitlesData title = new GroupTitlesData(); + title.Name = role.Name; + if (agentMembership != null) + { + title.Selected = agentMembership.ActiveRole == role.RoleID; + } + title.UUID = role.RoleID; + + titles.Add(title); + } + + return titles; + } + + public List GroupMembersRequest(IClientAPI remoteClient, UUID groupID) + { + if (m_debugEnabled) + m_log.DebugFormat( + "[Groups]: GroupMembersRequest called for {0} from client {1}", groupID, remoteClient.Name); + + List data = m_groupData.GetGroupMembers(GetRequestingAgentIDStr(remoteClient), groupID); + + if (m_debugEnabled) + { + foreach (GroupMembersData member in data) + { + m_log.DebugFormat("[Groups]: Member({0}) - IsOwner({1})", member.AgentID, member.IsOwner); + } + } + + return data; + + } + + public List GroupRoleDataRequest(IClientAPI remoteClient, UUID groupID) + { + if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + List data = m_groupData.GetGroupRoles(GetRequestingAgentIDStr(remoteClient), groupID); + + return data; + } + + public List GroupRoleMembersRequest(IClientAPI remoteClient, UUID groupID) + { + if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + List data = m_groupData.GetGroupRoleMembers(GetRequestingAgentIDStr(remoteClient), groupID); + + if (m_debugEnabled) + { + foreach (GroupRoleMembersData member in data) + { + m_log.DebugFormat("[Groups]: Member({0}) - Role({1})", member.MemberID, member.RoleID); + } + } + return data; + } + + public GroupProfileData GroupProfileRequest(IClientAPI remoteClient, UUID groupID) + { + if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + GroupProfileData profile = new GroupProfileData(); + + // just to get the OwnerRole... + ExtendedGroupRecord groupInfo = m_groupData.GetGroupRecord(GetRequestingAgentIDStr(remoteClient), groupID, string.Empty); + GroupMembershipData memberInfo = m_groupData.GetAgentGroupMembership(GetRequestingAgentIDStr(remoteClient), GetRequestingAgentIDStr(remoteClient), groupID); + if (groupInfo != null) + { + profile.AllowPublish = groupInfo.AllowPublish; + profile.Charter = groupInfo.Charter; + profile.FounderID = groupInfo.FounderID; + profile.GroupID = groupID; + profile.GroupMembershipCount = groupInfo.MemberCount; + profile.GroupRolesCount = groupInfo.RoleCount; + profile.InsigniaID = groupInfo.GroupPicture; + profile.MaturePublish = groupInfo.MaturePublish; + profile.MembershipFee = groupInfo.MembershipFee; + profile.Money = 0; + profile.Name = groupInfo.GroupName; + profile.OpenEnrollment = groupInfo.OpenEnrollment; + profile.OwnerRole = groupInfo.OwnerRoleID; + profile.ShowInList = groupInfo.ShowInList; + } + if (memberInfo != null) + { + profile.MemberTitle = memberInfo.GroupTitle; + profile.PowersMask = memberInfo.GroupPowers; + } + + return profile; + } + + public GroupMembershipData[] GetMembershipData(UUID agentID) + { + if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + return m_groupData.GetAgentGroupMemberships(UUID.Zero.ToString(), agentID.ToString()).ToArray(); + } + + public GroupMembershipData GetMembershipData(UUID groupID, UUID agentID) + { + if (m_debugEnabled) + m_log.DebugFormat( + "[Groups]: {0} called with groupID={1}, agentID={2}", + System.Reflection.MethodBase.GetCurrentMethod().Name, groupID, agentID); + + return m_groupData.GetAgentGroupMembership(UUID.Zero.ToString(), agentID.ToString(), groupID); + } + + public void UpdateGroupInfo(IClientAPI remoteClient, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish) + { + if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + // Note: Permissions checking for modification rights is handled by the Groups Server/Service + string reason = string.Empty; + if (!m_groupData.UpdateGroup(GetRequestingAgentIDStr(remoteClient), groupID, charter, showInList, insigniaID, membershipFee, + openEnrollment, allowPublish, maturePublish, out reason)) + remoteClient.SendAgentAlertMessage(reason, false); + } + + public void SetGroupAcceptNotices(IClientAPI remoteClient, UUID groupID, bool acceptNotices, bool listInProfile) + { + // Note: Permissions checking for modification rights is handled by the Groups Server/Service + if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + m_groupData.UpdateMembership(GetRequestingAgentIDStr(remoteClient), GetRequestingAgentIDStr(remoteClient), groupID, acceptNotices, listInProfile); + } + + public UUID CreateGroup(IClientAPI remoteClient, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish) + { + if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called in {1}", System.Reflection.MethodBase.GetCurrentMethod().Name, remoteClient.Scene.RegionInfo.RegionName); + + if (m_groupData.GetGroupRecord(GetRequestingAgentIDStr(remoteClient), UUID.Zero, name) != null) + { + remoteClient.SendCreateGroupReply(UUID.Zero, false, "A group with the same name already exists."); + return UUID.Zero; + } + + // check user level + ScenePresence avatar = null; + Scene scene = (Scene)remoteClient.Scene; + scene.TryGetScenePresence(remoteClient.AgentId, out avatar); + + if (avatar != null) + { + if (avatar.UserLevel < m_levelGroupCreate) + { + remoteClient.SendCreateGroupReply(UUID.Zero, false, String.Format("Insufficient permissions to create a group. Requires level {0}", m_levelGroupCreate)); + return UUID.Zero; + } + } + + // check funds + // is there is a money module present ? + IMoneyModule money = scene.RequestModuleInterface(); + if (money != null) + { + // do the transaction, that is if the agent has got sufficient funds + if (!money.AmountCovered(remoteClient.AgentId, money.GroupCreationCharge)) { + remoteClient.SendCreateGroupReply(UUID.Zero, false, "Insufficient funds to create a group."); + return UUID.Zero; + } + money.ApplyCharge(remoteClient.AgentId, money.GroupCreationCharge, "Group Creation"); + } + string reason = string.Empty; + UUID groupID = m_groupData.CreateGroup(remoteClient.AgentId, name, charter, showInList, insigniaID, membershipFee, openEnrollment, + allowPublish, maturePublish, remoteClient.AgentId, out reason); + + if (groupID != UUID.Zero) + { + remoteClient.SendCreateGroupReply(groupID, true, "Group created successfullly"); + + // Update the founder with new group information. + SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); + } + else + remoteClient.SendCreateGroupReply(groupID, false, reason); + + return groupID; + } + + public GroupNoticeData[] GroupNoticesListRequest(IClientAPI remoteClient, UUID groupID) + { + if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + // ToDo: check if agent is a member of group and is allowed to see notices? + + List notices = m_groupData.GetGroupNotices(GetRequestingAgentIDStr(remoteClient), groupID); + List os_notices = new List(); + foreach (ExtendedGroupNoticeData n in notices) + { + GroupNoticeData osn = n.ToGroupNoticeData(); + os_notices.Add(osn); + } + + return os_notices.ToArray(); + } + + /// + /// Get the title of the agent's current role. + /// + public string GetGroupTitle(UUID avatarID) + { + if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + GroupMembershipData membership = m_groupData.GetAgentActiveMembership(UUID.Zero.ToString(), avatarID.ToString()); + if (membership != null) + { + return membership.GroupTitle; + } + return string.Empty; + } + + /// + /// Change the current Active Group Role for Agent + /// + public void GroupTitleUpdate(IClientAPI remoteClient, UUID groupID, UUID titleRoleID) + { + if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + m_groupData.SetAgentActiveGroupRole(GetRequestingAgentIDStr(remoteClient), GetRequestingAgentIDStr(remoteClient), groupID, titleRoleID); + + // TODO: Not sure what all is needed here, but if the active group role change is for the group + // the client currently has set active, then we need to do a scene presence update too + // if (m_groupData.GetAgentActiveMembership(GetRequestingAgentID(remoteClient)).GroupID == GroupID) + + UpdateAllClientsWithGroupInfo(GetRequestingAgentID(remoteClient)); + } + + + public void GroupRoleUpdate(IClientAPI remoteClient, UUID groupID, UUID roleID, string name, string description, string title, ulong powers, byte updateType) + { + if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + // Security Checks are handled in the Groups Service. + + switch ((OpenMetaverse.GroupRoleUpdate)updateType) + { + case OpenMetaverse.GroupRoleUpdate.Create: + string reason = string.Empty; + if (!m_groupData.AddGroupRole(GetRequestingAgentIDStr(remoteClient), groupID, UUID.Random(), name, description, title, powers, out reason)) + remoteClient.SendAgentAlertMessage("Unable to create role: " + reason, false); + break; + + case OpenMetaverse.GroupRoleUpdate.Delete: + m_groupData.RemoveGroupRole(GetRequestingAgentIDStr(remoteClient), groupID, roleID); + break; + + case OpenMetaverse.GroupRoleUpdate.UpdateAll: + case OpenMetaverse.GroupRoleUpdate.UpdateData: + case OpenMetaverse.GroupRoleUpdate.UpdatePowers: + if (m_debugEnabled) + { + GroupPowers gp = (GroupPowers)powers; + m_log.DebugFormat("[Groups]: Role ({0}) updated with Powers ({1}) ({2})", name, powers.ToString(), gp.ToString()); + } + m_groupData.UpdateGroupRole(GetRequestingAgentIDStr(remoteClient), groupID, roleID, name, description, title, powers); + break; + + case OpenMetaverse.GroupRoleUpdate.NoUpdate: + default: + // No Op + break; + + } + + // TODO: This update really should send out updates for everyone in the role that just got changed. + SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); + } + + public void GroupRoleChanges(IClientAPI remoteClient, UUID groupID, UUID roleID, UUID memberID, uint changes) + { + if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + // Todo: Security check + + switch (changes) + { + case 0: + // Add + m_groupData.AddAgentToGroupRole(GetRequestingAgentIDStr(remoteClient), memberID.ToString(), groupID, roleID); + + break; + case 1: + // Remove + m_groupData.RemoveAgentFromGroupRole(GetRequestingAgentIDStr(remoteClient), memberID.ToString(), groupID, roleID); + + break; + default: + m_log.ErrorFormat("[Groups]: {0} does not understand changes == {1}", System.Reflection.MethodBase.GetCurrentMethod().Name, changes); + break; + } + + // TODO: This update really should send out updates for everyone in the role that just got changed. + SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); + } + + public void GroupNoticeRequest(IClientAPI remoteClient, UUID groupNoticeID) + { + if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called for notice {1}", System.Reflection.MethodBase.GetCurrentMethod().Name, groupNoticeID); + + //GroupRecord groupInfo = m_groupData.GetGroupRecord(GetRequestingAgentID(remoteClient), data.GroupID, null); + + GridInstantMessage msg = CreateGroupNoticeIM(remoteClient.AgentId, groupNoticeID, (byte)InstantMessageDialog.GroupNoticeRequested); + //GridInstantMessage msg = new GridInstantMessage(); + //msg.imSessionID = UUID.Zero.Guid; + //msg.fromAgentID = data.GroupID.Guid; + //msg.toAgentID = GetRequestingAgentID(remoteClient).Guid; + //msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); + //msg.fromAgentName = "Group Notice : " + groupInfo == null ? "Unknown" : groupInfo.GroupName; + //msg.message = data.noticeData.Subject + "|" + data.Message; + //msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.GroupNoticeRequested; + //msg.fromGroup = true; + //msg.offline = (byte)0; + //msg.ParentEstateID = 0; + //msg.Position = Vector3.Zero; + //msg.RegionID = UUID.Zero.Guid; + //msg.binaryBucket = data.BinaryBucket; + + OutgoingInstantMessage(msg, GetRequestingAgentID(remoteClient)); + } + + public GridInstantMessage CreateGroupNoticeIM(UUID agentID, UUID groupNoticeID, byte dialog) + { + if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + GridInstantMessage msg = new GridInstantMessage(); + byte[] bucket; + + msg.imSessionID = groupNoticeID.Guid; + msg.toAgentID = agentID.Guid; + msg.dialog = dialog; + // msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.GroupNotice; + msg.fromGroup = true; + msg.offline = (byte)0; + msg.ParentEstateID = 0; + msg.Position = Vector3.Zero; + msg.RegionID = UUID.Zero.Guid; + + GroupNoticeInfo info = m_groupData.GetGroupNotice(agentID.ToString(), groupNoticeID); + if (info != null) + { + msg.fromAgentID = info.GroupID.Guid; + msg.timestamp = info.noticeData.Timestamp; + msg.fromAgentName = info.noticeData.FromName; + msg.message = info.noticeData.Subject + "|" + info.Message; + if (info.noticeData.HasAttachment) + { + byte[] name = System.Text.Encoding.UTF8.GetBytes(info.noticeData.AttachmentName); + bucket = new byte[19 + name.Length]; + bucket[0] = 1; // has attachment? + bucket[1] = info.noticeData.AttachmentType; // attachment type + name.CopyTo(bucket, 18); + } + else + { + bucket = new byte[19]; + bucket[0] = 0; // Has att? + bucket[1] = 0; // type + bucket[18] = 0; // null terminated + } + + info.GroupID.ToBytes(bucket, 2); + msg.binaryBucket = bucket; + } + else + { + m_log.DebugFormat("[Groups]: Group Notice {0} not found, composing empty message.", groupNoticeID); + msg.fromAgentID = UUID.Zero.Guid; + msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); ; + msg.fromAgentName = string.Empty; + msg.message = string.Empty; + msg.binaryBucket = new byte[0]; + } + + return msg; + } + + public void SendAgentGroupDataUpdate(IClientAPI remoteClient) + { + if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + // Send agent information about his groups + SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); + } + + public void JoinGroupRequest(IClientAPI remoteClient, UUID groupID) + { + if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + string reason = string.Empty; + // Should check to see if OpenEnrollment, or if there's an outstanding invitation + if (m_groupData.AddAgentToGroup(GetRequestingAgentIDStr(remoteClient), GetRequestingAgentIDStr(remoteClient), groupID, UUID.Zero, string.Empty, out reason)) + { + + remoteClient.SendJoinGroupReply(groupID, true); + + // Should this send updates to everyone in the group? + SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); + } + else + remoteClient.SendJoinGroupReply(groupID, false); + } + + public void LeaveGroupRequest(IClientAPI remoteClient, UUID groupID) + { + if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + m_groupData.RemoveAgentFromGroup(GetRequestingAgentIDStr(remoteClient), GetRequestingAgentIDStr(remoteClient), groupID); + + remoteClient.SendLeaveGroupReply(groupID, true); + + remoteClient.SendAgentDropGroup(groupID); + + // SL sends out notifcations to the group messaging session that the person has left + // Should this also update everyone who is in the group? + SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); + } + + public void EjectGroupMemberRequest(IClientAPI remoteClient, UUID groupID, UUID ejecteeID) + { + EjectGroupMember(remoteClient, GetRequestingAgentID(remoteClient), groupID, ejecteeID); + } + + public void EjectGroupMember(IClientAPI remoteClient, UUID agentID, UUID groupID, UUID ejecteeID) + { + if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + // Todo: Security check? + m_groupData.RemoveAgentFromGroup(agentID.ToString(), ejecteeID.ToString(), groupID); + + string agentName; + RegionInfo regionInfo; + + // remoteClient provided or just agentID? + if (remoteClient != null) + { + agentName = remoteClient.Name; + regionInfo = remoteClient.Scene.RegionInfo; + remoteClient.SendEjectGroupMemberReply(agentID, groupID, true); + } + else + { + IClientAPI client = GetActiveClient(agentID); + + if (client != null) + { + agentName = client.Name; + regionInfo = client.Scene.RegionInfo; + client.SendEjectGroupMemberReply(agentID, groupID, true); + } + else + { + regionInfo = m_sceneList[0].RegionInfo; + UserAccount acc = m_sceneList[0].UserAccountService.GetUserAccount(regionInfo.ScopeID, agentID); + + if (acc != null) + { + agentName = acc.FirstName + " " + acc.LastName; + } + else + { + agentName = "Unknown member"; + } + } + } + + GroupRecord groupInfo = m_groupData.GetGroupRecord(agentID.ToString(), groupID, null); + + UserAccount account = m_sceneList[0].UserAccountService.GetUserAccount(regionInfo.ScopeID, ejecteeID); + if ((groupInfo == null) || (account == null)) + { + return; + } + + // Send Message to Ejectee + GridInstantMessage msg = new GridInstantMessage(); + + msg.imSessionID = UUID.Zero.Guid; + msg.fromAgentID = agentID.Guid; + // msg.fromAgentID = info.GroupID; + msg.toAgentID = ejecteeID.Guid; + //msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); + msg.timestamp = 0; + msg.fromAgentName = agentName; + msg.message = string.Format("You have been ejected from '{1}' by {0}.", agentName, groupInfo.GroupName); + msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.MessageFromAgent; + msg.fromGroup = false; + msg.offline = (byte)0; + msg.ParentEstateID = 0; + msg.Position = Vector3.Zero; + msg.RegionID = regionInfo.RegionID.Guid; + msg.binaryBucket = new byte[0]; + OutgoingInstantMessage(msg, ejecteeID); + + // Message to ejector + // Interop, received special 210 code for ejecting a group member + // this only works within the comms servers domain, and won't work hypergrid + // TODO:FIXME: Use a presense server of some kind to find out where the + // client actually is, and try contacting that region directly to notify them, + // or provide the notification via xmlrpc update queue + + msg = new GridInstantMessage(); + msg.imSessionID = UUID.Zero.Guid; + msg.fromAgentID = agentID.Guid; + msg.toAgentID = agentID.Guid; + msg.timestamp = 0; + msg.fromAgentName = agentName; + if (account != null) + { + msg.message = string.Format("{2} has been ejected from '{1}' by {0}.", agentName, groupInfo.GroupName, account.FirstName + " " + account.LastName); + } + else + { + msg.message = string.Format("{2} has been ejected from '{1}' by {0}.", agentName, groupInfo.GroupName, "Unknown member"); + } + msg.dialog = (byte)210; //interop + msg.fromGroup = false; + msg.offline = (byte)0; + msg.ParentEstateID = 0; + msg.Position = Vector3.Zero; + msg.RegionID = regionInfo.RegionID.Guid; + msg.binaryBucket = new byte[0]; + OutgoingInstantMessage(msg, agentID); + + + // SL sends out messages to everyone in the group + // Who all should receive updates and what should they be updated with? + UpdateAllClientsWithGroupInfo(ejecteeID); + } + + public void InviteGroupRequest(IClientAPI remoteClient, UUID groupID, UUID invitedAgentID, UUID roleID) + { + InviteGroup(remoteClient, GetRequestingAgentID(remoteClient), groupID, invitedAgentID, roleID); + } + + public void InviteGroup(IClientAPI remoteClient, UUID agentID, UUID groupID, UUID invitedAgentID, UUID roleID) + { + if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + string agentName = m_UserManagement.GetUserName(agentID); + RegionInfo regionInfo = m_sceneList[0].RegionInfo; + + GroupRecord group = m_groupData.GetGroupRecord(agentID.ToString(), groupID, null); + if (group == null) + { + m_log.DebugFormat("[Groups]: No such group {0}", groupID); + return; + } + + // Todo: Security check, probably also want to send some kind of notification + UUID InviteID = UUID.Random(); + + if (m_groupData.AddAgentToGroupInvite(agentID.ToString(), InviteID, groupID, roleID, invitedAgentID.ToString())) + { + if (m_msgTransferModule != null) + { + Guid inviteUUID = InviteID.Guid; + + GridInstantMessage msg = new GridInstantMessage(); + + msg.imSessionID = inviteUUID; + + // msg.fromAgentID = agentID.Guid; + msg.fromAgentID = groupID.Guid; + msg.toAgentID = invitedAgentID.Guid; + //msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); + msg.timestamp = 0; + msg.fromAgentName = agentName; + msg.message = string.Format("{0} has invited you to join a group called {1}. There is no cost to join this group.", agentName, group.GroupName); + msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.GroupInvitation; + msg.fromGroup = true; + msg.offline = (byte)0; + msg.ParentEstateID = 0; + msg.Position = Vector3.Zero; + msg.RegionID = regionInfo.RegionID.Guid; + msg.binaryBucket = new byte[20]; + + OutgoingInstantMessage(msg, invitedAgentID); + } + } + } + + #endregion + + #region Client/Update Tools + + /// + /// Try to find an active IClientAPI reference for agentID giving preference to root connections + /// + private IClientAPI GetActiveClient(UUID agentID) + { + IClientAPI child = null; + + // Try root avatar first + foreach (Scene scene in m_sceneList) + { + ScenePresence sp = scene.GetScenePresence(agentID); + if (sp != null) + { + if (!sp.IsChildAgent) + { + return sp.ControllingClient; + } + else + { + child = sp.ControllingClient; + } + } + } + + // If we didn't find a root, then just return whichever child we found, or null if none + return child; + } + + /// + /// Send 'remoteClient' the group membership 'data' for agent 'dataForAgentID'. + /// + private void SendGroupMembershipInfoViaCaps(IClientAPI remoteClient, UUID dataForAgentID, GroupMembershipData[] data) + { + if (m_debugEnabled) m_log.InfoFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + OSDArray AgentData = new OSDArray(1); + OSDMap AgentDataMap = new OSDMap(1); + AgentDataMap.Add("AgentID", OSD.FromUUID(dataForAgentID)); + AgentData.Add(AgentDataMap); + + + OSDArray GroupData = new OSDArray(data.Length); + OSDArray NewGroupData = new OSDArray(data.Length); + + foreach (GroupMembershipData membership in data) + { + if (GetRequestingAgentID(remoteClient) != dataForAgentID) + { + if (!membership.ListInProfile) + { + // If we're sending group info to remoteclient about another agent, + // filter out groups the other agent doesn't want to share. + continue; + } + } + + OSDMap GroupDataMap = new OSDMap(6); + OSDMap NewGroupDataMap = new OSDMap(1); + + GroupDataMap.Add("GroupID", OSD.FromUUID(membership.GroupID)); + GroupDataMap.Add("GroupPowers", OSD.FromULong(membership.GroupPowers)); + GroupDataMap.Add("AcceptNotices", OSD.FromBoolean(membership.AcceptNotices)); + GroupDataMap.Add("GroupInsigniaID", OSD.FromUUID(membership.GroupPicture)); + GroupDataMap.Add("Contribution", OSD.FromInteger(membership.Contribution)); + GroupDataMap.Add("GroupName", OSD.FromString(membership.GroupName)); + NewGroupDataMap.Add("ListInProfile", OSD.FromBoolean(membership.ListInProfile)); + + GroupData.Add(GroupDataMap); + NewGroupData.Add(NewGroupDataMap); + } + + OSDMap llDataStruct = new OSDMap(3); + llDataStruct.Add("AgentData", AgentData); + llDataStruct.Add("GroupData", GroupData); + llDataStruct.Add("NewGroupData", NewGroupData); + + if (m_debugEnabled) + { + m_log.InfoFormat("[Groups]: {0}", OSDParser.SerializeJsonString(llDataStruct)); + } + + IEventQueue queue = remoteClient.Scene.RequestModuleInterface(); + + if (queue != null) + { + queue.Enqueue(queue.BuildEvent("AgentGroupDataUpdate", llDataStruct), GetRequestingAgentID(remoteClient)); + } + + } + + private void SendScenePresenceUpdate(UUID AgentID, string Title) + { + if (m_debugEnabled) m_log.DebugFormat("[Groups]: Updating scene title for {0} with title: {1}", AgentID, Title); + + ScenePresence presence = null; + + foreach (Scene scene in m_sceneList) + { + presence = scene.GetScenePresence(AgentID); + if (presence != null) + { + if (presence.Grouptitle != Title) + { + presence.Grouptitle = Title; + + if (! presence.IsChildAgent) + presence.SendAvatarDataToAllAgents(); + } + } + } + } + + /// + /// Send updates to all clients who might be interested in groups data for dataForClientID + /// + private void UpdateAllClientsWithGroupInfo(UUID dataForClientID) + { + if (m_debugEnabled) m_log.InfoFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + // TODO: Probably isn't nessesary to update every client in every scene. + // Need to examine client updates and do only what's nessesary. + lock (m_sceneList) + { + foreach (Scene scene in m_sceneList) + { + scene.ForEachClient(delegate(IClientAPI client) { SendAgentGroupDataUpdate(client, dataForClientID); }); + } + } + } + + /// + /// Update remoteClient with group information about dataForAgentID + /// + private void SendAgentGroupDataUpdate(IClientAPI remoteClient, UUID dataForAgentID) + { + if (m_debugEnabled) m_log.InfoFormat("[Groups]: {0} called for {1}", System.Reflection.MethodBase.GetCurrentMethod().Name, remoteClient.Name); + + // TODO: All the client update functions need to be reexamined because most do too much and send too much stuff + + OnAgentDataUpdateRequest(remoteClient, dataForAgentID, UUID.Zero); + + // Need to send a group membership update to the client + // UDP version doesn't seem to behave nicely. But we're going to send it out here + // with an empty group membership to hopefully remove groups being displayed due + // to the core Groups Stub + //remoteClient.SendGroupMembership(new GroupMembershipData[0]); + + GroupMembershipData[] membershipArray = GetProfileListedGroupMemberships(remoteClient, dataForAgentID); + SendGroupMembershipInfoViaCaps(remoteClient, dataForAgentID, membershipArray); + //remoteClient.SendAvatarGroupsReply(dataForAgentID, membershipArray); + if (remoteClient.AgentId == dataForAgentID) + remoteClient.RefreshGroupMembership(); + } + + /// + /// Get a list of groups memberships for the agent that are marked "ListInProfile" + /// (unless that agent has a godLike aspect, in which case get all groups) + /// + /// + /// + private GroupMembershipData[] GetProfileListedGroupMemberships(IClientAPI requestingClient, UUID dataForAgentID) + { + List membershipData = m_groupData.GetAgentGroupMemberships(requestingClient.AgentId.ToString(), dataForAgentID.ToString()); + GroupMembershipData[] membershipArray; + + // cScene and property accessor 'isGod' are in support of the opertions to bypass 'hidden' group attributes for + // those with a GodLike aspect. + Scene cScene = (Scene)requestingClient.Scene; + bool isGod = cScene.Permissions.IsGod(requestingClient.AgentId); + + if (isGod) + { + membershipArray = membershipData.ToArray(); + } + else + { + if (requestingClient.AgentId != dataForAgentID) + { + Predicate showInProfile = delegate(GroupMembershipData membership) + { + return membership.ListInProfile; + }; + + membershipArray = membershipData.FindAll(showInProfile).ToArray(); + } + else + { + membershipArray = membershipData.ToArray(); + } + } + + if (m_debugEnabled) + { + m_log.InfoFormat("[Groups]: Get group membership information for {0} requested by {1}", dataForAgentID, requestingClient.AgentId); + foreach (GroupMembershipData membership in membershipArray) + { + m_log.InfoFormat("[Groups]: {0} :: {1} - {2} - {3}", dataForAgentID, membership.GroupName, membership.GroupTitle, membership.GroupPowers); + } + } + + return membershipArray; + } + + + private void SendAgentDataUpdate(IClientAPI remoteClient, UUID dataForAgentID, UUID activeGroupID, string activeGroupName, ulong activeGroupPowers, string activeGroupTitle) + { + if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + // TODO: All the client update functions need to be reexamined because most do too much and send too much stuff + UserAccount account = m_sceneList[0].UserAccountService.GetUserAccount(remoteClient.Scene.RegionInfo.ScopeID, dataForAgentID); + string firstname, lastname; + if (account != null) + { + firstname = account.FirstName; + lastname = account.LastName; + } + else + { + firstname = "Unknown"; + lastname = "Unknown"; + } + + remoteClient.SendAgentDataUpdate(dataForAgentID, activeGroupID, firstname, + lastname, activeGroupPowers, activeGroupName, + activeGroupTitle); + } + + #endregion + + #region IM Backed Processes + + private void OutgoingInstantMessage(GridInstantMessage msg, UUID msgTo) + { + if (m_debugEnabled) m_log.InfoFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + IClientAPI localClient = GetActiveClient(msgTo); + if (localClient != null) + { + if (m_debugEnabled) m_log.InfoFormat("[Groups]: MsgTo ({0}) is local, delivering directly", localClient.Name); + localClient.SendInstantMessage(msg); + } + else if (m_msgTransferModule != null) + { + if (m_debugEnabled) m_log.InfoFormat("[Groups]: MsgTo ({0}) is not local, delivering via TransferModule", msgTo); + m_msgTransferModule.SendInstantMessage(msg, delegate(bool success) { if (m_debugEnabled) m_log.DebugFormat("[Groups]: Message Sent: {0}", success?"Succeeded":"Failed"); }); + } + } + + public void NotifyChange(UUID groupID) + { + // Notify all group members of a chnge in group roles and/or + // permissions + // + } + + #endregion + + private string GetRequestingAgentIDStr(IClientAPI client) + { + return GetRequestingAgentID(client).ToString(); + } + + private UUID GetRequestingAgentID(IClientAPI client) + { + UUID requestingAgentID = UUID.Zero; + if (client != null) + { + requestingAgentID = client.AgentId; + } + return requestingAgentID; + } + + } + +} diff --git a/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnector.cs b/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnector.cs new file mode 100644 index 0000000..59fec6f --- /dev/null +++ b/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnector.cs @@ -0,0 +1,289 @@ +/* + * 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.Linq; +using System.Reflection; +using System.Text; + +using OpenSim.Framework; +using OpenSim.Server.Base; + +using OpenMetaverse; +using log4net; + +namespace OpenSim.Groups +{ + public class GroupsServiceHGConnector + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private string m_ServerURI; + private object m_Lock = new object(); + + public GroupsServiceHGConnector(string url) + { + m_ServerURI = url; + if (!m_ServerURI.EndsWith("/")) + m_ServerURI += "/"; + + m_log.DebugFormat("[Groups.HGConnector]: Groups server at {0}", m_ServerURI); + } + + public bool CreateProxy(string RequestingAgentID, string AgentID, string accessToken, UUID groupID, string url, string name, out string reason) + { + reason = string.Empty; + + Dictionary sendData = new Dictionary(); + sendData["RequestingAgentID"] = RequestingAgentID; + sendData["AgentID"] = AgentID.ToString(); + sendData["AccessToken"] = accessToken; + sendData["GroupID"] = groupID.ToString(); + sendData["Location"] = url; + sendData["Name"] = name; + Dictionary ret = MakeRequest("POSTGROUP", sendData); + + if (ret == null) + return false; + + if (!ret.ContainsKey("RESULT")) + return false; + + if (ret["RESULT"].ToString().ToLower() != "true") + { + reason = ret["REASON"].ToString(); + return false; + } + + return true; + + } + + public void RemoveAgentFromGroup(string AgentID, UUID GroupID, string token) + { + Dictionary sendData = new Dictionary(); + sendData["AgentID"] = AgentID; + sendData["GroupID"] = GroupID.ToString(); + sendData["AccessToken"] = GroupsDataUtils.Sanitize(token); + MakeRequest("REMOVEAGENTFROMGROUP", sendData); + } + + public ExtendedGroupRecord GetGroupRecord(string RequestingAgentID, UUID GroupID, string GroupName, string token) + { + if (GroupID == UUID.Zero && (GroupName == null || (GroupName != null && GroupName == string.Empty))) + return null; + + Dictionary sendData = new Dictionary(); + if (GroupID != UUID.Zero) + sendData["GroupID"] = GroupID.ToString(); + if (GroupName != null && GroupName != string.Empty) + sendData["Name"] = GroupsDataUtils.Sanitize(GroupName); + + sendData["RequestingAgentID"] = RequestingAgentID; + sendData["AccessToken"] = GroupsDataUtils.Sanitize(token); + + Dictionary ret = MakeRequest("GETGROUP", sendData); + + if (ret == null) + return null; + + if (!ret.ContainsKey("RESULT")) + return null; + + if (ret["RESULT"].ToString() == "NULL") + return null; + + return GroupsDataUtils.GroupRecord((Dictionary)ret["RESULT"]); + } + + public List GetGroupMembers(string RequestingAgentID, UUID GroupID, string token) + { + List members = new List(); + + Dictionary sendData = new Dictionary(); + sendData["GroupID"] = GroupID.ToString(); + sendData["RequestingAgentID"] = RequestingAgentID; + sendData["AccessToken"] = GroupsDataUtils.Sanitize(token); + Dictionary ret = MakeRequest("GETGROUPMEMBERS", sendData); + + if (ret == null) + return members; + + if (!ret.ContainsKey("RESULT")) + return members; + + if (ret["RESULT"].ToString() == "NULL") + return members; + foreach (object v in ((Dictionary)ret["RESULT"]).Values) + { + ExtendedGroupMembersData m = GroupsDataUtils.GroupMembersData((Dictionary)v); + members.Add(m); + } + + return members; + } + + public List GetGroupRoles(string RequestingAgentID, UUID GroupID, string token) + { + List roles = new List(); + + Dictionary sendData = new Dictionary(); + sendData["GroupID"] = GroupID.ToString(); + sendData["RequestingAgentID"] = RequestingAgentID; + sendData["AccessToken"] = GroupsDataUtils.Sanitize(token); + Dictionary ret = MakeRequest("GETGROUPROLES", sendData); + + if (ret == null) + return roles; + + if (!ret.ContainsKey("RESULT")) + return roles; + + if (ret["RESULT"].ToString() == "NULL") + return roles; + foreach (object v in ((Dictionary)ret["RESULT"]).Values) + { + GroupRolesData m = GroupsDataUtils.GroupRolesData((Dictionary)v); + roles.Add(m); + } + + return roles; + } + + public List GetGroupRoleMembers(string RequestingAgentID, UUID GroupID, string token) + { + List rmembers = new List(); + + Dictionary sendData = new Dictionary(); + sendData["GroupID"] = GroupID.ToString(); + sendData["RequestingAgentID"] = RequestingAgentID; + sendData["AccessToken"] = GroupsDataUtils.Sanitize(token); + Dictionary ret = MakeRequest("GETROLEMEMBERS", sendData); + + if (ret == null) + return rmembers; + + if (!ret.ContainsKey("RESULT")) + return rmembers; + + if (ret["RESULT"].ToString() == "NULL") + return rmembers; + + foreach (object v in ((Dictionary)ret["RESULT"]).Values) + { + ExtendedGroupRoleMembersData m = GroupsDataUtils.GroupRoleMembersData((Dictionary)v); + rmembers.Add(m); + } + + return rmembers; + } + + public bool AddNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message, + bool hasAttachment, byte attType, string attName, UUID attItemID, string attOwnerID) + { + Dictionary sendData = new Dictionary(); + sendData["GroupID"] = groupID.ToString(); + sendData["NoticeID"] = noticeID.ToString(); + sendData["FromName"] = GroupsDataUtils.Sanitize(fromName); + sendData["Subject"] = GroupsDataUtils.Sanitize(subject); + sendData["Message"] = GroupsDataUtils.Sanitize(message); + sendData["HasAttachment"] = hasAttachment.ToString(); + if (hasAttachment) + { + sendData["AttachmentType"] = attType.ToString(); + sendData["AttachmentName"] = attName.ToString(); + sendData["AttachmentItemID"] = attItemID.ToString(); + sendData["AttachmentOwnerID"] = attOwnerID; + } + sendData["RequestingAgentID"] = RequestingAgentID; + + Dictionary ret = MakeRequest("ADDNOTICE", sendData); + + if (ret == null) + return false; + + if (!ret.ContainsKey("RESULT")) + return false; + + if (ret["RESULT"].ToString().ToLower() != "true") + return false; + + return true; + } + + public bool VerifyNotice(UUID noticeID, UUID groupID) + { + Dictionary sendData = new Dictionary(); + sendData["NoticeID"] = noticeID.ToString(); + sendData["GroupID"] = groupID.ToString(); + Dictionary ret = MakeRequest("VERIFYNOTICE", sendData); + + if (ret == null) + return false; + + if (!ret.ContainsKey("RESULT")) + return false; + + if (ret["RESULT"].ToString().ToLower() != "true") + return false; + + return true; + } + + // + // + // + // + // + + #region Make Request + + private Dictionary MakeRequest(string method, Dictionary sendData) + { + sendData["METHOD"] = method; + + string reply = string.Empty; + lock (m_Lock) + reply = SynchronousRestFormsRequester.MakeRequest("POST", + m_ServerURI + "hg-groups", + ServerUtils.BuildQueryString(sendData)); + + //m_log.DebugFormat("[XXX]: reply was {0}", reply); + + if (reply == string.Empty || reply == null) + return null; + + Dictionary replyData = ServerUtils.ParseXmlResponse( + reply); + + return replyData; + } + #endregion + + } +} diff --git a/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs b/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs new file mode 100644 index 0000000..f670272 --- /dev/null +++ b/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs @@ -0,0 +1,717 @@ +/* + * 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.Linq; +using System.Reflection; +using System.Text; + +using OpenSim.Framework; +using OpenSim.Framework.Servers; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Services.Interfaces; + +using OpenMetaverse; +using Mono.Addins; +using log4net; +using Nini.Config; + +namespace OpenSim.Groups +{ + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GroupsServiceHGConnectorModule")] + public class GroupsServiceHGConnectorModule : ISharedRegionModule, IGroupsServicesConnector + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private bool m_Enabled = false; + private IGroupsServicesConnector m_LocalGroupsConnector; + private string m_LocalGroupsServiceLocation; + private IUserManagement m_UserManagement; + private IOfflineIMService m_OfflineIM; + private IMessageTransferModule m_Messaging; + private List m_Scenes; + private ForeignImporter m_ForeignImporter; + private string m_ServiceLocation; + private IConfigSource m_Config; + + private Dictionary m_NetworkConnectors = new Dictionary(); + private RemoteConnectorCacheWrapper m_CacheWrapper; // for caching info of external group services + + #region ISharedRegionModule + + public void Initialise(IConfigSource config) + { + IConfig groupsConfig = config.Configs["Groups"]; + if (groupsConfig == null) + return; + + if ((groupsConfig.GetBoolean("Enabled", false) == false) + || (groupsConfig.GetString("ServicesConnectorModule", string.Empty) != Name)) + { + return; + } + + m_Config = config; + m_ServiceLocation = groupsConfig.GetString("LocalService", "local"); // local or remote + m_LocalGroupsServiceLocation = groupsConfig.GetString("GroupsExternalURI", "http://127.0.0.1"); + m_Scenes = new List(); + + m_Enabled = true; + + m_log.DebugFormat("[Groups]: Initializing {0} with LocalService {1}", this.Name, m_ServiceLocation); + } + + public string Name + { + get { return "Groups HG Service Connector"; } + } + + public Type ReplaceableInterface + { + get { return null; } + } + + public void AddRegion(Scene scene) + { + if (!m_Enabled) + return; + + m_log.DebugFormat("[Groups]: Registering {0} with {1}", this.Name, scene.RegionInfo.RegionName); + scene.RegisterModuleInterface(this); + m_Scenes.Add(scene); + + scene.EventManager.OnNewClient += OnNewClient; + } + + public void RemoveRegion(Scene scene) + { + if (!m_Enabled) + return; + + scene.UnregisterModuleInterface(this); + m_Scenes.Remove(scene); + } + + public void RegionLoaded(Scene scene) + { + if (!m_Enabled) + return; + + if (m_UserManagement == null) + { + m_UserManagement = scene.RequestModuleInterface(); + m_OfflineIM = scene.RequestModuleInterface(); + m_Messaging = scene.RequestModuleInterface(); + m_ForeignImporter = new ForeignImporter(m_UserManagement); + + if (m_ServiceLocation.Equals("local")) + { + m_LocalGroupsConnector = new GroupsServiceLocalConnectorModule(m_Config, m_UserManagement); + // Also, if local, create the endpoint for the HGGroupsService + new HGGroupsServiceRobustConnector(m_Config, MainServer.Instance, string.Empty, + scene.RequestModuleInterface(), scene.RequestModuleInterface()); + + } + else + m_LocalGroupsConnector = new GroupsServiceRemoteConnectorModule(m_Config, m_UserManagement); + + m_CacheWrapper = new RemoteConnectorCacheWrapper(m_UserManagement); + } + + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + #endregion + + private void OnNewClient(IClientAPI client) + { + client.OnCompleteMovementToRegion += OnCompleteMovementToRegion; + } + + void OnCompleteMovementToRegion(IClientAPI client, bool arg2) + { + object sp = null; + if (client.Scene.TryGetScenePresence(client.AgentId, out sp)) + { + if (sp is ScenePresence && ((ScenePresence)sp).PresenceType != PresenceType.Npc) + { + AgentCircuitData aCircuit = ((ScenePresence)sp).Scene.AuthenticateHandler.GetAgentCircuitData(client.AgentId); + if (aCircuit != null && (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0 && + m_OfflineIM != null && m_Messaging != null) + { + List ims = m_OfflineIM.GetMessages(aCircuit.AgentID); + if (ims != null && ims.Count > 0) + foreach (GridInstantMessage im in ims) + m_Messaging.SendInstantMessage(im, delegate(bool success) { }); + } + } + } + } + + #region IGroupsServicesConnector + + public UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, + bool allowPublish, bool maturePublish, UUID founderID, out string reason) + { + m_log.DebugFormat("[Groups]: Creating group {0}", name); + reason = string.Empty; + if (m_UserManagement.IsLocalGridUser(RequestingAgentID)) + return m_LocalGroupsConnector.CreateGroup(RequestingAgentID, name, charter, showInList, insigniaID, + membershipFee, openEnrollment, allowPublish, maturePublish, founderID, out reason); + else + { + reason = "Only local grid users are allowed to create a new group"; + return UUID.Zero; + } + } + + public bool UpdateGroup(string RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, + bool openEnrollment, bool allowPublish, bool maturePublish, out string reason) + { + reason = string.Empty; + string url = string.Empty; + string name = string.Empty; + if (IsLocal(groupID, out url, out name)) + return m_LocalGroupsConnector.UpdateGroup(AgentUUI(RequestingAgentID), groupID, charter, showInList, insigniaID, membershipFee, + openEnrollment, allowPublish, maturePublish, out reason); + else + { + reason = "Changes to remote group not allowed. Please go to the group's original world."; + return false; + } + } + + public ExtendedGroupRecord GetGroupRecord(string RequestingAgentID, UUID GroupID, string GroupName) + { + string url = string.Empty; + string name = string.Empty; + if (IsLocal(GroupID, out url, out name)) + return m_LocalGroupsConnector.GetGroupRecord(AgentUUI(RequestingAgentID), GroupID, GroupName); + else if (url != string.Empty) + { + ExtendedGroupMembershipData membership = m_LocalGroupsConnector.GetAgentGroupMembership(RequestingAgentID, RequestingAgentID, GroupID); + string accessToken = string.Empty; + if (membership != null) + accessToken = membership.AccessToken; + else + return null; + + GroupsServiceHGConnector c = GetConnector(url); + if (c != null) + { + ExtendedGroupRecord grec = m_CacheWrapper.GetGroupRecord(RequestingAgentID, GroupID, GroupName, delegate + { + return c.GetGroupRecord(AgentUUIForOutside(RequestingAgentID), GroupID, GroupName, accessToken); + }); + + if (grec != null) + ImportForeigner(grec.FounderUUI); + return grec; + } + } + + return null; + } + + public List FindGroups(string RequestingAgentID, string search) + { + return m_LocalGroupsConnector.FindGroups(AgentUUI(RequestingAgentID), search); + } + + public List GetGroupMembers(string RequestingAgentID, UUID GroupID) + { + string url = string.Empty, gname = string.Empty; + if (IsLocal(GroupID, out url, out gname)) + return m_LocalGroupsConnector.GetGroupMembers(AgentUUI(RequestingAgentID), GroupID); + else if (!string.IsNullOrEmpty(url)) + { + ExtendedGroupMembershipData membership = m_LocalGroupsConnector.GetAgentGroupMembership(RequestingAgentID, RequestingAgentID, GroupID); + string accessToken = string.Empty; + if (membership != null) + accessToken = membership.AccessToken; + else + return null; + + GroupsServiceHGConnector c = GetConnector(url); + if (c != null) + { + return m_CacheWrapper.GetGroupMembers(RequestingAgentID, GroupID, delegate + { + return c.GetGroupMembers(AgentUUIForOutside(RequestingAgentID), GroupID, accessToken); + }); + + } + } + return new List(); + } + + public bool AddGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers, out string reason) + { + reason = string.Empty; + string url = string.Empty, gname = string.Empty; + + if (IsLocal(groupID, out url, out gname)) + return m_LocalGroupsConnector.AddGroupRole(AgentUUI(RequestingAgentID), groupID, roleID, name, description, title, powers, out reason); + else + { + reason = "Operation not allowed outside this group's origin world."; + return false; + } + } + + public bool UpdateGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers) + { + string url = string.Empty, gname = string.Empty; + + if (IsLocal(groupID, out url, out gname)) + return m_LocalGroupsConnector.UpdateGroupRole(AgentUUI(RequestingAgentID), groupID, roleID, name, description, title, powers); + else + { + return false; + } + + } + + public void RemoveGroupRole(string RequestingAgentID, UUID groupID, UUID roleID) + { + string url = string.Empty, gname = string.Empty; + + if (IsLocal(groupID, out url, out gname)) + m_LocalGroupsConnector.RemoveGroupRole(AgentUUI(RequestingAgentID), groupID, roleID); + else + { + return; + } + } + + public List GetGroupRoles(string RequestingAgentID, UUID groupID) + { + string url = string.Empty, gname = string.Empty; + + if (IsLocal(groupID, out url, out gname)) + return m_LocalGroupsConnector.GetGroupRoles(AgentUUI(RequestingAgentID), groupID); + else if (!string.IsNullOrEmpty(url)) + { + ExtendedGroupMembershipData membership = m_LocalGroupsConnector.GetAgentGroupMembership(RequestingAgentID, RequestingAgentID, groupID); + string accessToken = string.Empty; + if (membership != null) + accessToken = membership.AccessToken; + else + return null; + + GroupsServiceHGConnector c = GetConnector(url); + if (c != null) + { + return m_CacheWrapper.GetGroupRoles(RequestingAgentID, groupID, delegate + { + return c.GetGroupRoles(AgentUUIForOutside(RequestingAgentID), groupID, accessToken); + }); + + } + } + + return new List(); + } + + public List GetGroupRoleMembers(string RequestingAgentID, UUID groupID) + { + string url = string.Empty, gname = string.Empty; + + if (IsLocal(groupID, out url, out gname)) + return m_LocalGroupsConnector.GetGroupRoleMembers(AgentUUI(RequestingAgentID), groupID); + else if (!string.IsNullOrEmpty(url)) + { + ExtendedGroupMembershipData membership = m_LocalGroupsConnector.GetAgentGroupMembership(RequestingAgentID, RequestingAgentID, groupID); + string accessToken = string.Empty; + if (membership != null) + accessToken = membership.AccessToken; + else + return null; + + GroupsServiceHGConnector c = GetConnector(url); + if (c != null) + { + return m_CacheWrapper.GetGroupRoleMembers(RequestingAgentID, groupID, delegate + { + return c.GetGroupRoleMembers(AgentUUIForOutside(RequestingAgentID), groupID, accessToken); + }); + + } + } + + return new List(); + } + + public bool AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID, string token, out string reason) + { + string url = string.Empty; + string name = string.Empty; + reason = string.Empty; + + UUID uid = new UUID(AgentID); + if (IsLocal(GroupID, out url, out name)) + { + if (m_UserManagement.IsLocalGridUser(uid)) // local user + { + // normal case: local group, local user + return m_LocalGroupsConnector.AddAgentToGroup(AgentUUI(RequestingAgentID), AgentUUI(AgentID), GroupID, RoleID, token, out reason); + } + else // local group, foreign user + { + // the user is accepting the invitation, or joining, where the group resides + token = UUID.Random().ToString(); + bool success = m_LocalGroupsConnector.AddAgentToGroup(AgentUUI(RequestingAgentID), AgentUUI(AgentID), GroupID, RoleID, token, out reason); + + if (success) + { + url = m_UserManagement.GetUserServerURL(uid, "GroupsServerURI"); + if (url == string.Empty) + { + reason = "User doesn't have a groups server"; + return false; + } + + GroupsServiceHGConnector c = GetConnector(url); + if (c != null) + return c.CreateProxy(AgentUUI(RequestingAgentID), AgentID, token, GroupID, m_LocalGroupsServiceLocation, name, out reason); + } + } + } + else if (m_UserManagement.IsLocalGridUser(uid)) // local user + { + // foreign group, local user. She's been added already by the HG service. + // Let's just check + if (m_LocalGroupsConnector.GetAgentGroupMembership(AgentUUI(RequestingAgentID), AgentUUI(AgentID), GroupID) != null) + return true; + } + + reason = "Operation not allowed outside this group's origin world"; + return false; + } + + + public void RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID) + { + string url = string.Empty, name = string.Empty; + if (!IsLocal(GroupID, out url, out name) && url != string.Empty) + { + ExtendedGroupMembershipData membership = m_LocalGroupsConnector.GetAgentGroupMembership(AgentUUI(RequestingAgentID), AgentUUI(AgentID), GroupID); + if (membership != null) + { + GroupsServiceHGConnector c = GetConnector(url); + if (c != null) + c.RemoveAgentFromGroup(AgentUUIForOutside(AgentID), GroupID, membership.AccessToken); + } + } + + // remove from local service + m_LocalGroupsConnector.RemoveAgentFromGroup(AgentUUI(RequestingAgentID), AgentUUI(AgentID), GroupID); + } + + public bool AddAgentToGroupInvite(string RequestingAgentID, UUID inviteID, UUID groupID, UUID roleID, string agentID) + { + string url = string.Empty, gname = string.Empty; + + if (IsLocal(groupID, out url, out gname)) + return m_LocalGroupsConnector.AddAgentToGroupInvite(AgentUUI(RequestingAgentID), inviteID, groupID, roleID, AgentUUI(agentID)); + else + return false; + } + + public GroupInviteInfo GetAgentToGroupInvite(string RequestingAgentID, UUID inviteID) + { + return m_LocalGroupsConnector.GetAgentToGroupInvite(AgentUUI(RequestingAgentID), inviteID); ; + } + + public void RemoveAgentToGroupInvite(string RequestingAgentID, UUID inviteID) + { + m_LocalGroupsConnector.RemoveAgentToGroupInvite(AgentUUI(RequestingAgentID), inviteID); + } + + public void AddAgentToGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID) + { + string url = string.Empty, gname = string.Empty; + + if (IsLocal(GroupID, out url, out gname)) + m_LocalGroupsConnector.AddAgentToGroupRole(AgentUUI(RequestingAgentID), AgentUUI(AgentID), GroupID, RoleID); + + } + + public void RemoveAgentFromGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID) + { + string url = string.Empty, gname = string.Empty; + + if (IsLocal(GroupID, out url, out gname)) + m_LocalGroupsConnector.RemoveAgentFromGroupRole(AgentUUI(RequestingAgentID), AgentUUI(AgentID), GroupID, RoleID); + } + + public List GetAgentGroupRoles(string RequestingAgentID, string AgentID, UUID GroupID) + { + string url = string.Empty, gname = string.Empty; + + if (IsLocal(GroupID, out url, out gname)) + return m_LocalGroupsConnector.GetAgentGroupRoles(AgentUUI(RequestingAgentID), AgentUUI(AgentID), GroupID); + else + return new List(); + } + + public void SetAgentActiveGroup(string RequestingAgentID, string AgentID, UUID GroupID) + { + string url = string.Empty, gname = string.Empty; + + if (IsLocal(GroupID, out url, out gname)) + m_LocalGroupsConnector.SetAgentActiveGroup(AgentUUI(RequestingAgentID), AgentUUI(AgentID), GroupID); + } + + public ExtendedGroupMembershipData GetAgentActiveMembership(string RequestingAgentID, string AgentID) + { + return m_LocalGroupsConnector.GetAgentActiveMembership(AgentUUI(RequestingAgentID), AgentUUI(AgentID)); + } + + public void SetAgentActiveGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID) + { + string url = string.Empty, gname = string.Empty; + + if (IsLocal(GroupID, out url, out gname)) + m_LocalGroupsConnector.SetAgentActiveGroupRole(AgentUUI(RequestingAgentID), AgentUUI(AgentID), GroupID, RoleID); + } + + public void UpdateMembership(string RequestingAgentID, string AgentID, UUID GroupID, bool AcceptNotices, bool ListInProfile) + { + m_LocalGroupsConnector.UpdateMembership(AgentUUI(RequestingAgentID), AgentUUI(AgentID), GroupID, AcceptNotices, ListInProfile); + } + + public ExtendedGroupMembershipData GetAgentGroupMembership(string RequestingAgentID, string AgentID, UUID GroupID) + { + string url = string.Empty, gname = string.Empty; + + if (IsLocal(GroupID, out url, out gname)) + return m_LocalGroupsConnector.GetAgentGroupMembership(AgentUUI(RequestingAgentID), AgentUUI(AgentID), GroupID); + else + return null; + } + + public List GetAgentGroupMemberships(string RequestingAgentID, string AgentID) + { + return m_LocalGroupsConnector.GetAgentGroupMemberships(AgentUUI(RequestingAgentID), AgentUUI(AgentID)); + } + + public bool AddGroupNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message, + bool hasAttachment, byte attType, string attName, UUID attItemID, string attOwnerID) + { + string url = string.Empty, gname = string.Empty; + + if (IsLocal(groupID, out url, out gname)) + { + if (m_LocalGroupsConnector.AddGroupNotice(AgentUUI(RequestingAgentID), groupID, noticeID, fromName, subject, message, + hasAttachment, attType, attName, attItemID, AgentUUI(attOwnerID))) + { + // then send the notice to every grid for which there are members in this group + List members = m_LocalGroupsConnector.GetGroupMembers(AgentUUI(RequestingAgentID), groupID); + List urls = new List(); + foreach (GroupMembersData m in members) + { + UUID userID = UUID.Zero; + if (!m_UserManagement.IsLocalGridUser(m.AgentID)) + { + string gURL = m_UserManagement.GetUserServerURL(m.AgentID, "GroupsServerURI"); + if (!urls.Contains(gURL)) + urls.Add(gURL); + } + } + + // so we have the list of urls to send the notice to + // this may take a long time... + Util.FireAndForget(delegate + { + foreach (string u in urls) + { + GroupsServiceHGConnector c = GetConnector(u); + if (c != null) + { + c.AddNotice(AgentUUIForOutside(RequestingAgentID), groupID, noticeID, fromName, subject, message, + hasAttachment, attType, attName, attItemID, AgentUUIForOutside(attOwnerID)); + } + } + }); + + return true; + } + + return false; + } + else + return false; + } + + public GroupNoticeInfo GetGroupNotice(string RequestingAgentID, UUID noticeID) + { + GroupNoticeInfo notice = m_LocalGroupsConnector.GetGroupNotice(AgentUUI(RequestingAgentID), noticeID); + + if (notice != null && notice.noticeData.HasAttachment && notice.noticeData.AttachmentOwnerID != null) + ImportForeigner(notice.noticeData.AttachmentOwnerID); + + return notice; + } + + public List GetGroupNotices(string RequestingAgentID, UUID GroupID) + { + return m_LocalGroupsConnector.GetGroupNotices(AgentUUI(RequestingAgentID), GroupID); + } + + public void ResetAgentGroupChatSessions(string agentID) + { + } + + public bool hasAgentBeenInvitedToGroupChatSession(string agentID, UUID groupID) + { + return false; + } + + public bool hasAgentDroppedGroupChatSession(string agentID, UUID groupID) + { + return false; + } + + public void AgentDroppedFromGroupChatSession(string agentID, UUID groupID) + { + } + + public void AgentInvitedToGroupChatSession(string agentID, UUID groupID) + { + } + + #endregion + + #region hypergrid groups + + private string AgentUUI(string AgentIDStr) + { + UUID AgentID = UUID.Zero; + try + { + AgentID = new UUID(AgentIDStr); + } + catch (FormatException) + { + return AgentID.ToString(); + } + + if (m_UserManagement.IsLocalGridUser(AgentID)) + return AgentID.ToString(); + + AgentCircuitData agent = null; + foreach (Scene scene in m_Scenes) + { + agent = scene.AuthenticateHandler.GetAgentCircuitData(AgentID); + if (agent != null) + break; + } + if (agent == null) // oops + return AgentID.ToString(); + + return Util.ProduceUserUniversalIdentifier(agent); + } + + private string AgentUUIForOutside(string AgentIDStr) + { + UUID AgentID = UUID.Zero; + try + { + AgentID = new UUID(AgentIDStr); + } + catch (FormatException) + { + return AgentID.ToString(); + } + + AgentCircuitData agent = null; + foreach (Scene scene in m_Scenes) + { + agent = scene.AuthenticateHandler.GetAgentCircuitData(AgentID); + if (agent != null) + break; + } + if (agent == null) // oops + return AgentID.ToString(); + + return Util.ProduceUserUniversalIdentifier(agent); + } + + private UUID ImportForeigner(string uID) + { + UUID userID = UUID.Zero; + string url = string.Empty, first = string.Empty, last = string.Empty, tmp = string.Empty; + if (Util.ParseUniversalUserIdentifier(uID, out userID, out url, out first, out last, out tmp)) + m_UserManagement.AddUser(userID, first, last, url); + + return userID; + } + + private bool IsLocal(UUID groupID, out string serviceLocation, out string name) + { + serviceLocation = string.Empty; + name = string.Empty; + ExtendedGroupRecord group = m_LocalGroupsConnector.GetGroupRecord(UUID.Zero.ToString(), groupID, string.Empty); + if (group == null) + { + //m_log.DebugFormat("[XXX]: IsLocal? group {0} not found -- no.", groupID); + return false; + } + + serviceLocation = group.ServiceLocation; + name = group.GroupName; + bool isLocal = (group.ServiceLocation == string.Empty); + //m_log.DebugFormat("[XXX]: IsLocal? {0}", isLocal); + return isLocal; + } + + private GroupsServiceHGConnector GetConnector(string url) + { + lock (m_NetworkConnectors) + { + if (m_NetworkConnectors.ContainsKey(url)) + return m_NetworkConnectors[url]; + + GroupsServiceHGConnector c = new GroupsServiceHGConnector(url); + m_NetworkConnectors[url] = c; + } + + return m_NetworkConnectors[url]; + } + #endregion + } +} diff --git a/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs b/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs new file mode 100644 index 0000000..92dd85c --- /dev/null +++ b/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs @@ -0,0 +1,443 @@ +/* + * 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.Reflection; +using System.Text; +using System.Xml; +using System.Collections.Generic; +using System.IO; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Server.Base; +using OpenSim.Services.Interfaces; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Server.Handlers.Base; +using log4net; +using OpenMetaverse; + +namespace OpenSim.Groups +{ + public class HGGroupsServiceRobustConnector : ServiceConnector + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private HGGroupsService m_GroupsService; + private string m_HomeURI = string.Empty; + private string m_ConfigName = "Groups"; + + // Called by Robust shell + public HGGroupsServiceRobustConnector(IConfigSource config, IHttpServer server, string configName) : + this(config, server, configName, null, null) + { + } + + // Called by the sim-bound module + public HGGroupsServiceRobustConnector(IConfigSource config, IHttpServer server, string configName, IOfflineIMService im, IUserAccountService users) : + base(config, server, configName) + { + if (configName != String.Empty) + m_ConfigName = configName; + + m_log.DebugFormat("[Groups.RobustHGConnector]: Starting with config name {0}", m_ConfigName); + + IConfig cnf = config.Configs[m_ConfigName]; + if (cnf == null) + throw new Exception(String.Format("[Groups.RobustHGConnector]: {0} section does not exist", m_ConfigName)); + + string homeURI = cnf.GetString("HomeURI", string.Empty); + if (homeURI == string.Empty) + throw new Exception(String.Format("[Groups.RobustHGConnector]: please provide the HomeURI in section {0}", m_ConfigName)); + + if (im == null) + { + string imDll = cnf.GetString("OfflineIMService", string.Empty); + if (imDll == string.Empty) + throw new Exception(String.Format("[Groups.RobustHGConnector]: please provide OfflineIMService in section {0}", m_ConfigName)); + + Object[] args = new Object[] { config }; + im = ServerUtils.LoadPlugin(imDll, args); + } + + if (users == null) + { + string usersDll = cnf.GetString("UserAccountService", string.Empty); + if (usersDll == string.Empty) + throw new Exception(String.Format("[Groups.RobustHGConnector]: please provide UserAccountService in section {0}", m_ConfigName)); + + Object[] args = new Object[] { config }; + users = ServerUtils.LoadPlugin(usersDll, args); + } + + m_GroupsService = new HGGroupsService(config, im, users, homeURI); + + server.AddStreamHandler(new HGGroupsServicePostHandler(m_GroupsService)); + } + + } + + public class HGGroupsServicePostHandler : BaseStreamHandler + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private HGGroupsService m_GroupsService; + + public HGGroupsServicePostHandler(HGGroupsService service) : + base("POST", "/hg-groups") + { + m_GroupsService = service; + } + + public override byte[] Handle(string path, Stream requestData, + IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) + { + StreamReader sr = new StreamReader(requestData); + string body = sr.ReadToEnd(); + sr.Close(); + body = body.Trim(); + + //m_log.DebugFormat("[XXX]: query String: {0}", body); + + try + { + Dictionary request = + ServerUtils.ParseQueryString(body); + + if (!request.ContainsKey("METHOD")) + return FailureResult(); + + string method = request["METHOD"].ToString(); + request.Remove("METHOD"); + + m_log.DebugFormat("[Groups.RobustHGConnector]: {0}", method); + switch (method) + { + case "POSTGROUP": + return HandleAddGroupProxy(request); + case "REMOVEAGENTFROMGROUP": + return HandleRemoveAgentFromGroup(request); + case "GETGROUP": + return HandleGetGroup(request); + case "ADDNOTICE": + return HandleAddNotice(request); + case "VERIFYNOTICE": + return HandleVerifyNotice(request); + case "GETGROUPMEMBERS": + return HandleGetGroupMembers(request); + case "GETGROUPROLES": + return HandleGetGroupRoles(request); + case "GETROLEMEMBERS": + return HandleGetRoleMembers(request); + + } + m_log.DebugFormat("[Groups.RobustHGConnector]: unknown method request: {0}", method); + } + catch (Exception e) + { + m_log.DebugFormat("[Groups.RobustHGConnector]: Exception {0}", e.StackTrace); + } + + return FailureResult(); + } + + byte[] HandleAddGroupProxy(Dictionary request) + { + Dictionary result = new Dictionary(); + + if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID") + || !request.ContainsKey("AgentID") + || !request.ContainsKey("AccessToken") || !request.ContainsKey("Location")) + NullResult(result, "Bad network data"); + + else + { + string RequestingAgentID = request["RequestingAgentID"].ToString(); + string agentID = request["AgentID"].ToString(); + UUID groupID = new UUID(request["GroupID"].ToString()); + string accessToken = request["AccessToken"].ToString(); + string location = request["Location"].ToString(); + string name = string.Empty; + if (request.ContainsKey("Name")) + name = request["Name"].ToString(); + + string reason = string.Empty; + bool success = m_GroupsService.CreateGroupProxy(RequestingAgentID, agentID, accessToken, groupID, location, name, out reason); + result["REASON"] = reason; + result["RESULT"] = success.ToString(); + } + + string xmlString = ServerUtils.BuildXmlResponse(result); + + //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString); + return Util.UTF8NoBomEncoding.GetBytes(xmlString); + } + + byte[] HandleRemoveAgentFromGroup(Dictionary request) + { + Dictionary result = new Dictionary(); + + if (!request.ContainsKey("AccessToken") || !request.ContainsKey("AgentID") || + !request.ContainsKey("GroupID")) + NullResult(result, "Bad network data"); + else + { + UUID groupID = new UUID(request["GroupID"].ToString()); + string agentID = request["AgentID"].ToString(); + string token = request["AccessToken"].ToString(); + string reason = string.Empty; + + m_GroupsService.RemoveAgentFromGroup(agentID, agentID, groupID, token); + } + + //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString); + result["RESULT"] = "true"; + return Util.UTF8NoBomEncoding.GetBytes(ServerUtils.BuildXmlResponse(result)); + } + + byte[] HandleGetGroup(Dictionary request) + { + Dictionary result = new Dictionary(); + + if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("AccessToken")) + NullResult(result, "Bad network data"); + else + { + string RequestingAgentID = request["RequestingAgentID"].ToString(); + string token = request["AccessToken"].ToString(); + + UUID groupID = UUID.Zero; + string groupName = string.Empty; + + if (request.ContainsKey("GroupID")) + groupID = new UUID(request["GroupID"].ToString()); + if (request.ContainsKey("Name")) + groupName = request["Name"].ToString(); + + ExtendedGroupRecord grec = m_GroupsService.GetGroupRecord(RequestingAgentID, groupID, groupName, token); + if (grec == null) + NullResult(result, "Group not found"); + else + result["RESULT"] = GroupsDataUtils.GroupRecord(grec); + } + + string xmlString = ServerUtils.BuildXmlResponse(result); + + //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString); + return Util.UTF8NoBomEncoding.GetBytes(xmlString); + } + + byte[] HandleGetGroupMembers(Dictionary request) + { + Dictionary result = new Dictionary(); + + if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID") || !request.ContainsKey("AccessToken")) + NullResult(result, "Bad network data"); + else + { + UUID groupID = new UUID(request["GroupID"].ToString()); + string requestingAgentID = request["RequestingAgentID"].ToString(); + string token = request["AccessToken"].ToString(); + + List members = m_GroupsService.GetGroupMembers(requestingAgentID, groupID, token); + if (members == null || (members != null && members.Count == 0)) + { + NullResult(result, "No members"); + } + else + { + Dictionary dict = new Dictionary(); + int i = 0; + foreach (ExtendedGroupMembersData m in members) + { + dict["m-" + i++] = GroupsDataUtils.GroupMembersData(m); + } + + result["RESULT"] = dict; + } + } + + string xmlString = ServerUtils.BuildXmlResponse(result); + + //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString); + return Util.UTF8NoBomEncoding.GetBytes(xmlString); + } + + byte[] HandleGetGroupRoles(Dictionary request) + { + Dictionary result = new Dictionary(); + + if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID") || !request.ContainsKey("AccessToken")) + NullResult(result, "Bad network data"); + else + { + UUID groupID = new UUID(request["GroupID"].ToString()); + string requestingAgentID = request["RequestingAgentID"].ToString(); + string token = request["AccessToken"].ToString(); + + List roles = m_GroupsService.GetGroupRoles(requestingAgentID, groupID, token); + if (roles == null || (roles != null && roles.Count == 0)) + { + NullResult(result, "No members"); + } + else + { + Dictionary dict = new Dictionary(); + int i = 0; + foreach (GroupRolesData r in roles) + dict["r-" + i++] = GroupsDataUtils.GroupRolesData(r); + + result["RESULT"] = dict; + } + } + + string xmlString = ServerUtils.BuildXmlResponse(result); + + //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString); + return Util.UTF8NoBomEncoding.GetBytes(xmlString); + } + + byte[] HandleGetRoleMembers(Dictionary request) + { + Dictionary result = new Dictionary(); + + if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID") || !request.ContainsKey("AccessToken")) + NullResult(result, "Bad network data"); + else + { + UUID groupID = new UUID(request["GroupID"].ToString()); + string requestingAgentID = request["RequestingAgentID"].ToString(); + string token = request["AccessToken"].ToString(); + + List rmembers = m_GroupsService.GetGroupRoleMembers(requestingAgentID, groupID, token); + if (rmembers == null || (rmembers != null && rmembers.Count == 0)) + { + NullResult(result, "No members"); + } + else + { + Dictionary dict = new Dictionary(); + int i = 0; + foreach (ExtendedGroupRoleMembersData rm in rmembers) + dict["rm-" + i++] = GroupsDataUtils.GroupRoleMembersData(rm); + + result["RESULT"] = dict; + } + } + + string xmlString = ServerUtils.BuildXmlResponse(result); + + //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString); + return Util.UTF8NoBomEncoding.GetBytes(xmlString); + } + + byte[] HandleAddNotice(Dictionary request) + { + Dictionary result = new Dictionary(); + + if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID") || !request.ContainsKey("NoticeID") || + !request.ContainsKey("FromName") || !request.ContainsKey("Subject") || !request.ContainsKey("Message") || + !request.ContainsKey("HasAttachment")) + NullResult(result, "Bad network data"); + + else + { + + bool hasAtt = bool.Parse(request["HasAttachment"].ToString()); + byte attType = 0; + string attName = string.Empty; + string attOwner = string.Empty; + UUID attItem = UUID.Zero; + if (request.ContainsKey("AttachmentType")) + attType = byte.Parse(request["AttachmentType"].ToString()); + if (request.ContainsKey("AttachmentName")) + attName = request["AttachmentType"].ToString(); + if (request.ContainsKey("AttachmentItemID")) + attItem = new UUID(request["AttachmentItemID"].ToString()); + if (request.ContainsKey("AttachmentOwnerID")) + attOwner = request["AttachmentOwnerID"].ToString(); + + bool success = m_GroupsService.AddNotice(request["RequestingAgentID"].ToString(), new UUID(request["GroupID"].ToString()), + new UUID(request["NoticeID"].ToString()), request["FromName"].ToString(), request["Subject"].ToString(), + request["Message"].ToString(), hasAtt, attType, attName, attItem, attOwner); + + result["RESULT"] = success.ToString(); + } + + string xmlString = ServerUtils.BuildXmlResponse(result); + + //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString); + return Util.UTF8NoBomEncoding.GetBytes(xmlString); + } + + byte[] HandleVerifyNotice(Dictionary request) + { + Dictionary result = new Dictionary(); + + if (!request.ContainsKey("NoticeID") || !request.ContainsKey("GroupID")) + NullResult(result, "Bad network data"); + + else + { + UUID noticeID = new UUID(request["NoticeID"].ToString()); + UUID groupID = new UUID(request["GroupID"].ToString()); + + bool success = m_GroupsService.VerifyNotice(noticeID, groupID); + //m_log.DebugFormat("[XXX]: VerifyNotice returned {0}", success); + result["RESULT"] = success.ToString(); + } + + string xmlString = ServerUtils.BuildXmlResponse(result); + + //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString); + return Util.UTF8NoBomEncoding.GetBytes(xmlString); + } + + // + // + // + // + // + + #region Helpers + + private void NullResult(Dictionary result, string reason) + { + result["RESULT"] = "NULL"; + result["REASON"] = reason; + } + + private byte[] FailureResult() + { + Dictionary result = new Dictionary(); + NullResult(result, "Unknown method"); + string xmlString = ServerUtils.BuildXmlResponse(result); + return Util.UTF8NoBomEncoding.GetBytes(xmlString); + } + + #endregion + } +} diff --git a/OpenSim/Addons/Groups/IGroupsServicesConnector.cs b/OpenSim/Addons/Groups/IGroupsServicesConnector.cs new file mode 100644 index 0000000..73deb7a --- /dev/null +++ b/OpenSim/Addons/Groups/IGroupsServicesConnector.cs @@ -0,0 +1,118 @@ +/* + * 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 OpenMetaverse; +using OpenSim.Framework; + +namespace OpenSim.Groups +{ + public interface IGroupsServicesConnector + { + UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, + bool openEnrollment, bool allowPublish, bool maturePublish, UUID founderID, out string reason); + bool UpdateGroup(string RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, + bool openEnrollment, bool allowPublish, bool maturePublish, out string reason); + ExtendedGroupRecord GetGroupRecord(string RequestingAgentID, UUID GroupID, string GroupName); + List FindGroups(string RequestingAgentID, string search); + List GetGroupMembers(string RequestingAgentID, UUID GroupID); + + bool AddGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers, out string reason); + bool UpdateGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers); + void RemoveGroupRole(string RequestingAgentID, UUID groupID, UUID roleID); + List GetGroupRoles(string RequestingAgentID, UUID GroupID); + List GetGroupRoleMembers(string RequestingAgentID, UUID GroupID); + + bool AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID, string token, out string reason); + void RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID); + + bool AddAgentToGroupInvite(string RequestingAgentID, UUID inviteID, UUID groupID, UUID roleID, string agentID); + GroupInviteInfo GetAgentToGroupInvite(string RequestingAgentID, UUID inviteID); + void RemoveAgentToGroupInvite(string RequestingAgentID, UUID inviteID); + + void AddAgentToGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID); + void RemoveAgentFromGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID); + List GetAgentGroupRoles(string RequestingAgentID, string AgentID, UUID GroupID); + + void SetAgentActiveGroup(string RequestingAgentID, string AgentID, UUID GroupID); + ExtendedGroupMembershipData GetAgentActiveMembership(string RequestingAgentID, string AgentID); + + void SetAgentActiveGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID); + void UpdateMembership(string RequestingAgentID, string AgentID, UUID GroupID, bool AcceptNotices, bool ListInProfile); + + /// + /// Get information about a specific group to which the user belongs. + /// + /// The agent requesting the information. + /// The agent requested. + /// The group requested. + /// + /// If the user is a member of the group then the data structure is returned. If not, then null is returned. + /// + ExtendedGroupMembershipData GetAgentGroupMembership(string RequestingAgentID, string AgentID, UUID GroupID); + + /// + /// Get information about the groups to which a user belongs. + /// + /// The agent requesting the information. + /// The agent requested. + /// + /// Information about the groups to which the user belongs. If the user belongs to no groups then an empty + /// list is returned. + /// + List GetAgentGroupMemberships(string RequestingAgentID, string AgentID); + + bool AddGroupNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message, + bool hasAttachment, byte attType, string attName, UUID attItemID, string attOwnerID); + GroupNoticeInfo GetGroupNotice(string RequestingAgentID, UUID noticeID); + List GetGroupNotices(string RequestingAgentID, UUID GroupID); + + void ResetAgentGroupChatSessions(string agentID); + bool hasAgentBeenInvitedToGroupChatSession(string agentID, UUID groupID); + bool hasAgentDroppedGroupChatSession(string agentID, UUID groupID); + void AgentDroppedFromGroupChatSession(string agentID, UUID groupID); + void AgentInvitedToGroupChatSession(string agentID, UUID groupID); + + } + + public class GroupInviteInfo + { + public UUID GroupID = UUID.Zero; + public UUID RoleID = UUID.Zero; + public string AgentID = string.Empty; + public UUID InviteID = UUID.Zero; + } + + public class GroupNoticeInfo + { + public ExtendedGroupNoticeData noticeData = new ExtendedGroupNoticeData(); + public UUID GroupID = UUID.Zero; + public string Message = string.Empty; + } + +} diff --git a/OpenSim/Addons/Groups/Local/GroupsServiceLocalConnectorModule.cs b/OpenSim/Addons/Groups/Local/GroupsServiceLocalConnectorModule.cs new file mode 100644 index 0000000..905bc91 --- /dev/null +++ b/OpenSim/Addons/Groups/Local/GroupsServiceLocalConnectorModule.cs @@ -0,0 +1,347 @@ +/* + * 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.Linq; +using System.Reflection; +using System.Text; + +using OpenSim.Framework; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.Framework.Interfaces; + +using OpenMetaverse; +using Mono.Addins; +using log4net; +using Nini.Config; + +namespace OpenSim.Groups +{ + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GroupsServiceLocalConnectorModule")] + public class GroupsServiceLocalConnectorModule : ISharedRegionModule, IGroupsServicesConnector + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private bool m_Enabled = false; + private GroupsService m_GroupsService; + private IUserManagement m_UserManagement; + private List m_Scenes; + private ForeignImporter m_ForeignImporter; + + #region constructors + public GroupsServiceLocalConnectorModule() + { + } + + public GroupsServiceLocalConnectorModule(IConfigSource config, IUserManagement uman) + { + Init(config); + m_UserManagement = uman; + m_ForeignImporter = new ForeignImporter(uman); + } + #endregion + + private void Init(IConfigSource config) + { + m_GroupsService = new GroupsService(config); + m_Scenes = new List(); + } + + #region ISharedRegionModule + + public void Initialise(IConfigSource config) + { + IConfig groupsConfig = config.Configs["Groups"]; + if (groupsConfig == null) + return; + + if ((groupsConfig.GetBoolean("Enabled", false) == false) + || (groupsConfig.GetString("ServicesConnectorModule", string.Empty) != Name)) + { + return; + } + + Init(config); + m_Enabled = true; + + m_log.DebugFormat("[Groups]: Initializing {0}", this.Name); + } + + public string Name + { + get { return "Groups Local Service Connector"; } + } + + public Type ReplaceableInterface + { + get { return null; } + } + + public void AddRegion(Scene scene) + { + if (!m_Enabled) + return; + + m_log.DebugFormat("[Groups]: Registering {0} with {1}", this.Name, scene.RegionInfo.RegionName); + scene.RegisterModuleInterface(this); + m_Scenes.Add(scene); + } + + public void RemoveRegion(Scene scene) + { + if (!m_Enabled) + return; + + scene.UnregisterModuleInterface(this); + m_Scenes.Remove(scene); + } + + public void RegionLoaded(Scene scene) + { + if (!m_Enabled) + return; + + if (m_UserManagement == null) + { + m_UserManagement = scene.RequestModuleInterface(); + m_ForeignImporter = new ForeignImporter(m_UserManagement); + } + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + #endregion + + #region IGroupsServicesConnector + + public UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, + bool allowPublish, bool maturePublish, UUID founderID, out string reason) + { + m_log.DebugFormat("[Groups]: Creating group {0}", name); + reason = string.Empty; + return m_GroupsService.CreateGroup(RequestingAgentID.ToString(), name, charter, showInList, insigniaID, + membershipFee, openEnrollment, allowPublish, maturePublish, founderID, out reason); + } + + public bool UpdateGroup(string RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, + bool openEnrollment, bool allowPublish, bool maturePublish, out string reason) + { + reason = string.Empty; + m_GroupsService.UpdateGroup(RequestingAgentID, groupID, charter, showInList, insigniaID, membershipFee, openEnrollment, allowPublish, maturePublish); + return true; + } + + public ExtendedGroupRecord GetGroupRecord(string RequestingAgentID, UUID GroupID, string GroupName) + { + if (GroupID != UUID.Zero) + return m_GroupsService.GetGroupRecord(RequestingAgentID, GroupID); + else if (GroupName != null) + return m_GroupsService.GetGroupRecord(RequestingAgentID, GroupName); + + return null; + } + + public List FindGroups(string RequestingAgentID, string search) + { + return m_GroupsService.FindGroups(RequestingAgentID, search); + } + + public List GetGroupMembers(string RequestingAgentID, UUID GroupID) + { + List _members = m_GroupsService.GetGroupMembers(RequestingAgentID, GroupID); + if (_members != null && _members.Count > 0) + { + List members = _members.ConvertAll(new Converter(m_ForeignImporter.ConvertGroupMembersData)); + return members; + } + + return new List(); + } + + public bool AddGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers, out string reason) + { + return m_GroupsService.AddGroupRole(RequestingAgentID, groupID, roleID, name, description, title, powers, out reason); + } + + public bool UpdateGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers) + { + return m_GroupsService.UpdateGroupRole(RequestingAgentID, groupID, roleID, name, description, title, powers); + } + + public void RemoveGroupRole(string RequestingAgentID, UUID groupID, UUID roleID) + { + m_GroupsService.RemoveGroupRole(RequestingAgentID, groupID, roleID); + } + + public List GetGroupRoles(string RequestingAgentID, UUID GroupID) + { + return m_GroupsService.GetGroupRoles(RequestingAgentID, GroupID); + } + + public List GetGroupRoleMembers(string RequestingAgentID, UUID GroupID) + { + List _rm = m_GroupsService.GetGroupRoleMembers(RequestingAgentID, GroupID); + if (_rm != null && _rm.Count > 0) + { + List rm = _rm.ConvertAll(new Converter(m_ForeignImporter.ConvertGroupRoleMembersData)); + return rm; + } + + return new List(); + + } + + public bool AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID, string token, out string reason) + { + return m_GroupsService.AddAgentToGroup(RequestingAgentID, AgentID, GroupID, RoleID, token, out reason); + } + + public void RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID) + { + m_GroupsService.RemoveAgentFromGroup(RequestingAgentID, AgentID, GroupID); + } + + public bool AddAgentToGroupInvite(string RequestingAgentID, UUID inviteID, UUID groupID, UUID roleID, string agentID) + { + return m_GroupsService.AddAgentToGroupInvite(RequestingAgentID, inviteID, groupID, roleID, agentID); + } + + public GroupInviteInfo GetAgentToGroupInvite(string RequestingAgentID, UUID inviteID) + { + return m_GroupsService.GetAgentToGroupInvite(RequestingAgentID, inviteID); ; + } + + public void RemoveAgentToGroupInvite(string RequestingAgentID, UUID inviteID) + { + m_GroupsService.RemoveAgentToGroupInvite(RequestingAgentID, inviteID); + } + + public void AddAgentToGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID) + { + m_GroupsService.AddAgentToGroupRole(RequestingAgentID, AgentID, GroupID, RoleID); + } + + public void RemoveAgentFromGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID) + { + m_GroupsService.RemoveAgentFromGroupRole(RequestingAgentID, AgentID, GroupID, RoleID); + } + + public List GetAgentGroupRoles(string RequestingAgentID, string AgentID, UUID GroupID) + { + return m_GroupsService.GetAgentGroupRoles(RequestingAgentID, AgentID, GroupID); + } + + public void SetAgentActiveGroup(string RequestingAgentID, string AgentID, UUID GroupID) + { + m_GroupsService.SetAgentActiveGroup(RequestingAgentID, AgentID, GroupID); + } + + public ExtendedGroupMembershipData GetAgentActiveMembership(string RequestingAgentID, string AgentID) + { + return m_GroupsService.GetAgentActiveMembership(RequestingAgentID, AgentID); + } + + public void SetAgentActiveGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID) + { + m_GroupsService.SetAgentActiveGroupRole(RequestingAgentID, AgentID, GroupID, RoleID); + } + + public void UpdateMembership(string RequestingAgentID, string AgentID, UUID GroupID, bool AcceptNotices, bool ListInProfile) + { + m_GroupsService.UpdateMembership(RequestingAgentID, AgentID, GroupID, AcceptNotices, ListInProfile); + } + + public ExtendedGroupMembershipData GetAgentGroupMembership(string RequestingAgentID, string AgentID, UUID GroupID) + { + return m_GroupsService.GetAgentGroupMembership(RequestingAgentID, AgentID, GroupID); ; + } + + public List GetAgentGroupMemberships(string RequestingAgentID, string AgentID) + { + return m_GroupsService.GetAgentGroupMemberships(RequestingAgentID, AgentID); + } + + public bool AddGroupNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message, + bool hasAttachment, byte attType, string attName, UUID attItemID, string attOwnerID) + { + return m_GroupsService.AddGroupNotice(RequestingAgentID, groupID, noticeID, fromName, subject, message, + hasAttachment, attType, attName, attItemID, attOwnerID); + } + + public GroupNoticeInfo GetGroupNotice(string RequestingAgentID, UUID noticeID) + { + GroupNoticeInfo notice = m_GroupsService.GetGroupNotice(RequestingAgentID, noticeID); + + //if (notice != null && notice.noticeData.HasAttachment && notice.noticeData.AttachmentOwnerID != null) + //{ + // UUID userID = UUID.Zero; + // string url = string.Empty, first = string.Empty, last = string.Empty, tmp = string.Empty; + // Util.ParseUniversalUserIdentifier(notice.noticeData.AttachmentOwnerID, out userID, out url, out first, out last, out tmp); + // if (url != string.Empty) + // m_UserManagement.AddUser(userID, first, last, url); + //} + + return notice; + } + + public List GetGroupNotices(string RequestingAgentID, UUID GroupID) + { + return m_GroupsService.GetGroupNotices(RequestingAgentID, GroupID); + } + + public void ResetAgentGroupChatSessions(string agentID) + { + } + + public bool hasAgentBeenInvitedToGroupChatSession(string agentID, UUID groupID) + { + return false; + } + + public bool hasAgentDroppedGroupChatSession(string agentID, UUID groupID) + { + return false; + } + + public void AgentDroppedFromGroupChatSession(string agentID, UUID groupID) + { + } + + public void AgentInvitedToGroupChatSession(string agentID, UUID groupID) + { + } + + #endregion + } +} diff --git a/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs b/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..166803f --- /dev/null +++ b/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs @@ -0,0 +1,37 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using Mono.Addins; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("OpenSim.Addons.Groups")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("http://opensimulator.org")] +[assembly: AssemblyProduct("OpenSim.Addons.Groups")] +[assembly: AssemblyCopyright("Copyright (c) OpenSimulator.org Developers")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("313d4865-d179-4735-9b5a-fe74885878b2")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +[assembly: AssemblyVersion("0.7.5.*")] +[assembly: AssemblyFileVersion("1.0.0.0")] + +[assembly: Addin("OpenSim.Groups", "0.1")] +[assembly: AddinDependency("OpenSim", "0.5")] diff --git a/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnector.cs b/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnector.cs new file mode 100644 index 0000000..04328c9 --- /dev/null +++ b/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnector.cs @@ -0,0 +1,642 @@ +/* + * 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.Linq; +using System.Reflection; +using System.Text; + +using OpenSim.Framework; +using OpenSim.Server.Base; + +using OpenMetaverse; +using log4net; + +namespace OpenSim.Groups +{ + public class GroupsServiceRemoteConnector + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private string m_ServerURI; + private object m_Lock = new object(); + + public GroupsServiceRemoteConnector(string url) + { + m_ServerURI = url; + if (!m_ServerURI.EndsWith("/")) + m_ServerURI += "/"; + + m_log.DebugFormat("[Groups.RemoteConnector]: Groups server at {0}", m_ServerURI); + } + + public ExtendedGroupRecord CreateGroup(string RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, + bool allowPublish, bool maturePublish, UUID founderID, out string reason) + { + reason = string.Empty; + + ExtendedGroupRecord rec = new ExtendedGroupRecord(); + rec.AllowPublish = allowPublish; + rec.Charter = charter; + rec.FounderID = founderID; + rec.GroupName = name; + rec.GroupPicture = insigniaID; + rec.MaturePublish = maturePublish; + rec.MembershipFee = membershipFee; + rec.OpenEnrollment = openEnrollment; + rec.ShowInList = showInList; + + Dictionary sendData = GroupsDataUtils.GroupRecord(rec); + sendData["RequestingAgentID"] = RequestingAgentID; + sendData["OP"] = "ADD"; + Dictionary ret = MakeRequest("PUTGROUP", sendData); + + if (ret == null) + return null; + + if (ret["RESULT"].ToString() == "NULL") + { + reason = ret["REASON"].ToString(); + return null; + } + + return GroupsDataUtils.GroupRecord((Dictionary)ret["RESULT"]); + + } + + public ExtendedGroupRecord UpdateGroup(string RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish) + { + ExtendedGroupRecord rec = new ExtendedGroupRecord(); + rec.AllowPublish = allowPublish; + rec.Charter = charter; + rec.GroupPicture = insigniaID; + rec.MaturePublish = maturePublish; + rec.GroupID = groupID; + rec.MembershipFee = membershipFee; + rec.OpenEnrollment = openEnrollment; + rec.ShowInList = showInList; + + Dictionary sendData = GroupsDataUtils.GroupRecord(rec); + sendData["RequestingAgentID"] = RequestingAgentID; + sendData["OP"] = "UPDATE"; + Dictionary ret = MakeRequest("PUTGROUP", sendData); + + if (ret == null || (ret != null && ret["RESULT"].ToString() == "NULL")) + return null; + + return GroupsDataUtils.GroupRecord((Dictionary)ret["RESULT"]); + } + + public ExtendedGroupRecord GetGroupRecord(string RequestingAgentID, UUID GroupID, string GroupName) + { + if (GroupID == UUID.Zero && (GroupName == null || (GroupName != null && GroupName == string.Empty))) + return null; + + Dictionary sendData = new Dictionary(); + if (GroupID != UUID.Zero) + sendData["GroupID"] = GroupID.ToString(); + if (GroupName != null && GroupName != string.Empty) + sendData["Name"] = GroupsDataUtils.Sanitize(GroupName); + + sendData["RequestingAgentID"] = RequestingAgentID; + + Dictionary ret = MakeRequest("GETGROUP", sendData); + + if (ret == null || (ret != null && ret["RESULT"].ToString() == "NULL")) + return null; + + return GroupsDataUtils.GroupRecord((Dictionary)ret["RESULT"]); + } + + public GroupMembershipData AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID, string token, out string reason) + { + reason = string.Empty; + + Dictionary sendData = new Dictionary(); + sendData["AgentID"] = AgentID; + sendData["GroupID"] = GroupID.ToString(); + sendData["RoleID"] = RoleID.ToString(); + sendData["RequestingAgentID"] = RequestingAgentID; + sendData["AccessToken"] = token; + Dictionary ret = MakeRequest("ADDAGENTTOGROUP", sendData); + + if (ret == null) + return null; + + if (!ret.ContainsKey("RESULT")) + return null; + + if (ret["RESULT"].ToString() == "NULL") + { + reason = ret["REASON"].ToString(); + return null; + } + + return GroupsDataUtils.GroupMembershipData((Dictionary)ret["RESULT"]); + + } + + public void RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID) + { + Dictionary sendData = new Dictionary(); + sendData["AgentID"] = AgentID; + sendData["GroupID"] = GroupID.ToString(); + sendData["RequestingAgentID"] = RequestingAgentID; + MakeRequest("REMOVEAGENTFROMGROUP", sendData); + } + + public ExtendedGroupMembershipData GetMembership(string RequestingAgentID, string AgentID, UUID GroupID) + { + Dictionary sendData = new Dictionary(); + sendData["AgentID"] = AgentID; + if (GroupID != UUID.Zero) + sendData["GroupID"] = GroupID.ToString(); + sendData["RequestingAgentID"] = RequestingAgentID; + Dictionary ret = MakeRequest("GETMEMBERSHIP", sendData); + + if (ret == null) + return null; + + if (!ret.ContainsKey("RESULT")) + return null; + + if (ret["RESULT"].ToString() == "NULL") + return null; + + return GroupsDataUtils.GroupMembershipData((Dictionary)ret["RESULT"]); + } + + public List GetMemberships(string RequestingAgentID, string AgentID) + { + List memberships = new List(); + + Dictionary sendData = new Dictionary(); + sendData["AgentID"] = AgentID; + sendData["ALL"] = "true"; + sendData["RequestingAgentID"] = RequestingAgentID; + Dictionary ret = MakeRequest("GETMEMBERSHIP", sendData); + + if (ret == null) + return memberships; + + if (!ret.ContainsKey("RESULT")) + return memberships; + + if (ret["RESULT"].ToString() == "NULL") + return memberships; + + foreach (object v in ((Dictionary)ret["RESULT"]).Values) + { + GroupMembershipData m = GroupsDataUtils.GroupMembershipData((Dictionary)v); + memberships.Add(m); + } + + return memberships; + } + + public List GetGroupMembers(string RequestingAgentID, UUID GroupID) + { + List members = new List(); + + Dictionary sendData = new Dictionary(); + sendData["GroupID"] = GroupID.ToString(); + sendData["RequestingAgentID"] = RequestingAgentID; + Dictionary ret = MakeRequest("GETGROUPMEMBERS", sendData); + + if (ret == null) + return members; + + if (!ret.ContainsKey("RESULT")) + return members; + + if (ret["RESULT"].ToString() == "NULL") + return members; + foreach (object v in ((Dictionary)ret["RESULT"]).Values) + { + ExtendedGroupMembersData m = GroupsDataUtils.GroupMembersData((Dictionary)v); + members.Add(m); + } + + return members; + } + + public bool AddGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers, out string reason) + { + reason = string.Empty; + + Dictionary sendData = new Dictionary(); + sendData["GroupID"] = groupID.ToString(); + sendData["RoleID"] = roleID.ToString(); + sendData["Name"] = GroupsDataUtils.Sanitize(name); + sendData["Description"] = GroupsDataUtils.Sanitize(description); + sendData["Title"] = GroupsDataUtils.Sanitize(title); + sendData["Powers"] = powers.ToString(); + sendData["RequestingAgentID"] = RequestingAgentID; + sendData["OP"] = "ADD"; + Dictionary ret = MakeRequest("PUTROLE", sendData); + + if (ret == null) + return false; + + if (!ret.ContainsKey("RESULT")) + return false; + + if (ret["RESULT"].ToString().ToLower() != "true") + { + reason = ret["REASON"].ToString(); + return false; + } + + return true; + } + + public bool UpdateGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers) + { + Dictionary sendData = new Dictionary(); + sendData["GroupID"] = groupID.ToString(); + sendData["RoleID"] = roleID.ToString(); + sendData["Name"] = GroupsDataUtils.Sanitize(name); + sendData["Description"] = GroupsDataUtils.Sanitize(description); + sendData["Title"] = GroupsDataUtils.Sanitize(title); + sendData["Powers"] = powers.ToString(); + sendData["RequestingAgentID"] = RequestingAgentID; + sendData["OP"] = "UPDATE"; + Dictionary ret = MakeRequest("PUTROLE", sendData); + + if (ret == null) + return false; + + if (!ret.ContainsKey("RESULT")) + return false; + + if (ret["RESULT"].ToString().ToLower() != "true") + return false; + + return true; + } + + public void RemoveGroupRole(string RequestingAgentID, UUID groupID, UUID roleID) + { + Dictionary sendData = new Dictionary(); + sendData["GroupID"] = groupID.ToString(); + sendData["RoleID"] = roleID.ToString(); + sendData["RequestingAgentID"] = RequestingAgentID; + MakeRequest("REMOVEROLE", sendData); + } + + public List GetGroupRoles(string RequestingAgentID, UUID GroupID) + { + List roles = new List(); + + Dictionary sendData = new Dictionary(); + sendData["GroupID"] = GroupID.ToString(); + sendData["RequestingAgentID"] = RequestingAgentID; + Dictionary ret = MakeRequest("GETGROUPROLES", sendData); + + if (ret == null) + return roles; + + if (!ret.ContainsKey("RESULT")) + return roles; + + if (ret["RESULT"].ToString() == "NULL") + return roles; + foreach (object v in ((Dictionary)ret["RESULT"]).Values) + { + GroupRolesData m = GroupsDataUtils.GroupRolesData((Dictionary)v); + roles.Add(m); + } + + return roles; + } + + public List GetGroupRoleMembers(string RequestingAgentID, UUID GroupID) + { + List rmembers = new List(); + + Dictionary sendData = new Dictionary(); + sendData["GroupID"] = GroupID.ToString(); + sendData["RequestingAgentID"] = RequestingAgentID; + Dictionary ret = MakeRequest("GETROLEMEMBERS", sendData); + + if (ret == null) + return rmembers; + + if (!ret.ContainsKey("RESULT")) + return rmembers; + + if (ret["RESULT"].ToString() == "NULL") + return rmembers; + + foreach (object v in ((Dictionary)ret["RESULT"]).Values) + { + ExtendedGroupRoleMembersData m = GroupsDataUtils.GroupRoleMembersData((Dictionary)v); + rmembers.Add(m); + } + + return rmembers; + } + + public bool AddAgentToGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID) + { + Dictionary sendData = new Dictionary(); + sendData["AgentID"] = AgentID.ToString(); + sendData["GroupID"] = GroupID.ToString(); + sendData["RoleID"] = RoleID.ToString(); + sendData["RequestingAgentID"] = RequestingAgentID; + sendData["OP"] = "ADD"; + + Dictionary ret = MakeRequest("AGENTROLE", sendData); + + if (ret == null) + return false; + + if (!ret.ContainsKey("RESULT")) + return false; + + if (ret["RESULT"].ToString().ToLower() != "true") + return false; + + return true; + } + + public bool RemoveAgentFromGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID) + { + Dictionary sendData = new Dictionary(); + sendData["AgentID"] = AgentID.ToString(); + sendData["GroupID"] = GroupID.ToString(); + sendData["RoleID"] = RoleID.ToString(); + sendData["RequestingAgentID"] = RequestingAgentID; + sendData["OP"] = "DELETE"; + + Dictionary ret = MakeRequest("AGENTROLE", sendData); + + if (ret == null) + return false; + + if (!ret.ContainsKey("RESULT")) + return false; + + if (ret["RESULT"].ToString().ToLower() != "true") + return false; + + return true; + } + + public List GetAgentGroupRoles(string RequestingAgentID, string AgentID, UUID GroupID) + { + List roles = new List(); + + Dictionary sendData = new Dictionary(); + sendData["AgentID"] = AgentID.ToString(); + sendData["GroupID"] = GroupID.ToString(); + sendData["RequestingAgentID"] = RequestingAgentID; + Dictionary ret = MakeRequest("GETAGENTROLES", sendData); + + if (ret == null) + return roles; + + if (!ret.ContainsKey("RESULT")) + return roles; + + if (ret["RESULT"].ToString() == "NULL") + return roles; + + foreach (object v in ((Dictionary)ret["RESULT"]).Values) + { + GroupRolesData m = GroupsDataUtils.GroupRolesData((Dictionary)v); + roles.Add(m); + } + + return roles; + } + + public GroupMembershipData SetAgentActiveGroup(string RequestingAgentID, string AgentID, UUID GroupID) + { + Dictionary sendData = new Dictionary(); + sendData["AgentID"] = AgentID.ToString(); + sendData["GroupID"] = GroupID.ToString(); + sendData["RequestingAgentID"] = RequestingAgentID; + sendData["OP"] = "GROUP"; + + Dictionary ret = MakeRequest("SETACTIVE", sendData); + + if (ret == null) + return null; + + if (!ret.ContainsKey("RESULT")) + return null; + + if (ret["RESULT"].ToString() == "NULL") + return null; + + return GroupsDataUtils.GroupMembershipData((Dictionary)ret["RESULT"]); + } + + public void SetAgentActiveGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID) + { + Dictionary sendData = new Dictionary(); + sendData["AgentID"] = AgentID.ToString(); + sendData["GroupID"] = GroupID.ToString(); + sendData["RoleID"] = RoleID.ToString(); + sendData["RequestingAgentID"] = RequestingAgentID; + sendData["OP"] = "ROLE"; + + MakeRequest("SETACTIVE", sendData); + } + + public void UpdateMembership(string RequestingAgentID, string AgentID, UUID GroupID, bool AcceptNotices, bool ListInProfile) + { + Dictionary sendData = new Dictionary(); + sendData["AgentID"] = AgentID.ToString(); + sendData["GroupID"] = GroupID.ToString(); + sendData["AcceptNotices"] = AcceptNotices.ToString(); + sendData["ListInProfile"] = ListInProfile.ToString(); + sendData["RequestingAgentID"] = RequestingAgentID; + MakeRequest("UPDATEMEMBERSHIP", sendData); + } + + public bool AddAgentToGroupInvite(string RequestingAgentID, UUID inviteID, UUID groupID, UUID roleID, string agentID) + { + Dictionary sendData = new Dictionary(); + sendData["InviteID"] = inviteID.ToString(); + sendData["GroupID"] = groupID.ToString(); + sendData["RoleID"] = roleID.ToString(); + sendData["AgentID"] = agentID.ToString(); + sendData["RequestingAgentID"] = RequestingAgentID; + sendData["OP"] = "ADD"; + + Dictionary ret = MakeRequest("INVITE", sendData); + + if (ret == null) + return false; + + if (!ret.ContainsKey("RESULT")) + return false; + + if (ret["RESULT"].ToString().ToLower() != "true") // it may return "NULL" + return false; + + return true; + } + + public GroupInviteInfo GetAgentToGroupInvite(string RequestingAgentID, UUID inviteID) + { + Dictionary sendData = new Dictionary(); + sendData["InviteID"] = inviteID.ToString(); + sendData["RequestingAgentID"] = RequestingAgentID; + sendData["OP"] = "GET"; + + Dictionary ret = MakeRequest("INVITE", sendData); + + if (ret == null) + return null; + + if (!ret.ContainsKey("RESULT")) + return null; + + if (ret["RESULT"].ToString() == "NULL") + return null; + + return GroupsDataUtils.GroupInviteInfo((Dictionary)ret["RESULT"]); + } + + public void RemoveAgentToGroupInvite(string RequestingAgentID, UUID inviteID) + { + Dictionary sendData = new Dictionary(); + sendData["InviteID"] = inviteID.ToString(); + sendData["RequestingAgentID"] = RequestingAgentID; + sendData["OP"] = "DELETE"; + + MakeRequest("INVITE", sendData); + } + + public bool AddGroupNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message, + bool hasAttachment, byte attType, string attName, UUID attItemID, string attOwnerID) + { + Dictionary sendData = new Dictionary(); + sendData["GroupID"] = groupID.ToString(); + sendData["NoticeID"] = noticeID.ToString(); + sendData["FromName"] = GroupsDataUtils.Sanitize(fromName); + sendData["Subject"] = GroupsDataUtils.Sanitize(subject); + sendData["Message"] = GroupsDataUtils.Sanitize(message); + sendData["HasAttachment"] = hasAttachment.ToString(); + if (hasAttachment) + { + sendData["AttachmentType"] = attType.ToString(); + sendData["AttachmentName"] = attName.ToString(); + sendData["AttachmentItemID"] = attItemID.ToString(); + sendData["AttachmentOwnerID"] = attOwnerID; + } + sendData["RequestingAgentID"] = RequestingAgentID; + + Dictionary ret = MakeRequest("ADDNOTICE", sendData); + + if (ret == null) + return false; + + if (!ret.ContainsKey("RESULT")) + return false; + + if (ret["RESULT"].ToString().ToLower() != "true") + return false; + + return true; + } + + public GroupNoticeInfo GetGroupNotice(string RequestingAgentID, UUID noticeID) + { + Dictionary sendData = new Dictionary(); + sendData["NoticeID"] = noticeID.ToString(); + sendData["RequestingAgentID"] = RequestingAgentID; + + Dictionary ret = MakeRequest("GETNOTICES", sendData); + + if (ret == null) + return null; + + if (!ret.ContainsKey("RESULT")) + return null; + + if (ret["RESULT"].ToString() == "NULL") + return null; + + return GroupsDataUtils.GroupNoticeInfo((Dictionary)ret["RESULT"]); + } + + public List GetGroupNotices(string RequestingAgentID, UUID GroupID) + { + List notices = new List(); + + Dictionary sendData = new Dictionary(); + sendData["GroupID"] = GroupID.ToString(); + sendData["RequestingAgentID"] = RequestingAgentID; + Dictionary ret = MakeRequest("GETNOTICES", sendData); + + if (ret == null) + return notices; + + if (!ret.ContainsKey("RESULT")) + return notices; + + if (ret["RESULT"].ToString() == "NULL") + return notices; + + foreach (object v in ((Dictionary)ret["RESULT"]).Values) + { + ExtendedGroupNoticeData m = GroupsDataUtils.GroupNoticeData((Dictionary)v); + notices.Add(m); + } + + return notices; + } + + #region Make Request + + private Dictionary MakeRequest(string method, Dictionary sendData) + { + sendData["METHOD"] = method; + + string reply = string.Empty; + lock (m_Lock) + reply = SynchronousRestFormsRequester.MakeRequest("POST", + m_ServerURI + "groups", + ServerUtils.BuildQueryString(sendData)); + + if (reply == string.Empty) + return null; + + Dictionary replyData = ServerUtils.ParseXmlResponse( + reply); + + return replyData; + } + #endregion + + } +} diff --git a/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnectorModule.cs b/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnectorModule.cs new file mode 100644 index 0000000..d1c02db --- /dev/null +++ b/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnectorModule.cs @@ -0,0 +1,437 @@ +/* + * 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.Linq; +using System.Reflection; +using System.Threading; +using System.Text; + +using OpenSim.Framework; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Server.Base; + +using OpenMetaverse; +using Mono.Addins; +using log4net; +using Nini.Config; + +namespace OpenSim.Groups +{ + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GroupsServiceRemoteConnectorModule")] + public class GroupsServiceRemoteConnectorModule : ISharedRegionModule, IGroupsServicesConnector + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private bool m_Enabled = false; + private GroupsServiceRemoteConnector m_GroupsService; + private IUserManagement m_UserManagement; + private List m_Scenes; + + private RemoteConnectorCacheWrapper m_CacheWrapper; + + #region constructors + public GroupsServiceRemoteConnectorModule() + { + } + + public GroupsServiceRemoteConnectorModule(IConfigSource config, IUserManagement uman) + { + Init(config); + m_UserManagement = uman; + m_CacheWrapper = new RemoteConnectorCacheWrapper(m_UserManagement); + + } + #endregion + + private void Init(IConfigSource config) + { + IConfig groupsConfig = config.Configs["Groups"]; + string url = groupsConfig.GetString("GroupsServerURI", string.Empty); + if (url == string.Empty) + { + m_log.WarnFormat("[Groups.RemoteConnector]: Groups server URL not provided. Groups will not work."); + return; + } + + m_GroupsService = new GroupsServiceRemoteConnector(url); + m_Scenes = new List(); + + } + + #region ISharedRegionModule + + public void Initialise(IConfigSource config) + { + IConfig groupsConfig = config.Configs["Groups"]; + if (groupsConfig == null) + return; + + if ((groupsConfig.GetBoolean("Enabled", false) == false) + || (groupsConfig.GetString("ServicesConnectorModule", string.Empty) != Name)) + { + return; + } + + Init(config); + + m_Enabled = true; + m_log.DebugFormat("[Groups.RemoteConnector]: Initializing {0}", this.Name); + } + + public string Name + { + get { return "Groups Remote Service Connector"; } + } + + public Type ReplaceableInterface + { + get { return null; } + } + + public void AddRegion(Scene scene) + { + if (!m_Enabled) + return; + + m_log.DebugFormat("[Groups.RemoteConnector]: Registering {0} with {1}", this.Name, scene.RegionInfo.RegionName); + scene.RegisterModuleInterface(this); + m_Scenes.Add(scene); + } + + public void RemoveRegion(Scene scene) + { + if (!m_Enabled) + return; + + scene.UnregisterModuleInterface(this); + m_Scenes.Remove(scene); + } + + public void RegionLoaded(Scene scene) + { + if (!m_Enabled) + return; + + if (m_UserManagement == null) + { + m_UserManagement = scene.RequestModuleInterface(); + m_CacheWrapper = new RemoteConnectorCacheWrapper(m_UserManagement); + } + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + #endregion + + #region IGroupsServicesConnector + + public UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, + bool allowPublish, bool maturePublish, UUID founderID, out string reason) + { + m_log.DebugFormat("[Groups.RemoteConnector]: Creating group {0}", name); + string r = string.Empty; + + UUID groupID = m_CacheWrapper.CreateGroup(RequestingAgentID, delegate + { + return m_GroupsService.CreateGroup(RequestingAgentID.ToString(), name, charter, showInList, insigniaID, + membershipFee, openEnrollment, allowPublish, maturePublish, founderID, out r); + }); + + reason = r; + return groupID; + } + + public bool UpdateGroup(string RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, + bool openEnrollment, bool allowPublish, bool maturePublish, out string reason) + { + string r = string.Empty; + + bool success = m_CacheWrapper.UpdateGroup(groupID, delegate + { + return m_GroupsService.UpdateGroup(RequestingAgentID, groupID, charter, showInList, insigniaID, membershipFee, openEnrollment, allowPublish, maturePublish); + }); + + reason = r; + return success; + } + + public ExtendedGroupRecord GetGroupRecord(string RequestingAgentID, UUID GroupID, string GroupName) + { + if (GroupID == UUID.Zero && (GroupName == null || GroupName != null && GroupName == string.Empty)) + return null; + + return m_CacheWrapper.GetGroupRecord(RequestingAgentID,GroupID,GroupName, delegate + { + return m_GroupsService.GetGroupRecord(RequestingAgentID, GroupID, GroupName); + }); + } + + public List FindGroups(string RequestingAgentID, string search) + { + // TODO! + return new List(); + } + + public bool AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID, string token, out string reason) + { + string agentFullID = AgentID; + m_log.DebugFormat("[Groups.RemoteConnector]: Add agent {0} to group {1}", agentFullID, GroupID); + string r = string.Empty; + + bool success = m_CacheWrapper.AddAgentToGroup(RequestingAgentID, AgentID, GroupID, delegate + { + return m_GroupsService.AddAgentToGroup(RequestingAgentID, agentFullID, GroupID, RoleID, token, out r); + }); + + reason = r; + return success; + } + + public void RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID) + { + m_CacheWrapper.RemoveAgentFromGroup(RequestingAgentID, AgentID, GroupID, delegate + { + m_GroupsService.RemoveAgentFromGroup(RequestingAgentID, AgentID, GroupID); + }); + + } + + public void SetAgentActiveGroup(string RequestingAgentID, string AgentID, UUID GroupID) + { + m_CacheWrapper.SetAgentActiveGroup(AgentID, delegate + { + return m_GroupsService.SetAgentActiveGroup(RequestingAgentID, AgentID, GroupID); + }); + } + + public ExtendedGroupMembershipData GetAgentActiveMembership(string RequestingAgentID, string AgentID) + { + return m_CacheWrapper.GetAgentActiveMembership(AgentID, delegate + { + return m_GroupsService.GetMembership(RequestingAgentID, AgentID, UUID.Zero); + }); + } + + public ExtendedGroupMembershipData GetAgentGroupMembership(string RequestingAgentID, string AgentID, UUID GroupID) + { + return m_CacheWrapper.GetAgentGroupMembership(AgentID, GroupID, delegate + { + return m_GroupsService.GetMembership(RequestingAgentID, AgentID, GroupID); + }); + } + + public List GetAgentGroupMemberships(string RequestingAgentID, string AgentID) + { + return m_CacheWrapper.GetAgentGroupMemberships(AgentID, delegate + { + return m_GroupsService.GetMemberships(RequestingAgentID, AgentID); + }); + } + + + public List GetGroupMembers(string RequestingAgentID, UUID GroupID) + { + return m_CacheWrapper.GetGroupMembers(RequestingAgentID, GroupID, delegate + { + return m_GroupsService.GetGroupMembers(RequestingAgentID, GroupID); + }); + } + + public bool AddGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers, out string reason) + { + string r = string.Empty; + bool success = m_CacheWrapper.AddGroupRole(roleID, description, name, powers, title, delegate + { + return m_GroupsService.AddGroupRole(RequestingAgentID, groupID, roleID, name, description, title, powers, out r); + }); + + reason = r; + return success; + } + + public bool UpdateGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers) + { + return m_CacheWrapper.UpdateGroupRole(groupID, roleID, name, description, title, powers, delegate + { + return m_GroupsService.UpdateGroupRole(RequestingAgentID, groupID, roleID, name, description, title, powers); + }); + } + + public void RemoveGroupRole(string RequestingAgentID, UUID groupID, UUID roleID) + { + m_CacheWrapper.RemoveGroupRole(RequestingAgentID, groupID, roleID, delegate + { + m_GroupsService.RemoveGroupRole(RequestingAgentID, groupID, roleID); + }); + } + + public List GetGroupRoles(string RequestingAgentID, UUID GroupID) + { + return m_CacheWrapper.GetGroupRoles(RequestingAgentID, GroupID, delegate + { + return m_GroupsService.GetGroupRoles(RequestingAgentID, GroupID); + }); + } + + public List GetGroupRoleMembers(string RequestingAgentID, UUID GroupID) + { + return m_CacheWrapper.GetGroupRoleMembers(RequestingAgentID, GroupID, delegate + { + return m_GroupsService.GetGroupRoleMembers(RequestingAgentID, GroupID); + }); + } + + public void AddAgentToGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID) + { + m_CacheWrapper.AddAgentToGroupRole(RequestingAgentID, AgentID, GroupID, RoleID, delegate + { + return m_GroupsService.AddAgentToGroupRole(RequestingAgentID, AgentID, GroupID, RoleID); + }); + } + + public void RemoveAgentFromGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID) + { + m_CacheWrapper.RemoveAgentFromGroupRole(RequestingAgentID, AgentID, GroupID, RoleID, delegate + { + return m_GroupsService.RemoveAgentFromGroupRole(RequestingAgentID, AgentID, GroupID, RoleID); + }); + } + + public List GetAgentGroupRoles(string RequestingAgentID, string AgentID, UUID GroupID) + { + return m_CacheWrapper.GetAgentGroupRoles(RequestingAgentID, AgentID, GroupID, delegate + { + return m_GroupsService.GetAgentGroupRoles(RequestingAgentID, AgentID, GroupID); ; + }); + } + + public void SetAgentActiveGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID) + { + m_CacheWrapper.SetAgentActiveGroupRole(AgentID, GroupID, delegate + { + m_GroupsService.SetAgentActiveGroupRole(RequestingAgentID, AgentID, GroupID, RoleID); + }); + } + + public void UpdateMembership(string RequestingAgentID, string AgentID, UUID GroupID, bool AcceptNotices, bool ListInProfile) + { + m_CacheWrapper.UpdateMembership(AgentID, GroupID, AcceptNotices, ListInProfile, delegate + { + m_GroupsService.UpdateMembership(RequestingAgentID, AgentID, GroupID, AcceptNotices, ListInProfile); + }); + } + + public bool AddAgentToGroupInvite(string RequestingAgentID, UUID inviteID, UUID groupID, UUID roleID, string agentID) + { + return m_GroupsService.AddAgentToGroupInvite(RequestingAgentID, inviteID, groupID, roleID, agentID); + } + + public GroupInviteInfo GetAgentToGroupInvite(string RequestingAgentID, UUID inviteID) + { + return m_GroupsService.GetAgentToGroupInvite(RequestingAgentID, inviteID); + } + + public void RemoveAgentToGroupInvite(string RequestingAgentID, UUID inviteID) + { + m_GroupsService.RemoveAgentToGroupInvite(RequestingAgentID, inviteID); + } + + public bool AddGroupNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message, + bool hasAttachment, byte attType, string attName, UUID attItemID, string attOwnerID) + { + GroupNoticeInfo notice = new GroupNoticeInfo(); + notice.GroupID = groupID; + notice.Message = message; + notice.noticeData = new ExtendedGroupNoticeData(); + notice.noticeData.AttachmentItemID = attItemID; + notice.noticeData.AttachmentName = attName; + notice.noticeData.AttachmentOwnerID = attOwnerID.ToString(); + notice.noticeData.AttachmentType = attType; + notice.noticeData.FromName = fromName; + notice.noticeData.HasAttachment = hasAttachment; + notice.noticeData.NoticeID = noticeID; + notice.noticeData.Subject = subject; + notice.noticeData.Timestamp = (uint)Util.UnixTimeSinceEpoch(); + + return m_CacheWrapper.AddGroupNotice(groupID, noticeID, notice, delegate + { + return m_GroupsService.AddGroupNotice(RequestingAgentID, groupID, noticeID, fromName, subject, message, + hasAttachment, attType, attName, attItemID, attOwnerID); + }); + } + + public GroupNoticeInfo GetGroupNotice(string RequestingAgentID, UUID noticeID) + { + return m_CacheWrapper.GetGroupNotice(noticeID, delegate + { + return m_GroupsService.GetGroupNotice(RequestingAgentID, noticeID); + }); + } + + public List GetGroupNotices(string RequestingAgentID, UUID GroupID) + { + return m_CacheWrapper.GetGroupNotices(GroupID, delegate + { + return m_GroupsService.GetGroupNotices(RequestingAgentID, GroupID); + }); + } + + public void ResetAgentGroupChatSessions(string agentID) + { + } + + public bool hasAgentBeenInvitedToGroupChatSession(string agentID, UUID groupID) + { + return false; + } + + public bool hasAgentDroppedGroupChatSession(string agentID, UUID groupID) + { + return false; + } + + public void AgentDroppedFromGroupChatSession(string agentID, UUID groupID) + { + } + + public void AgentInvitedToGroupChatSession(string agentID, UUID groupID) + { + } + + #endregion + } + +} diff --git a/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs b/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs new file mode 100644 index 0000000..8c257ed --- /dev/null +++ b/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs @@ -0,0 +1,760 @@ +/* + * 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.Reflection; +using System.Text; +using System.Xml; +using System.Collections.Generic; +using System.IO; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Server.Base; +using OpenSim.Services.Interfaces; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Server.Handlers.Base; +using log4net; +using OpenMetaverse; + +namespace OpenSim.Groups +{ + public class GroupsServiceRobustConnector : ServiceConnector + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private GroupsService m_GroupsService; + private string m_ConfigName = "Groups"; + + public GroupsServiceRobustConnector(IConfigSource config, IHttpServer server, string configName) : + base(config, server, configName) + { + if (configName != String.Empty) + m_ConfigName = configName; + + m_log.DebugFormat("[Groups.RobustConnector]: Starting with config name {0}", m_ConfigName); + + m_GroupsService = new GroupsService(config); + + server.AddStreamHandler(new GroupsServicePostHandler(m_GroupsService)); + } + } + + public class GroupsServicePostHandler : BaseStreamHandler + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private GroupsService m_GroupsService; + + public GroupsServicePostHandler(GroupsService service) : + base("POST", "/groups") + { + m_GroupsService = service; + } + + public override byte[] Handle(string path, Stream requestData, + IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) + { + StreamReader sr = new StreamReader(requestData); + string body = sr.ReadToEnd(); + sr.Close(); + body = body.Trim(); + + //m_log.DebugFormat("[XXX]: query String: {0}", body); + + try + { + Dictionary request = + ServerUtils.ParseQueryString(body); + + if (!request.ContainsKey("METHOD")) + return FailureResult(); + + string method = request["METHOD"].ToString(); + request.Remove("METHOD"); + + m_log.DebugFormat("[Groups.Handler]: {0}", method); + switch (method) + { + case "PUTGROUP": + return HandleAddOrUpdateGroup(request); + case "GETGROUP": + return HandleGetGroup(request); + case "ADDAGENTTOGROUP": + return HandleAddAgentToGroup(request); + case "REMOVEAGENTFROMGROUP": + return HandleRemoveAgentFromGroup(request); + case "GETMEMBERSHIP": + return HandleGetMembership(request); + case "GETGROUPMEMBERS": + return HandleGetGroupMembers(request); + case "PUTROLE": + return HandlePutRole(request); + case "REMOVEROLE": + return HandleRemoveRole(request); + case "GETGROUPROLES": + return HandleGetGroupRoles(request); + case "GETROLEMEMBERS": + return HandleGetRoleMembers(request); + case "AGENTROLE": + return HandleAgentRole(request); + case "GETAGENTROLES": + return HandleGetAgentRoles(request); + case "SETACTIVE": + return HandleSetActive(request); + case "UPDATEMEMBERSHIP": + return HandleUpdateMembership(request); + case "INVITE": + return HandleInvite(request); + case "ADDNOTICE": + return HandleAddNotice(request); + case "GETNOTICES": + return HandleGetNotices(request); + } + m_log.DebugFormat("[GROUPS HANDLER]: unknown method request: {0}", method); + } + catch (Exception e) + { + m_log.DebugFormat("[GROUPS HANDLER]: Exception {0}", e.StackTrace); + } + + return FailureResult(); + } + + byte[] HandleAddOrUpdateGroup(Dictionary request) + { + Dictionary result = new Dictionary(); + + ExtendedGroupRecord grec = GroupsDataUtils.GroupRecord(request); + if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("OP")) + NullResult(result, "Bad network data"); + + else + { + string RequestingAgentID = request["RequestingAgentID"].ToString(); + string reason = string.Empty; + string op = request["OP"].ToString(); + if (op == "ADD") + { + grec.GroupID = m_GroupsService.CreateGroup(RequestingAgentID, grec.GroupName, grec.Charter, grec.ShowInList, grec.GroupPicture, grec.MembershipFee, + grec.OpenEnrollment, grec.AllowPublish, grec.MaturePublish, grec.FounderID, out reason); + + } + else if (op == "UPDATE") + { + m_GroupsService.UpdateGroup(RequestingAgentID, grec.GroupID, grec.Charter, grec.ShowInList, grec.GroupPicture, grec.MembershipFee, + grec.OpenEnrollment, grec.AllowPublish, grec.MaturePublish); + + } + + grec = m_GroupsService.GetGroupRecord(RequestingAgentID, grec.GroupID); + if (grec == null) + NullResult(result, "Internal Error"); + else + result["RESULT"] = GroupsDataUtils.GroupRecord(grec); + } + + string xmlString = ServerUtils.BuildXmlResponse(result); + + //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString); + return Util.UTF8NoBomEncoding.GetBytes(xmlString); + } + + byte[] HandleGetGroup(Dictionary request) + { + Dictionary result = new Dictionary(); + + if (!request.ContainsKey("RequestingAgentID")) + NullResult(result, "Bad network data"); + else + { + string RequestingAgentID = request["RequestingAgentID"].ToString(); + ExtendedGroupRecord grec = null; + if (request.ContainsKey("GroupID")) + { + UUID groupID = new UUID(request["GroupID"].ToString()); + grec = m_GroupsService.GetGroupRecord(RequestingAgentID, groupID); + } + else if (request.ContainsKey("Name")) + { + string name = request["Name"].ToString(); + grec = m_GroupsService.GetGroupRecord(RequestingAgentID, name); + } + + if (grec == null) + NullResult(result, "Group not found"); + else + result["RESULT"] = GroupsDataUtils.GroupRecord(grec); + } + + string xmlString = ServerUtils.BuildXmlResponse(result); + + //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString); + return Util.UTF8NoBomEncoding.GetBytes(xmlString); + } + + byte[] HandleAddAgentToGroup(Dictionary request) + { + Dictionary result = new Dictionary(); + + if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("AgentID") || + !request.ContainsKey("GroupID") || !request.ContainsKey("RoleID")) + NullResult(result, "Bad network data"); + else + { + UUID groupID = new UUID(request["GroupID"].ToString()); + UUID roleID = new UUID(request["RoleID"].ToString()); + string agentID = request["AgentID"].ToString(); + string requestingAgentID = request["RequestingAgentID"].ToString(); + string token = string.Empty; + string reason = string.Empty; + + if (request.ContainsKey("AccessToken")) + token = request["AccessToken"].ToString(); + + if (!m_GroupsService.AddAgentToGroup(requestingAgentID, agentID, groupID, roleID, token, out reason)) + NullResult(result, reason); + else + { + GroupMembershipData membership = m_GroupsService.GetAgentGroupMembership(requestingAgentID, agentID, groupID); + if (membership == null) + NullResult(result, "Internal error"); + else + result["RESULT"] = GroupsDataUtils.GroupMembershipData((ExtendedGroupMembershipData)membership); + } + } + + string xmlString = ServerUtils.BuildXmlResponse(result); + + //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString); + return Util.UTF8NoBomEncoding.GetBytes(xmlString); + } + + byte[] HandleRemoveAgentFromGroup(Dictionary request) + { + Dictionary result = new Dictionary(); + + if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("AgentID") || !request.ContainsKey("GroupID")) + NullResult(result, "Bad network data"); + else + { + UUID groupID = new UUID(request["GroupID"].ToString()); + string agentID = request["AgentID"].ToString(); + string requestingAgentID = request["RequestingAgentID"].ToString(); + string reason = string.Empty; + + m_GroupsService.RemoveAgentFromGroup(requestingAgentID, agentID, groupID); + } + + //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString); + result["RESULT"] = "true"; + return Util.UTF8NoBomEncoding.GetBytes(ServerUtils.BuildXmlResponse(result)); + } + + byte[] HandleGetMembership(Dictionary request) + { + Dictionary result = new Dictionary(); + + if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("AgentID")) + NullResult(result, "Bad network data"); + else + { + string agentID = request["AgentID"].ToString(); + UUID groupID = UUID.Zero; + if (request.ContainsKey("GroupID")) + groupID = new UUID(request["GroupID"].ToString()); + string requestingAgentID = request["RequestingAgentID"].ToString(); + bool all = request.ContainsKey("ALL"); + + if (!all) + { + ExtendedGroupMembershipData membership = null; + if (groupID == UUID.Zero) + { + membership = m_GroupsService.GetAgentActiveMembership(requestingAgentID, agentID); + } + else + { + membership = m_GroupsService.GetAgentGroupMembership(requestingAgentID, agentID, groupID); + } + + if (membership == null) + NullResult(result, "No such membership"); + else + result["RESULT"] = GroupsDataUtils.GroupMembershipData(membership); + } + else + { + List memberships = m_GroupsService.GetAgentGroupMemberships(requestingAgentID, agentID); + if (memberships == null || (memberships != null && memberships.Count == 0)) + { + NullResult(result, "No memberships"); + } + else + { + Dictionary dict = new Dictionary(); + int i = 0; + foreach (GroupMembershipData m in memberships) + dict["m-" + i++] = GroupsDataUtils.GroupMembershipData((ExtendedGroupMembershipData)m); + + result["RESULT"] = dict; + } + } + } + + string xmlString = ServerUtils.BuildXmlResponse(result); + + //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString); + return Util.UTF8NoBomEncoding.GetBytes(xmlString); + } + + byte[] HandleGetGroupMembers(Dictionary request) + { + Dictionary result = new Dictionary(); + + if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID")) + NullResult(result, "Bad network data"); + else + { + UUID groupID = new UUID(request["GroupID"].ToString()); + string requestingAgentID = request["RequestingAgentID"].ToString(); + + List members = m_GroupsService.GetGroupMembers(requestingAgentID, groupID); + if (members == null || (members != null && members.Count == 0)) + { + NullResult(result, "No members"); + } + else + { + Dictionary dict = new Dictionary(); + int i = 0; + foreach (ExtendedGroupMembersData m in members) + { + dict["m-" + i++] = GroupsDataUtils.GroupMembersData(m); + } + + result["RESULT"] = dict; + } + } + + string xmlString = ServerUtils.BuildXmlResponse(result); + + //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString); + return Util.UTF8NoBomEncoding.GetBytes(xmlString); + } + + byte[] HandlePutRole(Dictionary request) + { + Dictionary result = new Dictionary(); + + if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID") || !request.ContainsKey("RoleID") || + !request.ContainsKey("Name") || !request.ContainsKey("Descrption") || !request.ContainsKey("Title") || + !request.ContainsKey("Powers") || !request.ContainsKey("OP")) + NullResult(result, "Bad network data"); + + else + { + string op = request["OP"].ToString(); + string reason = string.Empty; + + bool success = false; + if (op == "ADD") + success = m_GroupsService.AddGroupRole(request["RequestingAgentID"].ToString(), new UUID(request["GroupID"].ToString()), + new UUID(request["RoleID"].ToString()), request["Name"].ToString(), request["Description"].ToString(), + request["Title"].ToString(), UInt64.Parse(request["Powers"].ToString()), out reason); + + else if (op == "UPDATE") + success = m_GroupsService.UpdateGroupRole(request["RequestingAgentID"].ToString(), new UUID(request["GroupID"].ToString()), + new UUID(request["RoleID"].ToString()), request["Name"].ToString(), request["Description"].ToString(), + request["Title"].ToString(), UInt64.Parse(request["Powers"].ToString())); + + result["RESULT"] = success.ToString(); + } + + string xmlString = ServerUtils.BuildXmlResponse(result); + + //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString); + return Util.UTF8NoBomEncoding.GetBytes(xmlString); + } + + byte[] HandleRemoveRole(Dictionary request) + { + Dictionary result = new Dictionary(); + + if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID") || !request.ContainsKey("RoleID")) + NullResult(result, "Bad network data"); + + else + { + m_GroupsService.RemoveGroupRole(request["RequestingAgentID"].ToString(), new UUID(request["GroupID"].ToString()), + new UUID(request["RoleID"].ToString())); + result["RESULT"] = "true"; + } + + //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString); + return Util.UTF8NoBomEncoding.GetBytes(ServerUtils.BuildXmlResponse(result)); + } + + byte[] HandleGetGroupRoles(Dictionary request) + { + Dictionary result = new Dictionary(); + + if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID")) + NullResult(result, "Bad network data"); + else + { + UUID groupID = new UUID(request["GroupID"].ToString()); + string requestingAgentID = request["RequestingAgentID"].ToString(); + + List roles = m_GroupsService.GetGroupRoles(requestingAgentID, groupID); + if (roles == null || (roles != null && roles.Count == 0)) + { + NullResult(result, "No members"); + } + else + { + Dictionary dict = new Dictionary(); + int i = 0; + foreach (GroupRolesData r in roles) + dict["r-" + i++] = GroupsDataUtils.GroupRolesData(r); + + result["RESULT"] = dict; + } + } + + string xmlString = ServerUtils.BuildXmlResponse(result); + + //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString); + return Util.UTF8NoBomEncoding.GetBytes(xmlString); + } + + byte[] HandleGetRoleMembers(Dictionary request) + { + Dictionary result = new Dictionary(); + + if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID")) + NullResult(result, "Bad network data"); + else + { + UUID groupID = new UUID(request["GroupID"].ToString()); + string requestingAgentID = request["RequestingAgentID"].ToString(); + + List rmembers = m_GroupsService.GetGroupRoleMembers(requestingAgentID, groupID); + if (rmembers == null || (rmembers != null && rmembers.Count == 0)) + { + NullResult(result, "No members"); + } + else + { + Dictionary dict = new Dictionary(); + int i = 0; + foreach (ExtendedGroupRoleMembersData rm in rmembers) + dict["rm-" + i++] = GroupsDataUtils.GroupRoleMembersData(rm); + + result["RESULT"] = dict; + } + } + + string xmlString = ServerUtils.BuildXmlResponse(result); + + //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString); + return Util.UTF8NoBomEncoding.GetBytes(xmlString); + } + + byte[] HandleAgentRole(Dictionary request) + { + Dictionary result = new Dictionary(); + + if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID") || !request.ContainsKey("RoleID") || + !request.ContainsKey("AgentID") || !request.ContainsKey("OP")) + NullResult(result, "Bad network data"); + + else + { + string op = request["OP"].ToString(); + string reason = string.Empty; + + bool success = false; + if (op == "ADD") + success = m_GroupsService.AddAgentToGroupRole(request["RequestingAgentID"].ToString(), request["AgentID"].ToString(), + new UUID(request["GroupID"].ToString()), new UUID(request["RoleID"].ToString())); + + else if (op == "DELETE") + success = m_GroupsService.RemoveAgentFromGroupRole(request["RequestingAgentID"].ToString(), request["AgentID"].ToString(), + new UUID(request["GroupID"].ToString()), new UUID(request["RoleID"].ToString())); + + result["RESULT"] = success.ToString(); + } + + string xmlString = ServerUtils.BuildXmlResponse(result); + + //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString); + return Util.UTF8NoBomEncoding.GetBytes(xmlString); + } + + byte[] HandleGetAgentRoles(Dictionary request) + { + Dictionary result = new Dictionary(); + + if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID") || !request.ContainsKey("AgentID")) + NullResult(result, "Bad network data"); + else + { + UUID groupID = new UUID(request["GroupID"].ToString()); + string agentID = request["AgentID"].ToString(); + string requestingAgentID = request["RequestingAgentID"].ToString(); + + List roles = m_GroupsService.GetAgentGroupRoles(requestingAgentID, agentID, groupID); + if (roles == null || (roles != null && roles.Count == 0)) + { + NullResult(result, "No members"); + } + else + { + Dictionary dict = new Dictionary(); + int i = 0; + foreach (GroupRolesData r in roles) + dict["r-" + i++] = GroupsDataUtils.GroupRolesData(r); + + result["RESULT"] = dict; + } + } + + string xmlString = ServerUtils.BuildXmlResponse(result); + + //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString); + return Util.UTF8NoBomEncoding.GetBytes(xmlString); + } + + byte[] HandleSetActive(Dictionary request) + { + Dictionary result = new Dictionary(); + + if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID") || + !request.ContainsKey("AgentID") || !request.ContainsKey("OP")) + { + NullResult(result, "Bad network data"); + string xmlString = ServerUtils.BuildXmlResponse(result); + return Util.UTF8NoBomEncoding.GetBytes(xmlString); + } + else + { + string op = request["OP"].ToString(); + string reason = string.Empty; + + if (op == "GROUP") + { + ExtendedGroupMembershipData group = m_GroupsService.SetAgentActiveGroup(request["RequestingAgentID"].ToString(), + request["AgentID"].ToString(), new UUID(request["GroupID"].ToString())); + + if (group == null) + NullResult(result, "Internal error"); + else + result["RESULT"] = GroupsDataUtils.GroupMembershipData(group); + + string xmlString = ServerUtils.BuildXmlResponse(result); + + //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString); + return Util.UTF8NoBomEncoding.GetBytes(xmlString); + + } + else if (op == "ROLE" && request.ContainsKey("RoleID")) + { + m_GroupsService.SetAgentActiveGroupRole(request["RequestingAgentID"].ToString(), request["AgentID"].ToString(), + new UUID(request["GroupID"].ToString()), new UUID(request["RoleID"].ToString())); + result["RESULT"] = "true"; + } + + return Util.UTF8NoBomEncoding.GetBytes(ServerUtils.BuildXmlResponse(result)); + } + + } + + byte[] HandleUpdateMembership(Dictionary request) + { + Dictionary result = new Dictionary(); + + if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("AgentID") || !request.ContainsKey("GroupID") || + !request.ContainsKey("AcceptNotices") || !request.ContainsKey("ListInProfile")) + NullResult(result, "Bad network data"); + + else + { + m_GroupsService.UpdateMembership(request["RequestingAgentID"].ToString(), request["AgentID"].ToString(), new UUID(request["GroupID"].ToString()), + bool.Parse(request["AcceptNotices"].ToString()), bool.Parse(request["ListInProfile"].ToString())); + + result["RESULT"] = "true"; + } + + //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString); + return Util.UTF8NoBomEncoding.GetBytes(ServerUtils.BuildXmlResponse(result)); + } + + byte[] HandleInvite(Dictionary request) + { + Dictionary result = new Dictionary(); + + if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("InviteID")) + { + NullResult(result, "Bad network data"); + string xmlString = ServerUtils.BuildXmlResponse(result); + return Util.UTF8NoBomEncoding.GetBytes(xmlString); + } + else + { + string op = request["OP"].ToString(); + string reason = string.Empty; + + if (op == "ADD" && request.ContainsKey("GroupID") && request.ContainsKey("RoleID") && request.ContainsKey("AgentID")) + { + bool success = m_GroupsService.AddAgentToGroupInvite(request["RequestingAgentID"].ToString(), + new UUID(request["InviteID"].ToString()), new UUID(request["GroupID"].ToString()), + new UUID(request["RoleID"].ToString()), request["AgentID"].ToString()); + + result["RESULT"] = success.ToString(); + return Util.UTF8NoBomEncoding.GetBytes(ServerUtils.BuildXmlResponse(result)); + + } + else if (op == "DELETE") + { + m_GroupsService.RemoveAgentToGroupInvite(request["RequestingAgentID"].ToString(), new UUID(request["InviteID"].ToString())); + result["RESULT"] = "true"; + return Util.UTF8NoBomEncoding.GetBytes(ServerUtils.BuildXmlResponse(result)); + } + else if (op == "GET") + { + GroupInviteInfo invite = m_GroupsService.GetAgentToGroupInvite(request["RequestingAgentID"].ToString(), + new UUID(request["InviteID"].ToString())); + + result["RESULT"] = GroupsDataUtils.GroupInviteInfo(invite); + return Util.UTF8NoBomEncoding.GetBytes(ServerUtils.BuildXmlResponse(result)); + } + + NullResult(result, "Bad OP in request"); + return Util.UTF8NoBomEncoding.GetBytes(ServerUtils.BuildXmlResponse(result)); + } + + } + + byte[] HandleAddNotice(Dictionary request) + { + Dictionary result = new Dictionary(); + + if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID") || !request.ContainsKey("NoticeID") || + !request.ContainsKey("FromName") || !request.ContainsKey("Subject") || !request.ContainsKey("Message") || + !request.ContainsKey("HasAttachment")) + NullResult(result, "Bad network data"); + + else + { + + bool hasAtt = bool.Parse(request["HasAttachment"].ToString()); + byte attType = 0; + string attName = string.Empty; + string attOwner = string.Empty; + UUID attItem = UUID.Zero; + if (request.ContainsKey("AttachmentType")) + attType = byte.Parse(request["AttachmentType"].ToString()); + if (request.ContainsKey("AttachmentName")) + attName = request["AttachmentName"].ToString(); + if (request.ContainsKey("AttachmentItemID")) + attItem = new UUID(request["AttachmentItemID"].ToString()); + if (request.ContainsKey("AttachmentOwnerID")) + attOwner = request["AttachmentOwnerID"].ToString(); + + bool success = m_GroupsService.AddGroupNotice(request["RequestingAgentID"].ToString(), new UUID(request["GroupID"].ToString()), + new UUID(request["NoticeID"].ToString()), request["FromName"].ToString(), request["Subject"].ToString(), + request["Message"].ToString(), hasAtt, attType, attName, attItem, attOwner); + + result["RESULT"] = success.ToString(); + } + + string xmlString = ServerUtils.BuildXmlResponse(result); + + //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString); + return Util.UTF8NoBomEncoding.GetBytes(xmlString); + } + + byte[] HandleGetNotices(Dictionary request) + { + Dictionary result = new Dictionary(); + + if (!request.ContainsKey("RequestingAgentID")) + NullResult(result, "Bad network data"); + + else if (request.ContainsKey("NoticeID")) // just one + { + GroupNoticeInfo notice = m_GroupsService.GetGroupNotice(request["RequestingAgentID"].ToString(), new UUID(request["NoticeID"].ToString())); + + if (notice == null) + NullResult(result, "NO such notice"); + else + result["RESULT"] = GroupsDataUtils.GroupNoticeInfo(notice); + + } + else if (request.ContainsKey("GroupID")) // all notices for group + { + List notices = m_GroupsService.GetGroupNotices(request["RequestingAgentID"].ToString(), new UUID(request["GroupID"].ToString())); + + if (notices == null || (notices != null && notices.Count == 0)) + NullResult(result, "No notices"); + else + { + Dictionary dict = new Dictionary(); + int i = 0; + foreach (ExtendedGroupNoticeData n in notices) + dict["n-" + i++] = GroupsDataUtils.GroupNoticeData(n); + + result["RESULT"] = dict; + } + + } + else + NullResult(result, "Bad OP in request"); + + string xmlString = ServerUtils.BuildXmlResponse(result); + return Util.UTF8NoBomEncoding.GetBytes(xmlString); + } + + + #region Helpers + + private void NullResult(Dictionary result, string reason) + { + result["RESULT"] = "NULL"; + result["REASON"] = reason; + } + + private byte[] FailureResult() + { + Dictionary result = new Dictionary(); + NullResult(result, "Unknown method"); + string xmlString = ServerUtils.BuildXmlResponse(result); + return Util.UTF8NoBomEncoding.GetBytes(xmlString); + } + #endregion + } +} diff --git a/OpenSim/Addons/Groups/RemoteConnectorCacheWrapper.cs b/OpenSim/Addons/Groups/RemoteConnectorCacheWrapper.cs new file mode 100644 index 0000000..f789626 --- /dev/null +++ b/OpenSim/Addons/Groups/RemoteConnectorCacheWrapper.cs @@ -0,0 +1,824 @@ +/* + * 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.Reflection; +using System.Threading; + +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; + +using OpenMetaverse; + +namespace OpenSim.Groups +{ + public delegate ExtendedGroupRecord GroupRecordDelegate(); + public delegate GroupMembershipData GroupMembershipDelegate(); + public delegate List GroupMembershipListDelegate(); + public delegate List GroupMembersListDelegate(); + public delegate List GroupRolesListDelegate(); + public delegate List RoleMembersListDelegate(); + public delegate GroupNoticeInfo NoticeDelegate(); + public delegate List NoticeListDelegate(); + public delegate void VoidDelegate(); + public delegate bool BooleanDelegate(); + + public class RemoteConnectorCacheWrapper + { + private ForeignImporter m_ForeignImporter; + + private Dictionary m_ActiveRequests = new Dictionary(); + private const int GROUPS_CACHE_TIMEOUT = 5 * 60; // 5 minutes + + // This all important cache cahces objects of different types: + // group- or group- => ExtendedGroupRecord + // active- => GroupMembershipData + // membership-- => GroupMembershipData + // memberships- => List + // members-- => List + // role- => GroupRolesData + // roles- => List ; all roles in the group + // roles-- => List ; roles that the agent has + // rolemembers-- => List + // notice- => GroupNoticeInfo + // notices- => List + private ExpiringCache m_Cache = new ExpiringCache(); + + public RemoteConnectorCacheWrapper(IUserManagement uman) + { + m_ForeignImporter = new ForeignImporter(uman); + } + + public UUID CreateGroup(UUID RequestingAgentID, GroupRecordDelegate d) + { + //m_log.DebugFormat("[Groups.RemoteConnector]: Creating group {0}", name); + //reason = string.Empty; + + //ExtendedGroupRecord group = m_GroupsService.CreateGroup(RequestingAgentID.ToString(), name, charter, showInList, insigniaID, + // membershipFee, openEnrollment, allowPublish, maturePublish, founderID, out reason); + ExtendedGroupRecord group = d(); + + if (group == null) + return UUID.Zero; + + if (group.GroupID != UUID.Zero) + lock (m_Cache) + { + m_Cache.Add("group-" + group.GroupID.ToString(), group, GROUPS_CACHE_TIMEOUT); + if (m_Cache.Contains("memberships-" + RequestingAgentID.ToString())) + m_Cache.Remove("memberships-" + RequestingAgentID.ToString()); + } + + return group.GroupID; + } + + public bool UpdateGroup(UUID groupID, GroupRecordDelegate d) + { + //reason = string.Empty; + //ExtendedGroupRecord group = m_GroupsService.UpdateGroup(RequestingAgentID, groupID, charter, showInList, insigniaID, membershipFee, openEnrollment, allowPublish, maturePublish); + ExtendedGroupRecord group = d(); + + if (group != null && group.GroupID != UUID.Zero) + lock (m_Cache) + m_Cache.AddOrUpdate("group-" + group.GroupID.ToString(), group, GROUPS_CACHE_TIMEOUT); + return true; + } + + public ExtendedGroupRecord GetGroupRecord(string RequestingAgentID, UUID GroupID, string GroupName, GroupRecordDelegate d) + { + //if (GroupID == UUID.Zero && (GroupName == null || GroupName != null && GroupName == string.Empty)) + // return null; + + object group = null; + bool firstCall = false; + string cacheKey = "group-"; + if (GroupID != UUID.Zero) + cacheKey += GroupID.ToString(); + else + cacheKey += GroupName; + + //m_log.DebugFormat("[XXX]: GetGroupRecord {0}", cacheKey); + + while (true) + { + lock (m_Cache) + { + if (m_Cache.TryGetValue(cacheKey, out group)) + { + //m_log.DebugFormat("[XXX]: GetGroupRecord {0} cached!", cacheKey); + return (ExtendedGroupRecord)group; + } + + // not cached + if (!m_ActiveRequests.ContainsKey(cacheKey)) + { + m_ActiveRequests.Add(cacheKey, true); + firstCall = true; + } + } + + if (firstCall) + { + //group = m_GroupsService.GetGroupRecord(RequestingAgentID, GroupID, GroupName); + group = d(); + + lock (m_Cache) + { + m_Cache.AddOrUpdate(cacheKey, group, GROUPS_CACHE_TIMEOUT); + m_ActiveRequests.Remove(cacheKey); + return (ExtendedGroupRecord)group; + } + } + else + Thread.Sleep(50); + } + } + + public bool AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, GroupMembershipDelegate d) + { + GroupMembershipData membership = d(); + if (membership == null) + return false; + + lock (m_Cache) + { + // first, remove everything! add a user is a heavy-duty op + m_Cache.Clear(); + + m_Cache.AddOrUpdate("active-" + AgentID.ToString(), membership, GROUPS_CACHE_TIMEOUT); + m_Cache.AddOrUpdate("membership-" + AgentID.ToString() + "-" + GroupID.ToString(), membership, GROUPS_CACHE_TIMEOUT); + } + + + return true; + } + + public void RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID, VoidDelegate d) + { + d(); + + lock (m_Cache) + { + string cacheKey = "active-" + AgentID.ToString(); + if (m_Cache.Contains(cacheKey)) + m_Cache.Remove(cacheKey); + + cacheKey = "memberships-" + AgentID.ToString(); + if (m_Cache.Contains(cacheKey)) + m_Cache.Remove(cacheKey); + + cacheKey = "membership-" + AgentID.ToString() + "-" + GroupID.ToString(); + if (m_Cache.Contains(cacheKey)) + m_Cache.Remove(cacheKey); + + cacheKey = "members-" + RequestingAgentID.ToString() + "-" + GroupID.ToString(); + if (m_Cache.Contains(cacheKey)) + m_Cache.Remove(cacheKey); + + cacheKey = "roles-" + "-" + GroupID.ToString() + "-" + AgentID.ToString(); + if (m_Cache.Contains(cacheKey)) + m_Cache.Remove(cacheKey); + } + } + + public void SetAgentActiveGroup(string AgentID, GroupMembershipDelegate d) + { + GroupMembershipData activeGroup = d(); + if (activeGroup != null) + { + string cacheKey = "active-" + AgentID.ToString(); + lock (m_Cache) + if (m_Cache.Contains(cacheKey)) + m_Cache.AddOrUpdate(cacheKey, activeGroup, GROUPS_CACHE_TIMEOUT); + } + } + + public ExtendedGroupMembershipData GetAgentActiveMembership(string AgentID, GroupMembershipDelegate d) + { + object membership = null; + bool firstCall = false; + string cacheKey = "active-" + AgentID.ToString(); + + //m_log.DebugFormat("[XXX]: GetAgentActiveMembership {0}", cacheKey); + + while (true) + { + lock (m_Cache) + { + if (m_Cache.TryGetValue(cacheKey, out membership)) + { + //m_log.DebugFormat("[XXX]: GetAgentActiveMembership {0} cached!", cacheKey); + return (ExtendedGroupMembershipData)membership; + } + + // not cached + if (!m_ActiveRequests.ContainsKey(cacheKey)) + { + m_ActiveRequests.Add(cacheKey, true); + firstCall = true; + } + } + + if (firstCall) + { + membership = d(); + + lock (m_Cache) + { + m_Cache.AddOrUpdate(cacheKey, membership, GROUPS_CACHE_TIMEOUT); + m_ActiveRequests.Remove(cacheKey); + return (ExtendedGroupMembershipData)membership; + } + } + else + Thread.Sleep(50); + } + + } + + public ExtendedGroupMembershipData GetAgentGroupMembership(string AgentID, UUID GroupID, GroupMembershipDelegate d) + { + object membership = null; + bool firstCall = false; + string cacheKey = "membership-" + AgentID.ToString() + "-" + GroupID.ToString(); + + //m_log.DebugFormat("[XXX]: GetAgentGroupMembership {0}", cacheKey); + + while (true) + { + lock (m_Cache) + { + if (m_Cache.TryGetValue(cacheKey, out membership)) + { + //m_log.DebugFormat("[XXX]: GetAgentGroupMembership {0}", cacheKey); + return (ExtendedGroupMembershipData)membership; + } + + // not cached + if (!m_ActiveRequests.ContainsKey(cacheKey)) + { + m_ActiveRequests.Add(cacheKey, true); + firstCall = true; + } + } + + if (firstCall) + { + membership = d(); + lock (m_Cache) + { + m_Cache.AddOrUpdate(cacheKey, membership, GROUPS_CACHE_TIMEOUT); + m_ActiveRequests.Remove(cacheKey); + return (ExtendedGroupMembershipData)membership; + } + } + else + Thread.Sleep(50); + } + } + + public List GetAgentGroupMemberships(string AgentID, GroupMembershipListDelegate d) + { + object memberships = null; + bool firstCall = false; + string cacheKey = "memberships-" + AgentID.ToString(); + + //m_log.DebugFormat("[XXX]: GetAgentGroupMemberships {0}", cacheKey); + + while (true) + { + lock (m_Cache) + { + if (m_Cache.TryGetValue(cacheKey, out memberships)) + { + //m_log.DebugFormat("[XXX]: GetAgentGroupMemberships {0} cached!", cacheKey); + return (List)memberships; + } + + // not cached + if (!m_ActiveRequests.ContainsKey(cacheKey)) + { + m_ActiveRequests.Add(cacheKey, true); + firstCall = true; + } + } + + if (firstCall) + { + memberships = d(); + lock (m_Cache) + { + m_Cache.AddOrUpdate(cacheKey, memberships, GROUPS_CACHE_TIMEOUT); + m_ActiveRequests.Remove(cacheKey); + return (List)memberships; + } + } + else + Thread.Sleep(50); + } + } + + public List GetGroupMembers(string RequestingAgentID, UUID GroupID, GroupMembersListDelegate d) + { + object members = null; + bool firstCall = false; + // we need to key in also on the requester, because different ppl have different view privileges + string cacheKey = "members-" + RequestingAgentID.ToString() + "-" + GroupID.ToString(); + + //m_log.DebugFormat("[XXX]: GetGroupMembers {0}", cacheKey); + + while (true) + { + lock (m_Cache) + { + if (m_Cache.TryGetValue(cacheKey, out members)) + { + List xx = (List)members; + return xx.ConvertAll(new Converter(m_ForeignImporter.ConvertGroupMembersData)); + } + + // not cached + if (!m_ActiveRequests.ContainsKey(cacheKey)) + { + m_ActiveRequests.Add(cacheKey, true); + firstCall = true; + } + } + + if (firstCall) + { + List _members = d(); + + if (_members != null && _members.Count > 0) + members = _members.ConvertAll(new Converter(m_ForeignImporter.ConvertGroupMembersData)); + else + members = new List(); + + lock (m_Cache) + { + //m_Cache.AddOrUpdate(cacheKey, members, GROUPS_CACHE_TIMEOUT); + m_Cache.AddOrUpdate(cacheKey, _members, GROUPS_CACHE_TIMEOUT); + m_ActiveRequests.Remove(cacheKey); + + return (List)members; + } + } + else + Thread.Sleep(50); + } + } + + public bool AddGroupRole(UUID roleID, string description, string name, ulong powers, string title, BooleanDelegate d) + { + if (d()) + { + GroupRolesData role = new GroupRolesData(); + role.Description = description; + role.Members = 0; + role.Name = name; + role.Powers = powers; + role.RoleID = roleID; + role.Title = title; + + lock (m_Cache) + m_Cache.AddOrUpdate("role-" + roleID.ToString(), role, GROUPS_CACHE_TIMEOUT); + + return true; + } + + return false; + } + + public bool UpdateGroupRole(UUID groupID, UUID roleID, string name, string description, string title, ulong powers, BooleanDelegate d) + { + if (d()) + { + object role; + lock (m_Cache) + if (m_Cache.TryGetValue("role-" + roleID.ToString(), out role)) + { + GroupRolesData r = (GroupRolesData)role; + r.Description = description; + r.Name = name; + r.Powers = powers; + r.Title = title; + + m_Cache.Update("role-" + roleID.ToString(), r, GROUPS_CACHE_TIMEOUT); + } + return true; + } + else + { + lock (m_Cache) + { + if (m_Cache.Contains("role-" + roleID.ToString())) + m_Cache.Remove("role-" + roleID.ToString()); + + // also remove these lists, because they will have an outdated role + if (m_Cache.Contains("roles-" + groupID.ToString())) + m_Cache.Remove("roles-" + groupID.ToString()); + + } + + return false; + } + } + + public void RemoveGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, VoidDelegate d) + { + d(); + + lock (m_Cache) + { + if (m_Cache.Contains("role-" + roleID.ToString())) + m_Cache.Remove("role-" + roleID.ToString()); + + // also remove the list, because it will have an removed role + if (m_Cache.Contains("roles-" + groupID.ToString())) + m_Cache.Remove("roles-" + groupID.ToString()); + + if (m_Cache.Contains("roles-" + groupID.ToString() + "-" + RequestingAgentID.ToString())) + m_Cache.Remove("roles-" + groupID.ToString() + "-" + RequestingAgentID.ToString()); + + if (m_Cache.Contains("rolemembers-" + RequestingAgentID.ToString() + "-" + groupID.ToString())) + m_Cache.Remove("rolemembers-" + RequestingAgentID.ToString() + "-" + groupID.ToString()); + } + } + + public List GetGroupRoles(string RequestingAgentID, UUID GroupID, GroupRolesListDelegate d) + { + object roles = null; + bool firstCall = false; + string cacheKey = "roles-" + GroupID.ToString(); + + while (true) + { + lock (m_Cache) + { + if (m_Cache.TryGetValue(cacheKey, out roles)) + return (List)roles; + + // not cached + if (!m_ActiveRequests.ContainsKey(cacheKey)) + { + m_ActiveRequests.Add(cacheKey, true); + firstCall = true; + } + } + + if (firstCall) + { + roles = d(); + if (roles != null) + { + lock (m_Cache) + { + m_Cache.AddOrUpdate(cacheKey, roles, GROUPS_CACHE_TIMEOUT); + m_ActiveRequests.Remove(cacheKey); + return (List)roles; + } + } + } + else + Thread.Sleep(50); + } + } + + public List GetGroupRoleMembers(string RequestingAgentID, UUID GroupID, RoleMembersListDelegate d) + { + object rmembers = null; + bool firstCall = false; + // we need to key in also on the requester, because different ppl have different view privileges + string cacheKey = "rolemembers-" + RequestingAgentID.ToString() + "-" + GroupID.ToString(); + + //m_log.DebugFormat("[XXX]: GetGroupRoleMembers {0}", cacheKey); + while (true) + { + lock (m_Cache) + { + if (m_Cache.TryGetValue(cacheKey, out rmembers)) + { + List xx = (List)rmembers; + return xx.ConvertAll(m_ForeignImporter.ConvertGroupRoleMembersData); + } + + // not cached + if (!m_ActiveRequests.ContainsKey(cacheKey)) + { + m_ActiveRequests.Add(cacheKey, true); + firstCall = true; + } + } + + if (firstCall) + { + List _rmembers = d(); + + if (_rmembers != null && _rmembers.Count > 0) + rmembers = _rmembers.ConvertAll(new Converter(m_ForeignImporter.ConvertGroupRoleMembersData)); + else + rmembers = new List(); + + lock (m_Cache) + { + // For some strange reason, when I cache the list of GroupRoleMembersData, + // it gets emptied out. The TryGet gets an empty list... + //m_Cache.AddOrUpdate(cacheKey, rmembers, GROUPS_CACHE_TIMEOUT); + // Caching the list of ExtendedGroupRoleMembersData doesn't show that issue + // I don't get it. + m_Cache.AddOrUpdate(cacheKey, _rmembers, GROUPS_CACHE_TIMEOUT); + m_ActiveRequests.Remove(cacheKey); + return (List)rmembers; + } + } + else + Thread.Sleep(50); + } + } + + public void AddAgentToGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID, BooleanDelegate d) + { + if (d()) + { + lock (m_Cache) + { + // update the cached role + string cacheKey = "role-" + RoleID.ToString(); + object obj; + if (m_Cache.TryGetValue(cacheKey, out obj)) + { + GroupRolesData r = (GroupRolesData)obj; + r.Members++; + } + + // add this agent to the list of role members + cacheKey = "rolemembers-" + RequestingAgentID.ToString() + "-" + GroupID.ToString(); + if (m_Cache.TryGetValue(cacheKey, out obj)) + { + try + { + // This may throw an exception, in which case the agentID is not a UUID but a full ID + // In that case, let's just remove the whoe things from the cache + UUID id = new UUID(AgentID); + List xx = (List)obj; + List rmlist = xx.ConvertAll(m_ForeignImporter.ConvertGroupRoleMembersData); + GroupRoleMembersData rm = new GroupRoleMembersData(); + rm.MemberID = id; + rm.RoleID = RoleID; + rmlist.Add(rm); + } + catch + { + m_Cache.Remove(cacheKey); + } + } + + // Remove the cached info about this agent's roles + // because we don't have enough local info about the new role + cacheKey = "roles-" + GroupID.ToString() + "-" + AgentID.ToString(); + if (m_Cache.Contains(cacheKey)) + m_Cache.Remove(cacheKey); + + } + } + } + + public void RemoveAgentFromGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID, BooleanDelegate d) + { + if (d()) + { + lock (m_Cache) + { + // update the cached role + string cacheKey = "role-" + RoleID.ToString(); + object obj; + if (m_Cache.TryGetValue(cacheKey, out obj)) + { + GroupRolesData r = (GroupRolesData)obj; + r.Members--; + } + + cacheKey = "roles-" + GroupID.ToString() + "-" + AgentID.ToString(); + if (m_Cache.Contains(cacheKey)) + m_Cache.Remove(cacheKey); + + cacheKey = "rolemembers-" + RequestingAgentID.ToString() + "-" + GroupID.ToString(); + if (m_Cache.Contains(cacheKey)) + m_Cache.Remove(cacheKey); + } + } + } + + public List GetAgentGroupRoles(string RequestingAgentID, string AgentID, UUID GroupID, GroupRolesListDelegate d) + { + object roles = null; + bool firstCall = false; + string cacheKey = "roles-" + GroupID.ToString() + "-" + AgentID.ToString(); + + //m_log.DebugFormat("[XXX]: GetAgentGroupRoles {0}", cacheKey); + + while (true) + { + lock (m_Cache) + { + if (m_Cache.TryGetValue(cacheKey, out roles)) + { + //m_log.DebugFormat("[XXX]: GetAgentGroupRoles {0} cached!", cacheKey); + return (List)roles; + } + + // not cached + if (!m_ActiveRequests.ContainsKey(cacheKey)) + { + m_ActiveRequests.Add(cacheKey, true); + firstCall = true; + } + } + + if (firstCall) + { + roles = d(); + lock (m_Cache) + { + m_Cache.AddOrUpdate(cacheKey, roles, GROUPS_CACHE_TIMEOUT); + m_ActiveRequests.Remove(cacheKey); + return (List)roles; + } + } + else + Thread.Sleep(50); + } + } + + public void SetAgentActiveGroupRole(string AgentID, UUID GroupID, VoidDelegate d) + { + d(); + + lock (m_Cache) + { + // Invalidate cached info, because it has ActiveRoleID and Powers + string cacheKey = "membership-" + AgentID.ToString() + "-" + GroupID.ToString(); + if (m_Cache.Contains(cacheKey)) + m_Cache.Remove(cacheKey); + + cacheKey = "memberships-" + AgentID.ToString(); + if (m_Cache.Contains(cacheKey)) + m_Cache.Remove(cacheKey); + } + } + + public void UpdateMembership(string AgentID, UUID GroupID, bool AcceptNotices, bool ListInProfile, VoidDelegate d) + { + d(); + + lock (m_Cache) + { + string cacheKey = "membership-" + AgentID.ToString() + "-" + GroupID.ToString(); + if (m_Cache.Contains(cacheKey)) + m_Cache.Remove(cacheKey); + + cacheKey = "memberships-" + AgentID.ToString(); + if (m_Cache.Contains(cacheKey)) + m_Cache.Remove(cacheKey); + + cacheKey = "active-" + AgentID.ToString(); + object m = null; + if (m_Cache.TryGetValue(cacheKey, out m)) + { + GroupMembershipData membership = (GroupMembershipData)m; + membership.ListInProfile = ListInProfile; + membership.AcceptNotices = AcceptNotices; + } + } + } + + public bool AddGroupNotice(UUID groupID, UUID noticeID, GroupNoticeInfo notice, BooleanDelegate d) + { + if (d()) + { + lock (m_Cache) + { + m_Cache.AddOrUpdate("notice-" + noticeID.ToString(), notice, GROUPS_CACHE_TIMEOUT); + string cacheKey = "notices-" + groupID.ToString(); + if (m_Cache.Contains(cacheKey)) + m_Cache.Remove(cacheKey); + + } + + return true; + } + + return false; + } + + public GroupNoticeInfo GetGroupNotice(UUID noticeID, NoticeDelegate d) + { + object notice = null; + bool firstCall = false; + string cacheKey = "notice-" + noticeID.ToString(); + + //m_log.DebugFormat("[XXX]: GetAgentGroupRoles {0}", cacheKey); + + while (true) + { + lock (m_Cache) + { + if (m_Cache.TryGetValue(cacheKey, out notice)) + { + return (GroupNoticeInfo)notice; + } + + // not cached + if (!m_ActiveRequests.ContainsKey(cacheKey)) + { + m_ActiveRequests.Add(cacheKey, true); + firstCall = true; + } + } + + if (firstCall) + { + GroupNoticeInfo _notice = d(); + + lock (m_Cache) + { + m_Cache.AddOrUpdate(cacheKey, _notice, GROUPS_CACHE_TIMEOUT); + m_ActiveRequests.Remove(cacheKey); + return _notice; + } + } + else + Thread.Sleep(50); + } + } + + public List GetGroupNotices(UUID GroupID, NoticeListDelegate d) + { + object notices = null; + bool firstCall = false; + string cacheKey = "notices-" + GroupID.ToString(); + + //m_log.DebugFormat("[XXX]: GetGroupNotices {0}", cacheKey); + + while (true) + { + lock (m_Cache) + { + if (m_Cache.TryGetValue(cacheKey, out notices)) + { + //m_log.DebugFormat("[XXX]: GetGroupNotices {0} cached!", cacheKey); + return (List)notices; + } + + // not cached + if (!m_ActiveRequests.ContainsKey(cacheKey)) + { + m_ActiveRequests.Add(cacheKey, true); + firstCall = true; + } + } + + if (firstCall) + { + notices = d(); + + lock (m_Cache) + { + m_Cache.AddOrUpdate(cacheKey, notices, GROUPS_CACHE_TIMEOUT); + m_ActiveRequests.Remove(cacheKey); + return (List)notices; + } + } + else + Thread.Sleep(50); + } + } + + + } +} diff --git a/OpenSim/Addons/Groups/Service/GroupsService.cs b/OpenSim/Addons/Groups/Service/GroupsService.cs new file mode 100644 index 0000000..fc567dd --- /dev/null +++ b/OpenSim/Addons/Groups/Service/GroupsService.cs @@ -0,0 +1,1014 @@ +/* + * 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.Reflection; +using System.Timers; +using log4net; +using Nini.Config; + +using OpenMetaverse; +using OpenSim.Data; +using OpenSim.Framework; +using OpenSim.Services.Interfaces; + +namespace OpenSim.Groups +{ + public class GroupsService : GroupsServiceBase + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + public const GroupPowers DefaultEveryonePowers = GroupPowers.AllowSetHome | + GroupPowers.Accountable | + GroupPowers.JoinChat | + GroupPowers.AllowVoiceChat | + GroupPowers.ReceiveNotices | + GroupPowers.StartProposal | + GroupPowers.VoteOnProposal; + + public const GroupPowers OwnerPowers = GroupPowers.Accountable | + GroupPowers.AllowEditLand | + GroupPowers.AllowFly | + GroupPowers.AllowLandmark | + GroupPowers.AllowRez | + GroupPowers.AllowSetHome | + GroupPowers.AllowVoiceChat | + GroupPowers.AssignMember | + GroupPowers.AssignMemberLimited | + GroupPowers.ChangeActions | + GroupPowers.ChangeIdentity | + GroupPowers.ChangeMedia | + GroupPowers.ChangeOptions | + GroupPowers.CreateRole | + GroupPowers.DeedObject | + GroupPowers.DeleteRole | + GroupPowers.Eject | + GroupPowers.FindPlaces | + GroupPowers.Invite | + GroupPowers.JoinChat | + GroupPowers.LandChangeIdentity | + GroupPowers.LandDeed | + GroupPowers.LandDivideJoin | + GroupPowers.LandEdit | + GroupPowers.LandEjectAndFreeze | + GroupPowers.LandGardening | + GroupPowers.LandManageAllowed | + GroupPowers.LandManageBanned | + GroupPowers.LandManagePasses | + GroupPowers.LandOptions | + GroupPowers.LandRelease | + GroupPowers.LandSetSale | + GroupPowers.ModerateChat | + GroupPowers.ObjectManipulate | + GroupPowers.ObjectSetForSale | + GroupPowers.ReceiveNotices | + GroupPowers.RemoveMember | + GroupPowers.ReturnGroupOwned | + GroupPowers.ReturnGroupSet | + GroupPowers.ReturnNonGroup | + GroupPowers.RoleProperties | + GroupPowers.SendNotices | + GroupPowers.SetLandingPoint | + GroupPowers.StartProposal | + GroupPowers.VoteOnProposal; + + #region Daily Cleanup + + private Timer m_CleanupTimer; + + public GroupsService(IConfigSource config, string configName) + : base(config, configName) + { + } + + public GroupsService(IConfigSource config) + : this(config, string.Empty) + { + // Once a day + m_CleanupTimer = new Timer(24 * 60 * 60 * 1000); + m_CleanupTimer.AutoReset = true; + m_CleanupTimer.Elapsed += new ElapsedEventHandler(m_CleanupTimer_Elapsed); + m_CleanupTimer.Enabled = true; + m_CleanupTimer.Start(); + } + + private void m_CleanupTimer_Elapsed(object sender, ElapsedEventArgs e) + { + m_Database.DeleteOldNotices(); + m_Database.DeleteOldInvites(); + } + + #endregion + + public UUID CreateGroup(string RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, + bool allowPublish, bool maturePublish, UUID founderID, out string reason) + { + reason = string.Empty; + + // Create the group + GroupData data = new GroupData(); + data.GroupID = UUID.Random(); + data.Data = new Dictionary(); + data.Data["Name"] = name; + data.Data["Charter"] = charter; + data.Data["InsigniaID"] = insigniaID.ToString(); + data.Data["FounderID"] = founderID.ToString(); + data.Data["MembershipFee"] = membershipFee.ToString(); + data.Data["OpenEnrollment"] = openEnrollment ? "1" : "0"; + data.Data["ShowInList"] = showInList ? "1" : "0"; + data.Data["AllowPublish"] = allowPublish ? "1" : "0"; + data.Data["MaturePublish"] = maturePublish ? "1" : "0"; + data.Data["OwnerRoleID"] = UUID.Random().ToString(); + + if (!m_Database.StoreGroup(data)) + return UUID.Zero; + + // Create Everyone role + _AddOrUpdateGroupRole(RequestingAgentID, data.GroupID, UUID.Zero, "Everyone", "Everyone in the group", "Member of " + name, (ulong)DefaultEveryonePowers, true); + + // Create Owner role + UUID roleID = UUID.Random(); + _AddOrUpdateGroupRole(RequestingAgentID, data.GroupID, roleID, "Owners", "Owners of the group", "Owner of " + name, (ulong)OwnerPowers, true); + + // Add founder to group + _AddAgentToGroup(RequestingAgentID, founderID.ToString(), data.GroupID, roleID); + + return data.GroupID; + } + + public void UpdateGroup(string RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish) + { + GroupData data = m_Database.RetrieveGroup(groupID); + if (data == null) + return; + + // Check perms + if (!HasPower(RequestingAgentID, groupID, GroupPowers.ChangeActions)) + { + m_log.DebugFormat("[Groups]: ({0}) Attempt at updating group {1} denied because of lack of permission", RequestingAgentID, groupID); + return; + } + + data.GroupID = groupID; + data.Data["Charter"] = charter; + data.Data["ShowInList"] = showInList ? "1" : "0"; + data.Data["InsigniaID"] = insigniaID.ToString(); + data.Data["MembershipFee"] = membershipFee.ToString(); + data.Data["OpenEnrollment"] = openEnrollment ? "1" : "0"; + data.Data["AllowPublish"] = allowPublish ? "1" : "0"; + data.Data["MaturePublish"] = maturePublish ? "1" : "0"; + + m_Database.StoreGroup(data); + + } + + public ExtendedGroupRecord GetGroupRecord(string RequestingAgentID, UUID GroupID) + { + GroupData data = m_Database.RetrieveGroup(GroupID); + + return _GroupDataToRecord(data); + } + + public ExtendedGroupRecord GetGroupRecord(string RequestingAgentID, string GroupName) + { + GroupData data = m_Database.RetrieveGroup(GroupName); + + return _GroupDataToRecord(data); + } + + public List FindGroups(string RequestingAgentID, string search) + { + List groups = new List(); + + GroupData[] data = m_Database.RetrieveGroups(search); + + if (data != null && data.Length > 0) + { + foreach (GroupData d in data) + { + // Don't list group proxies + if (d.Data.ContainsKey("Location") && d.Data["Location"] != string.Empty) + continue; + + DirGroupsReplyData g = new DirGroupsReplyData(); + g.groupID = d.GroupID; + + if (d.Data.ContainsKey("Name")) + g.groupName = d.Data["Name"]; + else + m_log.DebugFormat("[Groups]: Key Name not found"); + + g.members = m_Database.MemberCount(d.GroupID); + + groups.Add(g); + } + } + + return groups; + } + + public List GetGroupMembers(string RequestingAgentID, UUID GroupID) + { + List members = new List(); + + GroupData group = m_Database.RetrieveGroup(GroupID); + if (group == null) + return members; + + UUID ownerRoleID = new UUID(group.Data["OwnerRoleID"]); + + RoleData[] roles = m_Database.RetrieveRoles(GroupID); + if (roles == null) + // something wrong with this group + return members; + List rolesList = new List(roles); + + // Is the requester a member of the group? + bool isInGroup = false; + if (m_Database.RetrieveMember(GroupID, RequestingAgentID) != null) + isInGroup = true; + + if (!isInGroup) // reduce the roles to the visible ones + rolesList = rolesList.FindAll(r => (UInt64.Parse(r.Data["Powers"]) & (ulong)GroupPowers.MemberVisible) != 0); + + MembershipData[] datas = m_Database.RetrieveMembers(GroupID); + if (datas == null || (datas != null && datas.Length == 0)) + return members; + + // OK, we have everything we need + + foreach (MembershipData d in datas) + { + RoleMembershipData[] rolememberships = m_Database.RetrieveMemberRoles(GroupID, d.PrincipalID); + List rolemembershipsList = new List(rolememberships); + + ExtendedGroupMembersData m = new ExtendedGroupMembersData(); + + // What's this person's current role in the group? + UUID selectedRole = new UUID(d.Data["SelectedRoleID"]); + RoleData selected = rolesList.Find(r => r.RoleID == selectedRole); + + if (selected != null) + { + m.Title = selected.Data["Title"]; + m.AgentPowers = UInt64.Parse(selected.Data["Powers"]); + + m.AgentID = d.PrincipalID; + m.AcceptNotices = d.Data["AcceptNotices"] == "1" ? true : false; + m.Contribution = Int32.Parse(d.Data["Contribution"]); + m.ListInProfile = d.Data["ListInProfile"] == "1" ? true : false; + + // Is this person an owner of the group? + m.IsOwner = (rolemembershipsList.Find(r => r.RoleID == ownerRoleID) != null) ? true : false; + + members.Add(m); + } + } + + return members; + } + + public bool AddGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers, out string reason) + { + reason = string.Empty; + // check that the requesting agent has permissions to add role + if (!HasPower(RequestingAgentID, groupID, GroupPowers.CreateRole)) + { + m_log.DebugFormat("[Groups]: ({0}) Attempt at creating role in group {1} denied because of lack of permission", RequestingAgentID, groupID); + reason = "Insufficient permission to create role"; + return false; + } + + return _AddOrUpdateGroupRole(RequestingAgentID, groupID, roleID, name, description, title, powers, true); + + } + + public bool UpdateGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers) + { + // check perms + if (!HasPower(RequestingAgentID, groupID, GroupPowers.ChangeActions)) + { + m_log.DebugFormat("[Groups]: ({0}) Attempt at changing role in group {1} denied because of lack of permission", RequestingAgentID, groupID); + return false; + } + + return _AddOrUpdateGroupRole(RequestingAgentID, groupID, roleID, name, description, title, powers, false); + } + + public void RemoveGroupRole(string RequestingAgentID, UUID groupID, UUID roleID) + { + // check perms + if (!HasPower(RequestingAgentID, groupID, GroupPowers.DeleteRole)) + { + m_log.DebugFormat("[Groups]: ({0}) Attempt at deleting role from group {1} denied because of lack of permission", RequestingAgentID, groupID); + return; + } + + // Can't delete Everyone and Owners roles + if (roleID == UUID.Zero) + { + m_log.DebugFormat("[Groups]: Attempt at deleting Everyone role from group {0} denied", groupID); + return; + } + + GroupData group = m_Database.RetrieveGroup(groupID); + if (group == null) + { + m_log.DebugFormat("[Groups]: Attempt at deleting role from non-existing group {0}", groupID); + return; + } + + if (roleID == new UUID(group.Data["OwnerRoleID"])) + { + m_log.DebugFormat("[Groups]: Attempt at deleting Owners role from group {0} denied", groupID); + return; + } + + _RemoveGroupRole(groupID, roleID); + } + + public List GetGroupRoles(string RequestingAgentID, UUID GroupID) + { + // TODO: check perms + return _GetGroupRoles(GroupID); + } + + public List GetGroupRoleMembers(string RequestingAgentID, UUID GroupID) + { + // TODO: check perms + + // Is the requester a member of the group? + bool isInGroup = false; + if (m_Database.RetrieveMember(GroupID, RequestingAgentID) != null) + isInGroup = true; + + return _GetGroupRoleMembers(GroupID, isInGroup); + } + + public bool AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID, string token, out string reason) + { + reason = string.Empty; + + _AddAgentToGroup(RequestingAgentID, AgentID, GroupID, RoleID, token); + + return true; + } + + public void RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID) + { + // check perms + if (RequestingAgentID != AgentID && !HasPower(RequestingAgentID, GroupID, GroupPowers.Eject)) + return; + + _RemoveAgentFromGroup(RequestingAgentID, AgentID, GroupID); + } + + public bool AddAgentToGroupInvite(string RequestingAgentID, UUID inviteID, UUID groupID, UUID roleID, string agentID) + { + // Check whether the invitee is already a member of the group + MembershipData m = m_Database.RetrieveMember(groupID, agentID); + if (m != null) + return false; + + // Check permission to invite + if (!HasPower(RequestingAgentID, groupID, GroupPowers.Invite)) + { + m_log.DebugFormat("[Groups]: ({0}) Attempt at inviting to group {1} denied because of lack of permission", RequestingAgentID, groupID); + return false; + } + + // Check whether there are pending invitations and delete them + InvitationData invite = m_Database.RetrieveInvitation(groupID, agentID); + if (invite != null) + m_Database.DeleteInvite(invite.InviteID); + + invite = new InvitationData(); + invite.InviteID = inviteID; + invite.PrincipalID = agentID; + invite.GroupID = groupID; + invite.RoleID = roleID; + invite.Data = new Dictionary(); + + return m_Database.StoreInvitation(invite); + } + + public GroupInviteInfo GetAgentToGroupInvite(string RequestingAgentID, UUID inviteID) + { + InvitationData data = m_Database.RetrieveInvitation(inviteID); + + if (data == null) + return null; + + GroupInviteInfo inviteInfo = new GroupInviteInfo(); + inviteInfo.AgentID = data.PrincipalID; + inviteInfo.GroupID = data.GroupID; + inviteInfo.InviteID = data.InviteID; + inviteInfo.RoleID = data.RoleID; + + return inviteInfo; + } + + public void RemoveAgentToGroupInvite(string RequestingAgentID, UUID inviteID) + { + m_Database.DeleteInvite(inviteID); + } + + public bool AddAgentToGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID) + { + //if (!m_Database.CheckOwnerRole(RequestingAgentID, GroupID, RoleID)) + // return; + + // check permissions + bool limited = HasPower(RequestingAgentID, GroupID, GroupPowers.AssignMemberLimited); + bool unlimited = HasPower(RequestingAgentID, GroupID, GroupPowers.AssignMember) | IsOwner(RequestingAgentID, GroupID); + if (!limited || !unlimited) + { + m_log.DebugFormat("[Groups]: ({0}) Attempt at assigning {1} to role {2} denied because of lack of permission", RequestingAgentID, AgentID, RoleID); + return false; + } + + // AssignMemberLimited means that the person can assign another person to the same roles that she has in the group + if (!unlimited && limited) + { + // check whether person's has this role + RoleMembershipData rolemembership = m_Database.RetrieveRoleMember(GroupID, RoleID, AgentID); + if (rolemembership == null) + { + m_log.DebugFormat("[Groups]: ({0}) Attempt at assigning {1} to role {2} denied because of limited permission", RequestingAgentID, AgentID, RoleID); + return false; + } + } + + _AddAgentToGroupRole(RequestingAgentID, AgentID, GroupID, RoleID); + + return true; + } + + public bool RemoveAgentFromGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID) + { + // Don't remove from Everyone role! + if (RoleID == UUID.Zero) + return false; + + // check permissions + bool unlimited = HasPower(RequestingAgentID, GroupID, GroupPowers.AssignMember) || IsOwner(RequestingAgentID, GroupID); + if (!unlimited) + { + m_log.DebugFormat("[Groups]: ({0}) Attempt at removing {1} from role {2} denied because of lack of permission", RequestingAgentID, AgentID, RoleID); + return false; + } + + RoleMembershipData rolemember = m_Database.RetrieveRoleMember(GroupID, RoleID, AgentID); + + if (rolemember == null) + return false; + + m_Database.DeleteRoleMember(rolemember); + + // Find another role for this person + UUID newRoleID = UUID.Zero; // Everyone + RoleMembershipData[] rdata = m_Database.RetrieveMemberRoles(GroupID, AgentID); + if (rdata != null) + foreach (RoleMembershipData r in rdata) + { + if (r.RoleID != UUID.Zero) + { + newRoleID = r.RoleID; + break; + } + } + + MembershipData member = m_Database.RetrieveMember(GroupID, AgentID); + if (member != null) + { + member.Data["SelectedRoleID"] = newRoleID.ToString(); + m_Database.StoreMember(member); + } + + return true; + } + + public List GetAgentGroupRoles(string RequestingAgentID, string AgentID, UUID GroupID) + { + List roles = new List(); + // TODO: check permissions + + RoleMembershipData[] data = m_Database.RetrieveMemberRoles(GroupID, AgentID); + if (data == null || (data != null && data.Length ==0)) + return roles; + + foreach (RoleMembershipData d in data) + { + RoleData rdata = m_Database.RetrieveRole(GroupID, d.RoleID); + if (rdata == null) // hippos + continue; + + GroupRolesData r = new GroupRolesData(); + r.Name = rdata.Data["Name"]; + r.Powers = UInt64.Parse(rdata.Data["Powers"]); + r.RoleID = rdata.RoleID; + r.Title = rdata.Data["Title"]; + + roles.Add(r); + } + + return roles; + } + + public ExtendedGroupMembershipData SetAgentActiveGroup(string RequestingAgentID, string AgentID, UUID GroupID) + { + // TODO: check perms + PrincipalData principal = new PrincipalData(); + principal.PrincipalID = AgentID; + principal.ActiveGroupID = GroupID; + m_Database.StorePrincipal(principal); + + return GetAgentGroupMembership(RequestingAgentID, AgentID, GroupID); + } + + public ExtendedGroupMembershipData GetAgentActiveMembership(string RequestingAgentID, string AgentID) + { + // 1. get the principal data for the active group + PrincipalData principal = m_Database.RetrievePrincipal(AgentID); + if (principal == null) + return null; + + return GetAgentGroupMembership(RequestingAgentID, AgentID, principal.ActiveGroupID); + } + + public ExtendedGroupMembershipData GetAgentGroupMembership(string RequestingAgentID, string AgentID, UUID GroupID) + { + return GetAgentGroupMembership(RequestingAgentID, AgentID, GroupID, null); + } + + private ExtendedGroupMembershipData GetAgentGroupMembership(string RequestingAgentID, string AgentID, UUID GroupID, MembershipData membership) + { + // 2. get the active group + GroupData group = m_Database.RetrieveGroup(GroupID); + if (group == null) + return null; + + // 3. get the membership info if we don't have it already + if (membership == null) + { + membership = m_Database.RetrieveMember(group.GroupID, AgentID); + if (membership == null) + return null; + } + + // 4. get the active role + UUID activeRoleID = new UUID(membership.Data["SelectedRoleID"]); + RoleData role = m_Database.RetrieveRole(group.GroupID, activeRoleID); + + ExtendedGroupMembershipData data = new ExtendedGroupMembershipData(); + data.AcceptNotices = membership.Data["AcceptNotices"] == "1" ? true : false; + data.AccessToken = membership.Data["AccessToken"]; + data.Active = true; + data.ActiveRole = activeRoleID; + data.AllowPublish = group.Data["AllowPublish"] == "1" ? true : false; + data.Charter = group.Data["Charter"]; + data.Contribution = Int32.Parse(membership.Data["Contribution"]); + data.FounderID = new UUID(group.Data["FounderID"]); + data.GroupID = new UUID(group.GroupID); + data.GroupName = group.Data["Name"]; + data.GroupPicture = new UUID(group.Data["InsigniaID"]); + if (role != null) + { + data.GroupPowers = UInt64.Parse(role.Data["Powers"]); + data.GroupTitle = role.Data["Title"]; + } + data.ListInProfile = membership.Data["ListInProfile"] == "1" ? true : false; + data.MaturePublish = group.Data["MaturePublish"] == "1" ? true : false; + data.MembershipFee = Int32.Parse(group.Data["MembershipFee"]); + data.OpenEnrollment = group.Data["OpenEnrollment"] == "1" ? true : false; + data.ShowInList = group.Data["ShowInList"] == "1" ? true : false; + + return data; + } + + public List GetAgentGroupMemberships(string RequestingAgentID, string AgentID) + { + List memberships = new List(); + + // 1. Get all the groups that this person is a member of + MembershipData[] mdata = m_Database.RetrieveMemberships(AgentID); + + if (mdata == null || (mdata != null && mdata.Length == 0)) + return memberships; + + foreach (MembershipData d in mdata) + { + GroupMembershipData gmember = GetAgentGroupMembership(RequestingAgentID, AgentID, d.GroupID, d); + if (gmember != null) + { + memberships.Add(gmember); + //m_log.DebugFormat("[XXX]: Member of {0} as {1}", gmember.GroupName, gmember.GroupTitle); + //Util.PrintCallStack(); + } + } + + return memberships; + } + + public void SetAgentActiveGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID) + { + MembershipData data = m_Database.RetrieveMember(GroupID, AgentID); + if (data == null) + return; + + data.Data["SelectedRoleID"] = RoleID.ToString(); + m_Database.StoreMember(data); + } + + public void UpdateMembership(string RequestingAgentID, string AgentID, UUID GroupID, bool AcceptNotices, bool ListInProfile) + { + // TODO: check perms + + MembershipData membership = m_Database.RetrieveMember(GroupID, AgentID); + if (membership == null) + return; + + membership.Data["AcceptNotices"] = AcceptNotices ? "1" : "0"; + membership.Data["ListInProfile"] = ListInProfile ? "1" : "0"; + + m_Database.StoreMember(membership); + } + + public bool AddGroupNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message, + bool hasAttachment, byte attType, string attName, UUID attItemID, string attOwnerID) + { + // Check perms + if (!HasPower(RequestingAgentID, groupID, GroupPowers.SendNotices)) + { + m_log.DebugFormat("[Groups]: ({0}) Attempt at sending notice to group {1} denied because of lack of permission", RequestingAgentID, groupID); + return false; + } + + return _AddNotice(groupID, noticeID, fromName, subject, message, hasAttachment, attType, attName, attItemID, attOwnerID); + } + + public GroupNoticeInfo GetGroupNotice(string RequestingAgentID, UUID noticeID) + { + NoticeData data = m_Database.RetrieveNotice(noticeID); + + if (data == null) + return null; + + return _NoticeDataToInfo(data); + } + + public List GetGroupNotices(string RequestingAgentID, UUID groupID) + { + NoticeData[] data = m_Database.RetrieveNotices(groupID); + List infos = new List(); + + if (data == null || (data != null && data.Length == 0)) + return infos; + + foreach (NoticeData d in data) + { + ExtendedGroupNoticeData info = _NoticeDataToData(d); + infos.Add(info); + } + + return infos; + } + + public void ResetAgentGroupChatSessions(string agentID) + { + } + + public bool hasAgentBeenInvitedToGroupChatSession(string agentID, UUID groupID) + { + return false; + } + + public bool hasAgentDroppedGroupChatSession(string agentID, UUID groupID) + { + return false; + } + + public void AgentDroppedFromGroupChatSession(string agentID, UUID groupID) + { + } + + public void AgentInvitedToGroupChatSession(string agentID, UUID groupID) + { + } + + #region Actions without permission checks + + private void _AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID) + { + _AddAgentToGroup(RequestingAgentID, AgentID, GroupID, RoleID, string.Empty); + } + + public void _RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID) + { + // 1. Delete membership + m_Database.DeleteMember(GroupID, AgentID); + + // 2. Remove from rolememberships + m_Database.DeleteMemberAllRoles(GroupID, AgentID); + + // 3. if it was active group, inactivate it + PrincipalData principal = m_Database.RetrievePrincipal(AgentID); + if (principal != null && principal.ActiveGroupID == GroupID) + { + principal.ActiveGroupID = UUID.Zero; + m_Database.StorePrincipal(principal); + } + } + + protected void _AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID, string accessToken) + { + // Check if it's already there + MembershipData data = m_Database.RetrieveMember(GroupID, AgentID); + if (data != null) + return; + + // Add the membership + data = new MembershipData(); + data.PrincipalID = AgentID; + data.GroupID = GroupID; + data.Data = new Dictionary(); + data.Data["SelectedRoleID"] = RoleID.ToString(); + data.Data["Contribution"] = "0"; + data.Data["ListInProfile"] = "1"; + data.Data["AcceptNotices"] = "1"; + data.Data["AccessToken"] = accessToken; + + m_Database.StoreMember(data); + + // Add principal to everyone role + _AddAgentToGroupRole(RequestingAgentID, AgentID, GroupID, UUID.Zero); + + // Add principal to role, if different from everyone role + if (RoleID != UUID.Zero) + _AddAgentToGroupRole(RequestingAgentID, AgentID, GroupID, RoleID); + + // Make thit this active group + PrincipalData pdata = new PrincipalData(); + pdata.PrincipalID = AgentID; + pdata.ActiveGroupID = GroupID; + m_Database.StorePrincipal(pdata); + + } + + private bool _AddOrUpdateGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers, bool add) + { + RoleData data = m_Database.RetrieveRole(groupID, roleID); + + if (add && data != null) // it already exists, can't create + return false; + + if (!add && data == null) // it deosn't exist, can't update + return false; + + if (add) + data = new RoleData(); + + data.GroupID = groupID; + data.RoleID = roleID; + data.Data = new Dictionary(); + data.Data["Name"] = name; + data.Data["Description"] = description; + data.Data["Title"] = title; + data.Data["Powers"] = powers.ToString(); + + return m_Database.StoreRole(data); + } + + private void _RemoveGroupRole(UUID groupID, UUID roleID) + { + m_Database.DeleteRole(groupID, roleID); + } + + private void _AddAgentToGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID) + { + RoleMembershipData data = m_Database.RetrieveRoleMember(GroupID, RoleID, AgentID); + if (data != null) + return; + + data = new RoleMembershipData(); + data.GroupID = GroupID; + data.PrincipalID = AgentID; + data.RoleID = RoleID; + m_Database.StoreRoleMember(data); + + // Make it the SelectedRoleID + MembershipData membership = m_Database.RetrieveMember(GroupID, AgentID); + if (membership == null) + { + m_log.DebugFormat("[Groups]: ({0}) No such member {0} in group {1}", AgentID, GroupID); + return; + } + + membership.Data["SelectedRoleID"] = RoleID.ToString(); + m_Database.StoreMember(membership); + + } + + private List _GetGroupRoles(UUID groupID) + { + List roles = new List(); + + RoleData[] data = m_Database.RetrieveRoles(groupID); + + if (data == null || (data != null && data.Length == 0)) + return roles; + + foreach (RoleData d in data) + { + GroupRolesData r = new GroupRolesData(); + r.Description = d.Data["Description"]; + r.Members = m_Database.RoleMemberCount(groupID, d.RoleID); + r.Name = d.Data["Name"]; + r.Powers = UInt64.Parse(d.Data["Powers"]); + r.RoleID = d.RoleID; + r.Title = d.Data["Title"]; + + roles.Add(r); + } + + return roles; + } + + private List _GetGroupRoleMembers(UUID GroupID, bool isInGroup) + { + List rmembers = new List(); + + RoleData[] rdata = new RoleData[0]; + if (!isInGroup) + { + rdata = m_Database.RetrieveRoles(GroupID); + if (rdata == null || (rdata != null && rdata.Length == 0)) + return rmembers; + } + List rlist = new List(rdata); + if (!isInGroup) + rlist = rlist.FindAll(r => (UInt64.Parse(r.Data["Powers"]) & (ulong)GroupPowers.MemberVisible) != 0); + + RoleMembershipData[] data = m_Database.RetrieveRolesMembers(GroupID); + + if (data == null || (data != null && data.Length == 0)) + return rmembers; + + foreach (RoleMembershipData d in data) + { + if (!isInGroup) + { + RoleData rd = rlist.Find(_r => _r.RoleID == d.RoleID); // visible role + if (rd == null) + continue; + } + + ExtendedGroupRoleMembersData r = new ExtendedGroupRoleMembersData(); + r.MemberID = d.PrincipalID; + r.RoleID = d.RoleID; + + rmembers.Add(r); + } + + return rmembers; + } + + protected bool _AddNotice(UUID groupID, UUID noticeID, string fromName, string subject, string message, + bool hasAttachment, byte attType, string attName, UUID attItemID, string attOwnerID) + { + NoticeData data = new NoticeData(); + data.GroupID = groupID; + data.NoticeID = noticeID; + data.Data = new Dictionary(); + data.Data["FromName"] = fromName; + data.Data["Subject"] = subject; + data.Data["Message"] = message; + data.Data["HasAttachment"] = hasAttachment ? "1" : "0"; + if (hasAttachment) + { + data.Data["AttachmentType"] = attType.ToString(); + data.Data["AttachmentName"] = attName; + data.Data["AttachmentItemID"] = attItemID.ToString(); + data.Data["AttachmentOwnerID"] = attOwnerID; + } + data.Data["TMStamp"] = ((uint)Util.UnixTimeSinceEpoch()).ToString(); + + return m_Database.StoreNotice(data); + } + + #endregion + + #region structure translations + ExtendedGroupRecord _GroupDataToRecord(GroupData data) + { + if (data == null) + return null; + + ExtendedGroupRecord rec = new ExtendedGroupRecord(); + rec.AllowPublish = data.Data["AllowPublish"] == "1" ? true : false; + rec.Charter = data.Data["Charter"]; + rec.FounderID = new UUID(data.Data["FounderID"]); + rec.GroupID = data.GroupID; + rec.GroupName = data.Data["Name"]; + rec.GroupPicture = new UUID(data.Data["InsigniaID"]); + rec.MaturePublish = data.Data["MaturePublish"] == "1" ? true : false; + rec.MembershipFee = Int32.Parse(data.Data["MembershipFee"]); + rec.OpenEnrollment = data.Data["OpenEnrollment"] == "1" ? true : false; + rec.OwnerRoleID = new UUID(data.Data["OwnerRoleID"]); + rec.ShowInList = data.Data["ShowInList"] == "1" ? true : false; + rec.ServiceLocation = data.Data["Location"]; + rec.MemberCount = m_Database.MemberCount(data.GroupID); + rec.RoleCount = m_Database.RoleCount(data.GroupID); + + return rec; + } + + GroupNoticeInfo _NoticeDataToInfo(NoticeData data) + { + GroupNoticeInfo notice = new GroupNoticeInfo(); + notice.GroupID = data.GroupID; + notice.Message = data.Data["Message"]; + notice.noticeData = _NoticeDataToData(data); + + return notice; + } + + ExtendedGroupNoticeData _NoticeDataToData(NoticeData data) + { + ExtendedGroupNoticeData notice = new ExtendedGroupNoticeData(); + notice.FromName = data.Data["FromName"]; + notice.NoticeID = data.NoticeID; + notice.Subject = data.Data["Subject"]; + notice.Timestamp = uint.Parse((string)data.Data["TMStamp"]); + notice.HasAttachment = data.Data["HasAttachment"] == "1" ? true : false; + if (notice.HasAttachment) + { + notice.AttachmentName = data.Data["AttachmentName"]; + notice.AttachmentItemID = new UUID(data.Data["AttachmentItemID"].ToString()); + notice.AttachmentType = byte.Parse(data.Data["AttachmentType"].ToString()); + notice.AttachmentOwnerID = data.Data["AttachmentOwnerID"].ToString(); + } + + + return notice; + } + + #endregion + + #region permissions + private bool HasPower(string agentID, UUID groupID, GroupPowers power) + { + RoleMembershipData[] rmembership = m_Database.RetrieveMemberRoles(groupID, agentID); + if (rmembership == null || (rmembership != null && rmembership.Length == 0)) + return false; + + foreach (RoleMembershipData rdata in rmembership) + { + RoleData role = m_Database.RetrieveRole(groupID, rdata.RoleID); + if ( (UInt64.Parse(role.Data["Powers"]) & (ulong)power) != 0 ) + return true; + } + return false; + } + + private bool IsOwner(string agentID, UUID groupID) + { + GroupData group = m_Database.RetrieveGroup(groupID); + if (group == null) + return false; + + RoleMembershipData rmembership = m_Database.RetrieveRoleMember(groupID, new UUID(group.Data["OwnerRoleID"]), agentID); + if (rmembership == null) + return false; + + return true; + } + #endregion + + } +} diff --git a/OpenSim/Addons/Groups/Service/GroupsServiceBase.cs b/OpenSim/Addons/Groups/Service/GroupsServiceBase.cs new file mode 100644 index 0000000..2611a3d --- /dev/null +++ b/OpenSim/Addons/Groups/Service/GroupsServiceBase.cs @@ -0,0 +1,84 @@ +/* + * 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.Reflection; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Data; +using OpenSim.Services.Interfaces; +using OpenSim.Services.Base; + +namespace OpenSim.Groups +{ + public class GroupsServiceBase : ServiceBase + { + protected IGroupsData m_Database = null; + + public GroupsServiceBase(IConfigSource config, string cName) + : base(config) + { + string dllName = String.Empty; + string connString = String.Empty; + string realm = "os_groups"; + string configName = (cName == string.Empty) ? "Groups" : cName; + + // + // Try reading the [DatabaseService] section, if it exists + // + IConfig dbConfig = config.Configs["DatabaseService"]; + if (dbConfig != null) + { + if (dllName == String.Empty) + dllName = dbConfig.GetString("StorageProvider", String.Empty); + if (connString == String.Empty) + connString = dbConfig.GetString("ConnectionString", String.Empty); + } + + // + // [Groups] section overrides [DatabaseService], if it exists + // + IConfig groupsConfig = config.Configs[configName]; + if (groupsConfig != null) + { + dllName = groupsConfig.GetString("StorageProvider", dllName); + connString = groupsConfig.GetString("ConnectionString", connString); + realm = groupsConfig.GetString("Realm", realm); + } + + // + // We tried, but this doesn't exist. We can't proceed. + // + if (dllName.Equals(String.Empty)) + throw new Exception("No StorageProvider configured"); + + m_Database = LoadPlugin(dllName, new Object[] { connString, realm }); + if (m_Database == null) + throw new Exception("Could not find a storage interface in the given module " + dllName); + } + } +} \ No newline at end of file diff --git a/OpenSim/Addons/Groups/Service/HGGroupsService.cs b/OpenSim/Addons/Groups/Service/HGGroupsService.cs new file mode 100644 index 0000000..9d7961c --- /dev/null +++ b/OpenSim/Addons/Groups/Service/HGGroupsService.cs @@ -0,0 +1,353 @@ +/* + * 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.Reflection; +using System.Timers; +using log4net; +using Nini.Config; + +using OpenMetaverse; +using OpenSim.Data; +using OpenSim.Framework; +using OpenSim.Services.Interfaces; + +namespace OpenSim.Groups +{ + public class HGGroupsService : GroupsService + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private IOfflineIMService m_OfflineIM; + private IUserAccountService m_UserAccounts; + private string m_HomeURI; + + public HGGroupsService(IConfigSource config, IOfflineIMService im, IUserAccountService users, string homeURI) + : base(config, string.Empty) + { + m_OfflineIM = im; + m_UserAccounts = users; + m_HomeURI = homeURI; + if (!m_HomeURI.EndsWith("/")) + m_HomeURI += "/"; + } + + + #region HG specific operations + + public bool CreateGroupProxy(string RequestingAgentID, string agentID, string accessToken, UUID groupID, string serviceLocation, string name, out string reason) + { + reason = string.Empty; + Uri uri = null; + try + { + uri = new Uri(serviceLocation); + } + catch (UriFormatException) + { + reason = "Bad location for group proxy"; + return false; + } + + // Check if it already exists + GroupData grec = m_Database.RetrieveGroup(groupID); + if (grec == null || + (grec != null && grec.Data["Location"] != string.Empty && grec.Data["Location"].ToLower() != serviceLocation.ToLower())) + { + // Create the group + grec = new GroupData(); + grec.GroupID = groupID; + grec.Data = new Dictionary(); + grec.Data["Name"] = name + " @ " + uri.Authority; + grec.Data["Location"] = serviceLocation; + grec.Data["Charter"] = string.Empty; + grec.Data["InsigniaID"] = UUID.Zero.ToString(); + grec.Data["FounderID"] = UUID.Zero.ToString(); + grec.Data["MembershipFee"] = "0"; + grec.Data["OpenEnrollment"] = "0"; + grec.Data["ShowInList"] = "0"; + grec.Data["AllowPublish"] = "0"; + grec.Data["MaturePublish"] = "0"; + grec.Data["OwnerRoleID"] = UUID.Zero.ToString(); + + + if (!m_Database.StoreGroup(grec)) + return false; + } + + if (grec.Data["Location"] == string.Empty) + { + reason = "Cannot add proxy membership to non-proxy group"; + return false; + } + + UUID uid = UUID.Zero; + string url = string.Empty, first = string.Empty, last = string.Empty, tmp = string.Empty; + Util.ParseUniversalUserIdentifier(RequestingAgentID, out uid, out url, out first, out last, out tmp); + string fromName = first + "." + last + "@" + url; + + // Invite to group again + InviteToGroup(fromName, groupID, new UUID(agentID), grec.Data["Name"]); + + // Stick the proxy membership in the DB already + // we'll delete it if the agent declines the invitation + MembershipData membership = new MembershipData(); + membership.PrincipalID = agentID; + membership.GroupID = groupID; + membership.Data = new Dictionary(); + membership.Data["SelectedRoleID"] = UUID.Zero.ToString(); + membership.Data["Contribution"] = "0"; + membership.Data["ListInProfile"] = "1"; + membership.Data["AcceptNotices"] = "1"; + membership.Data["AccessToken"] = accessToken; + + m_Database.StoreMember(membership); + + return true; + } + + public void RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID, string token) + { + // check the token + MembershipData membership = m_Database.RetrieveMember(GroupID, AgentID); + if (membership != null) + { + if (token != string.Empty && token.Equals(membership.Data["AccessToken"])) + RemoveAgentFromGroup(RequestingAgentID, AgentID, GroupID); + else + m_log.DebugFormat("[Groups.HGGroupsService]: access token {0} did not match stored one {1}", token, membership.Data["AccessToken"]); + } + else + m_log.DebugFormat("[Groups.HGGroupsService]: membership not found for {0}", AgentID); + } + + public ExtendedGroupRecord GetGroupRecord(string RequestingAgentID, UUID GroupID, string groupName, string token) + { + // check the token + if (!VerifyToken(GroupID, RequestingAgentID, token)) + return null; + + ExtendedGroupRecord grec; + if (GroupID == UUID.Zero) + grec = GetGroupRecord(RequestingAgentID, groupName); + else + grec = GetGroupRecord(RequestingAgentID, GroupID); + + if (grec != null) + FillFounderUUI(grec); + + return grec; + } + + public List GetGroupMembers(string RequestingAgentID, UUID GroupID, string token) + { + if (!VerifyToken(GroupID, RequestingAgentID, token)) + return new List(); + + List members = GetGroupMembers(RequestingAgentID, GroupID); + + // convert UUIDs to UUIs + members.ForEach(delegate (ExtendedGroupMembersData m) + { + if (m.AgentID.ToString().Length == 36) // UUID + { + UserAccount account = m_UserAccounts.GetUserAccount(UUID.Zero, new UUID(m.AgentID)); + if (account != null) + m.AgentID = Util.UniversalIdentifier(account.PrincipalID, account.FirstName, account.LastName, m_HomeURI); + } + }); + + return members; + } + + public List GetGroupRoles(string RequestingAgentID, UUID GroupID, string token) + { + if (!VerifyToken(GroupID, RequestingAgentID, token)) + return new List(); + + return GetGroupRoles(RequestingAgentID, GroupID); + } + + public List GetGroupRoleMembers(string RequestingAgentID, UUID GroupID, string token) + { + if (!VerifyToken(GroupID, RequestingAgentID, token)) + return new List(); + + List rolemembers = GetGroupRoleMembers(RequestingAgentID, GroupID); + + // convert UUIDs to UUIs + rolemembers.ForEach(delegate(ExtendedGroupRoleMembersData m) + { + if (m.MemberID.ToString().Length == 36) // UUID + { + UserAccount account = m_UserAccounts.GetUserAccount(UUID.Zero, new UUID(m.MemberID)); + if (account != null) + m.MemberID = Util.UniversalIdentifier(account.PrincipalID, account.FirstName, account.LastName, m_HomeURI); + } + }); + + return rolemembers; + } + + public bool AddNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message, + bool hasAttachment, byte attType, string attName, UUID attItemID, string attOwnerID) + { + // check that the group proxy exists + ExtendedGroupRecord grec = GetGroupRecord(RequestingAgentID, groupID); + if (grec == null) + { + m_log.DebugFormat("[Groups.HGGroupsService]: attempt at adding notice to non-existent group proxy"); + return false; + } + + // check that the group is remote + if (grec.ServiceLocation == string.Empty) + { + m_log.DebugFormat("[Groups.HGGroupsService]: attempt at adding notice to local (non-proxy) group"); + return false; + } + + // check that there isn't already a notice with the same ID + if (GetGroupNotice(RequestingAgentID, noticeID) != null) + { + m_log.DebugFormat("[Groups.HGGroupsService]: a notice with the same ID already exists", grec.ServiceLocation); + return false; + } + + // This has good intentions (security) but it will potentially DDS the origin... + // We'll need to send a proof along with the message. Maybe encrypt the message + // using key pairs + // + //// check that the notice actually exists in the origin + //GroupsServiceHGConnector c = new GroupsServiceHGConnector(grec.ServiceLocation); + //if (!c.VerifyNotice(noticeID, groupID)) + //{ + // m_log.DebugFormat("[Groups.HGGroupsService]: notice does not exist at origin {0}", grec.ServiceLocation); + // return false; + //} + + // ok, we're good! + return _AddNotice(groupID, noticeID, fromName, subject, message, hasAttachment, attType, attName, attItemID, attOwnerID); + } + + public bool VerifyNotice(UUID noticeID, UUID groupID) + { + GroupNoticeInfo notice = GetGroupNotice(string.Empty, noticeID); + + if (notice == null) + return false; + + if (notice.GroupID != groupID) + return false; + + return true; + } + + #endregion + + private void InviteToGroup(string fromName, UUID groupID, UUID invitedAgentID, string groupName) + { + // Todo: Security check, probably also want to send some kind of notification + UUID InviteID = UUID.Random(); + + if (AddAgentToGroupInvite(InviteID, groupID, invitedAgentID.ToString())) + { + Guid inviteUUID = InviteID.Guid; + + GridInstantMessage msg = new GridInstantMessage(); + + msg.imSessionID = inviteUUID; + + // msg.fromAgentID = agentID.Guid; + msg.fromAgentID = groupID.Guid; + msg.toAgentID = invitedAgentID.Guid; + //msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); + msg.timestamp = 0; + msg.fromAgentName = fromName; + msg.message = string.Format("Please confirm your acceptance to join group {0}.", groupName); + msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.GroupInvitation; + msg.fromGroup = true; + msg.offline = (byte)0; + msg.ParentEstateID = 0; + msg.Position = Vector3.Zero; + msg.RegionID = UUID.Zero.Guid; + msg.binaryBucket = new byte[20]; + + string reason = string.Empty; + m_OfflineIM.StoreMessage(msg, out reason); + + } + } + + private bool AddAgentToGroupInvite(UUID inviteID, UUID groupID, string agentID) + { + // Check whether the invitee is already a member of the group + MembershipData m = m_Database.RetrieveMember(groupID, agentID); + if (m != null) + return false; + + // Check whether there are pending invitations and delete them + InvitationData invite = m_Database.RetrieveInvitation(groupID, agentID); + if (invite != null) + m_Database.DeleteInvite(invite.InviteID); + + invite = new InvitationData(); + invite.InviteID = inviteID; + invite.PrincipalID = agentID; + invite.GroupID = groupID; + invite.RoleID = UUID.Zero; + invite.Data = new Dictionary(); + + return m_Database.StoreInvitation(invite); + } + + private void FillFounderUUI(ExtendedGroupRecord grec) + { + UserAccount account = m_UserAccounts.GetUserAccount(UUID.Zero, grec.FounderID); + if (account != null) + grec.FounderUUI = Util.UniversalIdentifier(account.PrincipalID, account.FirstName, account.LastName, m_HomeURI); + } + + private bool VerifyToken(UUID groupID, string agentID, string token) + { + // check the token + MembershipData membership = m_Database.RetrieveMember(groupID, agentID); + if (membership != null) + { + if (token != string.Empty && token.Equals(membership.Data["AccessToken"])) + return true; + else + m_log.DebugFormat("[Groups.HGGroupsService]: access token {0} did not match stored one {1}", token, membership.Data["AccessToken"]); + } + else + m_log.DebugFormat("[Groups.HGGroupsService]: membership not found for {0}", agentID); + + return false; + } + } +} -- cgit v1.1 From 66bc526e4c52be5985eef648d27cc2c9edca8d34 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Tue, 19 Feb 2013 17:04:21 -0800 Subject: Updated AssemblyInfo.cs for Groups and OfflineIM to 0.7.6.*. Removed AssemblyFileVersionNumber too. --- OpenSim/Addons/Groups/Properties/AssemblyInfo.cs | 3 +-- OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs b/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs index 166803f..5ccd7fe 100644 --- a/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs +++ b/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs @@ -30,8 +30,7 @@ using Mono.Addins; // Build Number // Revision // -[assembly: AssemblyVersion("0.7.5.*")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("0.7.6.*")] [assembly: Addin("OpenSim.Groups", "0.1")] [assembly: AddinDependency("OpenSim", "0.5")] diff --git a/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs b/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs index 31667eb..ffe8a3e 100644 --- a/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs +++ b/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs @@ -30,8 +30,7 @@ using Mono.Addins; // Build Number // Revision // -[assembly: AssemblyVersion("0.7.5.*")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("0.7.6.*")] [assembly: Addin("OpenSim.OfflineIM", "0.1")] [assembly: AddinDependency("OpenSim", "0.5")] -- cgit v1.1 From e515cdddec435e97e9ed4722de08ee410e94a7e6 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Thu, 21 Feb 2013 17:26:19 -0800 Subject: Simplification of HG configs: HomeURI and GatekeeperURI now are defined as default under [Startup]. They can then be overwritten in the other sections (but probably shouldn't). I kept the existing code for backwards compatibility, so this should not cause any breaks from people's current configurations. But people should move to have these 2 vars under [Startup] -- see OpenSim.ini.example and Robust.HG.ini.example. And yes, both names now end with "URI" for consistency. --- OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs b/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs index 92dd85c..0e71c72 100644 --- a/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs +++ b/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs @@ -65,14 +65,14 @@ namespace OpenSim.Groups m_log.DebugFormat("[Groups.RobustHGConnector]: Starting with config name {0}", m_ConfigName); + string homeURI = Util.GetConfigVarWithDefaultSection(config, "HomeURI", m_ConfigName); //cnf.GetString("HomeURI", string.Empty); + if (homeURI == string.Empty) + throw new Exception(String.Format("[Groups.RobustHGConnector]: please provide the HomeURI [Startup] or in section {0}", m_ConfigName)); + IConfig cnf = config.Configs[m_ConfigName]; if (cnf == null) throw new Exception(String.Format("[Groups.RobustHGConnector]: {0} section does not exist", m_ConfigName)); - string homeURI = cnf.GetString("HomeURI", string.Empty); - if (homeURI == string.Empty) - throw new Exception(String.Format("[Groups.RobustHGConnector]: please provide the HomeURI in section {0}", m_ConfigName)); - if (im == null) { string imDll = cnf.GetString("OfflineIMService", string.Empty); -- cgit v1.1 From 0e8289cd002b1947e172d1bfc77fdd0b16d92ffb Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 22 Feb 2013 15:57:33 -0800 Subject: Added new Util function for reading config vars that's more generic than the one I added yesterday -- this is for helping move config vars out of [Startup] --- OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs b/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs index 0e71c72..7cc9ff4 100644 --- a/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs +++ b/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs @@ -65,7 +65,7 @@ namespace OpenSim.Groups m_log.DebugFormat("[Groups.RobustHGConnector]: Starting with config name {0}", m_ConfigName); - string homeURI = Util.GetConfigVarWithDefaultSection(config, "HomeURI", m_ConfigName); //cnf.GetString("HomeURI", string.Empty); + string homeURI = Util.GetConfigVarFromSections(config, "HomeURI", new string[] { "Startup", m_ConfigName} ); //cnf.GetString("HomeURI", string.Empty); if (homeURI == string.Empty) throw new Exception(String.Format("[Groups.RobustHGConnector]: please provide the HomeURI [Startup] or in section {0}", m_ConfigName)); -- cgit v1.1 From f7aa018a783d2e04cdba6d23b9012695f1554061 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Mon, 25 Feb 2013 10:24:28 -0800 Subject: Fixes mantis #6551 -- misspelled key name. Also fixed an issue with the roles cache. --- .../Addons/Groups/Remote/GroupsServiceRemoteConnectorModule.cs | 2 +- OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs | 2 +- OpenSim/Addons/Groups/RemoteConnectorCacheWrapper.cs | 9 ++++++++- OpenSim/Addons/Groups/Service/GroupsService.cs | 6 ++++++ 4 files changed, 16 insertions(+), 3 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnectorModule.cs b/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnectorModule.cs index d1c02db..628ce4d 100644 --- a/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnectorModule.cs +++ b/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnectorModule.cs @@ -273,7 +273,7 @@ namespace OpenSim.Groups public bool AddGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers, out string reason) { string r = string.Empty; - bool success = m_CacheWrapper.AddGroupRole(roleID, description, name, powers, title, delegate + bool success = m_CacheWrapper.AddGroupRole(groupID, roleID, description, name, powers, title, delegate { return m_GroupsService.AddGroupRole(RequestingAgentID, groupID, roleID, name, description, title, powers, out r); }); diff --git a/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs b/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs index 8c257ed..f991d01 100644 --- a/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs +++ b/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs @@ -371,7 +371,7 @@ namespace OpenSim.Groups Dictionary result = new Dictionary(); if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID") || !request.ContainsKey("RoleID") || - !request.ContainsKey("Name") || !request.ContainsKey("Descrption") || !request.ContainsKey("Title") || + !request.ContainsKey("Name") || !request.ContainsKey("Description") || !request.ContainsKey("Title") || !request.ContainsKey("Powers") || !request.ContainsKey("OP")) NullResult(result, "Bad network data"); diff --git a/OpenSim/Addons/Groups/RemoteConnectorCacheWrapper.cs b/OpenSim/Addons/Groups/RemoteConnectorCacheWrapper.cs index f789626..e7d38c2 100644 --- a/OpenSim/Addons/Groups/RemoteConnectorCacheWrapper.cs +++ b/OpenSim/Addons/Groups/RemoteConnectorCacheWrapper.cs @@ -393,7 +393,7 @@ namespace OpenSim.Groups } } - public bool AddGroupRole(UUID roleID, string description, string name, ulong powers, string title, BooleanDelegate d) + public bool AddGroupRole(UUID groupID, UUID roleID, string description, string name, ulong powers, string title, BooleanDelegate d) { if (d()) { @@ -406,8 +406,15 @@ namespace OpenSim.Groups role.Title = title; lock (m_Cache) + { m_Cache.AddOrUpdate("role-" + roleID.ToString(), role, GROUPS_CACHE_TIMEOUT); + // also remove this list + if (m_Cache.Contains("roles-" + groupID.ToString())) + m_Cache.Remove("roles-" + groupID.ToString()); + + } + return true; } diff --git a/OpenSim/Addons/Groups/Service/GroupsService.cs b/OpenSim/Addons/Groups/Service/GroupsService.cs index fc567dd..0668870 100644 --- a/OpenSim/Addons/Groups/Service/GroupsService.cs +++ b/OpenSim/Addons/Groups/Service/GroupsService.cs @@ -785,10 +785,16 @@ namespace OpenSim.Groups RoleData data = m_Database.RetrieveRole(groupID, roleID); if (add && data != null) // it already exists, can't create + { + m_log.DebugFormat("[Groups]: Group {0} already exists. Can't create it again", groupID); return false; + } if (!add && data == null) // it deosn't exist, can't update + { + m_log.DebugFormat("[Groups]: Group {0} doesn't exist. Can't update it", groupID); return false; + } if (add) data = new RoleData(); -- cgit v1.1 From 00da59ae52e2a7f205376e7cc2e450e94e13754b Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Mon, 25 Feb 2013 16:27:41 -0800 Subject: Mantis #6552 -- stricter error (crash) if server URL is malformed. --- OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnectorModule.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnectorModule.cs b/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnectorModule.cs index 628ce4d..f1cf66c 100644 --- a/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnectorModule.cs +++ b/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnectorModule.cs @@ -74,11 +74,8 @@ namespace OpenSim.Groups { IConfig groupsConfig = config.Configs["Groups"]; string url = groupsConfig.GetString("GroupsServerURI", string.Empty); - if (url == string.Empty) - { - m_log.WarnFormat("[Groups.RemoteConnector]: Groups server URL not provided. Groups will not work."); - return; - } + if (!Uri.IsWellFormedUriString(url, UriKind.Absolute)) + throw new Exception(string.Format("[Groups.RemoteConnector]: Malformed groups server URL {0}. Fix it or disable the Groups feature.", url)); m_GroupsService = new GroupsServiceRemoteConnector(url); m_Scenes = new List(); -- cgit v1.1 From f1010d7b152b68e2961b40482006221e28e976af Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Wed, 27 Feb 2013 20:49:41 -0800 Subject: Moved the HG default variables out of [Startup] and into their own section [Hypergrid] in *Common.ini.example. Backwards compatible for now. --- OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs b/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs index 7cc9ff4..9dc03e2 100644 --- a/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs +++ b/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs @@ -65,7 +65,7 @@ namespace OpenSim.Groups m_log.DebugFormat("[Groups.RobustHGConnector]: Starting with config name {0}", m_ConfigName); - string homeURI = Util.GetConfigVarFromSections(config, "HomeURI", new string[] { "Startup", m_ConfigName} ); //cnf.GetString("HomeURI", string.Empty); + string homeURI = Util.GetConfigVarFromSections(config, "HomeURI", new string[] { "Startup", "Hypergrid", m_ConfigName} ); //cnf.GetString("HomeURI", string.Empty); if (homeURI == string.Empty) throw new Exception(String.Format("[Groups.RobustHGConnector]: please provide the HomeURI [Startup] or in section {0}", m_ConfigName)); -- cgit v1.1 From bb447581795cb622e88a071d3050370c64ace946 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Wed, 27 Feb 2013 20:59:16 -0800 Subject: Switched to using the other Util function with a default value. --- OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs b/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs index 9dc03e2..3584f78 100644 --- a/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs +++ b/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs @@ -65,7 +65,8 @@ namespace OpenSim.Groups m_log.DebugFormat("[Groups.RobustHGConnector]: Starting with config name {0}", m_ConfigName); - string homeURI = Util.GetConfigVarFromSections(config, "HomeURI", new string[] { "Startup", "Hypergrid", m_ConfigName} ); //cnf.GetString("HomeURI", string.Empty); + string homeURI = Util.GetConfigVarFromSections(config, "HomeURI", + new string[] { "Startup", "Hypergrid", m_ConfigName}, string.Empty); if (homeURI == string.Empty) throw new Exception(String.Format("[Groups.RobustHGConnector]: please provide the HomeURI [Startup] or in section {0}", m_ConfigName)); -- cgit v1.1 From 0e162511cf0e2b507a94ad91a5e36be76eda18ef Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Thu, 25 Apr 2013 17:01:57 -0700 Subject: Groups: make some methods protected. --- OpenSim/Addons/Groups/Service/GroupsService.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/Service/GroupsService.cs b/OpenSim/Addons/Groups/Service/GroupsService.cs index 0668870..6a4348b 100644 --- a/OpenSim/Addons/Groups/Service/GroupsService.cs +++ b/OpenSim/Addons/Groups/Service/GroupsService.cs @@ -723,12 +723,12 @@ namespace OpenSim.Groups #region Actions without permission checks - private void _AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID) + protected void _AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID) { _AddAgentToGroup(RequestingAgentID, AgentID, GroupID, RoleID, string.Empty); } - public void _RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID) + protected void _RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID) { // 1. Delete membership m_Database.DeleteMember(GroupID, AgentID); @@ -780,7 +780,7 @@ namespace OpenSim.Groups } - private bool _AddOrUpdateGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers, bool add) + protected bool _AddOrUpdateGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers, bool add) { RoleData data = m_Database.RetrieveRole(groupID, roleID); @@ -810,12 +810,12 @@ namespace OpenSim.Groups return m_Database.StoreRole(data); } - private void _RemoveGroupRole(UUID groupID, UUID roleID) + protected void _RemoveGroupRole(UUID groupID, UUID roleID) { m_Database.DeleteRole(groupID, roleID); } - private void _AddAgentToGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID) + protected void _AddAgentToGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID) { RoleMembershipData data = m_Database.RetrieveRoleMember(GroupID, RoleID, AgentID); if (data != null) @@ -840,7 +840,7 @@ namespace OpenSim.Groups } - private List _GetGroupRoles(UUID groupID) + protected List _GetGroupRoles(UUID groupID) { List roles = new List(); @@ -865,7 +865,7 @@ namespace OpenSim.Groups return roles; } - private List _GetGroupRoleMembers(UUID GroupID, bool isInGroup) + protected List _GetGroupRoleMembers(UUID GroupID, bool isInGroup) { List rmembers = new List(); -- cgit v1.1 From 25fea820490603227432639dde1305957555abb2 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Mon, 13 May 2013 07:29:17 -0700 Subject: Fixes mantis #6636 -- Groups --- OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs | 1 - OpenSim/Addons/Groups/Service/GroupsService.cs | 7 +++++++ 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs b/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs index f670272..7e0b112 100644 --- a/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs +++ b/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs @@ -186,7 +186,6 @@ namespace OpenSim.Groups public UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish, UUID founderID, out string reason) { - m_log.DebugFormat("[Groups]: Creating group {0}", name); reason = string.Empty; if (m_UserManagement.IsLocalGridUser(RequestingAgentID)) return m_LocalGroupsConnector.CreateGroup(RequestingAgentID, name, charter, showInList, insigniaID, diff --git a/OpenSim/Addons/Groups/Service/GroupsService.cs b/OpenSim/Addons/Groups/Service/GroupsService.cs index 6a4348b..a2ef13a 100644 --- a/OpenSim/Addons/Groups/Service/GroupsService.cs +++ b/OpenSim/Addons/Groups/Service/GroupsService.cs @@ -130,6 +130,13 @@ namespace OpenSim.Groups { reason = string.Empty; + // Check if the group already exists + if (m_Database.RetrieveGroup(name) != null) + { + reason = "A group with that name already exists"; + return UUID.Zero; + } + // Create the group GroupData data = new GroupData(); data.GroupID = UUID.Random(); -- cgit v1.1 From af1fa958756a2c76810847a2059befa071956d09 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Mon, 13 May 2013 11:36:17 -0700 Subject: Groups: Improve error handling on remote connector. --- .../Addons/Groups/Remote/GroupsServiceRobustConnector.cs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs b/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs index f991d01..28f7acc 100644 --- a/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs +++ b/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs @@ -170,11 +170,16 @@ namespace OpenSim.Groups } - grec = m_GroupsService.GetGroupRecord(RequestingAgentID, grec.GroupID); - if (grec == null) - NullResult(result, "Internal Error"); + if (grec.GroupID != UUID.Zero) + { + grec = m_GroupsService.GetGroupRecord(RequestingAgentID, grec.GroupID); + if (grec == null) + NullResult(result, "Internal Error"); + else + result["RESULT"] = GroupsDataUtils.GroupRecord(grec); + } else - result["RESULT"] = GroupsDataUtils.GroupRecord(grec); + NullResult(result, reason); } string xmlString = ServerUtils.BuildXmlResponse(result); -- cgit v1.1 From 533bbf033df88fd231eb0e7d2b0aa5a0058163ea Mon Sep 17 00:00:00 2001 From: Melanie Date: Sat, 25 May 2013 02:08:54 +0100 Subject: Update the money framework to allow sending the new style linden "serverside is now viewerside" messages regarding currency This will require all money modules to be refactored! --- OpenSim/Addons/Groups/GroupsModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs index 10bfa8f..f805d69 100644 --- a/OpenSim/Addons/Groups/GroupsModule.cs +++ b/OpenSim/Addons/Groups/GroupsModule.cs @@ -766,7 +766,7 @@ namespace OpenSim.Groups remoteClient.SendCreateGroupReply(UUID.Zero, false, "Insufficient funds to create a group."); return UUID.Zero; } - money.ApplyCharge(remoteClient.AgentId, money.GroupCreationCharge, "Group Creation"); + money.ApplyCharge(remoteClient.AgentId, money.GroupCreationCharge, MoneyTransactionType.GroupCreate); } string reason = string.Empty; UUID groupID = m_groupData.CreateGroup(remoteClient.AgentId, name, charter, showInList, insigniaID, membershipFee, openEnrollment, -- cgit v1.1 From 664c6191edbbff2a88fccc2c9755c7fa0938dad3 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 7 Jun 2013 08:37:18 -0700 Subject: Mantis #6620 (removed debug message) --- OpenSim/Addons/Groups/GroupsModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs index f805d69..5b3b9f6 100644 --- a/OpenSim/Addons/Groups/GroupsModule.cs +++ b/OpenSim/Addons/Groups/GroupsModule.cs @@ -347,7 +347,7 @@ namespace OpenSim.Groups { if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - m_log.DebugFormat("[Groups]: IM From {0} to {1} msg {2} type {3}", im.fromAgentID, im.toAgentID, im.message, (InstantMessageDialog)im.dialog); + //m_log.DebugFormat("[Groups]: IM From {0} to {1} msg {2} type {3}", im.fromAgentID, im.toAgentID, im.message, (InstantMessageDialog)im.dialog); // Group invitations if ((im.dialog == (byte)InstantMessageDialog.GroupInvitationAccept) || (im.dialog == (byte)InstantMessageDialog.GroupInvitationDecline)) { -- cgit v1.1 From d00770d56bf00640f23f462d8ab51f851530234c Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sat, 8 Jun 2013 11:00:22 -0700 Subject: Groups V2 -- fix mantis #6666 --- OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs | 3 +++ 1 file changed, 3 insertions(+) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs b/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs index 7e0b112..cff7adf 100644 --- a/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs +++ b/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs @@ -684,6 +684,9 @@ namespace OpenSim.Groups { serviceLocation = string.Empty; name = string.Empty; + if (groupID.Equals(UUID.Zero)) + return true; + ExtendedGroupRecord group = m_LocalGroupsConnector.GetGroupRecord(UUID.Zero.ToString(), groupID, string.Empty); if (group == null) { -- cgit v1.1 From e741e5ebce7759a7ee75c638d73e17c8a5f38394 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 9 Jun 2013 20:20:37 -0700 Subject: More on mantis #6666 -- Groups V2 remote connector. --- OpenSim/Addons/Groups/RemoteConnectorCacheWrapper.cs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/RemoteConnectorCacheWrapper.cs b/OpenSim/Addons/Groups/RemoteConnectorCacheWrapper.cs index e7d38c2..79d6fc5 100644 --- a/OpenSim/Addons/Groups/RemoteConnectorCacheWrapper.cs +++ b/OpenSim/Addons/Groups/RemoteConnectorCacheWrapper.cs @@ -209,13 +209,10 @@ namespace OpenSim.Groups public void SetAgentActiveGroup(string AgentID, GroupMembershipDelegate d) { GroupMembershipData activeGroup = d(); - if (activeGroup != null) - { - string cacheKey = "active-" + AgentID.ToString(); - lock (m_Cache) - if (m_Cache.Contains(cacheKey)) - m_Cache.AddOrUpdate(cacheKey, activeGroup, GROUPS_CACHE_TIMEOUT); - } + string cacheKey = "active-" + AgentID.ToString(); + lock (m_Cache) + if (m_Cache.Contains(cacheKey)) + m_Cache.AddOrUpdate(cacheKey, activeGroup, GROUPS_CACHE_TIMEOUT); } public ExtendedGroupMembershipData GetAgentActiveMembership(string AgentID, GroupMembershipDelegate d) -- cgit v1.1 From 1a72f62d7be483cf3a0612528c2b7d7880e0ce0c Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 18 Jun 2013 23:52:15 +0100 Subject: minor: remove mono compiler warning in OfflineIMService --- OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs b/OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs index 6ba022c..6731923 100644 --- a/OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs +++ b/OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs @@ -46,7 +46,7 @@ namespace OpenSim.OfflineIM { public class OfflineIMService : OfflineIMServiceBase, IOfflineIMService { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); +// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private const int MAX_IM = 25; private XmlSerializer m_serializer; -- cgit v1.1 From e377abcc35c5fb4d47418524ae68364705995915 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 30 Jun 2013 08:39:35 -0700 Subject: Groups V2: charge for group creation only after the group has been successfully created --- OpenSim/Addons/Groups/GroupsModule.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs index 5b3b9f6..5959bac 100644 --- a/OpenSim/Addons/Groups/GroupsModule.cs +++ b/OpenSim/Addons/Groups/GroupsModule.cs @@ -766,14 +766,17 @@ namespace OpenSim.Groups remoteClient.SendCreateGroupReply(UUID.Zero, false, "Insufficient funds to create a group."); return UUID.Zero; } - money.ApplyCharge(remoteClient.AgentId, money.GroupCreationCharge, MoneyTransactionType.GroupCreate); } + string reason = string.Empty; UUID groupID = m_groupData.CreateGroup(remoteClient.AgentId, name, charter, showInList, insigniaID, membershipFee, openEnrollment, allowPublish, maturePublish, remoteClient.AgentId, out reason); if (groupID != UUID.Zero) { + if (money != null) + money.ApplyCharge(remoteClient.AgentId, money.GroupCreationCharge, MoneyTransactionType.GroupCreate); + remoteClient.SendCreateGroupReply(groupID, true, "Group created successfullly"); // Update the founder with new group information. -- cgit v1.1 From e19defde36ddbd5ff90d8304c6fe3b57110f8078 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 8 Jul 2013 22:03:07 +0100 Subject: Add "show caps stats by user" and "show caps stats by cap" console commands to print various counts of capability invocation by user and by cap This currently prints caps requests received and handled, so that overload of received compared to handled or deadlock can be detected. This involves making BaseStreamHandler and BaseOutputStream record the ints, which means inheritors should subclass ProcessRequest() instead of Handle() However, existing inheriting classes overriding Handle() will still work, albeit without stats recording. "show caps" becomes "show caps list" to disambiguate between show caps commands --- OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs | 2 +- OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs | 2 +- OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRobustConnector.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs b/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs index 3584f78..67750f5 100644 --- a/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs +++ b/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs @@ -113,7 +113,7 @@ namespace OpenSim.Groups m_GroupsService = service; } - public override byte[] Handle(string path, Stream requestData, + protected override byte[] ProcessRequest(string path, Stream requestData, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { StreamReader sr = new StreamReader(requestData); diff --git a/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs b/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs index 28f7acc..515b818 100644 --- a/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs +++ b/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs @@ -75,7 +75,7 @@ namespace OpenSim.Groups m_GroupsService = service; } - public override byte[] Handle(string path, Stream requestData, + protected override byte[] ProcessRequest(string path, Stream requestData, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { StreamReader sr = new StreamReader(requestData); diff --git a/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRobustConnector.cs b/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRobustConnector.cs index 2b3a01d..32c24db 100644 --- a/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRobustConnector.cs +++ b/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRobustConnector.cs @@ -75,7 +75,7 @@ namespace OpenSim.OfflineIM m_OfflineIMService = service; } - public override byte[] Handle(string path, Stream requestData, + protected override byte[] ProcessRequest(string path, Stream requestData, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { StreamReader sr = new StreamReader(requestData); -- cgit v1.1 From 83da14008f9a8a4ad0cf0dd5487327e4a319fd5d Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 8 Jul 2013 23:57:05 +0100 Subject: minor: remove some mono compiler warnings in new groups code --- OpenSim/Addons/Groups/GroupsModule.cs | 2 +- OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs | 1 - OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs | 2 -- OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs | 4 ---- 4 files changed, 1 insertion(+), 8 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs index 5959bac..82e2d6f 100644 --- a/OpenSim/Addons/Groups/GroupsModule.cs +++ b/OpenSim/Addons/Groups/GroupsModule.cs @@ -485,7 +485,7 @@ namespace OpenSim.Groups return; //// 16 bytes are the UUID. Maybe. - UUID folderID = new UUID(im.binaryBucket, 0); +// UUID folderID = new UUID(im.binaryBucket, 0); UUID noticeID = new UUID(im.imSessionID); GroupNoticeInfo notice = m_groupData.GetGroupNotice(remoteClient.AgentId.ToString(), noticeID); diff --git a/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs b/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs index cff7adf..c3c759e 100644 --- a/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs +++ b/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs @@ -543,7 +543,6 @@ namespace OpenSim.Groups List urls = new List(); foreach (GroupMembersData m in members) { - UUID userID = UUID.Zero; if (!m_UserManagement.IsLocalGridUser(m.AgentID)) { string gURL = m_UserManagement.GetUserServerURL(m.AgentID, "GroupsServerURI"); diff --git a/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs b/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs index 67750f5..d2bcba5 100644 --- a/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs +++ b/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs @@ -47,7 +47,6 @@ namespace OpenSim.Groups private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private HGGroupsService m_GroupsService; - private string m_HomeURI = string.Empty; private string m_ConfigName = "Groups"; // Called by Robust shell @@ -209,7 +208,6 @@ namespace OpenSim.Groups UUID groupID = new UUID(request["GroupID"].ToString()); string agentID = request["AgentID"].ToString(); string token = request["AccessToken"].ToString(); - string reason = string.Empty; m_GroupsService.RemoveAgentFromGroup(agentID, agentID, groupID, token); } diff --git a/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs b/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs index 515b818..106c6c4 100644 --- a/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs +++ b/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs @@ -269,7 +269,6 @@ namespace OpenSim.Groups UUID groupID = new UUID(request["GroupID"].ToString()); string agentID = request["AgentID"].ToString(); string requestingAgentID = request["RequestingAgentID"].ToString(); - string reason = string.Empty; m_GroupsService.RemoveAgentFromGroup(requestingAgentID, agentID, groupID); } @@ -500,7 +499,6 @@ namespace OpenSim.Groups else { string op = request["OP"].ToString(); - string reason = string.Empty; bool success = false; if (op == "ADD") @@ -568,7 +566,6 @@ namespace OpenSim.Groups else { string op = request["OP"].ToString(); - string reason = string.Empty; if (op == "GROUP") { @@ -631,7 +628,6 @@ namespace OpenSim.Groups else { string op = request["OP"].ToString(); - string reason = string.Empty; if (op == "ADD" && request.ContainsKey("GroupID") && request.ContainsKey("RoleID") && request.ContainsKey("AgentID")) { -- cgit v1.1 From 42e52f544df5210b41b96176c364d1f1d2d96b00 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Tue, 23 Jul 2013 11:29:53 -0700 Subject: Improvement of fetching name in groups --- OpenSim/Addons/Groups/GroupsModule.cs | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs index 82e2d6f..69d03a9 100644 --- a/OpenSim/Addons/Groups/GroupsModule.cs +++ b/OpenSim/Addons/Groups/GroupsModule.cs @@ -1402,19 +1402,18 @@ namespace OpenSim.Groups if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); // TODO: All the client update functions need to be reexamined because most do too much and send too much stuff - UserAccount account = m_sceneList[0].UserAccountService.GetUserAccount(remoteClient.Scene.RegionInfo.ScopeID, dataForAgentID); - string firstname, lastname; - if (account != null) - { - firstname = account.FirstName; - lastname = account.LastName; - } - else + string firstname = "Unknown", lastname = "Unknown"; + string name = m_UserManagement.GetUserName(dataForAgentID); + if (!string.IsNullOrEmpty(name)) { - firstname = "Unknown"; - lastname = "Unknown"; + string[] parts = name.Split(new char[] { ' ' }); + if (parts.Length >= 2) + { + firstname = parts[0]; + lastname = parts[1]; + } } - + remoteClient.SendAgentDataUpdate(dataForAgentID, activeGroupID, firstname, lastname, activeGroupPowers, activeGroupName, activeGroupTitle); -- cgit v1.1 From d8a6eb5641f3b16811695ff34d925ae27de8fa38 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Wed, 24 Jul 2013 11:13:31 -0700 Subject: Decreased the time of group cache to 1 min, because it was getting on my nerves that it takes so long to let go of old info. --- OpenSim/Addons/Groups/RemoteConnectorCacheWrapper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/RemoteConnectorCacheWrapper.cs b/OpenSim/Addons/Groups/RemoteConnectorCacheWrapper.cs index 79d6fc5..3ac74fc 100644 --- a/OpenSim/Addons/Groups/RemoteConnectorCacheWrapper.cs +++ b/OpenSim/Addons/Groups/RemoteConnectorCacheWrapper.cs @@ -53,7 +53,7 @@ namespace OpenSim.Groups private ForeignImporter m_ForeignImporter; private Dictionary m_ActiveRequests = new Dictionary(); - private const int GROUPS_CACHE_TIMEOUT = 5 * 60; // 5 minutes + private const int GROUPS_CACHE_TIMEOUT = 1 * 60; // 1 minutes // This all important cache cahces objects of different types: // group- or group- => ExtendedGroupRecord -- cgit v1.1 From 85428c49bb99484e15dd948ec48a285291e5a74c Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 26 Jul 2013 21:27:00 -0700 Subject: Trying to decrease the lag on group chat. (Groups V2 only) --- OpenSim/Addons/Groups/GroupsMessagingModule.cs | 40 +++++++++++++++----------- 1 file changed, 24 insertions(+), 16 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsMessagingModule.cs b/OpenSim/Addons/Groups/GroupsMessagingModule.cs index d172d48..31e9175 100644 --- a/OpenSim/Addons/Groups/GroupsMessagingModule.cs +++ b/OpenSim/Addons/Groups/GroupsMessagingModule.cs @@ -264,8 +264,32 @@ namespace OpenSim.Groups int requestStartTick = Environment.TickCount; + // Copy Message + GridInstantMessage msg = new GridInstantMessage(); + msg.imSessionID = groupID.Guid; + msg.fromAgentName = im.fromAgentName; + msg.message = im.message; + msg.dialog = im.dialog; + msg.offline = im.offline; + msg.ParentEstateID = im.ParentEstateID; + msg.Position = im.Position; + msg.RegionID = im.RegionID; + msg.binaryBucket = im.binaryBucket; + msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); + + msg.fromAgentID = im.fromAgentID; + msg.fromGroup = true; + + // Send to self first of all + msg.toAgentID = msg.fromAgentID; + ProcessMessageFromGroupSession(msg); + + // Then send to everybody else foreach (GroupMembersData member in groupMembers) { + if (member.AgentID.Guid == im.fromAgentID) + continue; + if (m_groupData.hasAgentDroppedGroupChatSession(member.AgentID.ToString(), groupID)) { // Don't deliver messages to people who have dropped this session @@ -273,22 +297,6 @@ namespace OpenSim.Groups continue; } - // Copy Message - GridInstantMessage msg = new GridInstantMessage(); - msg.imSessionID = groupID.Guid; - msg.fromAgentName = im.fromAgentName; - msg.message = im.message; - msg.dialog = im.dialog; - msg.offline = im.offline; - msg.ParentEstateID = im.ParentEstateID; - msg.Position = im.Position; - msg.RegionID = im.RegionID; - msg.binaryBucket = im.binaryBucket; - msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); - - msg.fromAgentID = im.fromAgentID; - msg.fromGroup = true; - msg.toAgentID = member.AgentID.Guid; IClientAPI client = GetActiveClient(member.AgentID); -- cgit v1.1 From 69975763d2a735eb2696d2e27e5796a472a208ea Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sat, 27 Jul 2013 15:38:56 -0700 Subject: Several major improvements to group (V2) chat. Specifically: handle join/drop appropriately, invitechatboxes. The major departure from flotsam is to send only one message per destination region, as opposed to one message per group member. This reduces messaging considerably in large groups that have clusters of members in certain regions. --- OpenSim/Addons/Groups/GroupsMessagingModule.cs | 385 +++++++++++++++------ OpenSim/Addons/Groups/GroupsModule.cs | 26 +- .../Hypergrid/GroupsServiceHGConnectorModule.cs | 22 -- OpenSim/Addons/Groups/IGroupsServicesConnector.cs | 6 - .../Local/GroupsServiceLocalConnectorModule.cs | 22 -- .../Remote/GroupsServiceRemoteConnectorModule.cs | 22 -- 6 files changed, 292 insertions(+), 191 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsMessagingModule.cs b/OpenSim/Addons/Groups/GroupsMessagingModule.cs index 31e9175..be76ef1 100644 --- a/OpenSim/Addons/Groups/GroupsMessagingModule.cs +++ b/OpenSim/Addons/Groups/GroupsMessagingModule.cs @@ -39,6 +39,7 @@ using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; using OpenSim.Services.Interfaces; using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo; +using GridRegion = OpenSim.Services.Interfaces.GridRegion; namespace OpenSim.Groups { @@ -79,6 +80,10 @@ namespace OpenSim.Groups private int m_usersOnlineCacheExpirySeconds = 20; + private Dictionary> m_groupsAgentsDroppedFromChatSession = new Dictionary>(); + private Dictionary> m_groupsAgentsInvitedToChatSession = new Dictionary>(); + + #region Region Module interfaceBase Members public void Initialise(IConfigSource config) @@ -227,62 +232,50 @@ namespace OpenSim.Groups public void SendMessageToGroup(GridInstantMessage im, UUID groupID) { - List groupMembers = m_groupData.GetGroupMembers(new UUID(im.fromAgentID).ToString(), groupID); + UUID fromAgentID = new UUID(im.fromAgentID); + List groupMembers = m_groupData.GetGroupMembers(fromAgentID.ToString(), groupID); int groupMembersCount = groupMembers.Count; + PresenceInfo[] onlineAgents = null; - if (m_messageOnlineAgentsOnly) - { - string[] t1 = groupMembers.ConvertAll(gmd => gmd.AgentID.ToString()).ToArray(); + // In V2 we always only send to online members. + // Sending to offline members is not an option. + string[] t1 = groupMembers.ConvertAll(gmd => gmd.AgentID.ToString()).ToArray(); - // We cache in order not to overwhlem the presence service on large grids with many groups. This does - // mean that members coming online will not see all group members until after m_usersOnlineCacheExpirySeconds has elapsed. - // (assuming this is the same across all grid simulators). - PresenceInfo[] onlineAgents; - if (!m_usersOnlineCache.TryGetValue(groupID, out onlineAgents)) - { - onlineAgents = m_presenceService.GetAgents(t1); - m_usersOnlineCache.Add(groupID, onlineAgents, m_usersOnlineCacheExpirySeconds); - } + // We cache in order not to overwhlem the presence service on large grids with many groups. This does + // mean that members coming online will not see all group members until after m_usersOnlineCacheExpirySeconds has elapsed. + // (assuming this is the same across all grid simulators). + if (!m_usersOnlineCache.TryGetValue(groupID, out onlineAgents)) + { + onlineAgents = m_presenceService.GetAgents(t1); + m_usersOnlineCache.Add(groupID, onlineAgents, m_usersOnlineCacheExpirySeconds); + } - HashSet onlineAgentsUuidSet = new HashSet(); - Array.ForEach(onlineAgents, pi => onlineAgentsUuidSet.Add(pi.UserID)); + HashSet onlineAgentsUuidSet = new HashSet(); + Array.ForEach(onlineAgents, pi => onlineAgentsUuidSet.Add(pi.UserID)); - groupMembers = groupMembers.Where(gmd => onlineAgentsUuidSet.Contains(gmd.AgentID.ToString())).ToList(); + groupMembers = groupMembers.Where(gmd => onlineAgentsUuidSet.Contains(gmd.AgentID.ToString())).ToList(); - // if (m_debugEnabled) +// if (m_debugEnabled) // m_log.DebugFormat( // "[Groups.Messaging]: SendMessageToGroup called for group {0} with {1} visible members, {2} online", // groupID, groupMembersCount, groupMembers.Count()); - } - else - { - if (m_debugEnabled) - m_log.DebugFormat( - "[Groups.Messaging]: SendMessageToGroup called for group {0} with {1} visible members", - groupID, groupMembers.Count); - } int requestStartTick = Environment.TickCount; - // Copy Message - GridInstantMessage msg = new GridInstantMessage(); - msg.imSessionID = groupID.Guid; - msg.fromAgentName = im.fromAgentName; - msg.message = im.message; - msg.dialog = im.dialog; - msg.offline = im.offline; - msg.ParentEstateID = im.ParentEstateID; - msg.Position = im.Position; - msg.RegionID = im.RegionID; - msg.binaryBucket = im.binaryBucket; - msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); - - msg.fromAgentID = im.fromAgentID; - msg.fromGroup = true; + im.imSessionID = groupID.Guid; + im.fromGroup = true; + IClientAPI thisClient = GetActiveClient(fromAgentID); + if (thisClient != null) + { + im.RegionID = thisClient.Scene.RegionInfo.RegionID.Guid; + } // Send to self first of all - msg.toAgentID = msg.fromAgentID; - ProcessMessageFromGroupSession(msg); + im.toAgentID = im.fromAgentID; + ProcessMessageFromGroupSession(im); + + List regions = new List(); + List clientsAlreadySent = new List(); // Then send to everybody else foreach (GroupMembersData member in groupMembers) @@ -290,27 +283,50 @@ namespace OpenSim.Groups if (member.AgentID.Guid == im.fromAgentID) continue; - if (m_groupData.hasAgentDroppedGroupChatSession(member.AgentID.ToString(), groupID)) + if (hasAgentDroppedGroupChatSession(member.AgentID.ToString(), groupID)) { // Don't deliver messages to people who have dropped this session if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: {0} has dropped session, not delivering to them", member.AgentID); continue; } - msg.toAgentID = member.AgentID.Guid; + im.toAgentID = member.AgentID.Guid; IClientAPI client = GetActiveClient(member.AgentID); if (client == null) { // If they're not local, forward across the grid + // BUT do it only once per region, please! Sim would be even better! if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Delivering to {0} via Grid", member.AgentID); - m_msgTransferModule.SendInstantMessage(msg, delegate(bool success) { }); + + bool reallySend = true; + if (onlineAgents != null) + { + PresenceInfo presence = onlineAgents.First(p => p.UserID == member.AgentID.ToString()); + if (regions.Contains(presence.RegionID)) + reallySend = false; + else + regions.Add(presence.RegionID); + } + + if (reallySend) + { + // We have to create a new IM structure because the transfer module + // uses async send + GridInstantMessage msg = new GridInstantMessage(im, true); + m_msgTransferModule.SendInstantMessage(msg, delegate(bool success) { }); + } } else { // Deliver locally, directly if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Passing to ProcessMessageFromGroupSession to deliver to {0} locally", client.Name); - ProcessMessageFromGroupSession(msg); + + if (clientsAlreadySent.Contains(member.AgentID)) + continue; + clientsAlreadySent.Add(member.AgentID); + + ProcessMessageFromGroupSession(im); } } @@ -343,21 +359,90 @@ namespace OpenSim.Groups // Any other message type will not be delivered to a client by the // Instant Message Module - + UUID regionID = new UUID(msg.RegionID); if (m_debugEnabled) { - m_log.DebugFormat("[Groups.Messaging]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + m_log.DebugFormat("[Groups.Messaging]: {0} called, IM from region {1}", + System.Reflection.MethodBase.GetCurrentMethod().Name, regionID); DebugGridInstantMessage(msg); } // Incoming message from a group - if ((msg.fromGroup == true) && - ((msg.dialog == (byte)InstantMessageDialog.SessionSend) - || (msg.dialog == (byte)InstantMessageDialog.SessionAdd) - || (msg.dialog == (byte)InstantMessageDialog.SessionDrop))) + if ((msg.fromGroup == true) && (msg.dialog == (byte)InstantMessageDialog.SessionSend)) { - ProcessMessageFromGroupSession(msg); + // We have to redistribute the message across all members of the group who are here + // on this sim + + UUID GroupID = new UUID(msg.imSessionID); + + Scene aScene = m_sceneList[0]; + GridRegion regionOfOrigin = aScene.GridService.GetRegionByUUID(aScene.RegionInfo.ScopeID, regionID); + + List groupMembers = m_groupData.GetGroupMembers(new UUID(msg.fromAgentID).ToString(), GroupID); + List alreadySeen = new List(); + + foreach (Scene s in m_sceneList) + { + s.ForEachScenePresence(sp => + { + // We need this, because we are searching through all + // SPs, both root and children + if (alreadySeen.Contains(sp.UUID)) + { + if (m_debugEnabled) + m_log.DebugFormat("[Groups.Messaging]: skipping agent {0} because we've already seen it", sp.UUID); + return; + } + alreadySeen.Add(sp.UUID); + + GroupMembersData m = groupMembers.Find(gmd => + { + return gmd.AgentID == sp.UUID; + }); + if (m.AgentID == UUID.Zero) + { + if (m_debugEnabled) + m_log.DebugFormat("[Groups.Messaging]: skipping agent {0} because he is not a member of the group", sp.UUID); + return; + } + + // Check if the user has an agent in the region where + // the IM came from, and if so, skip it, because the IM + // was already sent via that agent + if (regionOfOrigin != null) + { + AgentCircuitData aCircuit = s.AuthenticateHandler.GetAgentCircuitData(sp.UUID); + if (aCircuit != null) + { + if (aCircuit.ChildrenCapSeeds.Keys.Contains(regionOfOrigin.RegionHandle)) + { + if (m_debugEnabled) + m_log.DebugFormat("[Groups.Messaging]: skipping agent {0} because he has an agent in region of origin", sp.UUID); + return; + } + else + { + if (m_debugEnabled) + m_log.DebugFormat("[Groups.Messaging]: not skipping agent {0}", sp.UUID); + } + } + } + + UUID AgentID = sp.UUID; + msg.toAgentID = AgentID.Guid; + + if (!hasAgentDroppedGroupChatSession(AgentID.ToString(), GroupID) + && !hasAgentBeenInvitedToGroupChatSession(AgentID.ToString(), GroupID)) + { + AddAgentToSession(AgentID, GroupID, msg); + } + + if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Passing to ProcessMessageFromGroupSession to deliver to {0} locally", sp.Name); + + ProcessMessageFromGroupSession(msg); + }); + } } } @@ -367,82 +452,40 @@ namespace OpenSim.Groups UUID AgentID = new UUID(msg.fromAgentID); UUID GroupID = new UUID(msg.imSessionID); + UUID toAgentID = new UUID(msg.toAgentID); switch (msg.dialog) { case (byte)InstantMessageDialog.SessionAdd: - m_groupData.AgentInvitedToGroupChatSession(AgentID.ToString(), GroupID); + AgentInvitedToGroupChatSession(AgentID.ToString(), GroupID); break; case (byte)InstantMessageDialog.SessionDrop: - m_groupData.AgentDroppedFromGroupChatSession(AgentID.ToString(), GroupID); + AgentDroppedFromGroupChatSession(AgentID.ToString(), GroupID); break; case (byte)InstantMessageDialog.SessionSend: - if (!m_groupData.hasAgentDroppedGroupChatSession(AgentID.ToString(), GroupID) - && !m_groupData.hasAgentBeenInvitedToGroupChatSession(AgentID.ToString(), GroupID) - ) + // User hasn't dropped, so they're in the session, + // maybe we should deliver it. + IClientAPI client = GetActiveClient(new UUID(msg.toAgentID)); + if (client != null) { - // Agent not in session and hasn't dropped from session - // Add them to the session for now, and Invite them - m_groupData.AgentInvitedToGroupChatSession(AgentID.ToString(), GroupID); + // Deliver locally, directly + if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Delivering to {0} locally", client.Name); - UUID toAgentID = new UUID(msg.toAgentID); - IClientAPI activeClient = GetActiveClient(toAgentID); - if (activeClient != null) + if (!hasAgentDroppedGroupChatSession(toAgentID.ToString(), GroupID)) { - GroupRecord groupInfo = m_groupData.GetGroupRecord(UUID.Zero.ToString(), GroupID, null); - if (groupInfo != null) - { - if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Sending chatterbox invite instant message"); - - // Force? open the group session dialog??? - // and simultanously deliver the message, so we don't need to do a seperate client.SendInstantMessage(msg); - IEventQueue eq = activeClient.Scene.RequestModuleInterface(); - eq.ChatterboxInvitation( - GroupID - , groupInfo.GroupName - , new UUID(msg.fromAgentID) - , msg.message - , new UUID(msg.toAgentID) - , msg.fromAgentName - , msg.dialog - , msg.timestamp - , msg.offline == 1 - , (int)msg.ParentEstateID - , msg.Position - , 1 - , new UUID(msg.imSessionID) - , msg.fromGroup - , OpenMetaverse.Utils.StringToBytes(groupInfo.GroupName) - ); - - eq.ChatterBoxSessionAgentListUpdates( - new UUID(GroupID) - , new UUID(msg.fromAgentID) - , new UUID(msg.toAgentID) - , false //canVoiceChat - , false //isModerator - , false //text mute - ); - } + if (!hasAgentBeenInvitedToGroupChatSession(toAgentID.ToString(), GroupID)) + // This actually sends the message too, so no need to resend it + // with client.SendInstantMessage + AddAgentToSession(toAgentID, GroupID, msg); + else + client.SendInstantMessage(msg); } } - else if (!m_groupData.hasAgentDroppedGroupChatSession(AgentID.ToString(), GroupID)) + else { - // User hasn't dropped, so they're in the session, - // maybe we should deliver it. - IClientAPI client = GetActiveClient(new UUID(msg.toAgentID)); - if (client != null) - { - // Deliver locally, directly - if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Delivering to {0} locally", client.Name); - client.SendInstantMessage(msg); - } - else - { - m_log.WarnFormat("[Groups.Messaging]: Received a message over the grid for a client that isn't here: {0}", msg.toAgentID); - } + m_log.WarnFormat("[Groups.Messaging]: Received a message over the grid for a client that isn't here: {0}", msg.toAgentID); } break; @@ -452,6 +495,53 @@ namespace OpenSim.Groups } } + private void AddAgentToSession(UUID AgentID, UUID GroupID, GridInstantMessage msg) + { + // Agent not in session and hasn't dropped from session + // Add them to the session for now, and Invite them + AgentInvitedToGroupChatSession(AgentID.ToString(), GroupID); + + IClientAPI activeClient = GetActiveClient(AgentID); + if (activeClient != null) + { + GroupRecord groupInfo = m_groupData.GetGroupRecord(UUID.Zero.ToString(), GroupID, null); + if (groupInfo != null) + { + if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Sending chatterbox invite instant message"); + + // Force? open the group session dialog??? + // and simultanously deliver the message, so we don't need to do a seperate client.SendInstantMessage(msg); + IEventQueue eq = activeClient.Scene.RequestModuleInterface(); + eq.ChatterboxInvitation( + GroupID + , groupInfo.GroupName + , new UUID(msg.fromAgentID) + , msg.message + , AgentID + , msg.fromAgentName + , msg.dialog + , msg.timestamp + , msg.offline == 1 + , (int)msg.ParentEstateID + , msg.Position + , 1 + , new UUID(msg.imSessionID) + , msg.fromGroup + , OpenMetaverse.Utils.StringToBytes(groupInfo.GroupName) + ); + + eq.ChatterBoxSessionAgentListUpdates( + new UUID(GroupID) + , AgentID + , new UUID(msg.toAgentID) + , false //canVoiceChat + , false //isModerator + , false //text mute + ); + } + } + } + #endregion @@ -477,7 +567,7 @@ namespace OpenSim.Groups if (groupInfo != null) { - m_groupData.AgentInvitedToGroupChatSession(AgentID.ToString(), GroupID); + AgentInvitedToGroupChatSession(AgentID.ToString(), GroupID); ChatterBoxSessionStartReplyViaCaps(remoteClient, groupInfo.GroupName, GroupID); @@ -503,7 +593,7 @@ namespace OpenSim.Groups m_log.DebugFormat("[Groups.Messaging]: Send message to session for group {0} with session ID {1}", GroupID, im.imSessionID.ToString()); //If this agent is sending a message, then they want to be in the session - m_groupData.AgentInvitedToGroupChatSession(AgentID.ToString(), GroupID); + AgentInvitedToGroupChatSession(AgentID.ToString(), GroupID); SendMessageToGroup(im, GroupID); } @@ -598,5 +688,70 @@ namespace OpenSim.Groups } #endregion + + #region GroupSessionTracking + + public void ResetAgentGroupChatSessions(string agentID) + { + foreach (List agentList in m_groupsAgentsDroppedFromChatSession.Values) + { + agentList.Remove(agentID); + } + } + + public bool hasAgentBeenInvitedToGroupChatSession(string agentID, UUID groupID) + { + // If we're tracking this group, and we can find them in the tracking, then they've been invited + return m_groupsAgentsInvitedToChatSession.ContainsKey(groupID) + && m_groupsAgentsInvitedToChatSession[groupID].Contains(agentID); + } + + public bool hasAgentDroppedGroupChatSession(string agentID, UUID groupID) + { + // If we're tracking drops for this group, + // and we find them, well... then they've dropped + return m_groupsAgentsDroppedFromChatSession.ContainsKey(groupID) + && m_groupsAgentsDroppedFromChatSession[groupID].Contains(agentID); + } + + public void AgentDroppedFromGroupChatSession(string agentID, UUID groupID) + { + if (m_groupsAgentsDroppedFromChatSession.ContainsKey(groupID)) + { + // If not in dropped list, add + if (!m_groupsAgentsDroppedFromChatSession[groupID].Contains(agentID)) + { + m_groupsAgentsDroppedFromChatSession[groupID].Add(agentID); + } + } + } + + public void AgentInvitedToGroupChatSession(string agentID, UUID groupID) + { + // Add Session Status if it doesn't exist for this session + CreateGroupChatSessionTracking(groupID); + + // If nessesary, remove from dropped list + if (m_groupsAgentsDroppedFromChatSession[groupID].Contains(agentID)) + { + m_groupsAgentsDroppedFromChatSession[groupID].Remove(agentID); + } + + // Add to invited + if (!m_groupsAgentsInvitedToChatSession[groupID].Contains(agentID)) + m_groupsAgentsInvitedToChatSession[groupID].Add(agentID); + } + + private void CreateGroupChatSessionTracking(UUID groupID) + { + if (!m_groupsAgentsDroppedFromChatSession.ContainsKey(groupID)) + { + m_groupsAgentsDroppedFromChatSession.Add(groupID, new List()); + m_groupsAgentsInvitedToChatSession.Add(groupID, new List()); + } + + } + #endregion + } } diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs index 69d03a9..a14dc6a 100644 --- a/OpenSim/Addons/Groups/GroupsModule.cs +++ b/OpenSim/Addons/Groups/GroupsModule.cs @@ -141,6 +141,8 @@ namespace OpenSim.Groups if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); scene.EventManager.OnNewClient += OnNewClient; + scene.EventManager.OnMakeRootAgent += OnMakeRoot; + scene.EventManager.OnMakeChildAgent += OnMakeChild; scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; // The InstantMessageModule itself doesn't do this, // so lets see if things explode if we don't do it @@ -194,6 +196,7 @@ namespace OpenSim.Groups if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); scene.EventManager.OnNewClient -= OnNewClient; + scene.EventManager.OnMakeRootAgent -= OnMakeRoot; scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage; lock (m_sceneList) @@ -232,16 +235,31 @@ namespace OpenSim.Groups { if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - client.OnUUIDGroupNameRequest += HandleUUIDGroupNameRequest; client.OnAgentDataUpdateRequest += OnAgentDataUpdateRequest; - client.OnDirFindQuery += OnDirFindQuery; client.OnRequestAvatarProperties += OnRequestAvatarProperties; + } + private void OnMakeRoot(ScenePresence sp) + { + if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + sp.ControllingClient.OnUUIDGroupNameRequest += HandleUUIDGroupNameRequest; + sp.ControllingClient.OnDirFindQuery += OnDirFindQuery; // Used for Notices and Group Invites/Accept/Reject - client.OnInstantMessage += OnInstantMessage; + sp.ControllingClient.OnInstantMessage += OnInstantMessage; // Send client their groups information. - SendAgentGroupDataUpdate(client, client.AgentId); + SendAgentGroupDataUpdate(sp.ControllingClient, sp.UUID); + } + + private void OnMakeChild(ScenePresence sp) + { + if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + sp.ControllingClient.OnUUIDGroupNameRequest -= HandleUUIDGroupNameRequest; + sp.ControllingClient.OnDirFindQuery -= OnDirFindQuery; + // Used for Notices and Group Invites/Accept/Reject + sp.ControllingClient.OnInstantMessage -= OnInstantMessage; } private void OnRequestAvatarProperties(IClientAPI remoteClient, UUID avatarID) diff --git a/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs b/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs index c3c759e..daa0728 100644 --- a/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs +++ b/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs @@ -590,28 +590,6 @@ namespace OpenSim.Groups return m_LocalGroupsConnector.GetGroupNotices(AgentUUI(RequestingAgentID), GroupID); } - public void ResetAgentGroupChatSessions(string agentID) - { - } - - public bool hasAgentBeenInvitedToGroupChatSession(string agentID, UUID groupID) - { - return false; - } - - public bool hasAgentDroppedGroupChatSession(string agentID, UUID groupID) - { - return false; - } - - public void AgentDroppedFromGroupChatSession(string agentID, UUID groupID) - { - } - - public void AgentInvitedToGroupChatSession(string agentID, UUID groupID) - { - } - #endregion #region hypergrid groups diff --git a/OpenSim/Addons/Groups/IGroupsServicesConnector.cs b/OpenSim/Addons/Groups/IGroupsServicesConnector.cs index 73deb7a..a09b59e 100644 --- a/OpenSim/Addons/Groups/IGroupsServicesConnector.cs +++ b/OpenSim/Addons/Groups/IGroupsServicesConnector.cs @@ -92,12 +92,6 @@ namespace OpenSim.Groups GroupNoticeInfo GetGroupNotice(string RequestingAgentID, UUID noticeID); List GetGroupNotices(string RequestingAgentID, UUID GroupID); - void ResetAgentGroupChatSessions(string agentID); - bool hasAgentBeenInvitedToGroupChatSession(string agentID, UUID groupID); - bool hasAgentDroppedGroupChatSession(string agentID, UUID groupID); - void AgentDroppedFromGroupChatSession(string agentID, UUID groupID); - void AgentInvitedToGroupChatSession(string agentID, UUID groupID); - } public class GroupInviteInfo diff --git a/OpenSim/Addons/Groups/Local/GroupsServiceLocalConnectorModule.cs b/OpenSim/Addons/Groups/Local/GroupsServiceLocalConnectorModule.cs index 905bc91..564dec4 100644 --- a/OpenSim/Addons/Groups/Local/GroupsServiceLocalConnectorModule.cs +++ b/OpenSim/Addons/Groups/Local/GroupsServiceLocalConnectorModule.cs @@ -320,28 +320,6 @@ namespace OpenSim.Groups return m_GroupsService.GetGroupNotices(RequestingAgentID, GroupID); } - public void ResetAgentGroupChatSessions(string agentID) - { - } - - public bool hasAgentBeenInvitedToGroupChatSession(string agentID, UUID groupID) - { - return false; - } - - public bool hasAgentDroppedGroupChatSession(string agentID, UUID groupID) - { - return false; - } - - public void AgentDroppedFromGroupChatSession(string agentID, UUID groupID) - { - } - - public void AgentInvitedToGroupChatSession(string agentID, UUID groupID) - { - } - #endregion } } diff --git a/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnectorModule.cs b/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnectorModule.cs index f1cf66c..9b6bfbd 100644 --- a/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnectorModule.cs +++ b/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnectorModule.cs @@ -406,28 +406,6 @@ namespace OpenSim.Groups }); } - public void ResetAgentGroupChatSessions(string agentID) - { - } - - public bool hasAgentBeenInvitedToGroupChatSession(string agentID, UUID groupID) - { - return false; - } - - public bool hasAgentDroppedGroupChatSession(string agentID, UUID groupID) - { - return false; - } - - public void AgentDroppedFromGroupChatSession(string agentID, UUID groupID) - { - } - - public void AgentInvitedToGroupChatSession(string agentID, UUID groupID) - { - } - #endregion } -- cgit v1.1 From 18eca40af3592d9743cf50267a460968e601859c Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sat, 27 Jul 2013 19:12:47 -0700 Subject: More bug fixes on group chat --- OpenSim/Addons/Groups/GroupsMessagingModule.cs | 34 ++++++++++++++------------ 1 file changed, 19 insertions(+), 15 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsMessagingModule.cs b/OpenSim/Addons/Groups/GroupsMessagingModule.cs index be76ef1..04e2b80 100644 --- a/OpenSim/Addons/Groups/GroupsMessagingModule.cs +++ b/OpenSim/Addons/Groups/GroupsMessagingModule.cs @@ -132,7 +132,6 @@ namespace OpenSim.Groups scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; scene.EventManager.OnClientLogin += OnClientLogin; } - public void RegionLoaded(Scene scene) { if (!m_groupMessagingEnabled) @@ -271,7 +270,8 @@ namespace OpenSim.Groups } // Send to self first of all - im.toAgentID = im.fromAgentID; + im.toAgentID = im.fromAgentID; + im.fromGroup = true; ProcessMessageFromGroupSession(im); List regions = new List(); @@ -330,8 +330,7 @@ namespace OpenSim.Groups } } - // Temporary for assessing how long it still takes to send messages to large online groups. - if (m_messageOnlineAgentsOnly) + if (m_debugEnabled) m_log.DebugFormat( "[Groups.Messaging]: SendMessageToGroup for group {0} with {1} visible members, {2} online took {3}ms", groupID, groupMembersCount, groupMembers.Count(), Environment.TickCount - requestStartTick); @@ -349,6 +348,7 @@ namespace OpenSim.Groups if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: OnInstantMessage registered for {0}", client.Name); client.OnInstantMessage += OnInstantMessage; + ResetAgentGroupChatSessions(client.AgentId.ToString()); } private void OnGridInstantMessage(GridInstantMessage msg) @@ -432,16 +432,19 @@ namespace OpenSim.Groups UUID AgentID = sp.UUID; msg.toAgentID = AgentID.Guid; - if (!hasAgentDroppedGroupChatSession(AgentID.ToString(), GroupID) - && !hasAgentBeenInvitedToGroupChatSession(AgentID.ToString(), GroupID)) + if (!hasAgentDroppedGroupChatSession(AgentID.ToString(), GroupID)) { - AddAgentToSession(AgentID, GroupID, msg); - } - - if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Passing to ProcessMessageFromGroupSession to deliver to {0} locally", sp.Name); + if (!hasAgentBeenInvitedToGroupChatSession(AgentID.ToString(), GroupID)) + AddAgentToSession(AgentID, GroupID, msg); + else + { + if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Passing to ProcessMessageFromGroupSession to deliver to {0} locally", sp.Name); - ProcessMessageFromGroupSession(msg); + ProcessMessageFromGroupSession(msg); + } + } }); + } } } @@ -664,12 +667,12 @@ namespace OpenSim.Groups { if (!sp.IsChildAgent) { - if (m_debugEnabled) m_log.WarnFormat("[Groups.Messaging]: Found root agent for client : {0}", sp.ControllingClient.Name); + if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Found root agent for client : {0}", sp.ControllingClient.Name); return sp.ControllingClient; } else { - if (m_debugEnabled) m_log.WarnFormat("[Groups.Messaging]: Found child agent for client : {0}", sp.ControllingClient.Name); + if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Found child agent for client : {0}", sp.ControllingClient.Name); child = sp.ControllingClient; } } @@ -694,9 +697,10 @@ namespace OpenSim.Groups public void ResetAgentGroupChatSessions(string agentID) { foreach (List agentList in m_groupsAgentsDroppedFromChatSession.Values) - { agentList.Remove(agentID); - } + + foreach (List agentList in m_groupsAgentsInvitedToChatSession.Values) + agentList.Remove(agentID); } public bool hasAgentBeenInvitedToGroupChatSession(string agentID, UUID groupID) -- cgit v1.1 From 8dff05a89798543994cb6e5ac5e5f715daf5898b Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sat, 27 Jul 2013 20:30:00 -0700 Subject: More on group chat: only root agents should subscribe to OnInstantMessage, or else they'll see an echo of their own messages after teleporting. --- OpenSim/Addons/Groups/GroupsMessagingModule.cs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsMessagingModule.cs b/OpenSim/Addons/Groups/GroupsMessagingModule.cs index 04e2b80..ce4f597 100644 --- a/OpenSim/Addons/Groups/GroupsMessagingModule.cs +++ b/OpenSim/Addons/Groups/GroupsMessagingModule.cs @@ -129,9 +129,12 @@ namespace OpenSim.Groups m_sceneList.Add(scene); scene.EventManager.OnNewClient += OnNewClient; + scene.EventManager.OnMakeRootAgent += OnMakeRootAgent; + scene.EventManager.OnMakeChildAgent += OnMakeChildAgent; scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; scene.EventManager.OnClientLogin += OnClientLogin; } + public void RegionLoaded(Scene scene) { if (!m_groupMessagingEnabled) @@ -347,10 +350,20 @@ namespace OpenSim.Groups { if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: OnInstantMessage registered for {0}", client.Name); - client.OnInstantMessage += OnInstantMessage; ResetAgentGroupChatSessions(client.AgentId.ToString()); } + void OnMakeRootAgent(ScenePresence sp) + { + sp.ControllingClient.OnInstantMessage += OnInstantMessage; + } + + void OnMakeChildAgent(ScenePresence sp) + { + sp.ControllingClient.OnInstantMessage -= OnInstantMessage; + } + + private void OnGridInstantMessage(GridInstantMessage msg) { // The instant message module will only deliver messages of dialog types: -- cgit v1.1 From 170a6f0563c9b9e228dad0b1db5654f2114a05f4 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 28 Jul 2013 09:00:28 -0700 Subject: This makes group search work (Groups V2). --- OpenSim/Addons/Groups/GroupsExtendedData.cs | 24 +++++++++++++++++ OpenSim/Addons/Groups/GroupsModule.cs | 4 +++ .../Groups/Remote/GroupsServiceRemoteConnector.cs | 30 ++++++++++++++++++++++ .../Remote/GroupsServiceRemoteConnectorModule.cs | 2 +- .../Groups/Remote/GroupsServiceRobustConnector.cs | 28 ++++++++++++++++++++ 5 files changed, 87 insertions(+), 1 deletion(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsExtendedData.cs b/OpenSim/Addons/Groups/GroupsExtendedData.cs index 6f4db28..1632aee 100644 --- a/OpenSim/Addons/Groups/GroupsExtendedData.cs +++ b/OpenSim/Addons/Groups/GroupsExtendedData.cs @@ -504,6 +504,30 @@ namespace OpenSim.Groups return notice; } + + public static Dictionary DirGroupsReplyData(DirGroupsReplyData g) + { + Dictionary dict = new Dictionary(); + + dict["GroupID"] = g.groupID; + dict["Name"] = g.groupName; + dict["NMembers"] = g.members; + dict["SearchOrder"] = g.searchOrder; + + return dict; + } + + public static DirGroupsReplyData DirGroupsReplyData(Dictionary dict) + { + DirGroupsReplyData g; + + g.groupID = new UUID(dict["GroupID"].ToString()); + g.groupName = dict["Name"].ToString(); + Int32.TryParse(dict["NMembers"].ToString(), out g.members); + float.TryParse(dict["SearchOrder"].ToString(), out g.searchOrder); + + return g; + } } } diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs index a14dc6a..7d3c064 100644 --- a/OpenSim/Addons/Groups/GroupsModule.cs +++ b/OpenSim/Addons/Groups/GroupsModule.cs @@ -313,6 +313,10 @@ namespace OpenSim.Groups m_log.DebugFormat( "[Groups]: {0} called with queryText({1}) queryFlags({2}) queryStart({3})", System.Reflection.MethodBase.GetCurrentMethod().Name, queryText, (DirFindFlags)queryFlags, queryStart); + + + if (string.IsNullOrEmpty(queryText)) + remoteClient.SendDirGroupsReply(queryID, new DirGroupsReplyData[0]); // TODO: This currently ignores pretty much all the query flags including Mature and sort order remoteClient.SendDirGroupsReply(queryID, m_groupData.FindGroups(GetRequestingAgentIDStr(remoteClient), queryText).ToArray()); diff --git a/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnector.cs b/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnector.cs index 04328c9..9a3e125 100644 --- a/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnector.cs +++ b/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnector.cs @@ -133,6 +133,36 @@ namespace OpenSim.Groups return GroupsDataUtils.GroupRecord((Dictionary)ret["RESULT"]); } + public List FindGroups(string RequestingAgentID, string query) + { + List hits = new List(); + if (string.IsNullOrEmpty(query)) + return hits; + + Dictionary sendData = new Dictionary(); + sendData["Query"] = query; + sendData["RequestingAgentID"] = RequestingAgentID; + + Dictionary ret = MakeRequest("FINDGROUPS", sendData); + + if (ret == null) + return hits; + + if (!ret.ContainsKey("RESULT")) + return hits; + + if (ret["RESULT"].ToString() == "NULL") + return hits; + + foreach (object v in ((Dictionary)ret["RESULT"]).Values) + { + DirGroupsReplyData m = GroupsDataUtils.DirGroupsReplyData((Dictionary)v); + hits.Add(m); + } + + return hits; + } + public GroupMembershipData AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID, string token, out string reason) { reason = string.Empty; diff --git a/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnectorModule.cs b/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnectorModule.cs index 9b6bfbd..d3de0e8 100644 --- a/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnectorModule.cs +++ b/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnectorModule.cs @@ -199,7 +199,7 @@ namespace OpenSim.Groups public List FindGroups(string RequestingAgentID, string search) { // TODO! - return new List(); + return m_GroupsService.FindGroups(RequestingAgentID, search); } public bool AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID, string token, out string reason) diff --git a/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs b/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs index 106c6c4..249d974 100644 --- a/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs +++ b/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs @@ -133,6 +133,8 @@ namespace OpenSim.Groups return HandleAddNotice(request); case "GETNOTICES": return HandleGetNotices(request); + case "FINDGROUPS": + return HandleFindGroups(request); } m_log.DebugFormat("[GROUPS HANDLER]: unknown method request: {0}", method); } @@ -740,6 +742,32 @@ namespace OpenSim.Groups return Util.UTF8NoBomEncoding.GetBytes(xmlString); } + byte[] HandleFindGroups(Dictionary request) + { + Dictionary result = new Dictionary(); + + if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("Query")) + NullResult(result, "Bad network data"); + + List hits = m_GroupsService.FindGroups(request["RequestingAgentID"].ToString(), request["Query"].ToString()); + + if (hits == null || (hits != null && hits.Count == 0)) + NullResult(result, "No hits"); + else + { + Dictionary dict = new Dictionary(); + int i = 0; + foreach (DirGroupsReplyData n in hits) + dict["n-" + i++] = GroupsDataUtils.DirGroupsReplyData(n); + + result["RESULT"] = dict; + } + + + string xmlString = ServerUtils.BuildXmlResponse(result); + return Util.UTF8NoBomEncoding.GetBytes(xmlString); + } + #region Helpers -- cgit v1.1 From 7b0b5c9d97dea840e1ede6e2318b3c049c804983 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 28 Jul 2013 13:49:58 -0700 Subject: Added BasicSearchModule.cs which handles OnDirFindQuery events. Removed that handler from both Groups modules in core, and replaced them with an operation on IGroupsModule. --- OpenSim/Addons/Groups/GroupsModule.cs | 27 ++++++--------------------- 1 file changed, 6 insertions(+), 21 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs index 7d3c064..214a131 100644 --- a/OpenSim/Addons/Groups/GroupsModule.cs +++ b/OpenSim/Addons/Groups/GroupsModule.cs @@ -197,6 +197,7 @@ namespace OpenSim.Groups scene.EventManager.OnNewClient -= OnNewClient; scene.EventManager.OnMakeRootAgent -= OnMakeRoot; + scene.EventManager.OnMakeChildAgent -= OnMakeChild; scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage; lock (m_sceneList) @@ -244,7 +245,6 @@ namespace OpenSim.Groups if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); sp.ControllingClient.OnUUIDGroupNameRequest += HandleUUIDGroupNameRequest; - sp.ControllingClient.OnDirFindQuery += OnDirFindQuery; // Used for Notices and Group Invites/Accept/Reject sp.ControllingClient.OnInstantMessage += OnInstantMessage; @@ -257,7 +257,6 @@ namespace OpenSim.Groups if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); sp.ControllingClient.OnUUIDGroupNameRequest -= HandleUUIDGroupNameRequest; - sp.ControllingClient.OnDirFindQuery -= OnDirFindQuery; // Used for Notices and Group Invites/Accept/Reject sp.ControllingClient.OnInstantMessage -= OnInstantMessage; } @@ -305,25 +304,6 @@ namespace OpenSim.Groups } */ - void OnDirFindQuery(IClientAPI remoteClient, UUID queryID, string queryText, uint queryFlags, int queryStart) - { - if (((DirFindFlags)queryFlags & DirFindFlags.Groups) == DirFindFlags.Groups) - { - if (m_debugEnabled) - m_log.DebugFormat( - "[Groups]: {0} called with queryText({1}) queryFlags({2}) queryStart({3})", - System.Reflection.MethodBase.GetCurrentMethod().Name, queryText, (DirFindFlags)queryFlags, queryStart); - - - if (string.IsNullOrEmpty(queryText)) - remoteClient.SendDirGroupsReply(queryID, new DirGroupsReplyData[0]); - - // TODO: This currently ignores pretty much all the query flags including Mature and sort order - remoteClient.SendDirGroupsReply(queryID, m_groupData.FindGroups(GetRequestingAgentIDStr(remoteClient), queryText).ToArray()); - } - - } - private void OnAgentDataUpdateRequest(IClientAPI remoteClient, UUID dataForAgentID, UUID sessionID) { if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); @@ -1211,6 +1191,11 @@ namespace OpenSim.Groups } } + public List FindGroups(IClientAPI remoteClient, string query) + { + return m_groupData.FindGroups(GetRequestingAgentIDStr(remoteClient), query); + } + #endregion #region Client/Update Tools -- cgit v1.1 From 63f6c8f27ca280a7d362af08ba1716d5f28e3137 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 28 Jul 2013 13:53:47 -0700 Subject: Removed commented lines and useless debug message --- OpenSim/Addons/Groups/GroupsModule.cs | 16 ---------------- 1 file changed, 16 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs index 214a131..826fcbf 100644 --- a/OpenSim/Addons/Groups/GroupsModule.cs +++ b/OpenSim/Addons/Groups/GroupsModule.cs @@ -909,23 +909,7 @@ namespace OpenSim.Groups { if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called for notice {1}", System.Reflection.MethodBase.GetCurrentMethod().Name, groupNoticeID); - //GroupRecord groupInfo = m_groupData.GetGroupRecord(GetRequestingAgentID(remoteClient), data.GroupID, null); - GridInstantMessage msg = CreateGroupNoticeIM(remoteClient.AgentId, groupNoticeID, (byte)InstantMessageDialog.GroupNoticeRequested); - //GridInstantMessage msg = new GridInstantMessage(); - //msg.imSessionID = UUID.Zero.Guid; - //msg.fromAgentID = data.GroupID.Guid; - //msg.toAgentID = GetRequestingAgentID(remoteClient).Guid; - //msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); - //msg.fromAgentName = "Group Notice : " + groupInfo == null ? "Unknown" : groupInfo.GroupName; - //msg.message = data.noticeData.Subject + "|" + data.Message; - //msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.GroupNoticeRequested; - //msg.fromGroup = true; - //msg.offline = (byte)0; - //msg.ParentEstateID = 0; - //msg.Position = Vector3.Zero; - //msg.RegionID = UUID.Zero.Guid; - //msg.binaryBucket = data.BinaryBucket; OutgoingInstantMessage(msg, GetRequestingAgentID(remoteClient)); } -- cgit v1.1 From 698b2135eed747c24e3325cc7e5a7bae513a2c25 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 28 Jul 2013 15:59:24 -0700 Subject: Fix an issue where HG members of groups weren't seeing the entire membership for group chat. --- OpenSim/Addons/Groups/GroupsMessagingModule.cs | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsMessagingModule.cs b/OpenSim/Addons/Groups/GroupsMessagingModule.cs index ce4f597..3cece77 100644 --- a/OpenSim/Addons/Groups/GroupsMessagingModule.cs +++ b/OpenSim/Addons/Groups/GroupsMessagingModule.cs @@ -52,7 +52,7 @@ namespace OpenSim.Groups private IPresenceService m_presenceService; private IMessageTransferModule m_msgTransferModule = null; - + private IUserManagement m_UserManagement = null; private IGroupsServicesConnector m_groupData = null; // Config Options @@ -162,6 +162,17 @@ namespace OpenSim.Groups return; } + m_UserManagement = scene.RequestModuleInterface(); + + // No groups module, no groups messaging + if (m_UserManagement == null) + { + m_log.Error("[Groups.Messaging]: Could not get IUserManagement, GroupsMessagingModule is now disabled."); + RemoveRegion(scene); + return; + } + + if (m_presenceService == null) m_presenceService = scene.PresenceService; @@ -392,9 +403,16 @@ namespace OpenSim.Groups Scene aScene = m_sceneList[0]; GridRegion regionOfOrigin = aScene.GridService.GetRegionByUUID(aScene.RegionInfo.ScopeID, regionID); - List groupMembers = m_groupData.GetGroupMembers(new UUID(msg.fromAgentID).ToString(), GroupID); + // Let's find out who sent it + string requestingAgent = m_UserManagement.GetUserUUI(new UUID(msg.fromAgentID)); + + List groupMembers = m_groupData.GetGroupMembers(requestingAgent, GroupID); List alreadySeen = new List(); + if (m_debugEnabled) + foreach (GroupMembersData m in groupMembers) + m_log.DebugFormat("[Groups.Messaging]: member {0}", m.AgentID); + foreach (Scene s in m_sceneList) { s.ForEachScenePresence(sp => -- cgit v1.1 From c442ef346eee83320d92ebc829cf3dec7bd2ed98 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 28 Jul 2013 16:44:31 -0700 Subject: Same issue as previous commit. --- OpenSim/Addons/Groups/GroupsMessagingModule.cs | 13 +++++-------- OpenSim/Addons/Groups/Service/GroupsService.cs | 18 ++++++++++++------ 2 files changed, 17 insertions(+), 14 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsMessagingModule.cs b/OpenSim/Addons/Groups/GroupsMessagingModule.cs index 3cece77..5de1fb4 100644 --- a/OpenSim/Addons/Groups/GroupsMessagingModule.cs +++ b/OpenSim/Addons/Groups/GroupsMessagingModule.cs @@ -246,7 +246,7 @@ namespace OpenSim.Groups public void SendMessageToGroup(GridInstantMessage im, UUID groupID) { UUID fromAgentID = new UUID(im.fromAgentID); - List groupMembers = m_groupData.GetGroupMembers(fromAgentID.ToString(), groupID); + List groupMembers = m_groupData.GetGroupMembers("all", groupID); int groupMembersCount = groupMembers.Count; PresenceInfo[] onlineAgents = null; @@ -403,15 +403,12 @@ namespace OpenSim.Groups Scene aScene = m_sceneList[0]; GridRegion regionOfOrigin = aScene.GridService.GetRegionByUUID(aScene.RegionInfo.ScopeID, regionID); - // Let's find out who sent it - string requestingAgent = m_UserManagement.GetUserUUI(new UUID(msg.fromAgentID)); - - List groupMembers = m_groupData.GetGroupMembers(requestingAgent, GroupID); + List groupMembers = m_groupData.GetGroupMembers("all", GroupID); List alreadySeen = new List(); - if (m_debugEnabled) - foreach (GroupMembersData m in groupMembers) - m_log.DebugFormat("[Groups.Messaging]: member {0}", m.AgentID); + //if (m_debugEnabled) + // foreach (GroupMembersData m in groupMembers) + // m_log.DebugFormat("[Groups.Messaging]: member {0}", m.AgentID); foreach (Scene s in m_sceneList) { diff --git a/OpenSim/Addons/Groups/Service/GroupsService.cs b/OpenSim/Addons/Groups/Service/GroupsService.cs index a2ef13a..24eb7f3 100644 --- a/OpenSim/Addons/Groups/Service/GroupsService.cs +++ b/OpenSim/Addons/Groups/Service/GroupsService.cs @@ -255,13 +255,19 @@ namespace OpenSim.Groups return members; List rolesList = new List(roles); - // Is the requester a member of the group? - bool isInGroup = false; - if (m_Database.RetrieveMember(GroupID, RequestingAgentID) != null) - isInGroup = true; + // Check visibility? + // When we don't want to check visibility, we pass it "all" as the requestingAgentID + bool checkVisibility = !RequestingAgentID.Equals("all"); + if (checkVisibility) + { + // Is the requester a member of the group? + bool isInGroup = false; + if (m_Database.RetrieveMember(GroupID, RequestingAgentID) != null) + isInGroup = true; - if (!isInGroup) // reduce the roles to the visible ones - rolesList = rolesList.FindAll(r => (UInt64.Parse(r.Data["Powers"]) & (ulong)GroupPowers.MemberVisible) != 0); + if (!isInGroup) // reduce the roles to the visible ones + rolesList = rolesList.FindAll(r => (UInt64.Parse(r.Data["Powers"]) & (ulong)GroupPowers.MemberVisible) != 0); + } MembershipData[] datas = m_Database.RetrieveMembers(GroupID); if (datas == null || (datas != null && datas.Length == 0)) -- cgit v1.1 From 468ddd23736ce47e1cb881308785414ced504cee Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 28 Jul 2013 17:12:14 -0700 Subject: Same issue. --- OpenSim/Addons/Groups/Service/GroupsService.cs | 1 + 1 file changed, 1 insertion(+) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/Service/GroupsService.cs b/OpenSim/Addons/Groups/Service/GroupsService.cs index 24eb7f3..294b89a 100644 --- a/OpenSim/Addons/Groups/Service/GroupsService.cs +++ b/OpenSim/Addons/Groups/Service/GroupsService.cs @@ -258,6 +258,7 @@ namespace OpenSim.Groups // Check visibility? // When we don't want to check visibility, we pass it "all" as the requestingAgentID bool checkVisibility = !RequestingAgentID.Equals("all"); + m_log.DebugFormat("[ZZZ]: AgentID is {0}. checkVisibility is {1}", RequestingAgentID, checkVisibility); if (checkVisibility) { // Is the requester a member of the group? -- cgit v1.1 From 33b54807a1646a9457a7a718f767ccec1c0cb39f Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 28 Jul 2013 18:08:50 -0700 Subject: Changing the visibility test in groups service to be UUID.Zero.ToString() instead of "all" because some paths in the code assume there's a UUI in the RequestingAgent string. --- OpenSim/Addons/Groups/GroupsMessagingModule.cs | 4 ++-- OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs | 5 ++++- OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnector.cs | 1 + OpenSim/Addons/Groups/Service/GroupsService.cs | 4 ++-- 4 files changed, 9 insertions(+), 5 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsMessagingModule.cs b/OpenSim/Addons/Groups/GroupsMessagingModule.cs index 5de1fb4..cd45432 100644 --- a/OpenSim/Addons/Groups/GroupsMessagingModule.cs +++ b/OpenSim/Addons/Groups/GroupsMessagingModule.cs @@ -246,7 +246,7 @@ namespace OpenSim.Groups public void SendMessageToGroup(GridInstantMessage im, UUID groupID) { UUID fromAgentID = new UUID(im.fromAgentID); - List groupMembers = m_groupData.GetGroupMembers("all", groupID); + List groupMembers = m_groupData.GetGroupMembers(UUID.Zero.ToString(), groupID); int groupMembersCount = groupMembers.Count; PresenceInfo[] onlineAgents = null; @@ -403,7 +403,7 @@ namespace OpenSim.Groups Scene aScene = m_sceneList[0]; GridRegion regionOfOrigin = aScene.GridService.GetRegionByUUID(aScene.RegionInfo.ScopeID, regionID); - List groupMembers = m_groupData.GetGroupMembers("all", GroupID); + List groupMembers = m_groupData.GetGroupMembers(UUID.Zero.ToString(), GroupID); List alreadySeen = new List(); //if (m_debugEnabled) diff --git a/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs b/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs index daa0728..5e53981 100644 --- a/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs +++ b/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs @@ -254,7 +254,10 @@ namespace OpenSim.Groups { string url = string.Empty, gname = string.Empty; if (IsLocal(GroupID, out url, out gname)) - return m_LocalGroupsConnector.GetGroupMembers(AgentUUI(RequestingAgentID), GroupID); + { + string agentID = AgentUUI(RequestingAgentID); + return m_LocalGroupsConnector.GetGroupMembers(agentID, GroupID); + } else if (!string.IsNullOrEmpty(url)) { ExtendedGroupMembershipData membership = m_LocalGroupsConnector.GetAgentGroupMembership(RequestingAgentID, RequestingAgentID, GroupID); diff --git a/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnector.cs b/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnector.cs index 9a3e125..161ca0c 100644 --- a/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnector.cs +++ b/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnector.cs @@ -256,6 +256,7 @@ namespace OpenSim.Groups Dictionary sendData = new Dictionary(); sendData["GroupID"] = GroupID.ToString(); sendData["RequestingAgentID"] = RequestingAgentID; + Dictionary ret = MakeRequest("GETGROUPMEMBERS", sendData); if (ret == null) diff --git a/OpenSim/Addons/Groups/Service/GroupsService.cs b/OpenSim/Addons/Groups/Service/GroupsService.cs index 294b89a..037ef59 100644 --- a/OpenSim/Addons/Groups/Service/GroupsService.cs +++ b/OpenSim/Addons/Groups/Service/GroupsService.cs @@ -257,8 +257,8 @@ namespace OpenSim.Groups // Check visibility? // When we don't want to check visibility, we pass it "all" as the requestingAgentID - bool checkVisibility = !RequestingAgentID.Equals("all"); - m_log.DebugFormat("[ZZZ]: AgentID is {0}. checkVisibility is {1}", RequestingAgentID, checkVisibility); + bool checkVisibility = !RequestingAgentID.Equals(UUID.Zero.ToString()); + if (checkVisibility) { // Is the requester a member of the group? -- cgit v1.1 From 1d4bf06fe7731f4ca3d8f27a38d64f67d222c6af Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 28 Jul 2013 18:49:10 -0700 Subject: Group chat: guard against duplicate sends --- OpenSim/Addons/Groups/GroupsMessagingModule.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsMessagingModule.cs b/OpenSim/Addons/Groups/GroupsMessagingModule.cs index cd45432..83d296e 100644 --- a/OpenSim/Addons/Groups/GroupsMessagingModule.cs +++ b/OpenSim/Addons/Groups/GroupsMessagingModule.cs @@ -297,6 +297,10 @@ namespace OpenSim.Groups if (member.AgentID.Guid == im.fromAgentID) continue; + if (clientsAlreadySent.Contains(member.AgentID)) + continue; + clientsAlreadySent.Add(member.AgentID); + if (hasAgentDroppedGroupChatSession(member.AgentID.ToString(), groupID)) { // Don't deliver messages to people who have dropped this session @@ -336,12 +340,9 @@ namespace OpenSim.Groups // Deliver locally, directly if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Passing to ProcessMessageFromGroupSession to deliver to {0} locally", client.Name); - if (clientsAlreadySent.Contains(member.AgentID)) - continue; - clientsAlreadySent.Add(member.AgentID); - ProcessMessageFromGroupSession(im); } + } if (m_debugEnabled) -- cgit v1.1 From 1b94de8e58434cc882e1dde83919ecd3f1425e3f Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 28 Jul 2013 19:31:17 -0700 Subject: Group chat: prevent a situation where dupe IMs could occur. --- OpenSim/Addons/Groups/GroupsMessagingModule.cs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsMessagingModule.cs b/OpenSim/Addons/Groups/GroupsMessagingModule.cs index 83d296e..be59c62 100644 --- a/OpenSim/Addons/Groups/GroupsMessagingModule.cs +++ b/OpenSim/Addons/Groups/GroupsMessagingModule.cs @@ -405,7 +405,6 @@ namespace OpenSim.Groups GridRegion regionOfOrigin = aScene.GridService.GetRegionByUUID(aScene.RegionInfo.ScopeID, regionID); List groupMembers = m_groupData.GetGroupMembers(UUID.Zero.ToString(), GroupID); - List alreadySeen = new List(); //if (m_debugEnabled) // foreach (GroupMembersData m in groupMembers) @@ -415,15 +414,10 @@ namespace OpenSim.Groups { s.ForEachScenePresence(sp => { - // We need this, because we are searching through all - // SPs, both root and children - if (alreadySeen.Contains(sp.UUID)) - { - if (m_debugEnabled) - m_log.DebugFormat("[Groups.Messaging]: skipping agent {0} because we've already seen it", sp.UUID); + // If we got this via grid messaging, it's because the caller thinks + // that the root agent is here. We should only send the IM to root agents. + if (sp.IsChildAgent) return; - } - alreadySeen.Add(sp.UUID); GroupMembersData m = groupMembers.Find(gmd => { -- cgit v1.1 From 7eee9eb312e9f947d201e0ef3e2f34bceec4568d Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 28 Jul 2013 20:47:15 -0700 Subject: Groups: Better warning messages to the user. --- OpenSim/Addons/Groups/GroupsModule.cs | 4 ++++ .../Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs | 10 +++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs index 826fcbf..da8030c 100644 --- a/OpenSim/Addons/Groups/GroupsModule.cs +++ b/OpenSim/Addons/Groups/GroupsModule.cs @@ -991,6 +991,10 @@ namespace OpenSim.Groups // Should this send updates to everyone in the group? SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); + + if (reason != string.Empty) + // A warning + remoteClient.SendAlertMessage("Warning: " + reason); } else remoteClient.SendJoinGroupReply(groupID, false); diff --git a/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs b/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs index 5e53981..c33168c 100644 --- a/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs +++ b/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs @@ -399,17 +399,21 @@ namespace OpenSim.Groups if (success) { + // Here we always return true. The user has been added to the local group, + // independent of whether the remote operation succeeds or not url = m_UserManagement.GetUserServerURL(uid, "GroupsServerURI"); if (url == string.Empty) { - reason = "User doesn't have a groups server"; - return false; + reason = "You don't have have an accessible groups server in your home world. You membership to this group in only within this grid."; + return true; } GroupsServiceHGConnector c = GetConnector(url); if (c != null) - return c.CreateProxy(AgentUUI(RequestingAgentID), AgentID, token, GroupID, m_LocalGroupsServiceLocation, name, out reason); + c.CreateProxy(AgentUUI(RequestingAgentID), AgentID, token, GroupID, m_LocalGroupsServiceLocation, name, out reason); + return true; } + return false; } } else if (m_UserManagement.IsLocalGridUser(uid)) // local user -- cgit v1.1 From 05012bb0df9b109f792b83e82779d3f69fb37ecb Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Mon, 5 Aug 2013 08:09:30 -0700 Subject: Group notices bug fix: use a new IM for each member of the group, otherwise the fields get messed up because the transfer is async --- OpenSim/Addons/Groups/GroupsModule.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs index da8030c..830c671 100644 --- a/OpenSim/Addons/Groups/GroupsModule.cs +++ b/OpenSim/Addons/Groups/GroupsModule.cs @@ -467,12 +467,12 @@ namespace OpenSim.Groups } // Send notice out to everyone that wants notices - // Build notice IIM - GridInstantMessage msg = CreateGroupNoticeIM(UUID.Zero, NoticeID, (byte)OpenMetaverse.InstantMessageDialog.GroupNotice); foreach (GroupMembersData member in m_groupData.GetGroupMembers(GetRequestingAgentIDStr(remoteClient), GroupID)) { if (member.AcceptNotices) { + // Build notice IIM, one of reach, because the sending may be async + GridInstantMessage msg = CreateGroupNoticeIM(UUID.Zero, NoticeID, (byte)OpenMetaverse.InstantMessageDialog.GroupNotice); msg.toAgentID = member.AgentID.Guid; OutgoingInstantMessage(msg, member.AgentID); } -- cgit v1.1 From 377fe63c60b6632777da5f0a8a0c4c2d32a1f4ac Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 12 Aug 2013 21:02:50 +0100 Subject: Don't try and send group updates to NPCs via event queue, since NPCs have no event queue. I think there is an argument for sending this information to NPCs anyway since in some cases it appears a lot easier to write server-side bots by hooking into such internal events. However, would need to stop event messages building up on NPC queues if they are never retrieved. --- OpenSim/Addons/Groups/GroupsModule.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs index 830c671..b0493fa 100644 --- a/OpenSim/Addons/Groups/GroupsModule.cs +++ b/OpenSim/Addons/Groups/GroupsModule.cs @@ -1223,12 +1223,16 @@ namespace OpenSim.Groups { if (m_debugEnabled) m_log.InfoFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + // NPCs currently don't have a CAPs structure or event queues. There is a strong argument for conveying this information + // to them anyway since it makes writing server-side bots a lot easier, but for now we don't do anything. + if (remoteClient.SceneAgent.PresenceType == PresenceType.Npc) + return; + OSDArray AgentData = new OSDArray(1); OSDMap AgentDataMap = new OSDMap(1); AgentDataMap.Add("AgentID", OSD.FromUUID(dataForAgentID)); AgentData.Add(AgentDataMap); - OSDArray GroupData = new OSDArray(data.Length); OSDArray NewGroupData = new OSDArray(data.Length); @@ -1274,8 +1278,7 @@ namespace OpenSim.Groups if (queue != null) { queue.Enqueue(queue.BuildEvent("AgentGroupDataUpdate", llDataStruct), GetRequestingAgentID(remoteClient)); - } - + } } private void SendScenePresenceUpdate(UUID AgentID, string Title) @@ -1337,6 +1340,7 @@ namespace OpenSim.Groups GroupMembershipData[] membershipArray = GetProfileListedGroupMemberships(remoteClient, dataForAgentID); SendGroupMembershipInfoViaCaps(remoteClient, dataForAgentID, membershipArray); + //remoteClient.SendAvatarGroupsReply(dataForAgentID, membershipArray); if (remoteClient.AgentId == dataForAgentID) remoteClient.RefreshGroupMembership(); -- cgit v1.1 From e311f902ffeb0c1f36d6d4288e65d965d13a9fbe Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 13 Aug 2013 20:13:12 +0100 Subject: minor: Eliminate one of the duplicate 'have's in the HG message telling the user if no GroupsServerURI has been given in user data by the home grid --- OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs b/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs index c33168c..4642b2a 100644 --- a/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs +++ b/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs @@ -404,7 +404,7 @@ namespace OpenSim.Groups url = m_UserManagement.GetUserServerURL(uid, "GroupsServerURI"); if (url == string.Empty) { - reason = "You don't have have an accessible groups server in your home world. You membership to this group in only within this grid."; + reason = "You don't have an accessible groups server in your home world. You membership to this group in only within this grid."; return true; } -- cgit v1.1 From 04619a9b139ac67c92b5b8be9607544be2621d7e Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Thu, 5 Sep 2013 07:44:27 -0700 Subject: Restore group membership check for HG users in QueryAccess. --- .../Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs b/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs index 4642b2a..7d48516 100644 --- a/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs +++ b/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs @@ -623,10 +623,13 @@ namespace OpenSim.Groups if (agent != null) break; } - if (agent == null) // oops - return AgentID.ToString(); + if (agent != null) + return Util.ProduceUserUniversalIdentifier(agent); + + // we don't know anything about this foreign user + // try asking the user management module, which may know more + return m_UserManagement.GetUserUUI(AgentID); - return Util.ProduceUserUniversalIdentifier(agent); } private string AgentUUIForOutside(string AgentIDStr) -- cgit v1.1 From 42bdf446585007029faf4cd21abd289487f0f797 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 4 Oct 2013 23:33:47 +0100 Subject: Bump OPenSimulator version and assembly versions up to 0.8.0 Dev --- OpenSim/Addons/Groups/Properties/AssemblyInfo.cs | 2 +- OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs b/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs index 5ccd7fe..16fe03b 100644 --- a/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs +++ b/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs @@ -30,7 +30,7 @@ using Mono.Addins; // Build Number // Revision // -[assembly: AssemblyVersion("0.7.6.*")] +[assembly: AssemblyVersion("0.8.0.*")] [assembly: Addin("OpenSim.Groups", "0.1")] [assembly: AddinDependency("OpenSim", "0.5")] diff --git a/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs b/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs index ffe8a3e..5d71edc 100644 --- a/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs +++ b/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs @@ -30,7 +30,7 @@ using Mono.Addins; // Build Number // Revision // -[assembly: AssemblyVersion("0.7.6.*")] +[assembly: AssemblyVersion("0.8.0.*")] [assembly: Addin("OpenSim.OfflineIM", "0.1")] [assembly: AddinDependency("OpenSim", "0.5")] -- cgit v1.1 From 7cab41f4223b7febd3fdd42fa7cfefef25e4a9c9 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 15 Nov 2013 21:45:08 +0000 Subject: refactor: replace verbose checks with String.IsNullOrEmpty where applicable. Thanks to Kira for this patch from http://opensimulator.org/mantis/view.php?id=6845 --- OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnector.cs | 4 ++-- OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnector.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnector.cs b/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnector.cs index 59fec6f..653dbac 100644 --- a/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnector.cs +++ b/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnector.cs @@ -101,7 +101,7 @@ namespace OpenSim.Groups Dictionary sendData = new Dictionary(); if (GroupID != UUID.Zero) sendData["GroupID"] = GroupID.ToString(); - if (GroupName != null && GroupName != string.Empty) + if (!string.IsNullOrEmpty(GroupName)) sendData["Name"] = GroupsDataUtils.Sanitize(GroupName); sendData["RequestingAgentID"] = RequestingAgentID; @@ -275,7 +275,7 @@ namespace OpenSim.Groups //m_log.DebugFormat("[XXX]: reply was {0}", reply); - if (reply == string.Empty || reply == null) + if (string.IsNullOrEmpty(reply)) return null; Dictionary replyData = ServerUtils.ParseXmlResponse( diff --git a/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnector.cs b/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnector.cs index 161ca0c..ed41978 100644 --- a/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnector.cs +++ b/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnector.cs @@ -120,7 +120,7 @@ namespace OpenSim.Groups Dictionary sendData = new Dictionary(); if (GroupID != UUID.Zero) sendData["GroupID"] = GroupID.ToString(); - if (GroupName != null && GroupName != string.Empty) + if (!string.IsNullOrEmpty(GroupName)) sendData["Name"] = GroupsDataUtils.Sanitize(GroupName); sendData["RequestingAgentID"] = RequestingAgentID; -- cgit v1.1 From 21bc799a17f6f0315256d901f3ec226a39f93a51 Mon Sep 17 00:00:00 2001 From: Oren Hurvitz Date: Thu, 9 Jan 2014 18:34:10 +0200 Subject: Fixed offline IM --- OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs b/OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs index 6731923..d36f9a4 100644 --- a/OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs +++ b/OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) Contributors, http://opensimulator.org/ * See CONTRIBUTORS.TXT for a full list of copyright holders. * @@ -100,7 +100,7 @@ namespace OpenSim.OfflineIM return false; } - string imXml = string.Empty; + string imXml; using (MemoryStream mstream = new MemoryStream()) { XmlWriterSettings settings = new XmlWriterSettings(); @@ -110,13 +110,9 @@ namespace OpenSim.OfflineIM { m_serializer.Serialize(writer, im); writer.Flush(); - - mstream.Position = 0; - using (StreamReader sreader = new StreamReader(mstream)) - { - imXml = sreader.ReadToEnd(); - } } + + imXml = Util.UTF8.GetString(mstream.ToArray()); } OfflineIMData data = new OfflineIMData(); -- cgit v1.1 From 46c2791fe2f9ea92535d3933602e24dcba8f96f9 Mon Sep 17 00:00:00 2001 From: Oren Hurvitz Date: Tue, 29 Oct 2013 16:03:58 +0200 Subject: In the offline message table, store the sender. This data is useful for preventing abuse (e.g., someone who sends too many messages), or for deleting message if their sender has been deleted. --- OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRobustConnector.cs | 3 +-- OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRobustConnector.cs b/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRobustConnector.cs index 32c24db..6158abc 100644 --- a/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRobustConnector.cs +++ b/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRobustConnector.cs @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) Contributors, http://opensimulator.org/ * See CONTRIBUTORS.TXT for a full list of copyright holders. * @@ -96,7 +96,6 @@ namespace OpenSim.OfflineIM string method = request["METHOD"].ToString(); request.Remove("METHOD"); - m_log.DebugFormat("[OfflineIM.V2.Handler]: {0}", method); switch (method) { case "GET": diff --git a/OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs b/OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs index d36f9a4..df0c53f 100644 --- a/OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs +++ b/OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs @@ -91,7 +91,7 @@ namespace OpenSim.OfflineIM { reason = string.Empty; - // TODO Check limits + // Check limits UUID principalID = new UUID(im.toAgentID); long count = m_Database.GetCount("PrincipalID", principalID.ToString()); if (count >= MAX_IM) @@ -117,6 +117,7 @@ namespace OpenSim.OfflineIM OfflineIMData data = new OfflineIMData(); data.PrincipalID = principalID; + data.FromID = new UUID(im.fromAgentID); data.Data = new Dictionary(); data.Data["Message"] = imXml; -- cgit v1.1 From 2d9d6fe922c99e79489b19b18ac33338012137ff Mon Sep 17 00:00:00 2001 From: Oren Hurvitz Date: Tue, 29 Oct 2013 16:38:03 +0200 Subject: Can delete the Offline Messages sent to/from a user. This is useful if the user is deleted. --- OpenSim/Addons/OfflineIM/OfflineIMRegionModule.cs | 5 +++++ .../OfflineIM/Remote/OfflineIMServiceRemoteConnector.cs | 8 ++++++++ .../OfflineIM/Remote/OfflineIMServiceRobustConnector.cs | 17 +++++++++++++++++ OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs | 7 +++++++ 4 files changed, 37 insertions(+) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/OfflineIM/OfflineIMRegionModule.cs b/OpenSim/Addons/OfflineIM/OfflineIMRegionModule.cs index 050ebd2..5ef068a 100644 --- a/OpenSim/Addons/OfflineIM/OfflineIMRegionModule.cs +++ b/OpenSim/Addons/OfflineIM/OfflineIMRegionModule.cs @@ -261,6 +261,11 @@ namespace OpenSim.OfflineIM return m_OfflineIMService.StoreMessage(im, out reason); } + public void DeleteMessages(UUID userID) + { + m_OfflineIMService.DeleteMessages(userID); + } + #endregion } } diff --git a/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRemoteConnector.cs b/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRemoteConnector.cs index 69feb76..f6b17e5 100644 --- a/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRemoteConnector.cs +++ b/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRemoteConnector.cs @@ -117,6 +117,14 @@ namespace OpenSim.OfflineIM return true; } + public void DeleteMessages(UUID userID) + { + Dictionary sendData = new Dictionary(); + sendData["UserID"] = userID; + + MakeRequest("DELETE", sendData); + } + #endregion diff --git a/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRobustConnector.cs b/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRobustConnector.cs index 6158abc..13b0e7e 100644 --- a/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRobustConnector.cs +++ b/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRobustConnector.cs @@ -102,6 +102,8 @@ namespace OpenSim.OfflineIM return HandleGet(request); case "STORE": return HandleStore(request); + case "DELETE": + return HandleDelete(request); } m_log.DebugFormat("[OFFLINE IM HANDLER]: unknown method request: {0}", method); } @@ -158,6 +160,21 @@ namespace OpenSim.OfflineIM return Util.UTF8NoBomEncoding.GetBytes(xmlString); } + byte[] HandleDelete(Dictionary request) + { + if (!request.ContainsKey("UserID")) + { + return FailureResult(); + } + else + { + UUID userID = new UUID(request["UserID"].ToString()); + m_OfflineIMService.DeleteMessages(userID); + + return SuccessResult(); + } + } + #region Helpers private void NullResult(Dictionary result, string reason) diff --git a/OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs b/OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs index df0c53f..690c955 100644 --- a/OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs +++ b/OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs @@ -124,5 +124,12 @@ namespace OpenSim.OfflineIM return m_Database.Store(data); } + + public void DeleteMessages(UUID userID) + { + m_Database.Delete("PrincipalID", userID.ToString()); + m_Database.Delete("FromID", userID.ToString()); + } + } } -- cgit v1.1 From d1bb73d068077c7ca884fa5d326bbfb5ec5b850b Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 20 Feb 2014 19:17:21 +0000 Subject: In core.groups GroupsServiceRemoveConnector, if GetGroupRecord() or UpdateGroup() do not have a RESULT parameter in the result message, return null rather than fail with NullReferenceException This check was already done by other methods. Looks to resolve http://opensimulator.org/mantis/view.php?id=7012 --- OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnector.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnector.cs b/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnector.cs index ed41978..67402a2 100644 --- a/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnector.cs +++ b/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnector.cs @@ -106,7 +106,7 @@ namespace OpenSim.Groups sendData["OP"] = "UPDATE"; Dictionary ret = MakeRequest("PUTGROUP", sendData); - if (ret == null || (ret != null && ret["RESULT"].ToString() == "NULL")) + if (ret == null || (ret != null && (!ret.ContainsKey("RESULT") || ret["RESULT"].ToString() == "NULL"))) return null; return GroupsDataUtils.GroupRecord((Dictionary)ret["RESULT"]); @@ -127,7 +127,7 @@ namespace OpenSim.Groups Dictionary ret = MakeRequest("GETGROUP", sendData); - if (ret == null || (ret != null && ret["RESULT"].ToString() == "NULL")) + if (ret == null || (ret != null && (!ret.ContainsKey("RESULT") || ret["RESULT"].ToString() == "NULL"))) return null; return GroupsDataUtils.GroupRecord((Dictionary)ret["RESULT"]); @@ -267,6 +267,7 @@ namespace OpenSim.Groups if (ret["RESULT"].ToString() == "NULL") return members; + foreach (object v in ((Dictionary)ret["RESULT"]).Values) { ExtendedGroupMembersData m = GroupsDataUtils.GroupMembersData((Dictionary)v); @@ -357,6 +358,7 @@ namespace OpenSim.Groups if (ret["RESULT"].ToString() == "NULL") return roles; + foreach (object v in ((Dictionary)ret["RESULT"]).Values) { GroupRolesData m = GroupsDataUtils.GroupRolesData((Dictionary)v); @@ -667,7 +669,7 @@ namespace OpenSim.Groups return replyData; } - #endregion + #endregion } -} +} \ No newline at end of file -- cgit v1.1 From 77e7bbcbf753018074211ca8358c642dd7204f42 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 11 Mar 2014 00:11:18 +0000 Subject: Send group notices through the same messaging module mechanism used to send group chat to avoid timeout issues when sending messages to large groups. Only implementing for XmlRpcGroups initially to test. May require MessageOnlineUsersOnly = true in [Groups] to be effective. In relation to http://opensimulator.org/mantis/view.php?id=7037 --- OpenSim/Addons/Groups/GroupsMessagingModule.cs | 29 ++++++++++++++++++++------ OpenSim/Addons/Groups/GroupsModule.cs | 4 +--- 2 files changed, 24 insertions(+), 9 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsMessagingModule.cs b/OpenSim/Addons/Groups/GroupsMessagingModule.cs index be59c62..f701e48 100644 --- a/OpenSim/Addons/Groups/GroupsMessagingModule.cs +++ b/OpenSim/Addons/Groups/GroupsMessagingModule.cs @@ -172,10 +172,8 @@ namespace OpenSim.Groups return; } - if (m_presenceService == null) m_presenceService = scene.PresenceService; - } public void RemoveRegion(Scene scene) @@ -222,7 +220,6 @@ namespace OpenSim.Groups #endregion - /// /// Not really needed, but does confirm that the group exists. /// @@ -242,9 +239,14 @@ namespace OpenSim.Groups return false; } } - + public void SendMessageToGroup(GridInstantMessage im, UUID groupID) { + SendMessageToGroup(im, groupID, null); + } + + public void SendMessageToGroup(GridInstantMessage im, UUID groupID, Func sendCondition) + { UUID fromAgentID = new UUID(im.fromAgentID); List groupMembers = m_groupData.GetGroupMembers(UUID.Zero.ToString(), groupID); int groupMembersCount = groupMembers.Count; @@ -299,12 +301,27 @@ namespace OpenSim.Groups if (clientsAlreadySent.Contains(member.AgentID)) continue; + clientsAlreadySent.Add(member.AgentID); - if (hasAgentDroppedGroupChatSession(member.AgentID.ToString(), groupID)) + if (sendCondition != null) + { + if (!sendCondition(member)) + { + if (m_debugEnabled) + m_log.DebugFormat( + "[Groups.Messaging]: Not sending to {0} as they do not fulfill send condition", + member.AgentID); + + continue; + } + } + else if (hasAgentDroppedGroupChatSession(member.AgentID.ToString(), groupID)) { // Don't deliver messages to people who have dropped this session - if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: {0} has dropped session, not delivering to them", member.AgentID); + if (m_debugEnabled) + m_log.DebugFormat("[Groups.Messaging]: {0} has dropped session, not delivering to them", member.AgentID); + continue; } diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs index b0493fa..7f453db 100644 --- a/OpenSim/Addons/Groups/GroupsModule.cs +++ b/OpenSim/Addons/Groups/GroupsModule.cs @@ -45,9 +45,6 @@ namespace OpenSim.Groups [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GroupsModule")] public class GroupsModule : ISharedRegionModule, IGroupsModule { - /// - /// - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -466,6 +463,7 @@ namespace OpenSim.Groups OnNewGroupNotice(GroupID, NoticeID); } + // Send notice out to everyone that wants notices foreach (GroupMembersData member in m_groupData.GetGroupMembers(GetRequestingAgentIDStr(remoteClient), GroupID)) { -- cgit v1.1 From beba20846f1935e2769f78fb0c87746cf77a6b50 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 12 Mar 2014 19:31:04 +0000 Subject: When sending group notices through group messaging, allow the agent ID to use for fetching group data to be different from im.fromAgentID This is because xmlrpcgroups currently always checks visibility for the requesting agent ID (unlike Groups v2, which can accept UUID.Zero) But group notice IMs have a from agent which is the group rather than the sending agent. Further addresses http://opensimulator.org/mantis/view.php?id=7037 --- OpenSim/Addons/Groups/GroupsMessagingModule.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsMessagingModule.cs b/OpenSim/Addons/Groups/GroupsMessagingModule.cs index f701e48..92528a2 100644 --- a/OpenSim/Addons/Groups/GroupsMessagingModule.cs +++ b/OpenSim/Addons/Groups/GroupsMessagingModule.cs @@ -83,7 +83,6 @@ namespace OpenSim.Groups private Dictionary> m_groupsAgentsDroppedFromChatSession = new Dictionary>(); private Dictionary> m_groupsAgentsInvitedToChatSession = new Dictionary>(); - #region Region Module interfaceBase Members public void Initialise(IConfigSource config) @@ -242,13 +241,18 @@ namespace OpenSim.Groups public void SendMessageToGroup(GridInstantMessage im, UUID groupID) { - SendMessageToGroup(im, groupID, null); + SendMessageToGroup(im, groupID, UUID.Zero, null); } - public void SendMessageToGroup(GridInstantMessage im, UUID groupID, Func sendCondition) + public void SendMessageToGroup( + GridInstantMessage im, UUID groupID, UUID sendingAgentForGroupCalls, Func sendCondition) { UUID fromAgentID = new UUID(im.fromAgentID); + + // Unlike current XmlRpcGroups, Groups V2 can accept UUID.Zero when a perms check for the requesting agent + // is not necessary. List groupMembers = m_groupData.GetGroupMembers(UUID.Zero.ToString(), groupID); + int groupMembersCount = groupMembers.Count; PresenceInfo[] onlineAgents = null; -- cgit v1.1 From 6734b94761a4a8b1d03ea97fd6832c51af32bd8c Mon Sep 17 00:00:00 2001 From: Oren Hurvitz Date: Wed, 30 Oct 2013 15:10:29 +0200 Subject: Better error messages This resolves http://opensimulator.org/mantis/view.php?id=6936 --- OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs | 4 ++-- OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs | 2 +- OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRobustConnector.cs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs b/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs index d2bcba5..dc36787 100644 --- a/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs +++ b/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) Contributors, http://opensimulator.org/ * See CONTRIBUTORS.TXT for a full list of copyright holders. * @@ -158,7 +158,7 @@ namespace OpenSim.Groups } catch (Exception e) { - m_log.DebugFormat("[Groups.RobustHGConnector]: Exception {0}", e.StackTrace); + m_log.Error(string.Format("[Groups.RobustHGConnector]: Exception {0} ", e.Message), e); } return FailureResult(); diff --git a/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs b/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs index 249d974..616afa9 100644 --- a/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs +++ b/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs @@ -140,7 +140,7 @@ namespace OpenSim.Groups } catch (Exception e) { - m_log.DebugFormat("[GROUPS HANDLER]: Exception {0}", e.StackTrace); + m_log.Error(string.Format("[GROUPS HANDLER]: Exception {0} ", e.Message), e); } return FailureResult(); diff --git a/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRobustConnector.cs b/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRobustConnector.cs index 13b0e7e..ed5c742 100644 --- a/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRobustConnector.cs +++ b/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRobustConnector.cs @@ -109,7 +109,7 @@ namespace OpenSim.OfflineIM } catch (Exception e) { - m_log.DebugFormat("[OFFLINE IM HANDLER]: Exception {0}", e.StackTrace); + m_log.Error(string.Format("[OFFLINE IM HANDLER]: Exception {0} ", e.Message), e); } return FailureResult(); -- cgit v1.1 From 1d4551e52fc02db9393c5c3653139c671a2e6c97 Mon Sep 17 00:00:00 2001 From: Oren Hurvitz Date: Wed, 30 Oct 2013 15:59:53 +0200 Subject: Check settings for groups module Resolves http://opensimulator.org/mantis/view.php?id=6937 --- OpenSim/Addons/Groups/GroupsMessagingModule.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsMessagingModule.cs b/OpenSim/Addons/Groups/GroupsMessagingModule.cs index 92528a2..bbb5e05 100644 --- a/OpenSim/Addons/Groups/GroupsMessagingModule.cs +++ b/OpenSim/Addons/Groups/GroupsMessagingModule.cs @@ -110,7 +110,15 @@ namespace OpenSim.Groups m_messageOnlineAgentsOnly = groupsConfig.GetBoolean("MessageOnlineUsersOnly", false); if (m_messageOnlineAgentsOnly) + { m_usersOnlineCache = new ExpiringCache(); + } + else + { + m_log.Error("[Groups.Messaging]: GroupsMessagingModule V2 requires MessageOnlineUsersOnly = true"); + m_groupMessagingEnabled = false; + return; + } m_debugEnabled = groupsConfig.GetBoolean("DebugEnabled", true); @@ -260,7 +268,7 @@ namespace OpenSim.Groups // Sending to offline members is not an option. string[] t1 = groupMembers.ConvertAll(gmd => gmd.AgentID.ToString()).ToArray(); - // We cache in order not to overwhlem the presence service on large grids with many groups. This does + // We cache in order not to overwhelm the presence service on large grids with many groups. This does // mean that members coming online will not see all group members until after m_usersOnlineCacheExpirySeconds has elapsed. // (assuming this is the same across all grid simulators). if (!m_usersOnlineCache.TryGetValue(groupID, out onlineAgents)) -- cgit v1.1 From 8276a9e5f7f91e6c774658228df7bf84f45fc252 Mon Sep 17 00:00:00 2001 From: Oren Hurvitz Date: Sun, 1 Dec 2013 14:35:17 +0200 Subject: Fixed Debug command for Groups. (Use of wrong capitalization caused *two* "debug" options to appear in "help") This is a (small) part of http://opensimulator.org/mantis/view.php?id=6949 --- OpenSim/Addons/Groups/GroupsModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs index 7f453db..f11606a 100644 --- a/OpenSim/Addons/Groups/GroupsModule.cs +++ b/OpenSim/Addons/Groups/GroupsModule.cs @@ -101,7 +101,7 @@ namespace OpenSim.Groups { scene.RegisterModuleInterface(this); scene.AddCommand( - "debug", + "Debug", this, "debug groups verbose", "debug groups verbose ", -- cgit v1.1 From 7a47c15edbbebd93fc3355dfed68c2d5f635c897 Mon Sep 17 00:00:00 2001 From: Oren Hurvitz Date: Wed, 26 Mar 2014 21:31:16 +0200 Subject: - Increased the threadpool timeout to 10 minutes - Changed a few places that launch long-lasting threads to skip the timeout altogether --- OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs b/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs index 7d48516..a750d8d 100644 --- a/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs +++ b/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) Contributors, http://opensimulator.org/ * See CONTRIBUTORS.TXT for a full list of copyright holders. * @@ -560,7 +560,7 @@ namespace OpenSim.Groups // so we have the list of urls to send the notice to // this may take a long time... - Util.FireAndForget(delegate + Util.RunThreadNoTimeout(delegate { foreach (string u in urls) { @@ -571,7 +571,7 @@ namespace OpenSim.Groups hasAttachment, attType, attName, attItemID, AgentUUIForOutside(attOwnerID)); } } - }); + }, "AddGroupNotice", null); return true; } -- cgit v1.1 From 538ff31b284298083bdb0c6c998e4bae9a369f98 Mon Sep 17 00:00:00 2001 From: Oren Hurvitz Date: Mon, 21 Apr 2014 09:01:42 +0300 Subject: Better error handling when retrieving offline IMs --- .../Addons/OfflineIM/Remote/OfflineIMServiceRemoteConnector.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRemoteConnector.cs b/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRemoteConnector.cs index f6b17e5..eb287a4 100644 --- a/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRemoteConnector.cs +++ b/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRemoteConnector.cs @@ -82,8 +82,13 @@ namespace OpenSim.OfflineIM if (!ret.ContainsKey("RESULT")) return ims; - if (ret["RESULT"].ToString() == "NULL") + string result = ret["RESULT"].ToString(); + if (result == "NULL" || result.ToLower() == "false") + { + string reason = ret.ContainsKey("REASON") ? ret["REASON"].ToString() : "Unknown error"; + m_log.DebugFormat("[OfflineIM.V2.RemoteConnector]: GetMessages for {0} failed: {1}", principalID, reason); return ims; + } foreach (object v in ((Dictionary)ret["RESULT"]).Values) { @@ -110,7 +115,7 @@ namespace OpenSim.OfflineIM string result = ret["RESULT"].ToString(); if (result == "NULL" || result.ToLower() == "false") { - reason = ret["REASON"].ToString(); + reason = ret.ContainsKey("REASON") ? ret["REASON"].ToString() : "Unknown error"; return false; } -- cgit v1.1 From 5a10da3ee89934e366c1d69833b81605dbc35017 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sat, 3 May 2014 17:13:53 -0700 Subject: Added a optional key between the group remote connectors, sim and service. This allows for more secure group services, to be used by collections of mutually-trusting grids. --- .../Groups/Remote/GroupsServiceRemoteConnector.cs | 8 +++-- .../Remote/GroupsServiceRemoteConnectorModule.cs | 3 +- .../Groups/Remote/GroupsServiceRobustConnector.cs | 38 ++++++++++++++++++++-- 3 files changed, 44 insertions(+), 5 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnector.cs b/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnector.cs index 67402a2..1425a23 100644 --- a/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnector.cs +++ b/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnector.cs @@ -44,15 +44,17 @@ namespace OpenSim.Groups private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private string m_ServerURI; + private string m_SecretKey; private object m_Lock = new object(); - public GroupsServiceRemoteConnector(string url) + public GroupsServiceRemoteConnector(string url, string secret) { m_ServerURI = url; if (!m_ServerURI.EndsWith("/")) m_ServerURI += "/"; - m_log.DebugFormat("[Groups.RemoteConnector]: Groups server at {0}", m_ServerURI); + m_SecretKey = secret; + m_log.DebugFormat("[Groups.RemoteConnector]: Groups server at {0}, secret key {1}", m_ServerURI, m_SecretKey); } public ExtendedGroupRecord CreateGroup(string RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, @@ -654,6 +656,8 @@ namespace OpenSim.Groups private Dictionary MakeRequest(string method, Dictionary sendData) { sendData["METHOD"] = method; + if (m_SecretKey != string.Empty) + sendData["KEY"] = m_SecretKey; string reply = string.Empty; lock (m_Lock) diff --git a/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnectorModule.cs b/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnectorModule.cs index d3de0e8..5fb3c19 100644 --- a/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnectorModule.cs +++ b/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnectorModule.cs @@ -77,7 +77,8 @@ namespace OpenSim.Groups if (!Uri.IsWellFormedUriString(url, UriKind.Absolute)) throw new Exception(string.Format("[Groups.RemoteConnector]: Malformed groups server URL {0}. Fix it or disable the Groups feature.", url)); - m_GroupsService = new GroupsServiceRemoteConnector(url); + string secret = groupsConfig.GetString("SecretKey", string.Empty); + m_GroupsService = new GroupsServiceRemoteConnector(url, secret); m_Scenes = new List(); } diff --git a/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs b/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs index 616afa9..828965f 100644 --- a/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs +++ b/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs @@ -52,14 +52,24 @@ namespace OpenSim.Groups public GroupsServiceRobustConnector(IConfigSource config, IHttpServer server, string configName) : base(config, server, configName) { + string key = string.Empty; if (configName != String.Empty) m_ConfigName = configName; m_log.DebugFormat("[Groups.RobustConnector]: Starting with config name {0}", m_ConfigName); + IConfig groupsConfig = config.Configs[m_ConfigName]; + if (groupsConfig != null) + { + key = groupsConfig.GetString("SecretKey", string.Empty); + m_log.DebugFormat("[Groups.RobustConnector]: Starting with secret key {0}", key); + } + else + m_log.WarnFormat("[Groups.RobustConnector]: Unable to find {0} section in configuration", m_ConfigName); + m_GroupsService = new GroupsService(config); - server.AddStreamHandler(new GroupsServicePostHandler(m_GroupsService)); + server.AddStreamHandler(new GroupsServicePostHandler(m_GroupsService, key)); } } @@ -68,11 +78,13 @@ namespace OpenSim.Groups private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private GroupsService m_GroupsService; + private string m_SecretKey = String.Empty; - public GroupsServicePostHandler(GroupsService service) : + public GroupsServicePostHandler(GroupsService service, string key) : base("POST", "/groups") { m_GroupsService = service; + m_SecretKey = key; } protected override byte[] ProcessRequest(string path, Stream requestData, @@ -96,6 +108,20 @@ namespace OpenSim.Groups string method = request["METHOD"].ToString(); request.Remove("METHOD"); + if (!String.IsNullOrEmpty(m_SecretKey)) // Verification required + { + // Sender didn't send key + if (!request.ContainsKey("KEY") || (request["KEY"] == null)) + return FailureResult("This service requires a secret key"); + + // Sender sent wrong key + if (!m_SecretKey.Equals(request["KEY"])) + return FailureResult("Provided key does not match existing one"); + + // OK, key matches. Remove it. + request.Remove("KEY"); + } + m_log.DebugFormat("[Groups.Handler]: {0}", method); switch (method) { @@ -784,6 +810,14 @@ namespace OpenSim.Groups string xmlString = ServerUtils.BuildXmlResponse(result); return Util.UTF8NoBomEncoding.GetBytes(xmlString); } + + private byte[] FailureResult(string reason) + { + Dictionary result = new Dictionary(); + NullResult(result, reason); + string xmlString = ServerUtils.BuildXmlResponse(result); + return Util.UTF8NoBomEncoding.GetBytes(xmlString); + } #endregion } } -- cgit v1.1 From 1e5cff32fc41356971d6ad601cbee7ad62472c76 Mon Sep 17 00:00:00 2001 From: Oren Hurvitz Date: Mon, 5 May 2014 11:06:49 +0300 Subject: Show more meaningful error messages when failed to give an item to another user --- OpenSim/Addons/Groups/GroupsModule.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs index f11606a..2831326 100644 --- a/OpenSim/Addons/Groups/GroupsModule.cs +++ b/OpenSim/Addons/Groups/GroupsModule.cs @@ -496,12 +496,13 @@ namespace OpenSim.Groups Util.ParseUniversalUserIdentifier(notice.noticeData.AttachmentOwnerID, out giver, out tmp, out tmp, out tmp, out tmp); m_log.DebugFormat("[Groups]: Giving inventory from {0} to {1}", giver, remoteClient.AgentId); + string message; InventoryItemBase itemCopy = ((Scene)(remoteClient.Scene)).GiveInventoryItem(remoteClient.AgentId, - giver, notice.noticeData.AttachmentItemID); + giver, notice.noticeData.AttachmentItemID, out message); if (itemCopy == null) { - remoteClient.SendAgentAlertMessage("Can't find item to give. Nothing given.", false); + remoteClient.SendAgentAlertMessage(message, false); return; } -- cgit v1.1 From 8457044b2f46e477442e3dec520c9a47ca20dd6b Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 12 May 2014 22:23:24 +0100 Subject: Eliminate subsequently unused scene finding in UndeliveredMessage() method of xmlrpc and core offline IM modules --- OpenSim/Addons/OfflineIM/OfflineIMRegionModule.cs | 4 ---- 1 file changed, 4 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/OfflineIM/OfflineIMRegionModule.cs b/OpenSim/Addons/OfflineIM/OfflineIMRegionModule.cs index 5ef068a..950e1fd 100644 --- a/OpenSim/Addons/OfflineIM/OfflineIMRegionModule.cs +++ b/OpenSim/Addons/OfflineIM/OfflineIMRegionModule.cs @@ -226,10 +226,6 @@ namespace OpenSim.OfflineIM return; } - Scene scene = FindScene(new UUID(im.fromAgentID)); - if (scene == null) - scene = m_SceneList[0]; - string reason = string.Empty; bool success = m_OfflineIMService.StoreMessage(im, out reason); -- cgit v1.1 From d2c738fc09e4b4c9668cf5fb0114f909b6d6b808 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 15 May 2014 22:48:05 +0100 Subject: Don't warn on not seeing [Groups] Robust section for core groups as this does not contain any mandatory parameters and won't be present on older installations. --- OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs b/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs index 828965f..33dc301 100644 --- a/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs +++ b/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs @@ -64,8 +64,8 @@ namespace OpenSim.Groups key = groupsConfig.GetString("SecretKey", string.Empty); m_log.DebugFormat("[Groups.RobustConnector]: Starting with secret key {0}", key); } - else - m_log.WarnFormat("[Groups.RobustConnector]: Unable to find {0} section in configuration", m_ConfigName); +// else +// m_log.DebugFormat("[Groups.RobustConnector]: Unable to find {0} section in configuration", m_ConfigName); m_GroupsService = new GroupsService(config); -- cgit v1.1 From b46be88db62bcfa7dcf70c3677a1a1270d177a22 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 19 May 2014 22:45:17 +0100 Subject: Split verbose groups messaging logging into its own setting separate from that of the groups module. This is to allow us to get useful information on messaging without being overwhelmed by the rest of groups debug. Enabled with [Groups] DebugMessagingEnabled = true in config (default false) Or "debug groups messaging verbose true|false on the console" (similar to existing groups setting). Done for both xmlrpc and V2 groups. --- OpenSim/Addons/Groups/GroupsMessagingModule.cs | 34 +++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsMessagingModule.cs b/OpenSim/Addons/Groups/GroupsMessagingModule.cs index bbb5e05..bd8db32 100644 --- a/OpenSim/Addons/Groups/GroupsMessagingModule.cs +++ b/OpenSim/Addons/Groups/GroupsMessagingModule.cs @@ -56,8 +56,8 @@ namespace OpenSim.Groups private IGroupsServicesConnector m_groupData = null; // Config Options - private bool m_groupMessagingEnabled = false; - private bool m_debugEnabled = true; + private bool m_groupMessagingEnabled; + private bool m_debugEnabled; /// /// If enabled, module only tries to send group IMs to online users by querying cached presence information. @@ -120,7 +120,7 @@ namespace OpenSim.Groups return; } - m_debugEnabled = groupsConfig.GetBoolean("DebugEnabled", true); + m_debugEnabled = groupsConfig.GetBoolean("MessagingDebugEnabled", m_debugEnabled); m_log.InfoFormat( "[Groups.Messaging]: GroupsMessagingModule enabled with MessageOnlineOnly = {0}, DebugEnabled = {1}", @@ -140,6 +140,14 @@ namespace OpenSim.Groups scene.EventManager.OnMakeChildAgent += OnMakeChildAgent; scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; scene.EventManager.OnClientLogin += OnClientLogin; + + scene.AddCommand( + "Debug", + this, + "debug groups messaging verbose", + "debug groups messaging verbose ", + "This setting turns on very verbose groups messaging debugging", + HandleDebugGroupsMessagingVerbose); } public void RegionLoaded(Scene scene) @@ -227,6 +235,26 @@ namespace OpenSim.Groups #endregion + private void HandleDebugGroupsMessagingVerbose(object modules, string[] args) + { + if (args.Length < 5) + { + MainConsole.Instance.Output("Usage: debug groups messaging verbose "); + return; + } + + bool verbose = false; + if (!bool.TryParse(args[4], out verbose)) + { + MainConsole.Instance.Output("Usage: debug groups messaging verbose "); + return; + } + + m_debugEnabled = verbose; + + MainConsole.Instance.OutputFormat("{0} verbose logging set to {1}", Name, m_debugEnabled); + } + /// /// Not really needed, but does confirm that the group exists. /// -- cgit v1.1 From 5ec3429843ecb8058698f663556ae1d4cae53434 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 19 May 2014 23:01:48 +0100 Subject: On verbose groups messaging logging, count all operations in reported time when sending group messages, not just those after get group members and get presence status, as applicable --- OpenSim/Addons/Groups/GroupsMessagingModule.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsMessagingModule.cs b/OpenSim/Addons/Groups/GroupsMessagingModule.cs index bd8db32..e6a4765 100644 --- a/OpenSim/Addons/Groups/GroupsMessagingModule.cs +++ b/OpenSim/Addons/Groups/GroupsMessagingModule.cs @@ -283,6 +283,8 @@ namespace OpenSim.Groups public void SendMessageToGroup( GridInstantMessage im, UUID groupID, UUID sendingAgentForGroupCalls, Func sendCondition) { + int requestStartTick = Environment.TickCount; + UUID fromAgentID = new UUID(im.fromAgentID); // Unlike current XmlRpcGroups, Groups V2 can accept UUID.Zero when a perms check for the requesting agent @@ -315,8 +317,6 @@ namespace OpenSim.Groups // "[Groups.Messaging]: SendMessageToGroup called for group {0} with {1} visible members, {2} online", // groupID, groupMembersCount, groupMembers.Count()); - int requestStartTick = Environment.TickCount; - im.imSessionID = groupID.Guid; im.fromGroup = true; IClientAPI thisClient = GetActiveClient(fromAgentID); -- cgit v1.1 From 04aa13a086239b8d628821809bef9c9585c35f8f Mon Sep 17 00:00:00 2001 From: AliciaRaven Date: Thu, 22 May 2014 00:51:33 +0100 Subject: Fix mantis 6973. Prevent BOM being prefixed to message XML which was causing an exception when the service tried to read the data later on. Signed-off-by: Oren Hurvitz --- OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs b/OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs index 690c955..02084ff 100644 --- a/OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs +++ b/OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs @@ -104,7 +104,7 @@ namespace OpenSim.OfflineIM using (MemoryStream mstream = new MemoryStream()) { XmlWriterSettings settings = new XmlWriterSettings(); - settings.Encoding = Encoding.UTF8; + settings.Encoding = Util.UTF8NoBomEncoding; using (XmlWriter writer = XmlWriter.Create(mstream, settings)) { @@ -112,7 +112,7 @@ namespace OpenSim.OfflineIM writer.Flush(); } - imXml = Util.UTF8.GetString(mstream.ToArray()); + imXml = Util.UTF8NoBomEncoding.GetString(mstream.ToArray()); } OfflineIMData data = new OfflineIMData(); -- cgit v1.1 From ff9da2446583ffd95b42e7ced2a86c2166c993c1 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 23 May 2014 17:31:39 -0700 Subject: Added HTTP Authentication also to Groups and offline IM. --- .../Groups/Remote/GroupsServiceRemoteConnector.cs | 33 ++++++++++++++++------ .../Remote/GroupsServiceRemoteConnectorModule.cs | 8 +----- .../Groups/Remote/GroupsServiceRobustConnector.cs | 25 ++++------------ OpenSim/Addons/OfflineIM/OfflineIMRegionModule.cs | 2 +- .../Remote/OfflineIMServiceRemoteConnector.cs | 17 ++++++++++- .../Remote/OfflineIMServiceRobustConnector.cs | 9 ++++-- 6 files changed, 55 insertions(+), 39 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnector.cs b/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnector.cs index 1425a23..7450c14 100644 --- a/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnector.cs +++ b/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnector.cs @@ -32,29 +32,47 @@ using System.Reflection; using System.Text; using OpenSim.Framework; +using OpenSim.Framework.ServiceAuth; using OpenSim.Server.Base; using OpenMetaverse; using log4net; +using Nini.Config; namespace OpenSim.Groups { - public class GroupsServiceRemoteConnector + public class GroupsServiceRemoteConnector { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private string m_ServerURI; - private string m_SecretKey; + private IServiceAuth m_Auth; private object m_Lock = new object(); - public GroupsServiceRemoteConnector(string url, string secret) + public GroupsServiceRemoteConnector(IConfigSource config) { + IConfig groupsConfig = config.Configs["Groups"]; + string url = groupsConfig.GetString("GroupsServerURI", string.Empty); + if (!Uri.IsWellFormedUriString(url, UriKind.Absolute)) + throw new Exception(string.Format("[Groups.RemoteConnector]: Malformed groups server URL {0}. Fix it or disable the Groups feature.", url)); + m_ServerURI = url; if (!m_ServerURI.EndsWith("/")) m_ServerURI += "/"; - m_SecretKey = secret; - m_log.DebugFormat("[Groups.RemoteConnector]: Groups server at {0}, secret key {1}", m_ServerURI, m_SecretKey); + /// This is from BaseServiceConnector + string authType = Util.GetConfigVarFromSections(config, "AuthType", new string[] { "Network", "Groups" }, "None"); + + switch (authType) + { + case "BasicHttpAuthentication": + m_Auth = new BasicHttpAuthentication(config, "Groups"); + break; + } + /// + + m_log.DebugFormat("[Groups.RemoteConnector]: Groups server at {0}, authentication {1}", + m_ServerURI, (m_Auth == null ? "None" : m_Auth.GetType().ToString())); } public ExtendedGroupRecord CreateGroup(string RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, @@ -656,14 +674,13 @@ namespace OpenSim.Groups private Dictionary MakeRequest(string method, Dictionary sendData) { sendData["METHOD"] = method; - if (m_SecretKey != string.Empty) - sendData["KEY"] = m_SecretKey; string reply = string.Empty; lock (m_Lock) reply = SynchronousRestFormsRequester.MakeRequest("POST", m_ServerURI + "groups", - ServerUtils.BuildQueryString(sendData)); + ServerUtils.BuildQueryString(sendData), + m_Auth); if (reply == string.Empty) return null; diff --git a/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnectorModule.cs b/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnectorModule.cs index 5fb3c19..fddda22 100644 --- a/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnectorModule.cs +++ b/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnectorModule.cs @@ -72,13 +72,7 @@ namespace OpenSim.Groups private void Init(IConfigSource config) { - IConfig groupsConfig = config.Configs["Groups"]; - string url = groupsConfig.GetString("GroupsServerURI", string.Empty); - if (!Uri.IsWellFormedUriString(url, UriKind.Absolute)) - throw new Exception(string.Format("[Groups.RemoteConnector]: Malformed groups server URL {0}. Fix it or disable the Groups feature.", url)); - - string secret = groupsConfig.GetString("SecretKey", string.Empty); - m_GroupsService = new GroupsServiceRemoteConnector(url, secret); + m_GroupsService = new GroupsServiceRemoteConnector(config); m_Scenes = new List(); } diff --git a/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs b/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs index 33dc301..55ae6db 100644 --- a/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs +++ b/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs @@ -36,6 +36,7 @@ using OpenSim.Framework; using OpenSim.Server.Base; using OpenSim.Services.Interfaces; using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Framework.ServiceAuth; using OpenSim.Server.Handlers.Base; using log4net; using OpenMetaverse; @@ -69,7 +70,9 @@ namespace OpenSim.Groups m_GroupsService = new GroupsService(config); - server.AddStreamHandler(new GroupsServicePostHandler(m_GroupsService, key)); + IServiceAuth auth = ServiceAuth.Create(config, m_ConfigName); + + server.AddStreamHandler(new GroupsServicePostHandler(m_GroupsService, auth)); } } @@ -78,13 +81,11 @@ namespace OpenSim.Groups private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private GroupsService m_GroupsService; - private string m_SecretKey = String.Empty; - public GroupsServicePostHandler(GroupsService service, string key) : - base("POST", "/groups") + public GroupsServicePostHandler(GroupsService service, IServiceAuth auth) : + base("POST", "/groups", auth) { m_GroupsService = service; - m_SecretKey = key; } protected override byte[] ProcessRequest(string path, Stream requestData, @@ -108,20 +109,6 @@ namespace OpenSim.Groups string method = request["METHOD"].ToString(); request.Remove("METHOD"); - if (!String.IsNullOrEmpty(m_SecretKey)) // Verification required - { - // Sender didn't send key - if (!request.ContainsKey("KEY") || (request["KEY"] == null)) - return FailureResult("This service requires a secret key"); - - // Sender sent wrong key - if (!m_SecretKey.Equals(request["KEY"])) - return FailureResult("Provided key does not match existing one"); - - // OK, key matches. Remove it. - request.Remove("KEY"); - } - m_log.DebugFormat("[Groups.Handler]: {0}", method); switch (method) { diff --git a/OpenSim/Addons/OfflineIM/OfflineIMRegionModule.cs b/OpenSim/Addons/OfflineIM/OfflineIMRegionModule.cs index 950e1fd..5340bcd 100644 --- a/OpenSim/Addons/OfflineIM/OfflineIMRegionModule.cs +++ b/OpenSim/Addons/OfflineIM/OfflineIMRegionModule.cs @@ -66,7 +66,7 @@ namespace OpenSim.OfflineIM if (serviceLocation == string.Empty) m_OfflineIMService = new OfflineIMService(config); else - m_OfflineIMService = new OfflineIMServiceRemoteConnector(serviceLocation); + m_OfflineIMService = new OfflineIMServiceRemoteConnector(config); m_ForwardOfflineGroupMessages = cnf.GetBoolean("ForwardOfflineGroupMessages", m_ForwardOfflineGroupMessages); m_log.DebugFormat("[OfflineIM.V2]: Offline messages enabled by {0}", Name); diff --git a/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRemoteConnector.cs b/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRemoteConnector.cs index eb287a4..047b8be 100644 --- a/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRemoteConnector.cs +++ b/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRemoteConnector.cs @@ -32,6 +32,7 @@ using System.Reflection; using System.Text; using OpenSim.Framework; +using OpenSim.Framework.ServiceAuth; using OpenSim.Server.Base; using OpenSim.Services.Interfaces; @@ -46,6 +47,7 @@ namespace OpenSim.OfflineIM private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private string m_ServerURI = string.Empty; + private IServiceAuth m_Auth; private object m_Lock = new object(); public OfflineIMServiceRemoteConnector(string url) @@ -65,6 +67,18 @@ namespace OpenSim.OfflineIM m_ServerURI = cnf.GetString("OfflineMessageURL", string.Empty); + /// This is from BaseServiceConnector + string authType = Util.GetConfigVarFromSections(config, "AuthType", new string[] { "Network", "Messaging" }, "None"); + + switch (authType) + { + case "BasicHttpAuthentication": + m_Auth = new BasicHttpAuthentication(config, "Messaging"); + break; + } + /// + m_log.DebugFormat("[OfflineIM.V2.RemoteConnector]: Offline IM server at {0} with auth {1}", + m_ServerURI, (m_Auth == null ? "None" : m_Auth.GetType().ToString())); } #region IOfflineIMService @@ -143,7 +157,8 @@ namespace OpenSim.OfflineIM lock (m_Lock) reply = SynchronousRestFormsRequester.MakeRequest("POST", m_ServerURI + "/offlineim", - ServerUtils.BuildQueryString(sendData)); + ServerUtils.BuildQueryString(sendData), + m_Auth); Dictionary replyData = ServerUtils.ParseXmlResponse( reply); diff --git a/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRobustConnector.cs b/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRobustConnector.cs index ed5c742..c44b6cc 100644 --- a/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRobustConnector.cs +++ b/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRobustConnector.cs @@ -36,6 +36,7 @@ using OpenSim.Framework; using OpenSim.Server.Base; using OpenSim.Services.Interfaces; using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Framework.ServiceAuth; using OpenSim.Server.Handlers.Base; using log4net; using OpenMetaverse; @@ -59,7 +60,9 @@ namespace OpenSim.OfflineIM m_OfflineIMService = new OfflineIMService(config); - server.AddStreamHandler(new OfflineIMServicePostHandler(m_OfflineIMService)); + IServiceAuth auth = ServiceAuth.Create(config, m_ConfigName); + + server.AddStreamHandler(new OfflineIMServicePostHandler(m_OfflineIMService, auth)); } } @@ -69,8 +72,8 @@ namespace OpenSim.OfflineIM private IOfflineIMService m_OfflineIMService; - public OfflineIMServicePostHandler(IOfflineIMService service) : - base("POST", "/offlineim") + public OfflineIMServicePostHandler(IOfflineIMService service, IServiceAuth auth) : + base("POST", "/offlineim", auth) { m_OfflineIMService = service; } -- cgit v1.1 From 35c7fb203829c3618cfaa427d7026b93a5a67698 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 30 May 2014 19:45:05 +0100 Subject: minor: Comment out log line in Groups V2 GroupsServicePostHandler for now which logs every request it receives. --- OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs b/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs index 55ae6db..52b9728 100644 --- a/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs +++ b/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs @@ -109,7 +109,7 @@ namespace OpenSim.Groups string method = request["METHOD"].ToString(); request.Remove("METHOD"); - m_log.DebugFormat("[Groups.Handler]: {0}", method); +// m_log.DebugFormat("[Groups.Handler]: {0}", method); switch (method) { case "PUTGROUP": -- cgit v1.1 From 7f45ac72e1d45833abafbcaa38a36893a9cb4efc Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 8 Jun 2014 12:18:26 -0700 Subject: Don't try to package null invites. --- OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs b/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs index 52b9728..95c3208 100644 --- a/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs +++ b/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs @@ -665,7 +665,11 @@ namespace OpenSim.Groups GroupInviteInfo invite = m_GroupsService.GetAgentToGroupInvite(request["RequestingAgentID"].ToString(), new UUID(request["InviteID"].ToString())); - result["RESULT"] = GroupsDataUtils.GroupInviteInfo(invite); + if (invite != null) + result["RESULT"] = GroupsDataUtils.GroupInviteInfo(invite); + else + result["RESULT"] = "NULL"; + return Util.UTF8NoBomEncoding.GetBytes(ServerUtils.BuildXmlResponse(result)); } -- cgit v1.1 From 5450b1b0247bb3907f60f2b3f9b0582903de4f83 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 17 Jun 2014 18:37:15 +0100 Subject: Change assembly versions to 0.8.1 --- OpenSim/Addons/Groups/Properties/AssemblyInfo.cs | 2 +- OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs b/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs index 16fe03b..238c9a6 100644 --- a/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs +++ b/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs @@ -30,7 +30,7 @@ using Mono.Addins; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.0.*")] +[assembly: AssemblyVersion("0.8.1.*")] [assembly: Addin("OpenSim.Groups", "0.1")] [assembly: AddinDependency("OpenSim", "0.5")] diff --git a/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs b/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs index 5d71edc..91a9400 100644 --- a/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs +++ b/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs @@ -30,7 +30,7 @@ using Mono.Addins; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.0.*")] +[assembly: AssemblyVersion("0.8.1.*")] [assembly: Addin("OpenSim.OfflineIM", "0.1")] [assembly: AddinDependency("OpenSim", "0.5")] -- cgit v1.1 From 99ac770abbe3a95887c4b10c82f3985aa878eeef Mon Sep 17 00:00:00 2001 From: Oren Hurvitz Date: Sun, 1 Jun 2014 17:39:11 +0300 Subject: Close streams immediately when we finish using them --- .../OfflineIM/Remote/OfflineIMServiceRobustConnector.cs | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRobustConnector.cs b/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRobustConnector.cs index c44b6cc..b3673da 100644 --- a/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRobustConnector.cs +++ b/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRobustConnector.cs @@ -215,18 +215,7 @@ namespace OpenSim.OfflineIM rootElement.AppendChild(result); - return DocToBytes(doc); - } - - private byte[] DocToBytes(XmlDocument doc) - { - MemoryStream ms = new MemoryStream(); - XmlTextWriter xw = new XmlTextWriter(ms, null); - xw.Formatting = Formatting.Indented; - doc.WriteTo(xw); - xw.Flush(); - - return ms.ToArray(); + return Util.DocToBytes(doc); } #endregion -- cgit v1.1 From 0d70033a5db407526c37cf241a99743126b8d358 Mon Sep 17 00:00:00 2001 From: Oren Hurvitz Date: Sun, 29 Jun 2014 11:26:34 +0300 Subject: Include the group name in group IM's When sending an ImprovedInstantMessage to a group, the IM's binary bucket is supposed to contain the group's name (this is what SL does). Singularity uses this to show the group name when it shows the message at the bottom of the viewer for a few seconds: "[Group Name] From User: Message". Before this update, the group name was empty ("[]"). This update doesn't have any visible effect in Firestorm, because it doesn't use the group name sent in the IM. --- OpenSim/Addons/Groups/GroupsMessagingModule.cs | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsMessagingModule.cs b/OpenSim/Addons/Groups/GroupsMessagingModule.cs index e6a4765..e95db41 100644 --- a/OpenSim/Addons/Groups/GroupsMessagingModule.cs +++ b/OpenSim/Addons/Groups/GroupsMessagingModule.cs @@ -325,6 +325,13 @@ namespace OpenSim.Groups im.RegionID = thisClient.Scene.RegionInfo.RegionID.Guid; } + if ((im.binaryBucket == null) || (im.binaryBucket.Length == 0) || ((im.binaryBucket.Length == 1 && im.binaryBucket[0] == 0))) + { + ExtendedGroupRecord groupInfo = m_groupData.GetGroupRecord(UUID.Zero.ToString(), groupID, null); + if (groupInfo != null) + im.binaryBucket = Util.StringToBytes256(groupInfo.GroupName); + } + // Send to self first of all im.toAgentID = im.fromAgentID; im.fromGroup = true; -- cgit v1.1 From 6c4eed5539ac0d8d6bab9166a8e320aeb12c3cd6 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 31 Jul 2014 00:28:51 +0100 Subject: Fix bug where calling PUTGROUP on the core groups service without specifying a ServiceLocation would set the group name to an empty string. This should set the ServiceLocation to an empty string instead. --- OpenSim/Addons/Groups/GroupsExtendedData.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsExtendedData.cs b/OpenSim/Addons/Groups/GroupsExtendedData.cs index 1632aee..c783b9e 100644 --- a/OpenSim/Addons/Groups/GroupsExtendedData.cs +++ b/OpenSim/Addons/Groups/GroupsExtendedData.cs @@ -174,7 +174,7 @@ namespace OpenSim.Groups if (dict.ContainsKey("ServiceLocation") && dict["ServiceLocation"] != null) grec.ServiceLocation = dict["ServiceLocation"].ToString(); else - grec.GroupName = string.Empty; + grec.ServiceLocation = string.Empty; if (dict.ContainsKey("ShownInList") && dict["ShownInList"] != null) grec.ShowInList = bool.Parse(dict["ShownInList"].ToString()); -- cgit v1.1 From 6ab463a4461d84625e32afd19bfc64e77e1badd6 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 31 Jul 2014 21:20:10 +0100 Subject: Don't overwrite the null result with the true result is groups service REMOVEAGENTFROMGROUP call has failed because of missing parameters --- OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs | 3 ++- OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs b/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs index dc36787..207d810 100644 --- a/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs +++ b/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs @@ -210,10 +210,11 @@ namespace OpenSim.Groups string token = request["AccessToken"].ToString(); m_GroupsService.RemoveAgentFromGroup(agentID, agentID, groupID, token); + + result["RESULT"] = "true"; } //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString); - result["RESULT"] = "true"; return Util.UTF8NoBomEncoding.GetBytes(ServerUtils.BuildXmlResponse(result)); } diff --git a/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs b/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs index 95c3208..5cf6ec7 100644 --- a/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs +++ b/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs @@ -286,10 +286,11 @@ namespace OpenSim.Groups string requestingAgentID = request["RequestingAgentID"].ToString(); m_GroupsService.RemoveAgentFromGroup(requestingAgentID, agentID, groupID); + + result["RESULT"] = "true"; } //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString); - result["RESULT"] = "true"; return Util.UTF8NoBomEncoding.GetBytes(ServerUtils.BuildXmlResponse(result)); } -- cgit v1.1 From dfd0c2a54ab345e6120ae7f8d75870959771ef11 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 31 Jul 2014 21:32:20 +0100 Subject: If REMOVEAGENTFROMGROUP core groups call fails because requesting agent does not have sufficient permission, return null failure result rather than true. On non-HG this is on the only recognized failure state so we can return more information in the error result. On HG there are multiple failure states which would require more work to distinguish, so currently return the unsatisfying "Internal Error" like some other existing calls. --- .../Groups/Hypergrid/HGGroupsServiceRobustConnector.cs | 7 ++++--- OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs | 7 ++++--- OpenSim/Addons/Groups/Service/GroupsService.cs | 6 ++++-- OpenSim/Addons/Groups/Service/HGGroupsService.cs | 12 ++++++++++-- 4 files changed, 22 insertions(+), 10 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs b/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs index 207d810..f60c1a5 100644 --- a/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs +++ b/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs @@ -209,9 +209,10 @@ namespace OpenSim.Groups string agentID = request["AgentID"].ToString(); string token = request["AccessToken"].ToString(); - m_GroupsService.RemoveAgentFromGroup(agentID, agentID, groupID, token); - - result["RESULT"] = "true"; + if (!m_GroupsService.RemoveAgentFromGroup(agentID, agentID, groupID, token)) + NullResult(result, "Internal error"); + else + result["RESULT"] = "true"; } //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString); diff --git a/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs b/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs index 5cf6ec7..26e844e 100644 --- a/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs +++ b/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs @@ -285,9 +285,10 @@ namespace OpenSim.Groups string agentID = request["AgentID"].ToString(); string requestingAgentID = request["RequestingAgentID"].ToString(); - m_GroupsService.RemoveAgentFromGroup(requestingAgentID, agentID, groupID); - - result["RESULT"] = "true"; + if (!m_GroupsService.RemoveAgentFromGroup(requestingAgentID, agentID, groupID)) + NullResult(result, string.Format("Insufficient permissions.", agentID)); + else + result["RESULT"] = "true"; } //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString); diff --git a/OpenSim/Addons/Groups/Service/GroupsService.cs b/OpenSim/Addons/Groups/Service/GroupsService.cs index 037ef59..f44c094 100644 --- a/OpenSim/Addons/Groups/Service/GroupsService.cs +++ b/OpenSim/Addons/Groups/Service/GroupsService.cs @@ -393,13 +393,15 @@ namespace OpenSim.Groups return true; } - public void RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID) + public bool RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID) { // check perms if (RequestingAgentID != AgentID && !HasPower(RequestingAgentID, GroupID, GroupPowers.Eject)) - return; + return false; _RemoveAgentFromGroup(RequestingAgentID, AgentID, GroupID); + + return true; } public bool AddAgentToGroupInvite(string RequestingAgentID, UUID inviteID, UUID groupID, UUID roleID, string agentID) diff --git a/OpenSim/Addons/Groups/Service/HGGroupsService.cs b/OpenSim/Addons/Groups/Service/HGGroupsService.cs index 9d7961c..56e999b 100644 --- a/OpenSim/Addons/Groups/Service/HGGroupsService.cs +++ b/OpenSim/Addons/Groups/Service/HGGroupsService.cs @@ -131,19 +131,27 @@ namespace OpenSim.Groups return true; } - public void RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID, string token) + public bool RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID, string token) { // check the token MembershipData membership = m_Database.RetrieveMember(GroupID, AgentID); if (membership != null) { if (token != string.Empty && token.Equals(membership.Data["AccessToken"])) - RemoveAgentFromGroup(RequestingAgentID, AgentID, GroupID); + { + return RemoveAgentFromGroup(RequestingAgentID, AgentID, GroupID); + } else + { m_log.DebugFormat("[Groups.HGGroupsService]: access token {0} did not match stored one {1}", token, membership.Data["AccessToken"]); + return false; + } } else + { m_log.DebugFormat("[Groups.HGGroupsService]: membership not found for {0}", AgentID); + return false; + } } public ExtendedGroupRecord GetGroupRecord(string RequestingAgentID, UUID GroupID, string groupName, string token) -- cgit v1.1 From 91e1aaa5d41c29fa17609c69ca8bc2a8017dc161 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 15 Aug 2014 21:34:58 +0100 Subject: On teleport to a region that already has a child agent established (e.g. a neighbour) don't resend all the initial avatar and object data again. This is unnecessary since it has been received (and data continues to be received) in the existing child connection. --- OpenSim/Addons/Groups/GroupsModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs index 2831326..d121d1a 100644 --- a/OpenSim/Addons/Groups/GroupsModule.cs +++ b/OpenSim/Addons/Groups/GroupsModule.cs @@ -1296,7 +1296,7 @@ namespace OpenSim.Groups presence.Grouptitle = Title; if (! presence.IsChildAgent) - presence.SendAvatarDataToAllAgents(); + presence.SendAvatarDataToAllClients(); } } } -- cgit v1.1 From 41f2f3132bdcbfb8020c7fd6e5f3b7e48c75b1cf Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 5 Sep 2014 23:20:59 +0100 Subject: For monitoring purposes, start non-timeout tasks (which do not currently use a threadpool) via Watchdog.RunInThread() rather than Util.RunThreadNoTimeout() The functionality is the same but this allow us to monitor such tasks via "show threads" and abort them for test purposes, etc. Also extends thread names to provide more info (e.g. SendInitialDataToClient says what client the task is for). --- OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs b/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs index a750d8d..9fbc1b3 100644 --- a/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs +++ b/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs @@ -32,6 +32,7 @@ using System.Reflection; using System.Text; using OpenSim.Framework; +using OpenSim.Framework.Monitoring; using OpenSim.Framework.Servers; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Interfaces; @@ -560,7 +561,7 @@ namespace OpenSim.Groups // so we have the list of urls to send the notice to // this may take a long time... - Util.RunThreadNoTimeout(delegate + Watchdog.RunInThread(delegate { foreach (string u in urls) { @@ -571,7 +572,7 @@ namespace OpenSim.Groups hasAttachment, attType, attName, attItemID, AgentUUIForOutside(attOwnerID)); } } - }, "AddGroupNotice", null); + }, string.Format("AddGroupNotice (agent {0}, group {1})", RequestingAgentID, groupID) , null); return true; } -- cgit v1.1 From 94619cba58a6783efd61acae56599332d7c111ba Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 21 Sep 2014 09:22:32 -0700 Subject: Fixed a hard-to-run-into bug in groups: at the time of creation of a group, the OwnerRoleID in the groups table was inconsistent with the roleID in the roles table. OpenSim core was not running into this bug, but 3rd party modules (like Wifi) were. --- OpenSim/Addons/Groups/Service/GroupsService.cs | 28 +++++++++++++++++--------- 1 file changed, 18 insertions(+), 10 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/Service/GroupsService.cs b/OpenSim/Addons/Groups/Service/GroupsService.cs index f44c094..7cbc796 100644 --- a/OpenSim/Addons/Groups/Service/GroupsService.cs +++ b/OpenSim/Addons/Groups/Service/GroupsService.cs @@ -150,7 +150,8 @@ namespace OpenSim.Groups data.Data["ShowInList"] = showInList ? "1" : "0"; data.Data["AllowPublish"] = allowPublish ? "1" : "0"; data.Data["MaturePublish"] = maturePublish ? "1" : "0"; - data.Data["OwnerRoleID"] = UUID.Random().ToString(); + UUID roleID = UUID.Random(); + data.Data["OwnerRoleID"] = roleID.ToString(); if (!m_Database.StoreGroup(data)) return UUID.Zero; @@ -159,7 +160,6 @@ namespace OpenSim.Groups _AddOrUpdateGroupRole(RequestingAgentID, data.GroupID, UUID.Zero, "Everyone", "Everyone in the group", "Member of " + name, (ulong)DefaultEveryonePowers, true); // Create Owner role - UUID roleID = UUID.Random(); _AddOrUpdateGroupRole(RequestingAgentID, data.GroupID, roleID, "Owners", "Owners of the group", "Owner of " + name, (ulong)OwnerPowers, true); // Add founder to group @@ -247,6 +247,9 @@ namespace OpenSim.Groups if (group == null) return members; + // Unfortunately this doesn't quite work on legacy group data because of a bug + // that's also being fixed here on CreateGroup. The OwnerRoleID sent to the DB was wrong. + // See how to find the ownerRoleID a few lines below. UUID ownerRoleID = new UUID(group.Data["OwnerRoleID"]); RoleData[] roles = m_Database.RetrieveRoles(GroupID); @@ -255,6 +258,11 @@ namespace OpenSim.Groups return members; List rolesList = new List(roles); + // Let's find the "real" ownerRoleID + RoleData ownerRole = rolesList.Find(r => r.Data["Powers"] == ((long)OwnerPowers).ToString()); + if (ownerRole != null) + ownerRoleID = ownerRole.RoleID; + // Check visibility? // When we don't want to check visibility, we pass it "all" as the requestingAgentID bool checkVisibility = !RequestingAgentID.Equals(UUID.Zero.ToString()); @@ -291,17 +299,17 @@ namespace OpenSim.Groups { m.Title = selected.Data["Title"]; m.AgentPowers = UInt64.Parse(selected.Data["Powers"]); + } - m.AgentID = d.PrincipalID; - m.AcceptNotices = d.Data["AcceptNotices"] == "1" ? true : false; - m.Contribution = Int32.Parse(d.Data["Contribution"]); - m.ListInProfile = d.Data["ListInProfile"] == "1" ? true : false; + m.AgentID = d.PrincipalID; + m.AcceptNotices = d.Data["AcceptNotices"] == "1" ? true : false; + m.Contribution = Int32.Parse(d.Data["Contribution"]); + m.ListInProfile = d.Data["ListInProfile"] == "1" ? true : false; - // Is this person an owner of the group? - m.IsOwner = (rolemembershipsList.Find(r => r.RoleID == ownerRoleID) != null) ? true : false; + // Is this person an owner of the group? + m.IsOwner = (rolemembershipsList.Find(r => r.RoleID == ownerRoleID) != null) ? true : false; - members.Add(m); - } + members.Add(m); } return members; -- cgit v1.1 From c155656349ee2865498a756f5f4181065b741b44 Mon Sep 17 00:00:00 2001 From: AliciaRaven Date: Sun, 16 Nov 2014 10:26:38 +0000 Subject: Minor: Include missing EventHost power for group owner role. --- OpenSim/Addons/Groups/Service/GroupsService.cs | 1 + 1 file changed, 1 insertion(+) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/Service/GroupsService.cs b/OpenSim/Addons/Groups/Service/GroupsService.cs index 7cbc796..4da7233 100644 --- a/OpenSim/Addons/Groups/Service/GroupsService.cs +++ b/OpenSim/Addons/Groups/Service/GroupsService.cs @@ -69,6 +69,7 @@ namespace OpenSim.Groups GroupPowers.DeleteRole | GroupPowers.Eject | GroupPowers.FindPlaces | + GroupPowers.HostEvent | GroupPowers.Invite | GroupPowers.JoinChat | GroupPowers.LandChangeIdentity | -- cgit v1.1 From 86367d7219b3bd52f63045b2b17bcbde328844ed Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 25 Nov 2014 23:56:32 +0000 Subject: refactor: Move methods to start a monitored thread, start work in its own thread and run work in the jobengine from Watchdog to a WorkManager class. This is to achieve a clean separation of concerns - the watchdog is an inappropriate place for work management. Also adds a WorkManager.RunInThreadPool() class which feeds through to Util.FireAndForget. Also switches around the name and obj arguments to the new RunInThread() and RunJob() methods so that the callback obj comes after the callback as seen in the SDK and elsewhere --- OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs b/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs index 9fbc1b3..7d57de1 100644 --- a/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs +++ b/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs @@ -561,7 +561,7 @@ namespace OpenSim.Groups // so we have the list of urls to send the notice to // this may take a long time... - Watchdog.RunInThread(delegate + WorkManager.RunInThread(delegate { foreach (string u in urls) { @@ -572,7 +572,7 @@ namespace OpenSim.Groups hasAttachment, attType, attName, attItemID, AgentUUIForOutside(attOwnerID)); } } - }, string.Format("AddGroupNotice (agent {0}, group {1})", RequestingAgentID, groupID) , null); + }, null, string.Format("AddGroupNotice (agent {0}, group {1})", RequestingAgentID, groupID)); return true; } -- cgit v1.1 From 89c1ac4cff9e89da10d8b0aee4bb39d3da05a479 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Mon, 29 Dec 2014 15:05:44 -0800 Subject: Updated OpenSim-as-addin version from 0.5 to 0.8.1. The addin version number doesn't need to match the release version number, but I think it's a very good idea that they do. --- OpenSim/Addons/Groups/Properties/AssemblyInfo.cs | 2 +- OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs b/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs index 238c9a6..abafd34 100644 --- a/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs +++ b/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ using Mono.Addins; [assembly: AssemblyVersion("0.8.1.*")] [assembly: Addin("OpenSim.Groups", "0.1")] -[assembly: AddinDependency("OpenSim", "0.5")] +[assembly: AddinDependency("OpenSim", "0.8.1")] diff --git a/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs b/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs index 91a9400..0c9a576 100644 --- a/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs +++ b/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ using Mono.Addins; [assembly: AssemblyVersion("0.8.1.*")] [assembly: Addin("OpenSim.OfflineIM", "0.1")] -[assembly: AddinDependency("OpenSim", "0.5")] +[assembly: AddinDependency("OpenSim", "0.8.1")] -- cgit v1.1 From 5cf6a6f8302b4f03d45c21f0731978da1d3ddcab Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Tue, 30 Dec 2014 07:58:42 -0800 Subject: WARNING: BREAKING CHANGES FOR REGION MODULE DEVELOPMENT. This cleans up Opensim's use of mono addins. In particular, the extension points /OpenSim/RegionModules and /OpenSim/WindModule moved from OpenSim.exe to OpenSim.Region.Framework.dll. From here on, developers of region modules should declare their dlls to be dependent on OpenSim.Region.Framework, starting with version 0.8.1 Additional changes: - Addins version uniformly updated to 0.8.1. These numbers should be compatible with the release numbers or else it becomes very confusing. - Mono addins directives moved from files addins.xml to embedded directives in the class and assembly declarations, to make it all consistent --- OpenSim/Addons/Groups/Properties/AssemblyInfo.cs | 2 +- OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs b/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs index abafd34..aa31a14 100644 --- a/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs +++ b/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ using Mono.Addins; [assembly: AssemblyVersion("0.8.1.*")] [assembly: Addin("OpenSim.Groups", "0.1")] -[assembly: AddinDependency("OpenSim", "0.8.1")] +[assembly: AddinDependency("OpenSim.Region.Framework", "0.8.1")] diff --git a/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs b/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs index 0c9a576..054e1fb 100644 --- a/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs +++ b/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ using Mono.Addins; [assembly: AssemblyVersion("0.8.1.*")] [assembly: Addin("OpenSim.OfflineIM", "0.1")] -[assembly: AddinDependency("OpenSim", "0.8.1")] +[assembly: AddinDependency("OpenSim.Region.Framework", "0.8.1")] -- cgit v1.1 From 7466ef0525f5465596c415684000bd994055b280 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Tue, 30 Dec 2014 12:53:31 -0800 Subject: This cleans up versioning. Specifically: - It establishes 4 digits for opensim versions - It uses the same number between opensim releases and mono addins versions It also eliminates the last addin.xml files that were still there, for consistency. --- OpenSim/Addons/Groups/Properties/AssemblyInfo.cs | 4 ++-- OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs b/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs index aa31a14..de3dfd0 100644 --- a/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs +++ b/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ using Mono.Addins; // [assembly: AssemblyVersion("0.8.1.*")] -[assembly: Addin("OpenSim.Groups", "0.1")] -[assembly: AddinDependency("OpenSim.Region.Framework", "0.8.1")] +[assembly: Addin("OpenSim.Groups", OpenSim.VersionInfo.VERSION_NUMBER)] +[assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VERSION_NUMBER)] diff --git a/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs b/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs index 054e1fb..59758ff 100644 --- a/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs +++ b/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ using Mono.Addins; // [assembly: AssemblyVersion("0.8.1.*")] -[assembly: Addin("OpenSim.OfflineIM", "0.1")] -[assembly: AddinDependency("OpenSim.Region.Framework", "0.8.1")] +[assembly: Addin("OpenSim.OfflineIM", OpenSim.VersionInfo.VERSION_NUMBER)] +[assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VERSION_NUMBER)] -- cgit v1.1 From 2138d5c7f8dd13be9a7dd4cf4afed8094d871738 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Tue, 30 Dec 2014 15:27:28 -0800 Subject: Renamed VERSION_NUMBER to VersionNumber --- OpenSim/Addons/Groups/Properties/AssemblyInfo.cs | 4 ++-- OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs b/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs index de3dfd0..5ad087a 100644 --- a/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs +++ b/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ using Mono.Addins; // [assembly: AssemblyVersion("0.8.1.*")] -[assembly: Addin("OpenSim.Groups", OpenSim.VersionInfo.VERSION_NUMBER)] -[assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VERSION_NUMBER)] +[assembly: Addin("OpenSim.Groups", OpenSim.VersionInfo.VersionNumber)] +[assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)] diff --git a/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs b/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs index 59758ff..3868912 100644 --- a/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs +++ b/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ using Mono.Addins; // [assembly: AssemblyVersion("0.8.1.*")] -[assembly: Addin("OpenSim.OfflineIM", OpenSim.VersionInfo.VERSION_NUMBER)] -[assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VERSION_NUMBER)] +[assembly: Addin("OpenSim.OfflineIM", OpenSim.VersionInfo.VersionNumber)] +[assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)] -- cgit v1.1 From e2dd15625f158c7f7d8f5ceec14f09e85dd8e2b6 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 9 Jan 2015 08:31:56 -0800 Subject: Added GetDisplayNames capability. For now, we don't actually use display names, and this cap returns the regular name. But this moves the server side into the newer, preferred, protocol used by the viewer for fetching the names of agents in the scene given their UUIDs. (the old protocol is via UDP). This works fine in my limited tests, but could use further testing by others. --- OpenSim/Addons/Groups/ForeignImporter.cs | 1 + OpenSim/Addons/Groups/Local/GroupsServiceLocalConnectorModule.cs | 1 + OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnectorModule.cs | 1 + OpenSim/Addons/Groups/RemoteConnectorCacheWrapper.cs | 3 ++- 4 files changed, 5 insertions(+), 1 deletion(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/ForeignImporter.cs b/OpenSim/Addons/Groups/ForeignImporter.cs index 788d21d..055f76c 100644 --- a/OpenSim/Addons/Groups/ForeignImporter.cs +++ b/OpenSim/Addons/Groups/ForeignImporter.cs @@ -30,6 +30,7 @@ using System.Collections.Generic; using OpenSim.Framework; using OpenSim.Region.Framework.Interfaces; +using OpenSim.Services.Interfaces; namespace OpenSim.Groups { diff --git a/OpenSim/Addons/Groups/Local/GroupsServiceLocalConnectorModule.cs b/OpenSim/Addons/Groups/Local/GroupsServiceLocalConnectorModule.cs index 564dec4..8e30df5 100644 --- a/OpenSim/Addons/Groups/Local/GroupsServiceLocalConnectorModule.cs +++ b/OpenSim/Addons/Groups/Local/GroupsServiceLocalConnectorModule.cs @@ -34,6 +34,7 @@ using System.Text; using OpenSim.Framework; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Interfaces; +using OpenSim.Services.Interfaces; using OpenMetaverse; using Mono.Addins; diff --git a/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnectorModule.cs b/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnectorModule.cs index fddda22..d4739c6 100644 --- a/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnectorModule.cs +++ b/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnectorModule.cs @@ -36,6 +36,7 @@ using OpenSim.Framework; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Interfaces; using OpenSim.Server.Base; +using OpenSim.Services.Interfaces; using OpenMetaverse; using Mono.Addins; diff --git a/OpenSim/Addons/Groups/RemoteConnectorCacheWrapper.cs b/OpenSim/Addons/Groups/RemoteConnectorCacheWrapper.cs index 3ac74fc..f121737 100644 --- a/OpenSim/Addons/Groups/RemoteConnectorCacheWrapper.cs +++ b/OpenSim/Addons/Groups/RemoteConnectorCacheWrapper.cs @@ -31,7 +31,8 @@ using System.Reflection; using System.Threading; using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; +//using OpenSim.Region.Framework.Interfaces; +using OpenSim.Services.Interfaces; using OpenMetaverse; -- cgit v1.1 From 765fd024183aa855b50ce9c9707abebba55ca63a Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 4 Feb 2015 17:04:59 +0000 Subject: For built-in groups, if a delegate throws an exception (e.g. due to network failure), always remove its request from the m_ActiveRequests list. If this is not done, all subsequent calls for the same data see that a request is apparantly already in progress and so wait for the result indefinitely. --- .../Addons/Groups/RemoteConnectorCacheWrapper.cs | 181 ++++++++++++++------- 1 file changed, 120 insertions(+), 61 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/RemoteConnectorCacheWrapper.cs b/OpenSim/Addons/Groups/RemoteConnectorCacheWrapper.cs index f121737..813f796 100644 --- a/OpenSim/Addons/Groups/RemoteConnectorCacheWrapper.cs +++ b/OpenSim/Addons/Groups/RemoteConnectorCacheWrapper.cs @@ -145,14 +145,20 @@ namespace OpenSim.Groups if (firstCall) { - //group = m_GroupsService.GetGroupRecord(RequestingAgentID, GroupID, GroupName); - group = d(); + try + { + //group = m_GroupsService.GetGroupRecord(RequestingAgentID, GroupID, GroupName); + group = d(); - lock (m_Cache) + lock (m_Cache) + { + m_Cache.AddOrUpdate(cacheKey, group, GROUPS_CACHE_TIMEOUT); + return (ExtendedGroupRecord)group; + } + } + finally { - m_Cache.AddOrUpdate(cacheKey, group, GROUPS_CACHE_TIMEOUT); m_ActiveRequests.Remove(cacheKey); - return (ExtendedGroupRecord)group; } } else @@ -244,13 +250,19 @@ namespace OpenSim.Groups if (firstCall) { - membership = d(); + try + { + membership = d(); - lock (m_Cache) + lock (m_Cache) + { + m_Cache.AddOrUpdate(cacheKey, membership, GROUPS_CACHE_TIMEOUT); + return (ExtendedGroupMembershipData)membership; + } + } + finally { - m_Cache.AddOrUpdate(cacheKey, membership, GROUPS_CACHE_TIMEOUT); m_ActiveRequests.Remove(cacheKey); - return (ExtendedGroupMembershipData)membership; } } else @@ -287,12 +299,18 @@ namespace OpenSim.Groups if (firstCall) { - membership = d(); - lock (m_Cache) + try + { + membership = d(); + lock (m_Cache) + { + m_Cache.AddOrUpdate(cacheKey, membership, GROUPS_CACHE_TIMEOUT); + return (ExtendedGroupMembershipData)membership; + } + } + finally { - m_Cache.AddOrUpdate(cacheKey, membership, GROUPS_CACHE_TIMEOUT); m_ActiveRequests.Remove(cacheKey); - return (ExtendedGroupMembershipData)membership; } } else @@ -328,12 +346,18 @@ namespace OpenSim.Groups if (firstCall) { - memberships = d(); - lock (m_Cache) + try + { + memberships = d(); + lock (m_Cache) + { + m_Cache.AddOrUpdate(cacheKey, memberships, GROUPS_CACHE_TIMEOUT); + return (List)memberships; + } + } + finally { - m_Cache.AddOrUpdate(cacheKey, memberships, GROUPS_CACHE_TIMEOUT); m_ActiveRequests.Remove(cacheKey); - return (List)memberships; } } else @@ -370,20 +394,26 @@ namespace OpenSim.Groups if (firstCall) { - List _members = d(); + try + { + List _members = d(); - if (_members != null && _members.Count > 0) - members = _members.ConvertAll(new Converter(m_ForeignImporter.ConvertGroupMembersData)); - else - members = new List(); + if (_members != null && _members.Count > 0) + members = _members.ConvertAll(new Converter(m_ForeignImporter.ConvertGroupMembersData)); + else + members = new List(); - lock (m_Cache) + lock (m_Cache) + { + //m_Cache.AddOrUpdate(cacheKey, members, GROUPS_CACHE_TIMEOUT); + m_Cache.AddOrUpdate(cacheKey, _members, GROUPS_CACHE_TIMEOUT); + + return (List)members; + } + } + finally { - //m_Cache.AddOrUpdate(cacheKey, members, GROUPS_CACHE_TIMEOUT); - m_Cache.AddOrUpdate(cacheKey, _members, GROUPS_CACHE_TIMEOUT); m_ActiveRequests.Remove(cacheKey); - - return (List)members; } } else @@ -498,16 +528,22 @@ namespace OpenSim.Groups if (firstCall) { - roles = d(); - if (roles != null) + try { - lock (m_Cache) + roles = d(); + if (roles != null) { - m_Cache.AddOrUpdate(cacheKey, roles, GROUPS_CACHE_TIMEOUT); - m_ActiveRequests.Remove(cacheKey); - return (List)roles; + lock (m_Cache) + { + m_Cache.AddOrUpdate(cacheKey, roles, GROUPS_CACHE_TIMEOUT); + return (List)roles; + } } } + finally + { + m_ActiveRequests.Remove(cacheKey); + } } else Thread.Sleep(50); @@ -542,23 +578,29 @@ namespace OpenSim.Groups if (firstCall) { - List _rmembers = d(); + try + { + List _rmembers = d(); - if (_rmembers != null && _rmembers.Count > 0) - rmembers = _rmembers.ConvertAll(new Converter(m_ForeignImporter.ConvertGroupRoleMembersData)); - else - rmembers = new List(); + if (_rmembers != null && _rmembers.Count > 0) + rmembers = _rmembers.ConvertAll(new Converter(m_ForeignImporter.ConvertGroupRoleMembersData)); + else + rmembers = new List(); - lock (m_Cache) + lock (m_Cache) + { + // For some strange reason, when I cache the list of GroupRoleMembersData, + // it gets emptied out. The TryGet gets an empty list... + //m_Cache.AddOrUpdate(cacheKey, rmembers, GROUPS_CACHE_TIMEOUT); + // Caching the list of ExtendedGroupRoleMembersData doesn't show that issue + // I don't get it. + m_Cache.AddOrUpdate(cacheKey, _rmembers, GROUPS_CACHE_TIMEOUT); + return (List)rmembers; + } + } + finally { - // For some strange reason, when I cache the list of GroupRoleMembersData, - // it gets emptied out. The TryGet gets an empty list... - //m_Cache.AddOrUpdate(cacheKey, rmembers, GROUPS_CACHE_TIMEOUT); - // Caching the list of ExtendedGroupRoleMembersData doesn't show that issue - // I don't get it. - m_Cache.AddOrUpdate(cacheKey, _rmembers, GROUPS_CACHE_TIMEOUT); m_ActiveRequests.Remove(cacheKey); - return (List)rmembers; } } else @@ -667,12 +709,19 @@ namespace OpenSim.Groups if (firstCall) { - roles = d(); - lock (m_Cache) + try + { + roles = d(); + lock (m_Cache) + { + m_Cache.AddOrUpdate(cacheKey, roles, GROUPS_CACHE_TIMEOUT); + m_ActiveRequests.Remove(cacheKey); + return (List)roles; + } + } + finally { - m_Cache.AddOrUpdate(cacheKey, roles, GROUPS_CACHE_TIMEOUT); m_ActiveRequests.Remove(cacheKey); - return (List)roles; } } else @@ -768,13 +817,19 @@ namespace OpenSim.Groups if (firstCall) { - GroupNoticeInfo _notice = d(); + try + { + GroupNoticeInfo _notice = d(); - lock (m_Cache) + lock (m_Cache) + { + m_Cache.AddOrUpdate(cacheKey, _notice, GROUPS_CACHE_TIMEOUT); + return _notice; + } + } + finally { - m_Cache.AddOrUpdate(cacheKey, _notice, GROUPS_CACHE_TIMEOUT); m_ActiveRequests.Remove(cacheKey); - return _notice; } } else @@ -810,20 +865,24 @@ namespace OpenSim.Groups if (firstCall) { - notices = d(); + try + { + notices = d(); - lock (m_Cache) + lock (m_Cache) + { + m_Cache.AddOrUpdate(cacheKey, notices, GROUPS_CACHE_TIMEOUT); + return (List)notices; + } + } + finally { - m_Cache.AddOrUpdate(cacheKey, notices, GROUPS_CACHE_TIMEOUT); m_ActiveRequests.Remove(cacheKey); - return (List)notices; } } else Thread.Sleep(50); } } - - } -} +} \ No newline at end of file -- cgit v1.1 From da32512ea449c2de2d4a6069f899fbd4a8bb03fa Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Wed, 29 Apr 2015 18:47:17 -0700 Subject: Updated all occurrences of AssemblyVersion("0.8.1.*") to AssemblyVersion("0.8.2.*") --- OpenSim/Addons/Groups/Properties/AssemblyInfo.cs | 2 +- OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs b/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs index 5ad087a..0a7fb5f 100644 --- a/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs +++ b/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs @@ -30,7 +30,7 @@ using Mono.Addins; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.1.*")] +[assembly: AssemblyVersion("0.8.2.*")] [assembly: Addin("OpenSim.Groups", OpenSim.VersionInfo.VersionNumber)] [assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)] diff --git a/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs b/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs index 3868912..3e993b4 100644 --- a/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs +++ b/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs @@ -30,7 +30,7 @@ using Mono.Addins; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.1.*")] +[assembly: AssemblyVersion("0.8.2.*")] [assembly: Addin("OpenSim.OfflineIM", OpenSim.VersionInfo.VersionNumber)] [assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)] -- cgit v1.1 From 368ea78d14ac301eda2920d82b7bc81ca848817e Mon Sep 17 00:00:00 2001 From: Cinder Date: Thu, 30 Jul 2015 08:50:07 -0600 Subject: Show last online status of group members from the PresenceService in group profiles Signed-off-by: Oren Hurvitz --- OpenSim/Addons/Groups/Service/GroupsService.cs | 15 +++ OpenSim/Addons/Groups/Service/GroupsServiceBase.cs | 103 ++++++++++++--------- 2 files changed, 75 insertions(+), 43 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/Service/GroupsService.cs b/OpenSim/Addons/Groups/Service/GroupsService.cs index 4da7233..07641ef 100644 --- a/OpenSim/Addons/Groups/Service/GroupsService.cs +++ b/OpenSim/Addons/Groups/Service/GroupsService.cs @@ -307,6 +307,21 @@ namespace OpenSim.Groups m.Contribution = Int32.Parse(d.Data["Contribution"]); m.ListInProfile = d.Data["ListInProfile"] == "1" ? true : false; + GridUserData gud = m_GridUserService.Get(d.PrincipalID); + if (gud != null) + { + if (bool.Parse(gud.Data["Online"])) + { + m.OnlineStatus = @"Online"; + } + else + { + int unixtime = int.Parse(gud.Data["Login"]); + // The viewer is very picky about how these strings are formed. Eg. it will crash on malformed dates! + m.OnlineStatus = (unixtime == 0) ? @"unknown" : Util.ToDateTime(unixtime).ToString("MM/dd/yyyy"); + } + } + // Is this person an owner of the group? m.IsOwner = (rolemembershipsList.Find(r => r.RoleID == ownerRoleID) != null) ? true : false; diff --git a/OpenSim/Addons/Groups/Service/GroupsServiceBase.cs b/OpenSim/Addons/Groups/Service/GroupsServiceBase.cs index 2611a3d..8e237aa 100644 --- a/OpenSim/Addons/Groups/Service/GroupsServiceBase.cs +++ b/OpenSim/Addons/Groups/Service/GroupsServiceBase.cs @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) Contributors, http://opensimulator.org/ * See CONTRIBUTORS.TXT for a full list of copyright holders. * @@ -35,50 +35,67 @@ using OpenSim.Services.Base; namespace OpenSim.Groups { - public class GroupsServiceBase : ServiceBase - { - protected IGroupsData m_Database = null; + public class GroupsServiceBase : ServiceBase + { + protected IGroupsData m_Database = null; + protected IGridUserData m_GridUserService = null; - public GroupsServiceBase(IConfigSource config, string cName) - : base(config) - { - string dllName = String.Empty; - string connString = String.Empty; - string realm = "os_groups"; - string configName = (cName == string.Empty) ? "Groups" : cName; + public GroupsServiceBase(IConfigSource config, string cName) + : base(config) + { + string dllName = String.Empty; + string connString = String.Empty; + string realm = "os_groups"; + string usersRealm = "GridUser"; + string configName = (cName == string.Empty) ? "Groups" : cName; - // - // Try reading the [DatabaseService] section, if it exists - // - IConfig dbConfig = config.Configs["DatabaseService"]; - if (dbConfig != null) - { - if (dllName == String.Empty) - dllName = dbConfig.GetString("StorageProvider", String.Empty); - if (connString == String.Empty) - connString = dbConfig.GetString("ConnectionString", String.Empty); - } + // + // Try reading the [DatabaseService] section, if it exists + // + IConfig dbConfig = config.Configs["DatabaseService"]; + if (dbConfig != null) + { + if (dllName == String.Empty) + dllName = dbConfig.GetString("StorageProvider", String.Empty); + if (connString == String.Empty) + connString = dbConfig.GetString("ConnectionString", String.Empty); + } - // - // [Groups] section overrides [DatabaseService], if it exists - // - IConfig groupsConfig = config.Configs[configName]; - if (groupsConfig != null) - { - dllName = groupsConfig.GetString("StorageProvider", dllName); - connString = groupsConfig.GetString("ConnectionString", connString); - realm = groupsConfig.GetString("Realm", realm); - } + // + // [Groups] section overrides [DatabaseService], if it exists + // + IConfig groupsConfig = config.Configs[configName]; + if (groupsConfig != null) + { + dllName = groupsConfig.GetString("StorageProvider", dllName); + connString = groupsConfig.GetString("ConnectionString", connString); + realm = groupsConfig.GetString("Realm", realm); + } - // - // We tried, but this doesn't exist. We can't proceed. - // - if (dllName.Equals(String.Empty)) - throw new Exception("No StorageProvider configured"); + // + // We tried, but this doesn't exist. We can't proceed. + // + if (dllName.Equals(String.Empty)) + throw new Exception("No StorageProvider configured"); - m_Database = LoadPlugin(dllName, new Object[] { connString, realm }); - if (m_Database == null) - throw new Exception("Could not find a storage interface in the given module " + dllName); - } - } -} \ No newline at end of file + m_Database = LoadPlugin(dllName, new Object[] { connString, realm }); + if (m_Database == null) + throw new Exception("Could not find a storage interface in the given module " + dllName); + + // + // [GridUserService] section overrides [DatabaseService], if it exists + // + IConfig usersConfig = config.Configs["GridUserService"]; + if (usersConfig != null) + { + dllName = usersConfig.GetString("StorageProvider", dllName); + connString = usersConfig.GetString("ConnectionString", connString); + usersRealm = usersConfig.GetString("Realm", usersRealm); + } + + m_GridUserService = LoadPlugin(dllName, new Object[] { connString, usersRealm }); + if (m_GridUserService == null) + throw new Exception("Could not find a storage inferface for the given users module " + dllName); + } + } +} -- cgit v1.1 From a11edceb00b5b86f825bd957bdac9edb91f893dd Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Wed, 2 Sep 2015 19:54:53 +0100 Subject: seems to compile ( tests comented out) --- OpenSim/Addons/Groups/GroupsModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs index d121d1a..2831326 100644 --- a/OpenSim/Addons/Groups/GroupsModule.cs +++ b/OpenSim/Addons/Groups/GroupsModule.cs @@ -1296,7 +1296,7 @@ namespace OpenSim.Groups presence.Grouptitle = Title; if (! presence.IsChildAgent) - presence.SendAvatarDataToAllClients(); + presence.SendAvatarDataToAllAgents(); } } } -- cgit v1.1 From dcd36d0c9b24afd751265b02f4c5f89befed2a4e Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Sun, 27 Sep 2015 16:53:36 +0100 Subject: apply changes to xmlrcp groups to groups V2, compiles but not tested :( --- OpenSim/Addons/Groups/GroupsModule.cs | 241 +++++++++++----------------------- 1 file changed, 77 insertions(+), 164 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs index 2831326..7b337cf 100644 --- a/OpenSim/Addons/Groups/GroupsModule.cs +++ b/OpenSim/Addons/Groups/GroupsModule.cs @@ -137,13 +137,6 @@ namespace OpenSim.Groups if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - scene.EventManager.OnNewClient += OnNewClient; - scene.EventManager.OnMakeRootAgent += OnMakeRoot; - scene.EventManager.OnMakeChildAgent += OnMakeChild; - scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; - // The InstantMessageModule itself doesn't do this, - // so lets see if things explode if we don't do it - // scene.EventManager.OnClientClosed += OnClientClosed; if (m_groupData == null) { @@ -182,6 +175,13 @@ namespace OpenSim.Groups m_sceneList.Add(scene); } + scene.EventManager.OnNewClient += OnNewClient; + scene.EventManager.OnMakeRootAgent += OnMakeRoot; + scene.EventManager.OnMakeChildAgent += OnMakeChild; + scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; + // The InstantMessageModule itself doesn't do this, + // so lets see if things explode if we don't do it + // scene.EventManager.OnClientClosed += OnClientClosed; } @@ -237,6 +237,7 @@ namespace OpenSim.Groups client.OnRequestAvatarProperties += OnRequestAvatarProperties; } + private void OnMakeRoot(ScenePresence sp) { if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); @@ -245,8 +246,9 @@ namespace OpenSim.Groups // Used for Notices and Group Invites/Accept/Reject sp.ControllingClient.OnInstantMessage += OnInstantMessage; - // Send client their groups information. - SendAgentGroupDataUpdate(sp.ControllingClient, sp.UUID); + // we should send a DataUpdate here for compatibility, + // but this is a bad place and a bad thread to do it + // also current viewers do ignore it and ask later on a much nicer thread } private void OnMakeChild(ScenePresence sp) @@ -262,7 +264,6 @@ namespace OpenSim.Groups { if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - //GroupMembershipData[] avatarGroups = m_groupData.GetAgentGroupMemberships(GetRequestingAgentID(remoteClient), avatarID).ToArray(); GroupMembershipData[] avatarGroups = GetProfileListedGroupMemberships(remoteClient, avatarID); remoteClient.SendAvatarGroupsReply(avatarID, avatarGroups); } @@ -303,24 +304,13 @@ namespace OpenSim.Groups private void OnAgentDataUpdateRequest(IClientAPI remoteClient, UUID dataForAgentID, UUID sessionID) { - if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - UUID activeGroupID = UUID.Zero; - string activeGroupTitle = string.Empty; - string activeGroupName = string.Empty; - ulong activeGroupPowers = (ulong)GroupPowers.None; - - GroupMembershipData membership = m_groupData.GetAgentActiveMembership(GetRequestingAgentIDStr(remoteClient), dataForAgentID.ToString()); - if (membership != null) - { - activeGroupID = membership.GroupID; - activeGroupTitle = membership.GroupTitle; - activeGroupPowers = membership.GroupPowers; - } - - SendAgentDataUpdate(remoteClient, dataForAgentID, activeGroupID, activeGroupName, activeGroupPowers, activeGroupTitle); + // this a private message for own agent only + if (dataForAgentID != GetRequestingAgentID(remoteClient)) + return; - SendScenePresenceUpdate(dataForAgentID, activeGroupTitle); + SendAgentGroupDataUpdate(remoteClient, false); + // its a info request not a change, so nothing is sent to others + // they do get the group title with the avatar object update on arrivel to a region } private void HandleUUIDGroupNameRequest(UUID GroupID, IClientAPI remoteClient) @@ -395,11 +385,12 @@ namespace OpenSim.Groups OutgoingInstantMessage(msg, invitee); - UpdateAllClientsWithGroupInfo(invitee); + IClientAPI client = GetActiveClient(invitee); + if (client != null) + SendDataUpdate(remoteClient, true); } m_groupData.RemoveAgentToGroupInvite(GetRequestingAgentIDStr(remoteClient), inviteID); - } // Reject @@ -462,7 +453,6 @@ namespace OpenSim.Groups { OnNewGroupNotice(GroupID, NoticeID); } - // Send notice out to everyone that wants notices foreach (GroupMembersData member in m_groupData.GetGroupMembers(GetRequestingAgentIDStr(remoteClient), GroupID)) @@ -508,7 +498,6 @@ namespace OpenSim.Groups remoteClient.SendInventoryItemCreateUpdate(itemCopy, 0); } - } // Interop, received special 210 code for ejecting a group member @@ -583,11 +572,7 @@ namespace OpenSim.Groups m_groupData.SetAgentActiveGroup(GetRequestingAgentIDStr(remoteClient), GetRequestingAgentIDStr(remoteClient), groupID); - // Changing active group changes title, active powers, all kinds of things - // anyone who is in any region that can see this client, should probably be - // updated with new group info. At a minimum, they should get ScenePresence - // updated with new title. - UpdateAllClientsWithGroupInfo(remoteClient.AgentId); + SendAgentGroupDataUpdate(remoteClient, true); } /// @@ -634,7 +619,6 @@ namespace OpenSim.Groups } return data; - } public List GroupRoleDataRequest(IClientAPI remoteClient, UUID groupID) @@ -781,7 +765,7 @@ namespace OpenSim.Groups remoteClient.SendCreateGroupReply(groupID, true, "Group created successfullly"); // Update the founder with new group information. - SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); + SendAgentGroupDataUpdate(remoteClient, false); } else remoteClient.SendCreateGroupReply(groupID, false, reason); @@ -834,7 +818,7 @@ namespace OpenSim.Groups // the client currently has set active, then we need to do a scene presence update too // if (m_groupData.GetAgentActiveMembership(GetRequestingAgentID(remoteClient)).GroupID == GroupID) - UpdateAllClientsWithGroupInfo(GetRequestingAgentID(remoteClient)); + SendDataUpdate(remoteClient, true); } @@ -875,7 +859,7 @@ namespace OpenSim.Groups } // TODO: This update really should send out updates for everyone in the role that just got changed. - SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); + SendDataUpdate(remoteClient, true); } public void GroupRoleChanges(IClientAPI remoteClient, UUID groupID, UUID roleID, UUID memberID, uint changes) @@ -901,7 +885,7 @@ namespace OpenSim.Groups } // TODO: This update really should send out updates for everyone in the role that just got changed. - SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); + SendDataUpdate(remoteClient, true); } public void GroupNoticeRequest(IClientAPI remoteClient, UUID groupNoticeID) @@ -969,14 +953,6 @@ namespace OpenSim.Groups return msg; } - public void SendAgentGroupDataUpdate(IClientAPI remoteClient) - { - if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - // Send agent information about his groups - SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); - } - public void JoinGroupRequest(IClientAPI remoteClient, UUID groupID) { if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); @@ -989,7 +965,7 @@ namespace OpenSim.Groups remoteClient.SendJoinGroupReply(groupID, true); // Should this send updates to everyone in the group? - SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); + SendAgentGroupDataUpdate(remoteClient, true); if (reason != string.Empty) // A warning @@ -1011,7 +987,7 @@ namespace OpenSim.Groups // SL sends out notifcations to the group messaging session that the person has left // Should this also update everyone who is in the group? - SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); + SendAgentGroupDataUpdate(remoteClient, true); } public void EjectGroupMemberRequest(IClientAPI remoteClient, UUID groupID, UUID ejecteeID) @@ -1123,7 +1099,7 @@ namespace OpenSim.Groups // SL sends out messages to everyone in the group // Who all should receive updates and what should they be updated with? - UpdateAllClientsWithGroupInfo(ejecteeID); + SendAgentGroupDataUpdate(remoteClient, false); } public void InviteGroupRequest(IClientAPI remoteClient, UUID groupID, UUID invitedAgentID, UUID roleID) @@ -1215,71 +1191,6 @@ namespace OpenSim.Groups return child; } - /// - /// Send 'remoteClient' the group membership 'data' for agent 'dataForAgentID'. - /// - private void SendGroupMembershipInfoViaCaps(IClientAPI remoteClient, UUID dataForAgentID, GroupMembershipData[] data) - { - if (m_debugEnabled) m_log.InfoFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - // NPCs currently don't have a CAPs structure or event queues. There is a strong argument for conveying this information - // to them anyway since it makes writing server-side bots a lot easier, but for now we don't do anything. - if (remoteClient.SceneAgent.PresenceType == PresenceType.Npc) - return; - - OSDArray AgentData = new OSDArray(1); - OSDMap AgentDataMap = new OSDMap(1); - AgentDataMap.Add("AgentID", OSD.FromUUID(dataForAgentID)); - AgentData.Add(AgentDataMap); - - OSDArray GroupData = new OSDArray(data.Length); - OSDArray NewGroupData = new OSDArray(data.Length); - - foreach (GroupMembershipData membership in data) - { - if (GetRequestingAgentID(remoteClient) != dataForAgentID) - { - if (!membership.ListInProfile) - { - // If we're sending group info to remoteclient about another agent, - // filter out groups the other agent doesn't want to share. - continue; - } - } - - OSDMap GroupDataMap = new OSDMap(6); - OSDMap NewGroupDataMap = new OSDMap(1); - - GroupDataMap.Add("GroupID", OSD.FromUUID(membership.GroupID)); - GroupDataMap.Add("GroupPowers", OSD.FromULong(membership.GroupPowers)); - GroupDataMap.Add("AcceptNotices", OSD.FromBoolean(membership.AcceptNotices)); - GroupDataMap.Add("GroupInsigniaID", OSD.FromUUID(membership.GroupPicture)); - GroupDataMap.Add("Contribution", OSD.FromInteger(membership.Contribution)); - GroupDataMap.Add("GroupName", OSD.FromString(membership.GroupName)); - NewGroupDataMap.Add("ListInProfile", OSD.FromBoolean(membership.ListInProfile)); - - GroupData.Add(GroupDataMap); - NewGroupData.Add(NewGroupDataMap); - } - - OSDMap llDataStruct = new OSDMap(3); - llDataStruct.Add("AgentData", AgentData); - llDataStruct.Add("GroupData", GroupData); - llDataStruct.Add("NewGroupData", NewGroupData); - - if (m_debugEnabled) - { - m_log.InfoFormat("[Groups]: {0}", OSDParser.SerializeJsonString(llDataStruct)); - } - - IEventQueue queue = remoteClient.Scene.RequestModuleInterface(); - - if (queue != null) - { - queue.Enqueue(queue.BuildEvent("AgentGroupDataUpdate", llDataStruct), GetRequestingAgentID(remoteClient)); - } - } - private void SendScenePresenceUpdate(UUID AgentID, string Title) { if (m_debugEnabled) m_log.DebugFormat("[Groups]: Updating scene title for {0} with title: {1}", AgentID, Title); @@ -1302,47 +1213,28 @@ namespace OpenSim.Groups } } - /// - /// Send updates to all clients who might be interested in groups data for dataForClientID - /// - private void UpdateAllClientsWithGroupInfo(UUID dataForClientID) + public void SendAgentGroupDataUpdate(IClientAPI remoteClient) { - if (m_debugEnabled) m_log.InfoFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - // TODO: Probably isn't nessesary to update every client in every scene. - // Need to examine client updates and do only what's nessesary. - lock (m_sceneList) - { - foreach (Scene scene in m_sceneList) - { - scene.ForEachClient(delegate(IClientAPI client) { SendAgentGroupDataUpdate(client, dataForClientID); }); - } - } + SendAgentGroupDataUpdate(remoteClient, true); } - - /// - /// Update remoteClient with group information about dataForAgentID - /// - private void SendAgentGroupDataUpdate(IClientAPI remoteClient, UUID dataForAgentID) + + /// + /// Tell remoteClient about its agent groups, and optionally send title to others + /// + private void SendAgentGroupDataUpdate(IClientAPI remoteClient, bool tellOthers) { if (m_debugEnabled) m_log.InfoFormat("[Groups]: {0} called for {1}", System.Reflection.MethodBase.GetCurrentMethod().Name, remoteClient.Name); // TODO: All the client update functions need to be reexamined because most do too much and send too much stuff - OnAgentDataUpdateRequest(remoteClient, dataForAgentID, UUID.Zero); + UUID agentID = GetRequestingAgentID(remoteClient); - // Need to send a group membership update to the client - // UDP version doesn't seem to behave nicely. But we're going to send it out here - // with an empty group membership to hopefully remove groups being displayed due - // to the core Groups Stub - //remoteClient.SendGroupMembership(new GroupMembershipData[0]); + SendDataUpdate(remoteClient, tellOthers); - GroupMembershipData[] membershipArray = GetProfileListedGroupMemberships(remoteClient, dataForAgentID); - SendGroupMembershipInfoViaCaps(remoteClient, dataForAgentID, membershipArray); + GroupMembershipData[] membershipArray = GetProfileListedGroupMemberships(remoteClient, agentID); + remoteClient.SendAgentGroupDataUpdate(agentID, membershipArray); - //remoteClient.SendAvatarGroupsReply(dataForAgentID, membershipArray); - if (remoteClient.AgentId == dataForAgentID) - remoteClient.RefreshGroupMembership(); + remoteClient.RefreshGroupMembership(); } /// @@ -1394,27 +1286,49 @@ namespace OpenSim.Groups return membershipArray; } - - private void SendAgentDataUpdate(IClientAPI remoteClient, UUID dataForAgentID, UUID activeGroupID, string activeGroupName, ulong activeGroupPowers, string activeGroupTitle) + //tell remoteClient about its agent group info, and optionally send title to others + private void SendDataUpdate(IClientAPI remoteClient, bool tellOthers) { - if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - // TODO: All the client update functions need to be reexamined because most do too much and send too much stuff - string firstname = "Unknown", lastname = "Unknown"; - string name = m_UserManagement.GetUserName(dataForAgentID); - if (!string.IsNullOrEmpty(name)) + UUID activeGroupID = UUID.Zero; + string activeGroupTitle = string.Empty; + string activeGroupName = string.Empty; + ulong activeGroupPowers = (ulong)GroupPowers.None; + + UUID agentID = GetRequestingAgentID(remoteClient); + GroupMembershipData membership = m_groupData.GetAgentActiveMembership(agentID.ToString(), agentID.ToString()); + if (membership != null) { - string[] parts = name.Split(new char[] { ' ' }); - if (parts.Length >= 2) - { - firstname = parts[0]; - lastname = parts[1]; - } + activeGroupID = membership.GroupID; + activeGroupTitle = membership.GroupTitle; + activeGroupPowers = membership.GroupPowers; + activeGroupName = membership.GroupName; } - - remoteClient.SendAgentDataUpdate(dataForAgentID, activeGroupID, firstname, + + UserAccount account = m_sceneList[0].UserAccountService.GetUserAccount(remoteClient.Scene.RegionInfo.ScopeID, agentID); + string firstname, lastname; + if (account != null) + { + firstname = account.FirstName; + lastname = account.LastName; + } + else + { + firstname = "Unknown"; + lastname = "Unknown"; + } + + remoteClient.SendAgentDataUpdate(agentID, activeGroupID, firstname, lastname, activeGroupPowers, activeGroupName, activeGroupTitle); + + if (tellOthers) + SendScenePresenceUpdate(agentID, activeGroupTitle); + + ScenePresence sp = (ScenePresence)remoteClient.SceneAgent; + if (sp != null) + sp.Grouptitle = activeGroupTitle; } #endregion @@ -1463,5 +1377,4 @@ namespace OpenSim.Groups } } - } -- cgit v1.1 From a580d945d14131a56b9547a8e8cf198d37ba56cd Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Mon, 28 Sep 2015 21:03:20 +0100 Subject: remove groups handlers onClientClose also on groups V2 --- OpenSim/Addons/Groups/GroupsModule.cs | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs index 7b337cf..da8c9ea 100644 --- a/OpenSim/Addons/Groups/GroupsModule.cs +++ b/OpenSim/Addons/Groups/GroupsModule.cs @@ -268,18 +268,24 @@ namespace OpenSim.Groups remoteClient.SendAvatarGroupsReply(avatarID, avatarGroups); } - /* - * This becomes very problematic in a shared module. In a shared module you may have more then one - * reference to IClientAPI's, one for 0 or 1 root connections, and 0 or more child connections. - * The OnClientClosed event does not provide anything to indicate which one of those should be closed - * nor does it provide what scene it was from so that the specific reference can be looked up. - * The InstantMessageModule.cs does not currently worry about unregistering the handles, - * and it should be an issue, since it's the client that references us not the other way around - * , so as long as we don't keep a reference to the client laying around, the client can still be GC'ed - private void OnClientClosed(UUID AgentId) + private void OnClientClosed(UUID AgentId, Scene scene) { - if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + if (scene == null) + return; + ScenePresence sp = scene.GetScenePresence(AgentId); + IClientAPI client = sp.ControllingClient; + if (client != null) + { + client.OnAgentDataUpdateRequest -= OnAgentDataUpdateRequest; + client.OnRequestAvatarProperties -= OnRequestAvatarProperties; + // make child possible not called? + client.OnUUIDGroupNameRequest -= HandleUUIDGroupNameRequest; + client.OnInstantMessage -= OnInstantMessage; + } + + /* lock (m_ActiveClients) { if (m_ActiveClients.ContainsKey(AgentId)) @@ -297,11 +303,11 @@ namespace OpenSim.Groups if (m_debugEnabled) m_log.WarnFormat("[Groups]: Client closed that wasn't registered here."); } - - } } */ + } + private void OnAgentDataUpdateRequest(IClientAPI remoteClient, UUID dataForAgentID, UUID sessionID) { // this a private message for own agent only -- cgit v1.1 From 59b63b64066d9da706c47e47bddd86a897ccd175 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 18 Oct 2015 21:47:10 -0700 Subject: On to 0.8.3! Conflicts: OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/Properties/AssemblyInfo.cs --- OpenSim/Addons/Groups/Properties/AssemblyInfo.cs | 2 +- OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs b/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs index 0a7fb5f..cf0de1d 100644 --- a/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs +++ b/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs @@ -30,7 +30,7 @@ using Mono.Addins; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.2.*")] +[assembly: AssemblyVersion("0.8.3.*")] [assembly: Addin("OpenSim.Groups", OpenSim.VersionInfo.VersionNumber)] [assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)] diff --git a/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs b/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs index 3e993b4..0699660 100644 --- a/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs +++ b/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs @@ -30,7 +30,7 @@ using Mono.Addins; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.2.*")] +[assembly: AssemblyVersion("0.8.3.*")] [assembly: Addin("OpenSim.OfflineIM", OpenSim.VersionInfo.VersionNumber)] [assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)] -- cgit v1.1 From ab12a142798a1358b82d927f3d6046e30fcc57c2 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 21 Feb 2016 11:14:02 -0800 Subject: Pushed AssemblyVersion up to VersionInfo, so that we don't need to do global replace anymore. --- OpenSim/Addons/Groups/Properties/AssemblyInfo.cs | 2 +- OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs b/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs index cf0de1d..98630eb 100644 --- a/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs +++ b/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs @@ -30,7 +30,7 @@ using Mono.Addins; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.3.*")] +[assembly: AssemblyVersion(OpenSim.VersionInfo.AssemblyVersionNumber)] [assembly: Addin("OpenSim.Groups", OpenSim.VersionInfo.VersionNumber)] [assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)] diff --git a/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs b/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs index 0699660..a980f22 100644 --- a/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs +++ b/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs @@ -30,7 +30,7 @@ using Mono.Addins; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.3.*")] +[assembly: AssemblyVersion(OpenSim.VersionInfo.AssemblyVersionNumber)] [assembly: Addin("OpenSim.OfflineIM", OpenSim.VersionInfo.VersionNumber)] [assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)] -- cgit v1.1 From 9ebdae8676f1e48bc1e12af9c28714dff295f8b9 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Sat, 11 Jun 2016 12:42:42 -0700 Subject: Restore SendAgentGroupDataUpdate() call in GroupsModule.cs. Restore linkage to OnAgentClosed since the merge solved the reference problem by looking up the agent. This should address Mantis 7915 and 7920. --- OpenSim/Addons/Groups/GroupsModule.cs | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs index da8c9ea..cdc98f5 100644 --- a/OpenSim/Addons/Groups/GroupsModule.cs +++ b/OpenSim/Addons/Groups/GroupsModule.cs @@ -179,9 +179,7 @@ namespace OpenSim.Groups scene.EventManager.OnMakeRootAgent += OnMakeRoot; scene.EventManager.OnMakeChildAgent += OnMakeChild; scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; - // The InstantMessageModule itself doesn't do this, - // so lets see if things explode if we don't do it - // scene.EventManager.OnClientClosed += OnClientClosed; + scene.EventManager.OnClientClosed += OnClientClosed; } @@ -246,9 +244,11 @@ namespace OpenSim.Groups // Used for Notices and Group Invites/Accept/Reject sp.ControllingClient.OnInstantMessage += OnInstantMessage; - // we should send a DataUpdate here for compatibility, - // but this is a bad place and a bad thread to do it - // also current viewers do ignore it and ask later on a much nicer thread + // Send out group data update for compatibility. + // There might be some problem with the thread we're generating this on but not + // doing the update at this time causes problems (Mantis #7920 and #7915) + // TODO: move sending this update to a later time in the rootification of the client. + SendAgentGroupDataUpdate(sp.ControllingClient, false); } private void OnMakeChild(ScenePresence sp) @@ -315,6 +315,8 @@ namespace OpenSim.Groups return; SendAgentGroupDataUpdate(remoteClient, false); + + // also current viewers do ignore it and ask later on a much nicer thread // its a info request not a change, so nothing is sent to others // they do get the group title with the avatar object update on arrivel to a region } @@ -578,6 +580,10 @@ namespace OpenSim.Groups m_groupData.SetAgentActiveGroup(GetRequestingAgentIDStr(remoteClient), GetRequestingAgentIDStr(remoteClient), groupID); + // Changing active group changes title, active powers, all kinds of things + // anyone who is in any region that can see this client, should probably be + // updated with new group info. At a minimum, they should get ScenePresence + // updated with new title. SendAgentGroupDataUpdate(remoteClient, true); } @@ -1240,7 +1246,7 @@ namespace OpenSim.Groups GroupMembershipData[] membershipArray = GetProfileListedGroupMemberships(remoteClient, agentID); remoteClient.SendAgentGroupDataUpdate(agentID, membershipArray); - remoteClient.RefreshGroupMembership(); + remoteClient.RefreshGroupMembership(); } /// -- cgit v1.1 From a9fb3d0e182becbc3cbff02cf175988805916e34 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 19 Jun 2016 15:14:50 -0700 Subject: Minor -- deregister an event handler in Groups V2 --- OpenSim/Addons/Groups/GroupsModule.cs | 1 + 1 file changed, 1 insertion(+) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs index cdc98f5..1a83f5b 100644 --- a/OpenSim/Addons/Groups/GroupsModule.cs +++ b/OpenSim/Addons/Groups/GroupsModule.cs @@ -194,6 +194,7 @@ namespace OpenSim.Groups scene.EventManager.OnMakeRootAgent -= OnMakeRoot; scene.EventManager.OnMakeChildAgent -= OnMakeChild; scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage; + scene.EventManager.OnClientClosed -= OnClientClosed; lock (m_sceneList) { -- cgit v1.1 From 76ab1ed10c57d8f2190366d8a61f9c989afff3df Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 19 Jun 2016 16:27:12 -0700 Subject: Restored sending group membership data via EventQueue -- this had been a regression. Took the opportunity to refactor that code, so that both Groups V2 and XmlRpcGroups can use the same function. --- OpenSim/Addons/Groups/GroupsModule.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs index 1a83f5b..f24670a 100644 --- a/OpenSim/Addons/Groups/GroupsModule.cs +++ b/OpenSim/Addons/Groups/GroupsModule.cs @@ -1245,7 +1245,8 @@ namespace OpenSim.Groups SendDataUpdate(remoteClient, tellOthers); GroupMembershipData[] membershipArray = GetProfileListedGroupMemberships(remoteClient, agentID); - remoteClient.SendAgentGroupDataUpdate(agentID, membershipArray); + IEventQueue eq = remoteClient.Scene.RequestModuleInterface(); + eq.GroupMembershipData(GetRequestingAgentID(remoteClient), membershipArray); remoteClient.RefreshGroupMembership(); } -- cgit v1.1 From 8d99fe095a231ba71ce71712cb87f8114672e7df Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 19 Jun 2016 17:35:11 -0700 Subject: Mantis #7920: group info was not being updated in many situations. (regression) Putting back the heavy messaging. --- OpenSim/Addons/Groups/GroupsModule.cs | 47 +++++++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 10 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs index f24670a..d27797e 100644 --- a/OpenSim/Addons/Groups/GroupsModule.cs +++ b/OpenSim/Addons/Groups/GroupsModule.cs @@ -394,9 +394,8 @@ namespace OpenSim.Groups OutgoingInstantMessage(msg, invitee); - IClientAPI client = GetActiveClient(invitee); - if (client != null) - SendDataUpdate(remoteClient, true); + UpdateAllClientsWithGroupInfo(invitee); + } m_groupData.RemoveAgentToGroupInvite(GetRequestingAgentIDStr(remoteClient), inviteID); @@ -1112,7 +1111,7 @@ namespace OpenSim.Groups // SL sends out messages to everyone in the group // Who all should receive updates and what should they be updated with? - SendAgentGroupDataUpdate(remoteClient, false); + UpdateAllClientsWithGroupInfo(ejecteeID); } public void InviteGroupRequest(IClientAPI remoteClient, UUID groupID, UUID invitedAgentID, UUID roleID) @@ -1226,16 +1225,44 @@ namespace OpenSim.Groups } } + /// + /// Send updates to all clients who might be interested in groups data for dataForClientID + /// + private void UpdateAllClientsWithGroupInfo(UUID dataForClientID) + { + if (m_debugEnabled) m_log.InfoFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + // TODO: Probably isn't nessesary to update every client in every scene. + // Need to examine client updates and do only what's nessesary. + lock (m_sceneList) + { + foreach (Scene scene in m_sceneList) + { + scene.ForEachClient(delegate (IClientAPI client) { SendAgentGroupDataUpdate(client, dataForClientID); }); + } + } + } + public void SendAgentGroupDataUpdate(IClientAPI remoteClient) { - SendAgentGroupDataUpdate(remoteClient, true); + SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient), true); + } + + public void SendAgentGroupDataUpdate(IClientAPI remoteClient, UUID dataForClientID) + { + SendAgentGroupDataUpdate(remoteClient, dataForClientID, true); } - - /// - /// Tell remoteClient about its agent groups, and optionally send title to others - /// + private void SendAgentGroupDataUpdate(IClientAPI remoteClient, bool tellOthers) { + SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient), tellOthers); + } + + /// + /// Tell remoteClient about its agent groups, and optionally send title to others + /// + private void SendAgentGroupDataUpdate(IClientAPI remoteClient, UUID dataForClientID, bool tellOthers) + { if (m_debugEnabled) m_log.InfoFormat("[Groups]: {0} called for {1}", System.Reflection.MethodBase.GetCurrentMethod().Name, remoteClient.Name); // TODO: All the client update functions need to be reexamined because most do too much and send too much stuff @@ -1246,7 +1273,7 @@ namespace OpenSim.Groups GroupMembershipData[] membershipArray = GetProfileListedGroupMemberships(remoteClient, agentID); IEventQueue eq = remoteClient.Scene.RequestModuleInterface(); - eq.GroupMembershipData(GetRequestingAgentID(remoteClient), membershipArray); + eq.GroupMembershipData(GetRequestingAgentID(remoteClient), dataForClientID, membershipArray); remoteClient.RefreshGroupMembership(); } -- cgit v1.1 From 55a4d1cf44528915e718f83f6c435a723eaab60c Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Thu, 23 Jun 2016 06:41:26 -0700 Subject: Same change here too. --- OpenSim/Addons/Groups/GroupsModule.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs index d27797e..1d0acf4 100644 --- a/OpenSim/Addons/Groups/GroupsModule.cs +++ b/OpenSim/Addons/Groups/GroupsModule.cs @@ -1273,7 +1273,10 @@ namespace OpenSim.Groups GroupMembershipData[] membershipArray = GetProfileListedGroupMemberships(remoteClient, agentID); IEventQueue eq = remoteClient.Scene.RequestModuleInterface(); - eq.GroupMembershipData(GetRequestingAgentID(remoteClient), dataForClientID, membershipArray); + if (eq != null) + eq.GroupMembershipData(GetRequestingAgentID(remoteClient), dataForClientID, membershipArray); + else + remoteClient.SendGroupMembership(membershipArray); remoteClient.RefreshGroupMembership(); } -- cgit v1.1 From cec5682da96a4f8e385197ec1e5d2dedf923c2e8 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Thu, 23 Jun 2016 12:10:50 -0700 Subject: Mantis #7937: don't send group info to NPCs --- OpenSim/Addons/Groups/GroupsModule.cs | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs index 1d0acf4..3336e94 100644 --- a/OpenSim/Addons/Groups/GroupsModule.cs +++ b/OpenSim/Addons/Groups/GroupsModule.cs @@ -1265,6 +1265,11 @@ namespace OpenSim.Groups { if (m_debugEnabled) m_log.InfoFormat("[Groups]: {0} called for {1}", System.Reflection.MethodBase.GetCurrentMethod().Name, remoteClient.Name); + // NPCs currently don't have a CAPs structure or event queues. There is a strong argument for conveying this information + // to them anyway since it makes writing server-side bots a lot easier, but for now we don't do anything. + if (remoteClient.SceneAgent.PresenceType == PresenceType.Npc) + return; + // TODO: All the client update functions need to be reexamined because most do too much and send too much stuff UUID agentID = GetRequestingAgentID(remoteClient); -- cgit v1.1 From 84a6a6e008c64d8197177aff1b42a412e5623638 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Tue, 28 Jun 2016 23:52:00 +0100 Subject: don't try to send initial AgentGroupDataUpdate to NPCs --- OpenSim/Addons/Groups/GroupsModule.cs | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs index 3336e94..2d5ebea 100644 --- a/OpenSim/Addons/Groups/GroupsModule.cs +++ b/OpenSim/Addons/Groups/GroupsModule.cs @@ -249,7 +249,8 @@ namespace OpenSim.Groups // There might be some problem with the thread we're generating this on but not // doing the update at this time causes problems (Mantis #7920 and #7915) // TODO: move sending this update to a later time in the rootification of the client. - SendAgentGroupDataUpdate(sp.ControllingClient, false); + if(!sp.isNPC) + SendAgentGroupDataUpdate(sp.ControllingClient, false); } private void OnMakeChild(ScenePresence sp) @@ -1265,11 +1266,6 @@ namespace OpenSim.Groups { if (m_debugEnabled) m_log.InfoFormat("[Groups]: {0} called for {1}", System.Reflection.MethodBase.GetCurrentMethod().Name, remoteClient.Name); - // NPCs currently don't have a CAPs structure or event queues. There is a strong argument for conveying this information - // to them anyway since it makes writing server-side bots a lot easier, but for now we don't do anything. - if (remoteClient.SceneAgent.PresenceType == PresenceType.Npc) - return; - // TODO: All the client update functions need to be reexamined because most do too much and send too much stuff UUID agentID = GetRequestingAgentID(remoteClient); @@ -1278,10 +1274,7 @@ namespace OpenSim.Groups GroupMembershipData[] membershipArray = GetProfileListedGroupMemberships(remoteClient, agentID); IEventQueue eq = remoteClient.Scene.RequestModuleInterface(); - if (eq != null) - eq.GroupMembershipData(GetRequestingAgentID(remoteClient), dataForClientID, membershipArray); - else - remoteClient.SendGroupMembership(membershipArray); + eq.GroupMembershipData(GetRequestingAgentID(remoteClient), dataForClientID, membershipArray); remoteClient.RefreshGroupMembership(); } -- cgit v1.1 From 158e0ae402bfc372934bcff475d2963453943f16 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Tue, 28 Jun 2016 23:57:14 +0100 Subject: Revert " don't try to send initial AgentGroupDataUpdate to NPCs" this was already done This reverts commit 84a6a6e008c64d8197177aff1b42a412e5623638. --- OpenSim/Addons/Groups/GroupsModule.cs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs index 2d5ebea..3336e94 100644 --- a/OpenSim/Addons/Groups/GroupsModule.cs +++ b/OpenSim/Addons/Groups/GroupsModule.cs @@ -249,8 +249,7 @@ namespace OpenSim.Groups // There might be some problem with the thread we're generating this on but not // doing the update at this time causes problems (Mantis #7920 and #7915) // TODO: move sending this update to a later time in the rootification of the client. - if(!sp.isNPC) - SendAgentGroupDataUpdate(sp.ControllingClient, false); + SendAgentGroupDataUpdate(sp.ControllingClient, false); } private void OnMakeChild(ScenePresence sp) @@ -1266,6 +1265,11 @@ namespace OpenSim.Groups { if (m_debugEnabled) m_log.InfoFormat("[Groups]: {0} called for {1}", System.Reflection.MethodBase.GetCurrentMethod().Name, remoteClient.Name); + // NPCs currently don't have a CAPs structure or event queues. There is a strong argument for conveying this information + // to them anyway since it makes writing server-side bots a lot easier, but for now we don't do anything. + if (remoteClient.SceneAgent.PresenceType == PresenceType.Npc) + return; + // TODO: All the client update functions need to be reexamined because most do too much and send too much stuff UUID agentID = GetRequestingAgentID(remoteClient); @@ -1274,7 +1278,10 @@ namespace OpenSim.Groups GroupMembershipData[] membershipArray = GetProfileListedGroupMemberships(remoteClient, agentID); IEventQueue eq = remoteClient.Scene.RequestModuleInterface(); - eq.GroupMembershipData(GetRequestingAgentID(remoteClient), dataForClientID, membershipArray); + if (eq != null) + eq.GroupMembershipData(GetRequestingAgentID(remoteClient), dataForClientID, membershipArray); + else + remoteClient.SendGroupMembership(membershipArray); remoteClient.RefreshGroupMembership(); } -- cgit v1.1 From 9358a6ad2979929655d0e25d404596772607f75b Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Fri, 1 Jul 2016 16:10:45 +0100 Subject: revert several changes to groups modules (agentGroupData is private). change interregions invite/eject messages, etc --- OpenSim/Addons/Groups/GroupsModule.cs | 102 +++++++++++++++++----------------- 1 file changed, 51 insertions(+), 51 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs index 3336e94..13b7123 100644 --- a/OpenSim/Addons/Groups/GroupsModule.cs +++ b/OpenSim/Addons/Groups/GroupsModule.cs @@ -393,9 +393,11 @@ namespace OpenSim.Groups msg.binaryBucket = new byte[0]; OutgoingInstantMessage(msg, invitee); - - UpdateAllClientsWithGroupInfo(invitee); - + IClientAPI inviteeClient = GetActiveRootClient(invitee); + if(inviteeClient !=null) + { + SendAgentGroupDataUpdate(inviteeClient,true); + } } m_groupData.RemoveAgentToGroupInvite(GetRequestingAgentIDStr(remoteClient), inviteID); @@ -521,14 +523,16 @@ namespace OpenSim.Groups UUID ejecteeID = new UUID(im.toAgentID); + im.imSessionID = UUID.Zero.Guid; im.dialog = (byte)InstantMessageDialog.MessageFromAgent; OutgoingInstantMessage(im, ejecteeID); - IClientAPI ejectee = GetActiveClient(ejecteeID); + IClientAPI ejectee = GetActiveRootClient(ejecteeID); if (ejectee != null) { UUID groupID = new UUID(im.imSessionID); ejectee.SendAgentDropGroup(groupID); + SendAgentGroupDataUpdate(ejectee,true); } } } @@ -548,7 +552,7 @@ namespace OpenSim.Groups case (byte)InstantMessageDialog.GroupInvitation: case (byte)InstantMessageDialog.GroupNotice: UUID toAgentID = new UUID(msg.toAgentID); - IClientAPI localClient = GetActiveClient(toAgentID); + IClientAPI localClient = GetActiveRootClient(toAgentID); if (localClient != null) { localClient.SendInstantMessage(msg); @@ -1058,10 +1062,31 @@ namespace OpenSim.Groups return; } + IClientAPI ejecteeClient = GetActiveRootClient(ejecteeID); + // Send Message to Ejectee GridInstantMessage msg = new GridInstantMessage(); - msg.imSessionID = UUID.Zero.Guid; + // if local send a normal message + if(ejecteeClient != null) + { + msg.imSessionID = UUID.Zero.Guid; + msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.MessageFromAgent; + // also execute and send update + ejecteeClient.SendAgentDropGroup(groupID); + SendAgentGroupDataUpdate(ejecteeClient,true); + } + else // send + { + // Interop, received special 210 code for ejecting a group member + // this only works within the comms servers domain, and won't work hypergrid + // TODO:FIXME: Use a presence server of some kind to find out where the + // client actually is, and try contacting that region directly to notify them, + // or provide the notification via xmlrpc update queue + + msg.imSessionID = groupInfo.GroupID.Guid; + msg.dialog = (byte)210; //interop + } msg.fromAgentID = agentID.Guid; // msg.fromAgentID = info.GroupID; msg.toAgentID = ejecteeID.Guid; @@ -1069,7 +1094,7 @@ namespace OpenSim.Groups msg.timestamp = 0; msg.fromAgentName = agentName; msg.message = string.Format("You have been ejected from '{1}' by {0}.", agentName, groupInfo.GroupName); - msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.MessageFromAgent; + msg.fromGroup = false; msg.offline = (byte)0; msg.ParentEstateID = 0; @@ -1079,11 +1104,7 @@ namespace OpenSim.Groups OutgoingInstantMessage(msg, ejecteeID); // Message to ejector - // Interop, received special 210 code for ejecting a group member - // this only works within the comms servers domain, and won't work hypergrid - // TODO:FIXME: Use a presense server of some kind to find out where the - // client actually is, and try contacting that region directly to notify them, - // or provide the notification via xmlrpc update queue + msg = new GridInstantMessage(); msg.imSessionID = UUID.Zero.Guid; @@ -1099,7 +1120,7 @@ namespace OpenSim.Groups { msg.message = string.Format("{2} has been ejected from '{1}' by {0}.", agentName, groupInfo.GroupName, "Unknown member"); } - msg.dialog = (byte)210; //interop + msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.MessageFromAgent; msg.fromGroup = false; msg.offline = (byte)0; msg.ParentEstateID = 0; @@ -1107,11 +1128,6 @@ namespace OpenSim.Groups msg.RegionID = regionInfo.RegionID.Guid; msg.binaryBucket = new byte[0]; OutgoingInstantMessage(msg, agentID); - - - // SL sends out messages to everyone in the group - // Who all should receive updates and what should they be updated with? - UpdateAllClientsWithGroupInfo(ejecteeID); } public void InviteGroupRequest(IClientAPI remoteClient, UUID groupID, UUID invitedAgentID, UUID roleID) @@ -1174,6 +1190,18 @@ namespace OpenSim.Groups #endregion #region Client/Update Tools + private IClientAPI GetActiveRootClient(UUID agentID) + { + foreach (Scene scene in m_sceneList) + { + ScenePresence sp = scene.GetScenePresence(agentID); + if (sp != null && !sp.IsChildAgent && !sp.IsDeleted) + { + return sp.ControllingClient; + } + } + return null; + } /// /// Try to find an active IClientAPI reference for agentID giving preference to root connections @@ -1186,7 +1214,7 @@ namespace OpenSim.Groups foreach (Scene scene in m_sceneList) { ScenePresence sp = scene.GetScenePresence(agentID); - if (sp != null) + if (sp != null&& !sp.IsDeleted) { if (!sp.IsChildAgent) { @@ -1225,43 +1253,15 @@ namespace OpenSim.Groups } } - /// - /// Send updates to all clients who might be interested in groups data for dataForClientID - /// - private void UpdateAllClientsWithGroupInfo(UUID dataForClientID) - { - if (m_debugEnabled) m_log.InfoFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - // TODO: Probably isn't nessesary to update every client in every scene. - // Need to examine client updates and do only what's nessesary. - lock (m_sceneList) - { - foreach (Scene scene in m_sceneList) - { - scene.ForEachClient(delegate (IClientAPI client) { SendAgentGroupDataUpdate(client, dataForClientID); }); - } - } - } - public void SendAgentGroupDataUpdate(IClientAPI remoteClient) { - SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient), true); - } - - public void SendAgentGroupDataUpdate(IClientAPI remoteClient, UUID dataForClientID) - { - SendAgentGroupDataUpdate(remoteClient, dataForClientID, true); - } - - private void SendAgentGroupDataUpdate(IClientAPI remoteClient, bool tellOthers) - { - SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient), tellOthers); + SendAgentGroupDataUpdate(remoteClient, true); } /// /// Tell remoteClient about its agent groups, and optionally send title to others /// - private void SendAgentGroupDataUpdate(IClientAPI remoteClient, UUID dataForClientID, bool tellOthers) + private void SendAgentGroupDataUpdate(IClientAPI remoteClient, bool tellOthers) { if (m_debugEnabled) m_log.InfoFormat("[Groups]: {0} called for {1}", System.Reflection.MethodBase.GetCurrentMethod().Name, remoteClient.Name); @@ -1279,7 +1279,7 @@ namespace OpenSim.Groups GroupMembershipData[] membershipArray = GetProfileListedGroupMemberships(remoteClient, agentID); IEventQueue eq = remoteClient.Scene.RequestModuleInterface(); if (eq != null) - eq.GroupMembershipData(GetRequestingAgentID(remoteClient), dataForClientID, membershipArray); + eq.GroupMembershipData(agentID, membershipArray); else remoteClient.SendGroupMembership(membershipArray); @@ -1388,7 +1388,7 @@ namespace OpenSim.Groups { if (m_debugEnabled) m_log.InfoFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - IClientAPI localClient = GetActiveClient(msgTo); + IClientAPI localClient = GetActiveRootClient(msgTo); if (localClient != null) { if (m_debugEnabled) m_log.InfoFormat("[Groups]: MsgTo ({0}) is local, delivering directly", localClient.Name); -- cgit v1.1 From 1777324a862a41c57d12bd6180129a30d9653841 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Fri, 1 Jul 2016 17:31:31 +0100 Subject: cleanup a bit AgentGroupDataUpdate sending --- OpenSim/Addons/Groups/GroupsModule.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs index 13b7123..11a2a12 100644 --- a/OpenSim/Addons/Groups/GroupsModule.cs +++ b/OpenSim/Addons/Groups/GroupsModule.cs @@ -1277,13 +1277,9 @@ namespace OpenSim.Groups SendDataUpdate(remoteClient, tellOthers); GroupMembershipData[] membershipArray = GetProfileListedGroupMemberships(remoteClient, agentID); - IEventQueue eq = remoteClient.Scene.RequestModuleInterface(); - if (eq != null) - eq.GroupMembershipData(agentID, membershipArray); - else - remoteClient.SendGroupMembership(membershipArray); remoteClient.RefreshGroupMembership(); + remoteClient.SendAgentGroupDataUpdate(agentID, membershipArray); } /// -- cgit v1.1 From ea8f3c83bf96453e8223d918933d5708fa49a3cc Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Mon, 4 Jul 2016 03:35:48 +0100 Subject: Finally remove the requirement for an InventoryItem/FolderBase object to be passed into inventory queries. This makes the API more homogenous and also will more clearly show coding errors related to HG inventory where the .Owner field has a meaning for a query but wasn't always set. --- OpenSim/Addons/Groups/GroupsModule.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs index 13b7123..ccd4da6 100644 --- a/OpenSim/Addons/Groups/GroupsModule.cs +++ b/OpenSim/Addons/Groups/GroupsModule.cs @@ -445,8 +445,7 @@ namespace OpenSim.Groups UUID itemID = binBucketMap["item_id"].AsUUID(); UUID ownerID = binBucketMap["owner_id"].AsUUID(); - item = new InventoryItemBase(itemID, ownerID); - item = m_sceneList[0].InventoryService.GetItem(item); + item = m_sceneList[0].InventoryService.GetItem(ownerID, itemID); } else m_log.DebugFormat("[Groups]: Received OSD with unexpected type: {0}", binBucketOSD.GetType()); -- cgit v1.1 From cdf215f6130b88a0fce9b56075947b539f1043a7 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Sat, 23 Jul 2016 01:28:47 +0100 Subject: add a missing field to ChatterBoxSessionAgentListUpdates. it is still wrong, and its use even worse --- OpenSim/Addons/Groups/GroupsMessagingModule.cs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsMessagingModule.cs b/OpenSim/Addons/Groups/GroupsMessagingModule.cs index e95db41..2ec9652 100644 --- a/OpenSim/Addons/Groups/GroupsMessagingModule.cs +++ b/OpenSim/Addons/Groups/GroupsMessagingModule.cs @@ -627,6 +627,7 @@ namespace OpenSim.Groups , false //canVoiceChat , false //isModerator , false //text mute + , true // Enter ); } } @@ -669,6 +670,7 @@ namespace OpenSim.Groups , false //canVoiceChat , false //isModerator , false //text mute + , true ); } } -- cgit v1.1 From e0e8b784a59dfdd36daf3b48b7d8dbbfe7abd716 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Tue, 26 Jul 2016 21:43:26 +0100 Subject: apply the change to groups v2 also --- OpenSim/Addons/Groups/GroupsModule.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs index 1afdd0f..e586dd7 100644 --- a/OpenSim/Addons/Groups/GroupsModule.cs +++ b/OpenSim/Addons/Groups/GroupsModule.cs @@ -249,7 +249,8 @@ namespace OpenSim.Groups // There might be some problem with the thread we're generating this on but not // doing the update at this time causes problems (Mantis #7920 and #7915) // TODO: move sending this update to a later time in the rootification of the client. - SendAgentGroupDataUpdate(sp.ControllingClient, false); + if(!sp.haveGroupInformation) + SendAgentGroupDataUpdate(sp.ControllingClient, false); } private void OnMakeChild(ScenePresence sp) -- cgit v1.1 From a66e747c95eb2b1fc090142ee5bba973a4ab1079 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Thu, 4 Aug 2016 20:57:57 +0100 Subject: add GetActiveMembershipData() to groups modules, let core groups also have GetMembershipData(), wait for client to ask for it not telling in OnNewClient, as other modules do. --- OpenSim/Addons/Groups/GroupsModule.cs | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs index e586dd7..b6bf5f1 100644 --- a/OpenSim/Addons/Groups/GroupsModule.cs +++ b/OpenSim/Addons/Groups/GroupsModule.cs @@ -714,6 +714,12 @@ namespace OpenSim.Groups return m_groupData.GetAgentGroupMembership(UUID.Zero.ToString(), agentID.ToString(), groupID); } + public GroupMembershipData GetActiveMembershipData(UUID agentID) + { + string agentIDstr = agentID.ToString(); + return m_groupData.GetAgentActiveMembership(agentIDstr, agentIDstr); + } + public void UpdateGroupInfo(IClientAPI remoteClient, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish) { if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); -- cgit v1.1 From e57d3edf6f483013461888c6acb65312101ab0eb Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Thu, 4 Aug 2016 21:36:41 +0100 Subject: make sure all new scenepresences have fresh groups information at creation time (grouptitle missing but not that needed at that point) (use direct calls exactly where we want things to happen), reusing a funtion name to rename later --- OpenSim/Addons/Groups/GroupsModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs index b6bf5f1..73fc22c 100644 --- a/OpenSim/Addons/Groups/GroupsModule.cs +++ b/OpenSim/Addons/Groups/GroupsModule.cs @@ -1284,7 +1284,7 @@ namespace OpenSim.Groups GroupMembershipData[] membershipArray = GetProfileListedGroupMemberships(remoteClient, agentID); - remoteClient.RefreshGroupMembership(); + remoteClient.UpdateGroupMembership(membershipArray); remoteClient.SendAgentGroupDataUpdate(agentID, membershipArray); } -- cgit v1.1 From df8f189f5c152e072e0b1cadc0b8c75ea553f56f Mon Sep 17 00:00:00 2001 From: Kevin Cozens Date: Wed, 17 Aug 2016 22:44:40 -0400 Subject: Fixed typo in two group messages --- OpenSim/Addons/Groups/GroupsModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs index 73fc22c..3144ed0 100644 --- a/OpenSim/Addons/Groups/GroupsModule.cs +++ b/OpenSim/Addons/Groups/GroupsModule.cs @@ -784,7 +784,7 @@ namespace OpenSim.Groups if (money != null) money.ApplyCharge(remoteClient.AgentId, money.GroupCreationCharge, MoneyTransactionType.GroupCreate); - remoteClient.SendCreateGroupReply(groupID, true, "Group created successfullly"); + remoteClient.SendCreateGroupReply(groupID, true, "Group created successfully"); // Update the founder with new group information. SendAgentGroupDataUpdate(remoteClient, false); -- cgit v1.1 From 847d351bf5efc466d028ee3c65a643b89d3a60ca Mon Sep 17 00:00:00 2001 From: Kevin Cozens Date: Thu, 18 Aug 2016 14:50:50 -0400 Subject: Fixed grammer in a comment --- OpenSim/Addons/Groups/GroupsModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs index 3144ed0..57fbbf7 100644 --- a/OpenSim/Addons/Groups/GroupsModule.cs +++ b/OpenSim/Addons/Groups/GroupsModule.cs @@ -764,7 +764,7 @@ namespace OpenSim.Groups } // check funds - // is there is a money module present ? + // is there a money module present ? IMoneyModule money = scene.RequestModuleInterface(); if (money != null) { -- cgit v1.1 From 7a2256a8cdbd5c9733f2af38c12635f37b871e06 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Tue, 23 Aug 2016 23:48:07 +0100 Subject: change odd condition on groupsV2 add to role --- OpenSim/Addons/Groups/Service/GroupsService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/Service/GroupsService.cs b/OpenSim/Addons/Groups/Service/GroupsService.cs index 07641ef..ae0518c 100644 --- a/OpenSim/Addons/Groups/Service/GroupsService.cs +++ b/OpenSim/Addons/Groups/Service/GroupsService.cs @@ -486,7 +486,7 @@ namespace OpenSim.Groups // check permissions bool limited = HasPower(RequestingAgentID, GroupID, GroupPowers.AssignMemberLimited); bool unlimited = HasPower(RequestingAgentID, GroupID, GroupPowers.AssignMember) | IsOwner(RequestingAgentID, GroupID); - if (!limited || !unlimited) + if (!limited && !unlimited) { m_log.DebugFormat("[Groups]: ({0}) Attempt at assigning {1} to role {2} denied because of lack of permission", RequestingAgentID, AgentID, RoleID); return false; -- cgit v1.1 From d1baa3e0c3b1783a68061980ffd8b9693c5a474a Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Wed, 9 Nov 2016 22:39:52 +0000 Subject: fix some invalid string.format arguments --- OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs b/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs index 26e844e..d79e4fa 100644 --- a/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs +++ b/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs @@ -286,7 +286,7 @@ namespace OpenSim.Groups string requestingAgentID = request["RequestingAgentID"].ToString(); if (!m_GroupsService.RemoveAgentFromGroup(requestingAgentID, agentID, groupID)) - NullResult(result, string.Format("Insufficient permissions.", agentID)); + NullResult(result, string.Format("Insufficient permissions. {0}", agentID)); else result["RESULT"] = "true"; } -- cgit v1.1 From f4a51116f63ac9641f3df254fbf8001c771903df Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Thu, 5 Jan 2017 14:17:00 +0000 Subject: Fix some permissions checks in groups The code checked the permissions of a person being added to a role rather than those of the person doing the adding. Also, limited permission role removal wasn't implemented. --- OpenSim/Addons/Groups/Service/GroupsService.cs | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/Service/GroupsService.cs b/OpenSim/Addons/Groups/Service/GroupsService.cs index ae0518c..710b00a 100644 --- a/OpenSim/Addons/Groups/Service/GroupsService.cs +++ b/OpenSim/Addons/Groups/Service/GroupsService.cs @@ -496,7 +496,7 @@ namespace OpenSim.Groups if (!unlimited && limited) { // check whether person's has this role - RoleMembershipData rolemembership = m_Database.RetrieveRoleMember(GroupID, RoleID, AgentID); + RoleMembershipData rolemembership = m_Database.RetrieveRoleMember(GroupID, RoleID, RequestingAgentID); if (rolemembership == null) { m_log.DebugFormat("[Groups]: ({0}) Attempt at assigning {1} to role {2} denied because of limited permission", RequestingAgentID, AgentID, RoleID); @@ -516,13 +516,26 @@ namespace OpenSim.Groups return false; // check permissions + bool limited = HasPower(RequestingAgentID, GroupID, GroupPowers.AssignMemberLimited); bool unlimited = HasPower(RequestingAgentID, GroupID, GroupPowers.AssignMember) || IsOwner(RequestingAgentID, GroupID); - if (!unlimited) + if (!limited && !unlimited) { m_log.DebugFormat("[Groups]: ({0}) Attempt at removing {1} from role {2} denied because of lack of permission", RequestingAgentID, AgentID, RoleID); return false; } + // AssignMemberLimited means that the person can assign another person to the same roles that she has in the group + if (!unlimited && limited) + { + // check whether person's has this role + RoleMembershipData rolemembership = m_Database.RetrieveRoleMember(GroupID, RoleID, RequestingAgentID); + if (rolemembership == null) + { + m_log.DebugFormat("[Groups]: ({0}) Attempt at removing {1} from role {2} denied because of limited permission", RequestingAgentID, AgentID, RoleID); + return false; + } + } + RoleMembershipData rolemember = m_Database.RetrieveRoleMember(GroupID, RoleID, AgentID); if (rolemember == null) @@ -812,7 +825,7 @@ namespace OpenSim.Groups if (RoleID != UUID.Zero) _AddAgentToGroupRole(RequestingAgentID, AgentID, GroupID, RoleID); - // Make thit this active group + // Make this the active group PrincipalData pdata = new PrincipalData(); pdata.PrincipalID = AgentID; pdata.ActiveGroupID = GroupID; -- cgit v1.1 From b16abc8166c29585cb76cc55c3bdd76e5833cb4f Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Thu, 5 Jan 2017 19:07:37 +0000 Subject: Massive tab and trailing space cleanup --- OpenSim/Addons/Groups/GroupsExtendedData.cs | 4 +- OpenSim/Addons/Groups/GroupsMessagingModule.cs | 32 +++--- OpenSim/Addons/Groups/GroupsModule.cs | 42 ++++---- .../Hypergrid/GroupsServiceHGConnectorModule.cs | 20 ++-- .../Hypergrid/HGGroupsServiceRobustConnector.cs | 4 +- OpenSim/Addons/Groups/IGroupsServicesConnector.cs | 8 +- .../Local/GroupsServiceLocalConnectorModule.cs | 10 +- OpenSim/Addons/Groups/Properties/AssemblyInfo.cs | 8 +- .../Groups/Remote/GroupsServiceRemoteConnector.cs | 4 +- .../Remote/GroupsServiceRemoteConnectorModule.cs | 14 +-- .../Groups/Remote/GroupsServiceRobustConnector.cs | 12 +-- OpenSim/Addons/Groups/Service/GroupsService.cs | 38 +++---- OpenSim/Addons/Groups/Service/GroupsServiceBase.cs | 110 ++++++++++----------- OpenSim/Addons/Groups/Service/HGGroupsService.cs | 2 +- .../Addons/OfflineIM/Properties/AssemblyInfo.cs | 8 +- .../Remote/OfflineIMServiceRemoteConnector.cs | 4 +- .../Addons/OfflineIM/Service/OfflineIMService.cs | 2 +- 17 files changed, 161 insertions(+), 161 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsExtendedData.cs b/OpenSim/Addons/Groups/GroupsExtendedData.cs index c783b9e..d92c442 100644 --- a/OpenSim/Addons/Groups/GroupsExtendedData.cs +++ b/OpenSim/Addons/Groups/GroupsExtendedData.cs @@ -46,7 +46,7 @@ namespace OpenSim.Groups public string AccessToken; } - public class ExtendedGroupMembersData + public class ExtendedGroupMembersData { // This is the only difference: this is a string public string AgentID; @@ -65,7 +65,7 @@ namespace OpenSim.Groups public UUID RoleID; // This is the only difference: this is a string public string MemberID; - + } public struct ExtendedGroupNoticeData diff --git a/OpenSim/Addons/Groups/GroupsMessagingModule.cs b/OpenSim/Addons/Groups/GroupsMessagingModule.cs index 2ec9652..f4d3490 100644 --- a/OpenSim/Addons/Groups/GroupsMessagingModule.cs +++ b/OpenSim/Addons/Groups/GroupsMessagingModule.cs @@ -131,7 +131,7 @@ namespace OpenSim.Groups { if (!m_groupMessagingEnabled) return; - + scene.RegisterModuleInterface(this); m_sceneList.Add(scene); @@ -163,7 +163,7 @@ namespace OpenSim.Groups if (m_groupData == null) { m_log.Error("[Groups.Messaging]: Could not get IGroupsServicesConnector, GroupsMessagingModule is now disabled."); - RemoveRegion(scene); + RemoveRegion(scene); return; } @@ -218,7 +218,7 @@ namespace OpenSim.Groups m_msgTransferModule = null; } - public Type ReplaceableInterface + public Type ReplaceableInterface { get { return null; } } @@ -262,7 +262,7 @@ namespace OpenSim.Groups { if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - + GroupRecord groupInfo = m_groupData.GetGroupRecord(agentID.ToString(), groupID, null); if (groupInfo != null) @@ -279,7 +279,7 @@ namespace OpenSim.Groups { SendMessageToGroup(im, groupID, UUID.Zero, null); } - + public void SendMessageToGroup( GridInstantMessage im, UUID groupID, UUID sendingAgentForGroupCalls, Func sendCondition) { @@ -355,9 +355,9 @@ namespace OpenSim.Groups { if (!sendCondition(member)) { - if (m_debugEnabled) + if (m_debugEnabled) m_log.DebugFormat( - "[Groups.Messaging]: Not sending to {0} as they do not fulfill send condition", + "[Groups.Messaging]: Not sending to {0} as they do not fulfill send condition", member.AgentID); continue; @@ -366,7 +366,7 @@ namespace OpenSim.Groups else if (hasAgentDroppedGroupChatSession(member.AgentID.ToString(), groupID)) { // Don't deliver messages to people who have dropped this session - if (m_debugEnabled) + if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: {0} has dropped session, not delivering to them", member.AgentID); continue; @@ -414,7 +414,7 @@ namespace OpenSim.Groups "[Groups.Messaging]: SendMessageToGroup for group {0} with {1} visible members, {2} online took {3}ms", groupID, groupMembersCount, groupMembers.Count(), Environment.TickCount - requestStartTick); } - + #region SimGridEventHandlers void OnClientLogin(IClientAPI client) @@ -445,13 +445,13 @@ namespace OpenSim.Groups // The instant message module will only deliver messages of dialog types: // MessageFromAgent, StartTyping, StopTyping, MessageFromObject // - // Any other message type will not be delivered to a client by the + // Any other message type will not be delivered to a client by the // Instant Message Module UUID regionID = new UUID(msg.RegionID); if (m_debugEnabled) { - m_log.DebugFormat("[Groups.Messaging]: {0} called, IM from region {1}", + m_log.DebugFormat("[Groups.Messaging]: {0} called, IM from region {1}", System.Reflection.MethodBase.GetCurrentMethod().Name, regionID); DebugGridInstantMessage(msg); @@ -508,7 +508,7 @@ namespace OpenSim.Groups m_log.DebugFormat("[Groups.Messaging]: skipping agent {0} because he has an agent in region of origin", sp.UUID); return; } - else + else { if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: not skipping agent {0}", sp.UUID); @@ -531,7 +531,7 @@ namespace OpenSim.Groups } } }); - + } } } @@ -555,7 +555,7 @@ namespace OpenSim.Groups break; case (byte)InstantMessageDialog.SessionSend: - // User hasn't dropped, so they're in the session, + // User hasn't dropped, so they're in the session, // maybe we should deliver it. IClientAPI client = GetActiveClient(new UUID(msg.toAgentID)); if (client != null) @@ -655,7 +655,7 @@ namespace OpenSim.Groups UUID AgentID = new UUID(im.fromAgentID); GroupRecord groupInfo = m_groupData.GetGroupRecord(UUID.Zero.ToString(), GroupID, null); - + if (groupInfo != null) { AgentInvitedToGroupChatSession(AgentID.ToString(), GroupID); @@ -681,7 +681,7 @@ namespace OpenSim.Groups UUID GroupID = new UUID(im.imSessionID); UUID AgentID = new UUID(im.fromAgentID); - if (m_debugEnabled) + if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Send message to session for group {0} with session ID {1}", GroupID, im.imSessionID.ToString()); //If this agent is sending a message, then they want to be in the session diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs index 57fbbf7..1e9f2b5 100644 --- a/OpenSim/Addons/Groups/GroupsModule.cs +++ b/OpenSim/Addons/Groups/GroupsModule.cs @@ -51,7 +51,7 @@ namespace OpenSim.Groups private List m_sceneList = new List(); private IMessageTransferModule m_msgTransferModule = null; - + private IGroupsServicesConnector m_groupData = null; private IUserManagement m_UserManagement; @@ -210,7 +210,7 @@ namespace OpenSim.Groups if (m_debugEnabled) m_log.Debug("[Groups]: Shutting down Groups module."); } - public Type ReplaceableInterface + public Type ReplaceableInterface { get { return null; } } @@ -318,7 +318,7 @@ namespace OpenSim.Groups SendAgentGroupDataUpdate(remoteClient, false); - // also current viewers do ignore it and ask later on a much nicer thread + // also current viewers do ignore it and ask later on a much nicer thread // its a info request not a change, so nothing is sent to others // they do get the group title with the avatar object update on arrivel to a region } @@ -453,9 +453,9 @@ namespace OpenSim.Groups } if (m_groupData.AddGroupNotice(GetRequestingAgentIDStr(remoteClient), GroupID, NoticeID, im.fromAgentName, Subject, Message, - hasAttachment, + hasAttachment, (byte)(item == null ? 0 : item.AssetType), - item == null ? null : item.Name, + item == null ? null : item.Name, item == null ? UUID.Zero : item.ID, item == null ? UUID.Zero.ToString() : item.Owner.ToString())) { @@ -463,7 +463,7 @@ namespace OpenSim.Groups { OnNewGroupNotice(GroupID, NoticeID); } - + // Send notice out to everyone that wants notices foreach (GroupMembersData member in m_groupData.GetGroupMembers(GetRequestingAgentIDStr(remoteClient), GroupID)) { @@ -497,7 +497,7 @@ namespace OpenSim.Groups m_log.DebugFormat("[Groups]: Giving inventory from {0} to {1}", giver, remoteClient.AgentId); string message; - InventoryItemBase itemCopy = ((Scene)(remoteClient.Scene)).GiveInventoryItem(remoteClient.AgentId, + InventoryItemBase itemCopy = ((Scene)(remoteClient.Scene)).GiveInventoryItem(remoteClient.AgentId, giver, notice.noticeData.AttachmentItemID, out message); if (itemCopy == null) @@ -509,10 +509,10 @@ namespace OpenSim.Groups remoteClient.SendInventoryItemCreateUpdate(itemCopy, 0); } } - + // Interop, received special 210 code for ejecting a group member // this only works within the comms servers domain, and won't work hypergrid - // TODO:FIXME: Use a presense server of some kind to find out where the + // TODO:FIXME: Use a presense server of some kind to find out where the // client actually is, and try contacting that region directly to notify them, // or provide the notification via xmlrpc update queue if ((im.dialog == 210)) @@ -523,7 +523,7 @@ namespace OpenSim.Groups UUID ejecteeID = new UUID(im.toAgentID); - im.imSessionID = UUID.Zero.Guid; + im.imSessionID = UUID.Zero.Guid; im.dialog = (byte)InstantMessageDialog.MessageFromAgent; OutgoingInstantMessage(im, ejecteeID); @@ -577,7 +577,7 @@ namespace OpenSim.Groups { return m_groupData.GetGroupRecord(UUID.Zero.ToString(), UUID.Zero, name); } - + public void ActivateGroup(IClientAPI remoteClient, UUID groupID) { if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); @@ -585,7 +585,7 @@ namespace OpenSim.Groups m_groupData.SetAgentActiveGroup(GetRequestingAgentIDStr(remoteClient), GetRequestingAgentIDStr(remoteClient), groupID); // Changing active group changes title, active powers, all kinds of things - // anyone who is in any region that can see this client, should probably be + // anyone who is in any region that can see this client, should probably be // updated with new group info. At a minimum, they should get ScenePresence // updated with new title. SendAgentGroupDataUpdate(remoteClient, true); @@ -620,10 +620,10 @@ namespace OpenSim.Groups public List GroupMembersRequest(IClientAPI remoteClient, UUID groupID) { - if (m_debugEnabled) + if (m_debugEnabled) m_log.DebugFormat( "[Groups]: GroupMembersRequest called for {0} from client {1}", groupID, remoteClient.Name); - + List data = m_groupData.GetGroupMembers(GetRequestingAgentIDStr(remoteClient), groupID); if (m_debugEnabled) @@ -706,7 +706,7 @@ namespace OpenSim.Groups public GroupMembershipData GetMembershipData(UUID groupID, UUID agentID) { - if (m_debugEnabled) + if (m_debugEnabled) m_log.DebugFormat( "[Groups]: {0} called with groupID={1}, agentID={2}", System.Reflection.MethodBase.GetCurrentMethod().Name, groupID, agentID); @@ -776,7 +776,7 @@ namespace OpenSim.Groups } string reason = string.Empty; - UUID groupID = m_groupData.CreateGroup(remoteClient.AgentId, name, charter, showInList, insigniaID, membershipFee, openEnrollment, + UUID groupID = m_groupData.CreateGroup(remoteClient.AgentId, name, charter, showInList, insigniaID, membershipFee, openEnrollment, allowPublish, maturePublish, remoteClient.AgentId, out reason); if (groupID != UUID.Zero) @@ -823,7 +823,7 @@ namespace OpenSim.Groups if (membership != null) { return membership.GroupTitle; - } + } return string.Empty; } @@ -839,7 +839,7 @@ namespace OpenSim.Groups // TODO: Not sure what all is needed here, but if the active group role change is for the group // the client currently has set active, then we need to do a scene presence update too // if (m_groupData.GetAgentActiveMembership(GetRequestingAgentID(remoteClient)).GroupID == GroupID) - + SendDataUpdate(remoteClient, true); } @@ -899,7 +899,7 @@ namespace OpenSim.Groups case 1: // Remove m_groupData.RemoveAgentFromGroupRole(GetRequestingAgentIDStr(remoteClient), memberID.ToString(), groupID, roleID); - + break; default: m_log.ErrorFormat("[Groups]: {0} does not understand changes == {1}", System.Reflection.MethodBase.GetCurrentMethod().Name, changes); @@ -1072,7 +1072,7 @@ namespace OpenSim.Groups // Send Message to Ejectee GridInstantMessage msg = new GridInstantMessage(); - + // if local send a normal message if(ejecteeClient != null) { @@ -1324,7 +1324,7 @@ namespace OpenSim.Groups membershipArray = membershipData.ToArray(); } } - + if (m_debugEnabled) { m_log.InfoFormat("[Groups]: Get group membership information for {0} requested by {1}", dataForAgentID, requestingClient.AgentId); diff --git a/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs b/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs index 7d57de1..9852581 100644 --- a/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs +++ b/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs @@ -103,7 +103,7 @@ namespace OpenSim.Groups if (!m_Enabled) return; - m_log.DebugFormat("[Groups]: Registering {0} with {1}", this.Name, scene.RegionInfo.RegionName); + m_log.DebugFormat("[Groups]: Registering {0} with {1}", this.Name, scene.RegionInfo.RegionName); scene.RegisterModuleInterface(this); m_Scenes.Add(scene); @@ -135,7 +135,7 @@ namespace OpenSim.Groups { m_LocalGroupsConnector = new GroupsServiceLocalConnectorModule(m_Config, m_UserManagement); // Also, if local, create the endpoint for the HGGroupsService - new HGGroupsServiceRobustConnector(m_Config, MainServer.Instance, string.Empty, + new HGGroupsServiceRobustConnector(m_Config, MainServer.Instance, string.Empty, scene.RequestModuleInterface(), scene.RequestModuleInterface()); } @@ -170,7 +170,7 @@ namespace OpenSim.Groups if (sp is ScenePresence && ((ScenePresence)sp).PresenceType != PresenceType.Npc) { AgentCircuitData aCircuit = ((ScenePresence)sp).Scene.AuthenticateHandler.GetAgentCircuitData(client.AgentId); - if (aCircuit != null && (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0 && + if (aCircuit != null && (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0 && m_OfflineIM != null && m_Messaging != null) { List ims = m_OfflineIM.GetMessages(aCircuit.AgentID); @@ -184,12 +184,12 @@ namespace OpenSim.Groups #region IGroupsServicesConnector - public UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, + public UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish, UUID founderID, out string reason) { reason = string.Empty; if (m_UserManagement.IsLocalGridUser(RequestingAgentID)) - return m_LocalGroupsConnector.CreateGroup(RequestingAgentID, name, charter, showInList, insigniaID, + return m_LocalGroupsConnector.CreateGroup(RequestingAgentID, name, charter, showInList, insigniaID, membershipFee, openEnrollment, allowPublish, maturePublish, founderID, out reason); else { @@ -198,14 +198,14 @@ namespace OpenSim.Groups } } - public bool UpdateGroup(string RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, + public bool UpdateGroup(string RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish, out string reason) { reason = string.Empty; string url = string.Empty; string name = string.Empty; if (IsLocal(groupID, out url, out name)) - return m_LocalGroupsConnector.UpdateGroup(AgentUUI(RequestingAgentID), groupID, charter, showInList, insigniaID, membershipFee, + return m_LocalGroupsConnector.UpdateGroup(AgentUUI(RequestingAgentID), groupID, charter, showInList, insigniaID, membershipFee, openEnrollment, allowPublish, maturePublish, out reason); else { @@ -374,7 +374,7 @@ namespace OpenSim.Groups } } - + return new List(); } @@ -626,7 +626,7 @@ namespace OpenSim.Groups } if (agent != null) return Util.ProduceUserUniversalIdentifier(agent); - + // we don't know anything about this foreign user // try asking the user management module, which may know more return m_UserManagement.GetUserUUI(AgentID); @@ -664,7 +664,7 @@ namespace OpenSim.Groups string url = string.Empty, first = string.Empty, last = string.Empty, tmp = string.Empty; if (Util.ParseUniversalUserIdentifier(uID, out userID, out url, out first, out last, out tmp)) m_UserManagement.AddUser(userID, first, last, url); - + return userID; } diff --git a/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs b/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs index f60c1a5..af00770 100644 --- a/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs +++ b/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs @@ -64,8 +64,8 @@ namespace OpenSim.Groups m_log.DebugFormat("[Groups.RobustHGConnector]: Starting with config name {0}", m_ConfigName); - string homeURI = Util.GetConfigVarFromSections(config, "HomeURI", - new string[] { "Startup", "Hypergrid", m_ConfigName}, string.Empty); + string homeURI = Util.GetConfigVarFromSections(config, "HomeURI", + new string[] { "Startup", "Hypergrid", m_ConfigName}, string.Empty); if (homeURI == string.Empty) throw new Exception(String.Format("[Groups.RobustHGConnector]: please provide the HomeURI [Startup] or in section {0}", m_ConfigName)); diff --git a/OpenSim/Addons/Groups/IGroupsServicesConnector.cs b/OpenSim/Addons/Groups/IGroupsServicesConnector.cs index a09b59e..8a6e88d 100644 --- a/OpenSim/Addons/Groups/IGroupsServicesConnector.cs +++ b/OpenSim/Addons/Groups/IGroupsServicesConnector.cs @@ -34,9 +34,9 @@ namespace OpenSim.Groups { public interface IGroupsServicesConnector { - UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, + UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish, UUID founderID, out string reason); - bool UpdateGroup(string RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, + bool UpdateGroup(string RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish, out string reason); ExtendedGroupRecord GetGroupRecord(string RequestingAgentID, UUID GroupID, string GroupName); List FindGroups(string RequestingAgentID, string search); @@ -75,7 +75,7 @@ namespace OpenSim.Groups /// If the user is a member of the group then the data structure is returned. If not, then null is returned. /// ExtendedGroupMembershipData GetAgentGroupMembership(string RequestingAgentID, string AgentID, UUID GroupID); - + /// /// Get information about the groups to which a user belongs. /// @@ -87,7 +87,7 @@ namespace OpenSim.Groups /// List GetAgentGroupMemberships(string RequestingAgentID, string AgentID); - bool AddGroupNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message, + bool AddGroupNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message, bool hasAttachment, byte attType, string attName, UUID attItemID, string attOwnerID); GroupNoticeInfo GetGroupNotice(string RequestingAgentID, UUID noticeID); List GetGroupNotices(string RequestingAgentID, UUID GroupID); diff --git a/OpenSim/Addons/Groups/Local/GroupsServiceLocalConnectorModule.cs b/OpenSim/Addons/Groups/Local/GroupsServiceLocalConnectorModule.cs index 8e30df5..c7877c6 100644 --- a/OpenSim/Addons/Groups/Local/GroupsServiceLocalConnectorModule.cs +++ b/OpenSim/Addons/Groups/Local/GroupsServiceLocalConnectorModule.cs @@ -108,7 +108,7 @@ namespace OpenSim.Groups if (!m_Enabled) return; - m_log.DebugFormat("[Groups]: Registering {0} with {1}", this.Name, scene.RegionInfo.RegionName); + m_log.DebugFormat("[Groups]: Registering {0} with {1}", this.Name, scene.RegionInfo.RegionName); scene.RegisterModuleInterface(this); m_Scenes.Add(scene); } @@ -146,16 +146,16 @@ namespace OpenSim.Groups #region IGroupsServicesConnector - public UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, + public UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish, UUID founderID, out string reason) { m_log.DebugFormat("[Groups]: Creating group {0}", name); reason = string.Empty; - return m_GroupsService.CreateGroup(RequestingAgentID.ToString(), name, charter, showInList, insigniaID, + return m_GroupsService.CreateGroup(RequestingAgentID.ToString(), name, charter, showInList, insigniaID, membershipFee, openEnrollment, allowPublish, maturePublish, founderID, out reason); } - public bool UpdateGroup(string RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, + public bool UpdateGroup(string RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish, out string reason) { reason = string.Empty; @@ -296,7 +296,7 @@ namespace OpenSim.Groups public bool AddGroupNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message, bool hasAttachment, byte attType, string attName, UUID attItemID, string attOwnerID) { - return m_GroupsService.AddGroupNotice(RequestingAgentID, groupID, noticeID, fromName, subject, message, + return m_GroupsService.AddGroupNotice(RequestingAgentID, groupID, noticeID, fromName, subject, message, hasAttachment, attType, attName, attItemID, attOwnerID); } diff --git a/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs b/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs index 98630eb..e9be9c4 100644 --- a/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs +++ b/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs @@ -3,7 +3,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using Mono.Addins; -// General Information about an assembly is controlled through the following +// General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("OpenSim.Addons.Groups")] @@ -15,8 +15,8 @@ using Mono.Addins; [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] @@ -26,7 +26,7 @@ using Mono.Addins; // Version information for an assembly consists of the following four values: // // Major Version -// Minor Version +// Minor Version // Build Number // Revision // diff --git a/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnector.cs b/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnector.cs index 7450c14..8f6be0d 100644 --- a/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnector.cs +++ b/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnector.cs @@ -41,7 +41,7 @@ using Nini.Config; namespace OpenSim.Groups { - public class GroupsServiceRemoteConnector + public class GroupsServiceRemoteConnector { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -71,7 +71,7 @@ namespace OpenSim.Groups } /// - m_log.DebugFormat("[Groups.RemoteConnector]: Groups server at {0}, authentication {1}", + m_log.DebugFormat("[Groups.RemoteConnector]: Groups server at {0}, authentication {1}", m_ServerURI, (m_Auth == null ? "None" : m_Auth.GetType().ToString())); } diff --git a/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnectorModule.cs b/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnectorModule.cs index d4739c6..b6c75a8 100644 --- a/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnectorModule.cs +++ b/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnectorModule.cs @@ -113,7 +113,7 @@ namespace OpenSim.Groups if (!m_Enabled) return; - m_log.DebugFormat("[Groups.RemoteConnector]: Registering {0} with {1}", this.Name, scene.RegionInfo.RegionName); + m_log.DebugFormat("[Groups.RemoteConnector]: Registering {0} with {1}", this.Name, scene.RegionInfo.RegionName); scene.RegisterModuleInterface(this); m_Scenes.Add(scene); } @@ -151,7 +151,7 @@ namespace OpenSim.Groups #region IGroupsServicesConnector - public UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, + public UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish, UUID founderID, out string reason) { m_log.DebugFormat("[Groups.RemoteConnector]: Creating group {0}", name); @@ -167,7 +167,7 @@ namespace OpenSim.Groups return groupID; } - public bool UpdateGroup(string RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, + public bool UpdateGroup(string RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish, out string reason) { string r = string.Empty; @@ -186,9 +186,9 @@ namespace OpenSim.Groups if (GroupID == UUID.Zero && (GroupName == null || GroupName != null && GroupName == string.Empty)) return null; - return m_CacheWrapper.GetGroupRecord(RequestingAgentID,GroupID,GroupName, delegate - { - return m_GroupsService.GetGroupRecord(RequestingAgentID, GroupID, GroupName); + return m_CacheWrapper.GetGroupRecord(RequestingAgentID,GroupID,GroupName, delegate + { + return m_GroupsService.GetGroupRecord(RequestingAgentID, GroupID, GroupName); }); } @@ -362,7 +362,7 @@ namespace OpenSim.Groups m_GroupsService.RemoveAgentToGroupInvite(RequestingAgentID, inviteID); } - public bool AddGroupNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message, + public bool AddGroupNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message, bool hasAttachment, byte attType, string attName, UUID attItemID, string attOwnerID) { GroupNoticeInfo notice = new GroupNoticeInfo(); diff --git a/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs b/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs index d79e4fa..598e7a5 100644 --- a/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs +++ b/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs @@ -393,7 +393,7 @@ namespace OpenSim.Groups if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID") || !request.ContainsKey("RoleID") || !request.ContainsKey("Name") || !request.ContainsKey("Description") || !request.ContainsKey("Title") || - !request.ContainsKey("Powers") || !request.ContainsKey("OP")) + !request.ContainsKey("Powers") || !request.ContainsKey("OP")) NullResult(result, "Bad network data"); else @@ -519,11 +519,11 @@ namespace OpenSim.Groups bool success = false; if (op == "ADD") - success = m_GroupsService.AddAgentToGroupRole(request["RequestingAgentID"].ToString(), request["AgentID"].ToString(), + success = m_GroupsService.AddAgentToGroupRole(request["RequestingAgentID"].ToString(), request["AgentID"].ToString(), new UUID(request["GroupID"].ToString()), new UUID(request["RoleID"].ToString())); else if (op == "DELETE") - success = m_GroupsService.RemoveAgentFromGroupRole(request["RequestingAgentID"].ToString(), request["AgentID"].ToString(), + success = m_GroupsService.RemoveAgentFromGroupRole(request["RequestingAgentID"].ToString(), request["AgentID"].ToString(), new UUID(request["GroupID"].ToString()), new UUID(request["RoleID"].ToString())); result["RESULT"] = success.ToString(); @@ -647,8 +647,8 @@ namespace OpenSim.Groups string op = request["OP"].ToString(); if (op == "ADD" && request.ContainsKey("GroupID") && request.ContainsKey("RoleID") && request.ContainsKey("AgentID")) - { - bool success = m_GroupsService.AddAgentToGroupInvite(request["RequestingAgentID"].ToString(), + { + bool success = m_GroupsService.AddAgentToGroupInvite(request["RequestingAgentID"].ToString(), new UUID(request["InviteID"].ToString()), new UUID(request["GroupID"].ToString()), new UUID(request["RoleID"].ToString()), request["AgentID"].ToString()); @@ -664,7 +664,7 @@ namespace OpenSim.Groups } else if (op == "GET") { - GroupInviteInfo invite = m_GroupsService.GetAgentToGroupInvite(request["RequestingAgentID"].ToString(), + GroupInviteInfo invite = m_GroupsService.GetAgentToGroupInvite(request["RequestingAgentID"].ToString(), new UUID(request["InviteID"].ToString())); if (invite != null) diff --git a/OpenSim/Addons/Groups/Service/GroupsService.cs b/OpenSim/Addons/Groups/Service/GroupsService.cs index 710b00a..ea0fedd 100644 --- a/OpenSim/Addons/Groups/Service/GroupsService.cs +++ b/OpenSim/Addons/Groups/Service/GroupsService.cs @@ -126,7 +126,7 @@ namespace OpenSim.Groups #endregion - public UUID CreateGroup(string RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, + public UUID CreateGroup(string RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish, UUID founderID, out string reason) { reason = string.Empty; @@ -264,7 +264,7 @@ namespace OpenSim.Groups if (ownerRole != null) ownerRoleID = ownerRole.RoleID; - // Check visibility? + // Check visibility? // When we don't want to check visibility, we pass it "all" as the requestingAgentID bool checkVisibility = !RequestingAgentID.Equals(UUID.Zero.ToString()); @@ -307,20 +307,20 @@ namespace OpenSim.Groups m.Contribution = Int32.Parse(d.Data["Contribution"]); m.ListInProfile = d.Data["ListInProfile"] == "1" ? true : false; - GridUserData gud = m_GridUserService.Get(d.PrincipalID); - if (gud != null) - { - if (bool.Parse(gud.Data["Online"])) - { - m.OnlineStatus = @"Online"; - } - else - { - int unixtime = int.Parse(gud.Data["Login"]); - // The viewer is very picky about how these strings are formed. Eg. it will crash on malformed dates! - m.OnlineStatus = (unixtime == 0) ? @"unknown" : Util.ToDateTime(unixtime).ToString("MM/dd/yyyy"); - } - } + GridUserData gud = m_GridUserService.Get(d.PrincipalID); + if (gud != null) + { + if (bool.Parse(gud.Data["Online"])) + { + m.OnlineStatus = @"Online"; + } + else + { + int unixtime = int.Parse(gud.Data["Login"]); + // The viewer is very picky about how these strings are formed. Eg. it will crash on malformed dates! + m.OnlineStatus = (unixtime == 0) ? @"unknown" : Util.ToDateTime(unixtime).ToString("MM/dd/yyyy"); + } + } // Is this person an owner of the group? m.IsOwner = (rolemembershipsList.Find(r => r.RoleID == ownerRoleID) != null) ? true : false; @@ -553,8 +553,8 @@ namespace OpenSim.Groups { newRoleID = r.RoleID; break; - } - } + } + } MembershipData member = m_Database.RetrieveMember(GroupID, AgentID); if (member != null) @@ -712,7 +712,7 @@ namespace OpenSim.Groups m_Database.StoreMember(membership); } - public bool AddGroupNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message, + public bool AddGroupNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message, bool hasAttachment, byte attType, string attName, UUID attItemID, string attOwnerID) { // Check perms diff --git a/OpenSim/Addons/Groups/Service/GroupsServiceBase.cs b/OpenSim/Addons/Groups/Service/GroupsServiceBase.cs index 8e237aa..98d0172 100644 --- a/OpenSim/Addons/Groups/Service/GroupsServiceBase.cs +++ b/OpenSim/Addons/Groups/Service/GroupsServiceBase.cs @@ -35,67 +35,67 @@ using OpenSim.Services.Base; namespace OpenSim.Groups { - public class GroupsServiceBase : ServiceBase - { - protected IGroupsData m_Database = null; - protected IGridUserData m_GridUserService = null; + public class GroupsServiceBase : ServiceBase + { + protected IGroupsData m_Database = null; + protected IGridUserData m_GridUserService = null; - public GroupsServiceBase(IConfigSource config, string cName) - : base(config) - { - string dllName = String.Empty; - string connString = String.Empty; - string realm = "os_groups"; - string usersRealm = "GridUser"; - string configName = (cName == string.Empty) ? "Groups" : cName; + public GroupsServiceBase(IConfigSource config, string cName) + : base(config) + { + string dllName = String.Empty; + string connString = String.Empty; + string realm = "os_groups"; + string usersRealm = "GridUser"; + string configName = (cName == string.Empty) ? "Groups" : cName; - // - // Try reading the [DatabaseService] section, if it exists - // - IConfig dbConfig = config.Configs["DatabaseService"]; - if (dbConfig != null) - { - if (dllName == String.Empty) - dllName = dbConfig.GetString("StorageProvider", String.Empty); - if (connString == String.Empty) - connString = dbConfig.GetString("ConnectionString", String.Empty); - } + // + // Try reading the [DatabaseService] section, if it exists + // + IConfig dbConfig = config.Configs["DatabaseService"]; + if (dbConfig != null) + { + if (dllName == String.Empty) + dllName = dbConfig.GetString("StorageProvider", String.Empty); + if (connString == String.Empty) + connString = dbConfig.GetString("ConnectionString", String.Empty); + } - // - // [Groups] section overrides [DatabaseService], if it exists - // - IConfig groupsConfig = config.Configs[configName]; - if (groupsConfig != null) - { - dllName = groupsConfig.GetString("StorageProvider", dllName); - connString = groupsConfig.GetString("ConnectionString", connString); - realm = groupsConfig.GetString("Realm", realm); - } + // + // [Groups] section overrides [DatabaseService], if it exists + // + IConfig groupsConfig = config.Configs[configName]; + if (groupsConfig != null) + { + dllName = groupsConfig.GetString("StorageProvider", dllName); + connString = groupsConfig.GetString("ConnectionString", connString); + realm = groupsConfig.GetString("Realm", realm); + } - // - // We tried, but this doesn't exist. We can't proceed. - // - if (dllName.Equals(String.Empty)) - throw new Exception("No StorageProvider configured"); + // + // We tried, but this doesn't exist. We can't proceed. + // + if (dllName.Equals(String.Empty)) + throw new Exception("No StorageProvider configured"); - m_Database = LoadPlugin(dllName, new Object[] { connString, realm }); - if (m_Database == null) - throw new Exception("Could not find a storage interface in the given module " + dllName); + m_Database = LoadPlugin(dllName, new Object[] { connString, realm }); + if (m_Database == null) + throw new Exception("Could not find a storage interface in the given module " + dllName); - // - // [GridUserService] section overrides [DatabaseService], if it exists - // - IConfig usersConfig = config.Configs["GridUserService"]; - if (usersConfig != null) - { - dllName = usersConfig.GetString("StorageProvider", dllName); - connString = usersConfig.GetString("ConnectionString", connString); + // + // [GridUserService] section overrides [DatabaseService], if it exists + // + IConfig usersConfig = config.Configs["GridUserService"]; + if (usersConfig != null) + { + dllName = usersConfig.GetString("StorageProvider", dllName); + connString = usersConfig.GetString("ConnectionString", connString); usersRealm = usersConfig.GetString("Realm", usersRealm); - } + } - m_GridUserService = LoadPlugin(dllName, new Object[] { connString, usersRealm }); - if (m_GridUserService == null) - throw new Exception("Could not find a storage inferface for the given users module " + dllName); - } - } + m_GridUserService = LoadPlugin(dllName, new Object[] { connString, usersRealm }); + if (m_GridUserService == null) + throw new Exception("Could not find a storage inferface for the given users module " + dllName); + } + } } diff --git a/OpenSim/Addons/Groups/Service/HGGroupsService.cs b/OpenSim/Addons/Groups/Service/HGGroupsService.cs index 56e999b..7d86f85 100644 --- a/OpenSim/Addons/Groups/Service/HGGroupsService.cs +++ b/OpenSim/Addons/Groups/Service/HGGroupsService.cs @@ -76,7 +76,7 @@ namespace OpenSim.Groups // Check if it already exists GroupData grec = m_Database.RetrieveGroup(groupID); - if (grec == null || + if (grec == null || (grec != null && grec.Data["Location"] != string.Empty && grec.Data["Location"].ToLower() != serviceLocation.ToLower())) { // Create the group diff --git a/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs b/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs index a980f22..fe828bc 100644 --- a/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs +++ b/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs @@ -3,7 +3,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using Mono.Addins; -// General Information about an assembly is controlled through the following +// General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("OpenSim.Addons.OfflineIM")] @@ -15,8 +15,8 @@ using Mono.Addins; [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] @@ -26,7 +26,7 @@ using Mono.Addins; // Version information for an assembly consists of the following four values: // // Major Version -// Minor Version +// Minor Version // Build Number // Revision // diff --git a/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRemoteConnector.cs b/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRemoteConnector.cs index 047b8be..46d4979 100644 --- a/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRemoteConnector.cs +++ b/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRemoteConnector.cs @@ -77,7 +77,7 @@ namespace OpenSim.OfflineIM break; } /// - m_log.DebugFormat("[OfflineIM.V2.RemoteConnector]: Offline IM server at {0} with auth {1}", + m_log.DebugFormat("[OfflineIM.V2.RemoteConnector]: Offline IM server at {0} with auth {1}", m_ServerURI, (m_Auth == null ? "None" : m_Auth.GetType().ToString())); } @@ -140,7 +140,7 @@ namespace OpenSim.OfflineIM { Dictionary sendData = new Dictionary(); sendData["UserID"] = userID; - + MakeRequest("DELETE", sendData); } diff --git a/OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs b/OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs index 02084ff..d1ecdce 100644 --- a/OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs +++ b/OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs @@ -90,7 +90,7 @@ namespace OpenSim.OfflineIM public bool StoreMessage(GridInstantMessage im, out string reason) { reason = string.Empty; - + // Check limits UUID principalID = new UUID(im.toAgentID); long count = m_Database.GetCount("PrincipalID", principalID.ToString()); -- cgit v1.1 From ad8915f154d2ce6ba1b3a021b1725a0b0a671635 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Fri, 6 Jan 2017 00:55:14 +0000 Subject: Restructure god level and permissions Create a class GodController which controls all aspects of god level, viewer modes and user levels at ScenePresence level. --- OpenSim/Addons/Groups/GroupsModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs index 1e9f2b5..aa5105e 100644 --- a/OpenSim/Addons/Groups/GroupsModule.cs +++ b/OpenSim/Addons/Groups/GroupsModule.cs @@ -756,7 +756,7 @@ namespace OpenSim.Groups if (avatar != null) { - if (avatar.UserLevel < m_levelGroupCreate) + if (avatar.GodController.UserLevel < m_levelGroupCreate) { remoteClient.SendCreateGroupReply(UUID.Zero, false, String.Format("Insufficient permissions to create a group. Requires level {0}", m_levelGroupCreate)); return UUID.Zero; -- cgit v1.1 From 5bc869391ab387954fe52e9e6522beda6ee1f022 Mon Sep 17 00:00:00 2001 From: Kevin Cozens Date: Fri, 6 Jan 2017 16:58:49 -0500 Subject: Only apply group creation fee > 0 and pass group name when applying fee --- OpenSim/Addons/Groups/GroupsModule.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs index aa5105e..d3085f6 100644 --- a/OpenSim/Addons/Groups/GroupsModule.cs +++ b/OpenSim/Addons/Groups/GroupsModule.cs @@ -781,8 +781,8 @@ namespace OpenSim.Groups if (groupID != UUID.Zero) { - if (money != null) - money.ApplyCharge(remoteClient.AgentId, money.GroupCreationCharge, MoneyTransactionType.GroupCreate); + if (money != null && money.GroupCreationCharge > 0) + money.ApplyCharge(remoteClient.AgentId, money.GroupCreationCharge, MoneyTransactionType.GroupCreate, name); remoteClient.SendCreateGroupReply(groupID, true, "Group created successfully"); -- cgit v1.1 From 4a18444e6e2965260f02b1fcadf25ce390d3e2bb Mon Sep 17 00:00:00 2001 From: Kevin Cozens Date: Fri, 6 Jan 2017 21:10:09 -0500 Subject: Allow avatar to be charged group membership fees when a money module is in use --- OpenSim/Addons/Groups/GroupsModule.cs | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs index d3085f6..0e3a172 100644 --- a/OpenSim/Addons/Groups/GroupsModule.cs +++ b/OpenSim/Addons/Groups/GroupsModule.cs @@ -979,10 +979,28 @@ namespace OpenSim.Groups { if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + GroupRecord groupRecord = GetGroupRecord(groupID); + IMoneyModule money = remoteClient.Scene.RequestModuleInterface(); + + // Should check to see if there's an outstanding invitation + + if (money != null && groupRecord.MembershipFee > 0) + { + // Does the agent have the funds to cover the group join fee? + if (!money.AmountCovered(remoteClient.AgentId, groupRecord.MembershipFee)) + { + remoteClient.SendAlertMessage("Insufficient funds to join the group."); + remoteClient.SendJoinGroupReply(groupID, false); + return; + } + } + string reason = string.Empty; - // Should check to see if OpenEnrollment, or if there's an outstanding invitation + if (m_groupData.AddAgentToGroup(GetRequestingAgentIDStr(remoteClient), GetRequestingAgentIDStr(remoteClient), groupID, UUID.Zero, string.Empty, out reason)) { + if (money != null && groupRecord.MembershipFee > 0) + money.ApplyCharge(remoteClient.AgentId, groupRecord.MembershipFee, MoneyTransactionType.GroupJoin, groupRecord.GroupName); remoteClient.SendJoinGroupReply(groupID, true); -- cgit v1.1 From 9e12ef92344d43356ae276ae3a03921e26986a38 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Fri, 5 May 2017 01:39:38 +0100 Subject: let all clients get a group title update on create group --- OpenSim/Addons/Groups/GroupsModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs index 0e3a172..5b76e0a 100644 --- a/OpenSim/Addons/Groups/GroupsModule.cs +++ b/OpenSim/Addons/Groups/GroupsModule.cs @@ -787,7 +787,7 @@ namespace OpenSim.Groups remoteClient.SendCreateGroupReply(groupID, true, "Group created successfully"); // Update the founder with new group information. - SendAgentGroupDataUpdate(remoteClient, false); + SendAgentGroupDataUpdate(remoteClient, true); } else remoteClient.SendCreateGroupReply(groupID, false, reason); -- cgit v1.1 From d0912b61516914f810ba306641aaaa813134462e Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Sun, 7 May 2017 00:47:45 +0100 Subject: let StreamReader be in using statements --- OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs | 7 ++++--- OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs b/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs index af00770..51f3ec1 100644 --- a/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs +++ b/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs @@ -115,9 +115,10 @@ namespace OpenSim.Groups protected override byte[] ProcessRequest(string path, Stream requestData, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { - StreamReader sr = new StreamReader(requestData); - string body = sr.ReadToEnd(); - sr.Close(); + string body; + using(StreamReader sr = new StreamReader(requestData)) + body = sr.ReadToEnd(); + body = body.Trim(); //m_log.DebugFormat("[XXX]: query String: {0}", body); diff --git a/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs b/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs index 598e7a5..8502bb5 100644 --- a/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs +++ b/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs @@ -91,9 +91,10 @@ namespace OpenSim.Groups protected override byte[] ProcessRequest(string path, Stream requestData, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { - StreamReader sr = new StreamReader(requestData); - string body = sr.ReadToEnd(); - sr.Close(); + string body; + using(StreamReader sr = new StreamReader(requestData)) + body = sr.ReadToEnd(); + body = body.Trim(); //m_log.DebugFormat("[XXX]: query String: {0}", body); -- cgit v1.1 From e0fd9661864da635504e0488dfff0631b595bd6d Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Sun, 12 Nov 2017 02:51:59 +0000 Subject: off line module V2 must not sent a empty mutes list. That is mutes modules job (or let viewers use they cached entries if none) --- OpenSim/Addons/OfflineIM/OfflineIMRegionModule.cs | 16 ---------------- 1 file changed, 16 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/OfflineIM/OfflineIMRegionModule.cs b/OpenSim/Addons/OfflineIM/OfflineIMRegionModule.cs index 5340bcd..d8164e7 100644 --- a/OpenSim/Addons/OfflineIM/OfflineIMRegionModule.cs +++ b/OpenSim/Addons/OfflineIM/OfflineIMRegionModule.cs @@ -114,7 +114,6 @@ namespace OpenSim.OfflineIM scene.ForEachClient(delegate(IClientAPI client) { client.OnRetrieveInstantMessages -= RetrieveInstantMessages; - client.OnMuteListRequest -= OnMuteListRequest; }); } @@ -162,7 +161,6 @@ namespace OpenSim.OfflineIM private void OnNewClient(IClientAPI client) { client.OnRetrieveInstantMessages += RetrieveInstantMessages; - client.OnMuteListRequest += OnMuteListRequest; } private void RetrieveInstantMessages(IClientAPI client) @@ -194,20 +192,6 @@ namespace OpenSim.OfflineIM } } - // Apparently this is needed in order for the viewer to request the IMs. - private void OnMuteListRequest(IClientAPI client, uint crc) - { - m_log.DebugFormat("[OfflineIM.V2] Got mute list request for crc {0}", crc); - string filename = "mutes" + client.AgentId.ToString(); - - IXfer xfer = client.Scene.RequestModuleInterface(); - if (xfer != null) - { - xfer.AddNewFile(filename, new Byte[0]); - client.SendMuteListUpdate(filename); - } - } - private void UndeliveredMessage(GridInstantMessage im) { if (im.dialog != (byte)InstantMessageDialog.MessageFromObject && -- cgit v1.1 From 334986ddc62fb29a595381c6cef62474543da1a1 Mon Sep 17 00:00:00 2001 From: fly-man- Date: Fri, 13 Jul 2018 15:59:28 +0200 Subject: Group Powers changed and Officers role brought back for Groups Signed-off-by: UbitUmarov --- OpenSim/Addons/Groups/Service/GroupsService.cs | 111 +++++++++++++------------ 1 file changed, 60 insertions(+), 51 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/Service/GroupsService.cs b/OpenSim/Addons/Groups/Service/GroupsService.cs index ea0fedd..c7763c9 100644 --- a/OpenSim/Addons/Groups/Service/GroupsService.cs +++ b/OpenSim/Addons/Groups/Service/GroupsService.cs @@ -51,52 +51,56 @@ namespace OpenSim.Groups GroupPowers.StartProposal | GroupPowers.VoteOnProposal; - public const GroupPowers OwnerPowers = GroupPowers.Accountable | - GroupPowers.AllowEditLand | - GroupPowers.AllowFly | - GroupPowers.AllowLandmark | - GroupPowers.AllowRez | - GroupPowers.AllowSetHome | - GroupPowers.AllowVoiceChat | - GroupPowers.AssignMember | - GroupPowers.AssignMemberLimited | - GroupPowers.ChangeActions | - GroupPowers.ChangeIdentity | - GroupPowers.ChangeMedia | - GroupPowers.ChangeOptions | - GroupPowers.CreateRole | - GroupPowers.DeedObject | - GroupPowers.DeleteRole | - GroupPowers.Eject | - GroupPowers.FindPlaces | - GroupPowers.HostEvent | - GroupPowers.Invite | - GroupPowers.JoinChat | - GroupPowers.LandChangeIdentity | - GroupPowers.LandDeed | - GroupPowers.LandDivideJoin | - GroupPowers.LandEdit | - GroupPowers.LandEjectAndFreeze | - GroupPowers.LandGardening | - GroupPowers.LandManageAllowed | - GroupPowers.LandManageBanned | - GroupPowers.LandManagePasses | - GroupPowers.LandOptions | - GroupPowers.LandRelease | - GroupPowers.LandSetSale | - GroupPowers.ModerateChat | - GroupPowers.ObjectManipulate | - GroupPowers.ObjectSetForSale | - GroupPowers.ReceiveNotices | - GroupPowers.RemoveMember | - GroupPowers.ReturnGroupOwned | - GroupPowers.ReturnGroupSet | - GroupPowers.ReturnNonGroup | - GroupPowers.RoleProperties | - GroupPowers.SendNotices | - GroupPowers.SetLandingPoint | - GroupPowers.StartProposal | - GroupPowers.VoteOnProposal; + public const GroupPowers OfficersPowers = + (GroupPowers)DefaultEveryonePowers | + GroupPowers.AllowFly | + GroupPowers.AllowLandmark | + GroupPowers.AllowRez | + GroupPowers.AssignMemberLimited | + GroupPowers.ChangeIdentity | + GroupPowers.ChangeMedia | + GroupPowers.ChangeOptions | + GroupPowers.DeedObject | + GroupPowers.Eject | + GroupPowers.FindPlaces | + GroupPowers.Invite | + GroupPowers.LandChangeIdentity | + GroupPowers.LandDeed | + GroupPowers.LandDivideJoin | + GroupPowers.LandEdit | + GroupPowers.LandEjectAndFreeze | + GroupPowers.LandGardening | + GroupPowers.LandManageAllowed | + GroupPowers.LandManageBanned | + GroupPowers.LandManagePasses | + GroupPowers.LandOptions | + GroupPowers.LandRelease | + GroupPowers.LandSetSale | + GroupPowers.MemberVisible | + GroupPowers.ModerateChat | + GroupPowers.ObjectManipulate | + GroupPowers.ObjectSetForSale | + GroupPowers.ReturnGroupOwned | + GroupPowers.ReturnGroupSet | + GroupPowers.ReturnNonGroup | + GroupPowers.RoleProperties | + GroupPowers.SendNotices | + GroupPowers.SetLandingPoint; + + + public const GroupPowers OwnerPowers = + (GroupPowers)OfficersPowers | + GroupPowers.Accountable | + GroupPowers.AllowEditLand | + GroupPowers.AssignMember | + GroupPowers.ChangeActions | + GroupPowers.CreateRole | + GroupPowers.DeleteRole | + GroupPowers.ExperienceAdmin | + GroupPowers.ExperienceCreator | + GroupPowers.GroupBanAccess | + GroupPowers.HostEvent | + GroupPowers.RemoveMember; #region Daily Cleanup @@ -151,20 +155,25 @@ namespace OpenSim.Groups data.Data["ShowInList"] = showInList ? "1" : "0"; data.Data["AllowPublish"] = allowPublish ? "1" : "0"; data.Data["MaturePublish"] = maturePublish ? "1" : "0"; - UUID roleID = UUID.Random(); - data.Data["OwnerRoleID"] = roleID.ToString(); + UUID ownerRoleID = UUID.Random(); + data.Data["OwnerRoleID"] = ownerRoleID.ToString(); if (!m_Database.StoreGroup(data)) return UUID.Zero; // Create Everyone role - _AddOrUpdateGroupRole(RequestingAgentID, data.GroupID, UUID.Zero, "Everyone", "Everyone in the group", "Member of " + name, (ulong)DefaultEveryonePowers, true); + _AddOrUpdateGroupRole(RequestingAgentID, data.GroupID, UUID.Zero, "Everyone", "Everyone in the group is in the everyone role.", "Member of " + name, (ulong)DefaultEveryonePowers, true); + + // Create Officers role + UUID officersRoleID = UUID.Random(); + _AddOrUpdateGroupRole(RequestingAgentID, data.GroupID, officersRoleID, "Officers", "The officers of the group, with more powers than regular members.", "Officer of " + name, (ulong)OfficersPowers, true); // Create Owner role - _AddOrUpdateGroupRole(RequestingAgentID, data.GroupID, roleID, "Owners", "Owners of the group", "Owner of " + name, (ulong)OwnerPowers, true); + _AddOrUpdateGroupRole(RequestingAgentID, data.GroupID, ownerRoleID, "Owners", "Owners of the group", "Owner of " + name, (ulong)OwnerPowers, true); // Add founder to group - _AddAgentToGroup(RequestingAgentID, founderID.ToString(), data.GroupID, roleID); + _AddAgentToGroup(RequestingAgentID, founderID.ToString(), data.GroupID, ownerRoleID); + _AddAgentToGroup(RequestingAgentID, founderID.ToString(), data.GroupID, officersRoleID); return data.GroupID; } -- cgit v1.1 From a235a281329e21e3db9f4629ed621996f1e9abd8 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Fri, 13 Jul 2018 23:03:26 +0100 Subject: minor changes to last patch --- OpenSim/Addons/Groups/Service/GroupsService.cs | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/Service/GroupsService.cs b/OpenSim/Addons/Groups/Service/GroupsService.cs index c7763c9..38f87a2 100644 --- a/OpenSim/Addons/Groups/Service/GroupsService.cs +++ b/OpenSim/Addons/Groups/Service/GroupsService.cs @@ -43,16 +43,16 @@ namespace OpenSim.Groups { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - public const GroupPowers DefaultEveryonePowers = GroupPowers.AllowSetHome | - GroupPowers.Accountable | - GroupPowers.JoinChat | - GroupPowers.AllowVoiceChat | - GroupPowers.ReceiveNotices | - GroupPowers.StartProposal | - GroupPowers.VoteOnProposal; - - public const GroupPowers OfficersPowers = - (GroupPowers)DefaultEveryonePowers | + public const GroupPowers DefaultEveryonePowers = + GroupPowers.AllowSetHome | + GroupPowers.Accountable | + GroupPowers.JoinChat | + GroupPowers.AllowVoiceChat | + GroupPowers.ReceiveNotices | + GroupPowers.StartProposal | + GroupPowers.VoteOnProposal; + + public const GroupPowers OfficersPowers = DefaultEveryonePowers | GroupPowers.AllowFly | GroupPowers.AllowLandmark | GroupPowers.AllowRez | @@ -87,9 +87,7 @@ namespace OpenSim.Groups GroupPowers.SendNotices | GroupPowers.SetLandingPoint; - - public const GroupPowers OwnerPowers = - (GroupPowers)OfficersPowers | + public const GroupPowers OwnerPowers = OfficersPowers | GroupPowers.Accountable | GroupPowers.AllowEditLand | GroupPowers.AssignMember | @@ -852,7 +850,7 @@ namespace OpenSim.Groups return false; } - if (!add && data == null) // it deosn't exist, can't update + if (!add && data == null) // it dosn't exist, can't update { m_log.DebugFormat("[Groups]: Group {0} doesn't exist. Can't update it", groupID); return false; -- cgit v1.1 From 8ed4bee521d9736abd753ed1e72c7e0461e49846 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Sat, 14 Jul 2018 00:46:47 +0100 Subject: mantis 8333: kept idea but my own code. With ini setting ConsoleHistoryTimeStamp set to true, the console history file will have timestamps. Im lazy date is in en-us culture for now. (robust also) --- OpenSim/Addons/Groups/Service/GroupsService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/Service/GroupsService.cs b/OpenSim/Addons/Groups/Service/GroupsService.cs index 38f87a2..bed91d9 100644 --- a/OpenSim/Addons/Groups/Service/GroupsService.cs +++ b/OpenSim/Addons/Groups/Service/GroupsService.cs @@ -850,7 +850,7 @@ namespace OpenSim.Groups return false; } - if (!add && data == null) // it dosn't exist, can't update + if (!add && data == null) // it doesn't exist, can't update { m_log.DebugFormat("[Groups]: Group {0} doesn't exist. Can't update it", groupID); return false; -- cgit v1.1 From e7d9fe966cf501d77370fa45639e40ac2f3f6ab7 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Sat, 20 Oct 2018 14:00:13 +0100 Subject: fix groups v2 agentUUI ofr uuid.zero case --- .../Hypergrid/GroupsServiceHGConnectorModule.cs | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs b/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs index 9852581..a1093c9 100644 --- a/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs +++ b/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs @@ -605,14 +605,8 @@ namespace OpenSim.Groups private string AgentUUI(string AgentIDStr) { UUID AgentID = UUID.Zero; - try - { - AgentID = new UUID(AgentIDStr); - } - catch (FormatException) - { - return AgentID.ToString(); - } + if (!UUID.TryParse(AgentIDStr, out AgentID) || AgentID == UUID.Zero) + return UUID.Zero.ToString(); if (m_UserManagement.IsLocalGridUser(AgentID)) return AgentID.ToString(); @@ -636,14 +630,8 @@ namespace OpenSim.Groups private string AgentUUIForOutside(string AgentIDStr) { UUID AgentID = UUID.Zero; - try - { - AgentID = new UUID(AgentIDStr); - } - catch (FormatException) - { - return AgentID.ToString(); - } + if (!UUID.TryParse(AgentIDStr, out AgentID) || AgentID == UUID.Zero) + return UUID.Zero.ToString(); AgentCircuitData agent = null; foreach (Scene scene in m_Scenes) -- cgit v1.1 From efd6fb05a9f3805ce19dc432b6d084497cd45573 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Sat, 17 Nov 2018 17:05:28 +0000 Subject: code aesthetics --- OpenSim/Addons/Groups/Service/GroupsService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/Service/GroupsService.cs b/OpenSim/Addons/Groups/Service/GroupsService.cs index bed91d9..0792a47 100644 --- a/OpenSim/Addons/Groups/Service/GroupsService.cs +++ b/OpenSim/Addons/Groups/Service/GroupsService.cs @@ -492,7 +492,7 @@ namespace OpenSim.Groups // check permissions bool limited = HasPower(RequestingAgentID, GroupID, GroupPowers.AssignMemberLimited); - bool unlimited = HasPower(RequestingAgentID, GroupID, GroupPowers.AssignMember) | IsOwner(RequestingAgentID, GroupID); + bool unlimited = HasPower(RequestingAgentID, GroupID, GroupPowers.AssignMember) || IsOwner(RequestingAgentID, GroupID); if (!limited && !unlimited) { m_log.DebugFormat("[Groups]: ({0}) Attempt at assigning {1} to role {2} denied because of lack of permission", RequestingAgentID, AgentID, RoleID); -- cgit v1.1 From 9225b783092d3265714520fdfdab8100902b27c2 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Tue, 30 Apr 2019 23:04:04 +0100 Subject: missing files... --- OpenSim/Addons/Groups/GroupsModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs index 5b76e0a..e98bc0f 100644 --- a/OpenSim/Addons/Groups/GroupsModule.cs +++ b/OpenSim/Addons/Groups/GroupsModule.cs @@ -249,7 +249,7 @@ namespace OpenSim.Groups // There might be some problem with the thread we're generating this on but not // doing the update at this time causes problems (Mantis #7920 and #7915) // TODO: move sending this update to a later time in the rootification of the client. - if(!sp.haveGroupInformation) + if(!sp.m_haveGroupInformation) SendAgentGroupDataUpdate(sp.ControllingClient, false); } -- cgit v1.1 From 0fd17c08ae642fac17b24dfad06c61cfe5739483 Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 20 Aug 2019 23:28:59 +0100 Subject: Massive console refactor. Greatly simplify interface. --- OpenSim/Addons/Groups/GroupsMessagingModule.cs | 2 +- OpenSim/Addons/Groups/GroupsModule.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) mode change 100644 => 100755 OpenSim/Addons/Groups/GroupsMessagingModule.cs mode change 100644 => 100755 OpenSim/Addons/Groups/GroupsModule.cs (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsMessagingModule.cs b/OpenSim/Addons/Groups/GroupsMessagingModule.cs old mode 100644 new mode 100755 index f4d3490..854a125 --- a/OpenSim/Addons/Groups/GroupsMessagingModule.cs +++ b/OpenSim/Addons/Groups/GroupsMessagingModule.cs @@ -252,7 +252,7 @@ namespace OpenSim.Groups m_debugEnabled = verbose; - MainConsole.Instance.OutputFormat("{0} verbose logging set to {1}", Name, m_debugEnabled); + MainConsole.Instance.Output("{0} verbose logging set to {1}", null, Name, m_debugEnabled); } /// diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs old mode 100644 new mode 100755 index e98bc0f..98264ad --- a/OpenSim/Addons/Groups/GroupsModule.cs +++ b/OpenSim/Addons/Groups/GroupsModule.cs @@ -127,7 +127,7 @@ namespace OpenSim.Groups m_debugEnabled = verbose; - MainConsole.Instance.OutputFormat("{0} verbose logging set to {1}", Name, m_debugEnabled); + MainConsole.Instance.Output("{0} verbose logging set to {1}", null, Name, m_debugEnabled); } public void RegionLoaded(Scene scene) -- cgit v1.1 From 0273baaef67824da5cb2cc2de2593a8800ce3cb6 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Sun, 13 Oct 2019 16:41:38 +0100 Subject: mantis 8598: filter dead groups from group search. honor querystart request. Viewers are very broken on this, seems protocol was made by someone with no idea about lludp --- OpenSim/Addons/Groups/Service/GroupsService.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/Service/GroupsService.cs b/OpenSim/Addons/Groups/Service/GroupsService.cs index 0792a47..b5f8ff5 100644 --- a/OpenSim/Addons/Groups/Service/GroupsService.cs +++ b/OpenSim/Addons/Groups/Service/GroupsService.cs @@ -230,15 +230,22 @@ namespace OpenSim.Groups if (d.Data.ContainsKey("Location") && d.Data["Location"] != string.Empty) continue; + int nmembers = m_Database.MemberCount(d.GroupID); + if(nmembers == 0) + continue; + DirGroupsReplyData g = new DirGroupsReplyData(); - g.groupID = d.GroupID; if (d.Data.ContainsKey("Name")) g.groupName = d.Data["Name"]; else + { m_log.DebugFormat("[Groups]: Key Name not found"); + continue; + } - g.members = m_Database.MemberCount(d.GroupID); + g.groupID = d.GroupID; + g.members = nmembers; groups.Add(g); } -- cgit v1.1 From 237659ba30a2d6a072aae989252a1e6be0423c3c Mon Sep 17 00:00:00 2001 From: onefang Date: Wed, 9 Sep 2020 00:52:35 +1000 Subject: Remove useless executable bit that Windows adds. --- OpenSim/Addons/Groups/GroupsMessagingModule.cs | 0 OpenSim/Addons/Groups/GroupsModule.cs | 0 2 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 OpenSim/Addons/Groups/GroupsMessagingModule.cs mode change 100755 => 100644 OpenSim/Addons/Groups/GroupsModule.cs (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsMessagingModule.cs b/OpenSim/Addons/Groups/GroupsMessagingModule.cs old mode 100755 new mode 100644 diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs old mode 100755 new mode 100644 -- cgit v1.1 From b95b03b409578da87f1dbaf809001e88e4e4fd56 Mon Sep 17 00:00:00 2001 From: onefang Date: Fri, 11 Sep 2020 00:41:12 +1000 Subject: Automatically add members to certain groups, and HGers from specific grids to certain other groups. It doesn't let them know, though the last group added will be their active group. This replaces a PHP script I used to use, that got broken by a PHP update. It also didn't let people know, no one complained. This is better. Another attempt at sorting out the auto group chicken and egg problems. Are you a local? Asking for a friend. Hypergridders have their full name in firstname, and their grid in lastname. Sometimes. Code filled with gotos may be spaghetti code, but object oriented code can be like chopped spaghetti that's hidden all over the kitchen. At least with gotos you can follow them. --- OpenSim/Addons/Groups/GroupsModule.cs | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'OpenSim/Addons') diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs index 98264ad..327504d 100644 --- a/OpenSim/Addons/Groups/GroupsModule.cs +++ b/OpenSim/Addons/Groups/GroupsModule.cs @@ -1015,6 +1015,15 @@ namespace OpenSim.Groups remoteClient.SendJoinGroupReply(groupID, false); } + public void JoinGroup(string agentID, UUID groupID) + { + string reason = string.Empty; + m_groupData.AddAgentToGroup(agentID, agentID, groupID, UUID.Zero, string.Empty, out reason); + if (reason != string.Empty) + // A warning + m_log.Warn("[Groups]: Join group warning - " + reason); + } + public void LeaveGroupRequest(IClientAPI remoteClient, UUID groupID) { if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); -- cgit v1.1