First commit of Diva Groups. The Data bits went to OpenSim.Data core, the rest to Addons.Groups.dll.
parent
46e182dbf5
commit
9380d01976
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<string, object> GroupRecord(ExtendedGroupRecord grec)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||||
|
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<string, object> 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<string, object> GroupMembershipData(ExtendedGroupMembershipData membership)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||||
|
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<string, object> 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<string, object> GroupMembersData(ExtendedGroupMembersData member)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
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<string, object> 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<string, object> GroupRolesData(GroupRolesData role)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
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<string, object> 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<string, object> GroupRoleMembersData(ExtendedGroupRoleMembersData rmember)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
dict["RoleID"] = rmember.RoleID.ToString();
|
||||||
|
dict["MemberID"] = rmember.MemberID;
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ExtendedGroupRoleMembersData GroupRoleMembersData(Dictionary<string, object> 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<string, object> GroupInviteInfo(GroupInviteInfo invite)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
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<string, object> 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<string, object> GroupNoticeData(ExtendedGroupNoticeData notice)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
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<string, object> 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<string, object> GroupNoticeInfo(GroupNoticeInfo notice)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> dict = GroupNoticeData(notice.noticeData);
|
||||||
|
|
||||||
|
dict["GroupID"] = notice.GroupID.ToString();
|
||||||
|
dict["Message"] = Sanitize(notice.Message);
|
||||||
|
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GroupNoticeInfo GroupNoticeInfo(Dictionary<string, object> dict)
|
||||||
|
{
|
||||||
|
GroupNoticeInfo notice = new GroupNoticeInfo();
|
||||||
|
|
||||||
|
notice.noticeData = GroupNoticeData(dict);
|
||||||
|
notice.GroupID = new UUID(dict["GroupID"].ToString());
|
||||||
|
notice.Message = Sanitize(dict["Message"].ToString());
|
||||||
|
|
||||||
|
return notice;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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<Scene> m_sceneList = new List<Scene>();
|
||||||
|
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;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If enabled, module only tries to send group IMs to online users by querying cached presence information.
|
||||||
|
/// </summary>
|
||||||
|
private bool m_messageOnlineAgentsOnly;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Cache for online users.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// 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.
|
||||||
|
/// </remarks>
|
||||||
|
private ExpiringCache<UUID, PresenceInfo[]> 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<UUID, PresenceInfo[]>();
|
||||||
|
|
||||||
|
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<IGroupsMessagingModule>(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<IGroupsServicesConnector>();
|
||||||
|
|
||||||
|
// 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<IMessageTransferModule>();
|
||||||
|
|
||||||
|
// 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<IGroupsMessagingModule>(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
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Not really needed, but does confirm that the group exists.
|
||||||
|
/// </summary>
|
||||||
|
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<GroupMembersData> groupMembers = m_groupData.GetGroupMembers(new UUID(im.fromAgentID).ToString(), groupID);
|
||||||
|
int groupMembersCount = groupMembers.Count;
|
||||||
|
|
||||||
|
if (m_messageOnlineAgentsOnly)
|
||||||
|
{
|
||||||
|
string[] t1 = groupMembers.ConvertAll<string>(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<string> onlineAgentsUuidSet = new HashSet<string>();
|
||||||
|
Array.ForEach<PresenceInfo>(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<IEventQueue>();
|
||||||
|
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<IEventQueue>();
|
||||||
|
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<IEventQueue>();
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Try to find an active IClientAPI reference for agentID giving preference to root connections
|
||||||
|
/// </summary>
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -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<string, object> sendData = new Dictionary<string,object>();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
sendData["AgentID"] = AgentID.ToString();
|
||||||
|
sendData["AccessToken"] = accessToken;
|
||||||
|
sendData["GroupID"] = groupID.ToString();
|
||||||
|
sendData["Location"] = url;
|
||||||
|
sendData["Name"] = name;
|
||||||
|
Dictionary<string, object> 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<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
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<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
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<string, object> 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<string, object>)ret["RESULT"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ExtendedGroupMembersData> GetGroupMembers(string RequestingAgentID, UUID GroupID, string token)
|
||||||
|
{
|
||||||
|
List<ExtendedGroupMembersData> members = new List<ExtendedGroupMembersData>();
|
||||||
|
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
sendData["AccessToken"] = GroupsDataUtils.Sanitize(token);
|
||||||
|
Dictionary<string, object> 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<string, object>)ret["RESULT"]).Values)
|
||||||
|
{
|
||||||
|
ExtendedGroupMembersData m = GroupsDataUtils.GroupMembersData((Dictionary<string, object>)v);
|
||||||
|
members.Add(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
return members;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupRolesData> GetGroupRoles(string RequestingAgentID, UUID GroupID, string token)
|
||||||
|
{
|
||||||
|
List<GroupRolesData> roles = new List<GroupRolesData>();
|
||||||
|
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
sendData["AccessToken"] = GroupsDataUtils.Sanitize(token);
|
||||||
|
Dictionary<string, object> 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<string, object>)ret["RESULT"]).Values)
|
||||||
|
{
|
||||||
|
GroupRolesData m = GroupsDataUtils.GroupRolesData((Dictionary<string, object>)v);
|
||||||
|
roles.Add(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
return roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ExtendedGroupRoleMembersData> GetGroupRoleMembers(string RequestingAgentID, UUID GroupID, string token)
|
||||||
|
{
|
||||||
|
List<ExtendedGroupRoleMembersData> rmembers = new List<ExtendedGroupRoleMembersData>();
|
||||||
|
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
sendData["AccessToken"] = GroupsDataUtils.Sanitize(token);
|
||||||
|
Dictionary<string, object> 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<string, object>)ret["RESULT"]).Values)
|
||||||
|
{
|
||||||
|
ExtendedGroupRoleMembersData m = GroupsDataUtils.GroupRoleMembersData((Dictionary<string, object>)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<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
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<string, object> 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<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["NoticeID"] = noticeID.ToString();
|
||||||
|
sendData["GroupID"] = groupID.ToString();
|
||||||
|
Dictionary<string, object> 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<string, object> MakeRequest(string method, Dictionary<string, object> 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<string, object> replyData = ServerUtils.ParseXmlResponse(
|
||||||
|
reply);
|
||||||
|
|
||||||
|
return replyData;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<Scene> m_Scenes;
|
||||||
|
private ForeignImporter m_ForeignImporter;
|
||||||
|
private string m_ServiceLocation;
|
||||||
|
private IConfigSource m_Config;
|
||||||
|
|
||||||
|
private Dictionary<string, GroupsServiceHGConnector> m_NetworkConnectors = new Dictionary<string, GroupsServiceHGConnector>();
|
||||||
|
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<Scene>();
|
||||||
|
|
||||||
|
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<IGroupsServicesConnector>(this);
|
||||||
|
m_Scenes.Add(scene);
|
||||||
|
|
||||||
|
scene.EventManager.OnNewClient += OnNewClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveRegion(Scene scene)
|
||||||
|
{
|
||||||
|
if (!m_Enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
scene.UnregisterModuleInterface<IGroupsServicesConnector>(this);
|
||||||
|
m_Scenes.Remove(scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RegionLoaded(Scene scene)
|
||||||
|
{
|
||||||
|
if (!m_Enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (m_UserManagement == null)
|
||||||
|
{
|
||||||
|
m_UserManagement = scene.RequestModuleInterface<IUserManagement>();
|
||||||
|
m_OfflineIM = scene.RequestModuleInterface<IOfflineIMService>();
|
||||||
|
m_Messaging = scene.RequestModuleInterface<IMessageTransferModule>();
|
||||||
|
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<IOfflineIMService>(), scene.RequestModuleInterface<IUserAccountService>());
|
||||||
|
|
||||||
|
}
|
||||||
|
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<GridInstantMessage> 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<DirGroupsReplyData> FindGroups(string RequestingAgentID, string search)
|
||||||
|
{
|
||||||
|
return m_LocalGroupsConnector.FindGroups(AgentUUI(RequestingAgentID), search);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupMembersData> 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<GroupMembersData>();
|
||||||
|
}
|
||||||
|
|
||||||
|
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<GroupRolesData> 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<GroupRolesData>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupRoleMembersData> 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<GroupRoleMembersData>();
|
||||||
|
}
|
||||||
|
|
||||||
|
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<GroupRolesData> 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<GroupRolesData>();
|
||||||
|
}
|
||||||
|
|
||||||
|
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<GroupMembershipData> 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<GroupMembersData> members = m_LocalGroupsConnector.GetGroupMembers(AgentUUI(RequestingAgentID), groupID);
|
||||||
|
List<string> urls = new List<string>();
|
||||||
|
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<ExtendedGroupNoticeData> 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
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<IOfflineIMService>(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<IUserAccountService>(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<string, object> 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<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
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<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
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<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
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<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
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<ExtendedGroupMembersData> members = m_GroupsService.GetGroupMembers(requestingAgentID, groupID, token);
|
||||||
|
if (members == null || (members != null && members.Count == 0))
|
||||||
|
{
|
||||||
|
NullResult(result, "No members");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||||
|
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<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
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<GroupRolesData> roles = m_GroupsService.GetGroupRoles(requestingAgentID, groupID, token);
|
||||||
|
if (roles == null || (roles != null && roles.Count == 0))
|
||||||
|
{
|
||||||
|
NullResult(result, "No members");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||||
|
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<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
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<ExtendedGroupRoleMembersData> rmembers = m_GroupsService.GetGroupRoleMembers(requestingAgentID, groupID, token);
|
||||||
|
if (rmembers == null || (rmembers != null && rmembers.Count == 0))
|
||||||
|
{
|
||||||
|
NullResult(result, "No members");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||||
|
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<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
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<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
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<string, object> result, string reason)
|
||||||
|
{
|
||||||
|
result["RESULT"] = "NULL";
|
||||||
|
result["REASON"] = reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] FailureResult()
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
NullResult(result, "Unknown method");
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<DirGroupsReplyData> FindGroups(string RequestingAgentID, string search);
|
||||||
|
List<GroupMembersData> 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<GroupRolesData> GetGroupRoles(string RequestingAgentID, UUID GroupID);
|
||||||
|
List<GroupRoleMembersData> 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<GroupRolesData> 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);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get information about a specific group to which the user belongs.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="RequestingAgentID">The agent requesting the information.</param>
|
||||||
|
/// <param name="AgentID">The agent requested.</param>
|
||||||
|
/// <param name="GroupID">The group requested.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// If the user is a member of the group then the data structure is returned. If not, then null is returned.
|
||||||
|
/// </returns>
|
||||||
|
ExtendedGroupMembershipData GetAgentGroupMembership(string RequestingAgentID, string AgentID, UUID GroupID);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get information about the groups to which a user belongs.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="RequestingAgentID">The agent requesting the information.</param>
|
||||||
|
/// <param name="AgentID">The agent requested.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// Information about the groups to which the user belongs. If the user belongs to no groups then an empty
|
||||||
|
/// list is returned.
|
||||||
|
/// </returns>
|
||||||
|
List<GroupMembershipData> 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<ExtendedGroupNoticeData> 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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<Scene> 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<Scene>();
|
||||||
|
}
|
||||||
|
|
||||||
|
#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<IGroupsServicesConnector>(this);
|
||||||
|
m_Scenes.Add(scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveRegion(Scene scene)
|
||||||
|
{
|
||||||
|
if (!m_Enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
scene.UnregisterModuleInterface<IGroupsServicesConnector>(this);
|
||||||
|
m_Scenes.Remove(scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RegionLoaded(Scene scene)
|
||||||
|
{
|
||||||
|
if (!m_Enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (m_UserManagement == null)
|
||||||
|
{
|
||||||
|
m_UserManagement = scene.RequestModuleInterface<IUserManagement>();
|
||||||
|
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<DirGroupsReplyData> FindGroups(string RequestingAgentID, string search)
|
||||||
|
{
|
||||||
|
return m_GroupsService.FindGroups(RequestingAgentID, search);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupMembersData> GetGroupMembers(string RequestingAgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
List<ExtendedGroupMembersData> _members = m_GroupsService.GetGroupMembers(RequestingAgentID, GroupID);
|
||||||
|
if (_members != null && _members.Count > 0)
|
||||||
|
{
|
||||||
|
List<GroupMembersData> members = _members.ConvertAll<GroupMembersData>(new Converter<ExtendedGroupMembersData, GroupMembersData>(m_ForeignImporter.ConvertGroupMembersData));
|
||||||
|
return members;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new List<GroupMembersData>();
|
||||||
|
}
|
||||||
|
|
||||||
|
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<GroupRolesData> GetGroupRoles(string RequestingAgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
return m_GroupsService.GetGroupRoles(RequestingAgentID, GroupID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupRoleMembersData> GetGroupRoleMembers(string RequestingAgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
List<ExtendedGroupRoleMembersData> _rm = m_GroupsService.GetGroupRoleMembers(RequestingAgentID, GroupID);
|
||||||
|
if (_rm != null && _rm.Count > 0)
|
||||||
|
{
|
||||||
|
List<GroupRoleMembersData> rm = _rm.ConvertAll<GroupRoleMembersData>(new Converter<ExtendedGroupRoleMembersData, GroupRoleMembersData>(m_ForeignImporter.ConvertGroupRoleMembersData));
|
||||||
|
return rm;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new List<GroupRoleMembersData>();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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<GroupRolesData> 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<GroupMembershipData> 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<ExtendedGroupNoticeData> 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
|
||||||
|
}
|
||||||
|
}
|
|
@ -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")]
|
|
@ -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<string, object> sendData = GroupsDataUtils.GroupRecord(rec);
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
sendData["OP"] = "ADD";
|
||||||
|
Dictionary<string, object> ret = MakeRequest("PUTGROUP", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString() == "NULL")
|
||||||
|
{
|
||||||
|
reason = ret["REASON"].ToString();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GroupsDataUtils.GroupRecord((Dictionary<string, object>)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<string, object> sendData = GroupsDataUtils.GroupRecord(rec);
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
sendData["OP"] = "UPDATE";
|
||||||
|
Dictionary<string, object> ret = MakeRequest("PUTGROUP", sendData);
|
||||||
|
|
||||||
|
if (ret == null || (ret != null && ret["RESULT"].ToString() == "NULL"))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return GroupsDataUtils.GroupRecord((Dictionary<string, object>)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<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
if (GroupID != UUID.Zero)
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
if (GroupName != null && GroupName != string.Empty)
|
||||||
|
sendData["Name"] = GroupsDataUtils.Sanitize(GroupName);
|
||||||
|
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
|
||||||
|
Dictionary<string, object> ret = MakeRequest("GETGROUP", sendData);
|
||||||
|
|
||||||
|
if (ret == null || (ret != null && ret["RESULT"].ToString() == "NULL"))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return GroupsDataUtils.GroupRecord((Dictionary<string, object>)ret["RESULT"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupMembershipData AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID, string token, out string reason)
|
||||||
|
{
|
||||||
|
reason = string.Empty;
|
||||||
|
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string,object>();
|
||||||
|
sendData["AgentID"] = AgentID;
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
sendData["RoleID"] = RoleID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
sendData["AccessToken"] = token;
|
||||||
|
Dictionary<string, object> 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<string, object>)ret["RESULT"]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["AgentID"] = AgentID;
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
MakeRequest("REMOVEAGENTFROMGROUP", sendData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExtendedGroupMembershipData GetMembership(string RequestingAgentID, string AgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["AgentID"] = AgentID;
|
||||||
|
if (GroupID != UUID.Zero)
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
Dictionary<string, object> 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<string, object>)ret["RESULT"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupMembershipData> GetMemberships(string RequestingAgentID, string AgentID)
|
||||||
|
{
|
||||||
|
List<GroupMembershipData> memberships = new List<GroupMembershipData>();
|
||||||
|
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["AgentID"] = AgentID;
|
||||||
|
sendData["ALL"] = "true";
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
Dictionary<string, object> 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<string, object>)ret["RESULT"]).Values)
|
||||||
|
{
|
||||||
|
GroupMembershipData m = GroupsDataUtils.GroupMembershipData((Dictionary<string, object>)v);
|
||||||
|
memberships.Add(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
return memberships;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ExtendedGroupMembersData> GetGroupMembers(string RequestingAgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
List<ExtendedGroupMembersData> members = new List<ExtendedGroupMembersData>();
|
||||||
|
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
Dictionary<string, object> 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<string, object>)ret["RESULT"]).Values)
|
||||||
|
{
|
||||||
|
ExtendedGroupMembersData m = GroupsDataUtils.GroupMembersData((Dictionary<string, object>)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<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
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<string, object> 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<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
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<string, object> 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<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["GroupID"] = groupID.ToString();
|
||||||
|
sendData["RoleID"] = roleID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
MakeRequest("REMOVEROLE", sendData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupRolesData> GetGroupRoles(string RequestingAgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
List<GroupRolesData> roles = new List<GroupRolesData>();
|
||||||
|
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
Dictionary<string, object> 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<string, object>)ret["RESULT"]).Values)
|
||||||
|
{
|
||||||
|
GroupRolesData m = GroupsDataUtils.GroupRolesData((Dictionary<string, object>)v);
|
||||||
|
roles.Add(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
return roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ExtendedGroupRoleMembersData> GetGroupRoleMembers(string RequestingAgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
List<ExtendedGroupRoleMembersData> rmembers = new List<ExtendedGroupRoleMembersData>();
|
||||||
|
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
Dictionary<string, object> 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<string, object>)ret["RESULT"]).Values)
|
||||||
|
{
|
||||||
|
ExtendedGroupRoleMembersData m = GroupsDataUtils.GroupRoleMembersData((Dictionary<string, object>)v);
|
||||||
|
rmembers.Add(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rmembers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddAgentToGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["AgentID"] = AgentID.ToString();
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
sendData["RoleID"] = RoleID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
sendData["OP"] = "ADD";
|
||||||
|
|
||||||
|
Dictionary<string, object> 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<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["AgentID"] = AgentID.ToString();
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
sendData["RoleID"] = RoleID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
sendData["OP"] = "DELETE";
|
||||||
|
|
||||||
|
Dictionary<string, object> 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<GroupRolesData> GetAgentGroupRoles(string RequestingAgentID, string AgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
List<GroupRolesData> roles = new List<GroupRolesData>();
|
||||||
|
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["AgentID"] = AgentID.ToString();
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
Dictionary<string, object> 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<string, object>)ret["RESULT"]).Values)
|
||||||
|
{
|
||||||
|
GroupRolesData m = GroupsDataUtils.GroupRolesData((Dictionary<string, object>)v);
|
||||||
|
roles.Add(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
return roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupMembershipData SetAgentActiveGroup(string RequestingAgentID, string AgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["AgentID"] = AgentID.ToString();
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
sendData["OP"] = "GROUP";
|
||||||
|
|
||||||
|
Dictionary<string, object> 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<string, object>)ret["RESULT"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetAgentActiveGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
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<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
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<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["InviteID"] = inviteID.ToString();
|
||||||
|
sendData["GroupID"] = groupID.ToString();
|
||||||
|
sendData["RoleID"] = roleID.ToString();
|
||||||
|
sendData["AgentID"] = agentID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
sendData["OP"] = "ADD";
|
||||||
|
|
||||||
|
Dictionary<string, object> 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<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["InviteID"] = inviteID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
sendData["OP"] = "GET";
|
||||||
|
|
||||||
|
Dictionary<string, object> 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<string, object>)ret["RESULT"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveAgentToGroupInvite(string RequestingAgentID, UUID inviteID)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
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<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
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<string, object> 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<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["NoticeID"] = noticeID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
|
||||||
|
Dictionary<string, object> 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<string, object>)ret["RESULT"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ExtendedGroupNoticeData> GetGroupNotices(string RequestingAgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
List<ExtendedGroupNoticeData> notices = new List<ExtendedGroupNoticeData>();
|
||||||
|
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
Dictionary<string, object> 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<string, object>)ret["RESULT"]).Values)
|
||||||
|
{
|
||||||
|
ExtendedGroupNoticeData m = GroupsDataUtils.GroupNoticeData((Dictionary<string, object>)v);
|
||||||
|
notices.Add(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
return notices;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Make Request
|
||||||
|
|
||||||
|
private Dictionary<string, object> MakeRequest(string method, Dictionary<string, object> 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<string, object> replyData = ServerUtils.ParseXmlResponse(
|
||||||
|
reply);
|
||||||
|
|
||||||
|
return replyData;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<Scene> 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<Scene>();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#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<IGroupsServicesConnector>(this);
|
||||||
|
m_Scenes.Add(scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveRegion(Scene scene)
|
||||||
|
{
|
||||||
|
if (!m_Enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
scene.UnregisterModuleInterface<IGroupsServicesConnector>(this);
|
||||||
|
m_Scenes.Remove(scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RegionLoaded(Scene scene)
|
||||||
|
{
|
||||||
|
if (!m_Enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (m_UserManagement == null)
|
||||||
|
{
|
||||||
|
m_UserManagement = scene.RequestModuleInterface<IUserManagement>();
|
||||||
|
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<DirGroupsReplyData> FindGroups(string RequestingAgentID, string search)
|
||||||
|
{
|
||||||
|
// TODO!
|
||||||
|
return new List<DirGroupsReplyData>();
|
||||||
|
}
|
||||||
|
|
||||||
|
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<GroupMembershipData> GetAgentGroupMemberships(string RequestingAgentID, string AgentID)
|
||||||
|
{
|
||||||
|
return m_CacheWrapper.GetAgentGroupMemberships(AgentID, delegate
|
||||||
|
{
|
||||||
|
return m_GroupsService.GetMemberships(RequestingAgentID, AgentID);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public List<GroupMembersData> 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<GroupRolesData> GetGroupRoles(string RequestingAgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
return m_CacheWrapper.GetGroupRoles(RequestingAgentID, GroupID, delegate
|
||||||
|
{
|
||||||
|
return m_GroupsService.GetGroupRoles(RequestingAgentID, GroupID);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupRoleMembersData> 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<GroupRolesData> 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<ExtendedGroupNoticeData> 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
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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<string, object> 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<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
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<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
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<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
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<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
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<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
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<GroupMembershipData> memberships = m_GroupsService.GetAgentGroupMemberships(requestingAgentID, agentID);
|
||||||
|
if (memberships == null || (memberships != null && memberships.Count == 0))
|
||||||
|
{
|
||||||
|
NullResult(result, "No memberships");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||||
|
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<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
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<ExtendedGroupMembersData> members = m_GroupsService.GetGroupMembers(requestingAgentID, groupID);
|
||||||
|
if (members == null || (members != null && members.Count == 0))
|
||||||
|
{
|
||||||
|
NullResult(result, "No members");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||||
|
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<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
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<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
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<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
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<GroupRolesData> roles = m_GroupsService.GetGroupRoles(requestingAgentID, groupID);
|
||||||
|
if (roles == null || (roles != null && roles.Count == 0))
|
||||||
|
{
|
||||||
|
NullResult(result, "No members");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||||
|
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<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
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<ExtendedGroupRoleMembersData> rmembers = m_GroupsService.GetGroupRoleMembers(requestingAgentID, groupID);
|
||||||
|
if (rmembers == null || (rmembers != null && rmembers.Count == 0))
|
||||||
|
{
|
||||||
|
NullResult(result, "No members");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||||
|
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<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
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<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
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<GroupRolesData> roles = m_GroupsService.GetAgentGroupRoles(requestingAgentID, agentID, groupID);
|
||||||
|
if (roles == null || (roles != null && roles.Count == 0))
|
||||||
|
{
|
||||||
|
NullResult(result, "No members");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||||
|
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<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
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<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
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<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
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<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
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<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
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<ExtendedGroupNoticeData> 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<string, object> dict = new Dictionary<string, object>();
|
||||||
|
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<string, object> result, string reason)
|
||||||
|
{
|
||||||
|
result["RESULT"] = "NULL";
|
||||||
|
result["REASON"] = reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] FailureResult()
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
NullResult(result, "Unknown method");
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<GroupMembershipData> GroupMembershipListDelegate();
|
||||||
|
public delegate List<ExtendedGroupMembersData> GroupMembersListDelegate();
|
||||||
|
public delegate List<GroupRolesData> GroupRolesListDelegate();
|
||||||
|
public delegate List<ExtendedGroupRoleMembersData> RoleMembersListDelegate();
|
||||||
|
public delegate GroupNoticeInfo NoticeDelegate();
|
||||||
|
public delegate List<ExtendedGroupNoticeData> NoticeListDelegate();
|
||||||
|
public delegate void VoidDelegate();
|
||||||
|
public delegate bool BooleanDelegate();
|
||||||
|
|
||||||
|
public class RemoteConnectorCacheWrapper
|
||||||
|
{
|
||||||
|
private ForeignImporter m_ForeignImporter;
|
||||||
|
|
||||||
|
private Dictionary<string, bool> m_ActiveRequests = new Dictionary<string, bool>();
|
||||||
|
private const int GROUPS_CACHE_TIMEOUT = 5 * 60; // 5 minutes
|
||||||
|
|
||||||
|
// This all important cache cahces objects of different types:
|
||||||
|
// group-<GroupID> or group-<Name> => ExtendedGroupRecord
|
||||||
|
// active-<AgentID> => GroupMembershipData
|
||||||
|
// membership-<AgentID>-<GroupID> => GroupMembershipData
|
||||||
|
// memberships-<AgentID> => List<GroupMembershipData>
|
||||||
|
// members-<RequestingAgentID>-<GroupID> => List<ExtendedGroupMembersData>
|
||||||
|
// role-<RoleID> => GroupRolesData
|
||||||
|
// roles-<GroupID> => List<GroupRolesData> ; all roles in the group
|
||||||
|
// roles-<GroupID>-<AgentID> => List<GroupRolesData> ; roles that the agent has
|
||||||
|
// rolemembers-<RequestingAgentID>-<GroupID> => List<ExtendedGroupRoleMembersData>
|
||||||
|
// notice-<noticeID> => GroupNoticeInfo
|
||||||
|
// notices-<GroupID> => List<ExtendedGroupNoticeData>
|
||||||
|
private ExpiringCache<string, object> m_Cache = new ExpiringCache<string, object>();
|
||||||
|
|
||||||
|
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<GroupMembershipData> 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<GroupMembershipData>)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<GroupMembershipData>)memberships;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Thread.Sleep(50);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupMembersData> 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<ExtendedGroupMembersData> xx = (List<ExtendedGroupMembersData>)members;
|
||||||
|
return xx.ConvertAll<GroupMembersData>(new Converter<ExtendedGroupMembersData, GroupMembersData>(m_ForeignImporter.ConvertGroupMembersData));
|
||||||
|
}
|
||||||
|
|
||||||
|
// not cached
|
||||||
|
if (!m_ActiveRequests.ContainsKey(cacheKey))
|
||||||
|
{
|
||||||
|
m_ActiveRequests.Add(cacheKey, true);
|
||||||
|
firstCall = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (firstCall)
|
||||||
|
{
|
||||||
|
List<ExtendedGroupMembersData> _members = d();
|
||||||
|
|
||||||
|
if (_members != null && _members.Count > 0)
|
||||||
|
members = _members.ConvertAll<GroupMembersData>(new Converter<ExtendedGroupMembersData, GroupMembersData>(m_ForeignImporter.ConvertGroupMembersData));
|
||||||
|
else
|
||||||
|
members = new List<GroupMembersData>();
|
||||||
|
|
||||||
|
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<GroupMembersData>)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<GroupRolesData> 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<GroupRolesData>)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<GroupRolesData>)roles;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Thread.Sleep(50);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupRoleMembersData> 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<ExtendedGroupRoleMembersData> xx = (List<ExtendedGroupRoleMembersData>)rmembers;
|
||||||
|
return xx.ConvertAll<GroupRoleMembersData>(m_ForeignImporter.ConvertGroupRoleMembersData);
|
||||||
|
}
|
||||||
|
|
||||||
|
// not cached
|
||||||
|
if (!m_ActiveRequests.ContainsKey(cacheKey))
|
||||||
|
{
|
||||||
|
m_ActiveRequests.Add(cacheKey, true);
|
||||||
|
firstCall = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (firstCall)
|
||||||
|
{
|
||||||
|
List<ExtendedGroupRoleMembersData> _rmembers = d();
|
||||||
|
|
||||||
|
if (_rmembers != null && _rmembers.Count > 0)
|
||||||
|
rmembers = _rmembers.ConvertAll<GroupRoleMembersData>(new Converter<ExtendedGroupRoleMembersData, GroupRoleMembersData>(m_ForeignImporter.ConvertGroupRoleMembersData));
|
||||||
|
else
|
||||||
|
rmembers = new List<GroupRoleMembersData>();
|
||||||
|
|
||||||
|
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<GroupRoleMembersData>)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<ExtendedGroupRoleMembersData> xx = (List<ExtendedGroupRoleMembersData>)obj;
|
||||||
|
List<GroupRoleMembersData> rmlist = xx.ConvertAll<GroupRoleMembersData>(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<GroupRolesData> 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<GroupRolesData>)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<GroupRolesData>)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<ExtendedGroupNoticeData> 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<ExtendedGroupNoticeData>)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<ExtendedGroupNoticeData>)notices;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Thread.Sleep(50);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -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<IGroupsData>(dllName, new Object[] { connString, realm });
|
||||||
|
if (m_Database == null)
|
||||||
|
throw new Exception("Could not find a storage interface in the given module " + dllName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<string, string>();
|
||||||
|
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<string, string>();
|
||||||
|
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<ExtendedGroupMembersData> GetGroupMembers(string RequestingAgentID, UUID GroupID, string token)
|
||||||
|
{
|
||||||
|
if (!VerifyToken(GroupID, RequestingAgentID, token))
|
||||||
|
return new List<ExtendedGroupMembersData>();
|
||||||
|
|
||||||
|
List<ExtendedGroupMembersData> 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<GroupRolesData> GetGroupRoles(string RequestingAgentID, UUID GroupID, string token)
|
||||||
|
{
|
||||||
|
if (!VerifyToken(GroupID, RequestingAgentID, token))
|
||||||
|
return new List<GroupRolesData>();
|
||||||
|
|
||||||
|
return GetGroupRoles(RequestingAgentID, GroupID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ExtendedGroupRoleMembersData> GetGroupRoleMembers(string RequestingAgentID, UUID GroupID, string token)
|
||||||
|
{
|
||||||
|
if (!VerifyToken(GroupID, RequestingAgentID, token))
|
||||||
|
return new List<ExtendedGroupRoleMembersData>();
|
||||||
|
|
||||||
|
List<ExtendedGroupRoleMembersData> 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<string, string>();
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,144 @@
|
||||||
|
/*
|
||||||
|
* 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.Data
|
||||||
|
{
|
||||||
|
public class GroupData
|
||||||
|
{
|
||||||
|
public UUID GroupID;
|
||||||
|
public Dictionary<string, string> Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MembershipData
|
||||||
|
{
|
||||||
|
public UUID GroupID;
|
||||||
|
public string PrincipalID;
|
||||||
|
public Dictionary<string, string> Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class RoleData
|
||||||
|
{
|
||||||
|
public UUID GroupID;
|
||||||
|
public UUID RoleID;
|
||||||
|
public Dictionary<string, string> Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class RoleMembershipData
|
||||||
|
{
|
||||||
|
public UUID GroupID;
|
||||||
|
public UUID RoleID;
|
||||||
|
public string PrincipalID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PrincipalData
|
||||||
|
{
|
||||||
|
public string PrincipalID;
|
||||||
|
public UUID ActiveGroupID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class InvitationData
|
||||||
|
{
|
||||||
|
public UUID InviteID;
|
||||||
|
public UUID GroupID;
|
||||||
|
public UUID RoleID;
|
||||||
|
public string PrincipalID;
|
||||||
|
public Dictionary<string, string> Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class NoticeData
|
||||||
|
{
|
||||||
|
public UUID GroupID;
|
||||||
|
public UUID NoticeID;
|
||||||
|
public Dictionary<string, string> Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public interface IGroupsData
|
||||||
|
{
|
||||||
|
// groups table
|
||||||
|
bool StoreGroup(GroupData data);
|
||||||
|
GroupData RetrieveGroup(UUID groupID);
|
||||||
|
GroupData RetrieveGroup(string name);
|
||||||
|
GroupData[] RetrieveGroups(string pattern);
|
||||||
|
bool DeleteGroup(UUID groupID);
|
||||||
|
int GroupsCount();
|
||||||
|
|
||||||
|
// membership table
|
||||||
|
MembershipData RetrieveMember(UUID groupID, string pricipalID);
|
||||||
|
MembershipData[] RetrieveMembers(UUID groupID);
|
||||||
|
MembershipData[] RetrieveMemberships(string pricipalID);
|
||||||
|
bool StoreMember(MembershipData data);
|
||||||
|
bool DeleteMember(UUID groupID, string pricipalID);
|
||||||
|
int MemberCount(UUID groupID);
|
||||||
|
|
||||||
|
// roles table
|
||||||
|
bool StoreRole(RoleData data);
|
||||||
|
RoleData RetrieveRole(UUID groupID, UUID roleID);
|
||||||
|
RoleData[] RetrieveRoles(UUID groupID);
|
||||||
|
bool DeleteRole(UUID groupID, UUID roleID);
|
||||||
|
int RoleCount(UUID groupID);
|
||||||
|
|
||||||
|
// rolememberhip table
|
||||||
|
RoleMembershipData[] RetrieveRolesMembers(UUID groupID);
|
||||||
|
RoleMembershipData[] RetrieveRoleMembers(UUID groupID, UUID roleID);
|
||||||
|
RoleMembershipData[] RetrieveMemberRoles(UUID groupID, string principalID);
|
||||||
|
RoleMembershipData RetrieveRoleMember(UUID groupID, UUID roleID, string principalID);
|
||||||
|
int RoleMemberCount(UUID groupID, UUID roleID);
|
||||||
|
bool StoreRoleMember(RoleMembershipData data);
|
||||||
|
bool DeleteRoleMember(RoleMembershipData data);
|
||||||
|
bool DeleteMemberAllRoles(UUID groupID, string principalID);
|
||||||
|
|
||||||
|
// principals table
|
||||||
|
bool StorePrincipal(PrincipalData data);
|
||||||
|
PrincipalData RetrievePrincipal(string principalID);
|
||||||
|
bool DeletePrincipal(string principalID);
|
||||||
|
|
||||||
|
// invites table
|
||||||
|
bool StoreInvitation(InvitationData data);
|
||||||
|
InvitationData RetrieveInvitation(UUID inviteID);
|
||||||
|
InvitationData RetrieveInvitation(UUID groupID, string principalID);
|
||||||
|
bool DeleteInvite(UUID inviteID);
|
||||||
|
void DeleteOldInvites();
|
||||||
|
|
||||||
|
// notices table
|
||||||
|
bool StoreNotice(NoticeData data);
|
||||||
|
NoticeData RetrieveNotice(UUID noticeID);
|
||||||
|
NoticeData[] RetrieveNotices(UUID groupID);
|
||||||
|
bool DeleteNotice(UUID noticeID);
|
||||||
|
void DeleteOldNotices();
|
||||||
|
|
||||||
|
// combinations
|
||||||
|
MembershipData RetrievePrincipalGroupMembership(string principalID, UUID groupID);
|
||||||
|
MembershipData[] RetrievePrincipalGroupMemberships(string principalID);
|
||||||
|
|
||||||
|
// Misc
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,484 @@
|
||||||
|
/*
|
||||||
|
* 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.Data.MySQL
|
||||||
|
{
|
||||||
|
public class MySQLGroupsData : IGroupsData
|
||||||
|
{
|
||||||
|
private MySqlGroupsGroupsHandler m_Groups;
|
||||||
|
private MySqlGroupsMembershipHandler m_Membership;
|
||||||
|
private MySqlGroupsRolesHandler m_Roles;
|
||||||
|
private MySqlGroupsRoleMembershipHandler m_RoleMembership;
|
||||||
|
private MySqlGroupsInvitesHandler m_Invites;
|
||||||
|
private MySqlGroupsNoticesHandler m_Notices;
|
||||||
|
private MySqlGroupsPrincipalsHandler m_Principals;
|
||||||
|
|
||||||
|
public MySQLGroupsData(string connectionString, string realm)
|
||||||
|
{
|
||||||
|
m_Groups = new MySqlGroupsGroupsHandler(connectionString, realm + "_groups", realm + "_Store");
|
||||||
|
m_Membership = new MySqlGroupsMembershipHandler(connectionString, realm + "_membership");
|
||||||
|
m_Roles = new MySqlGroupsRolesHandler(connectionString, realm + "_roles");
|
||||||
|
m_RoleMembership = new MySqlGroupsRoleMembershipHandler(connectionString, realm + "_rolemembership");
|
||||||
|
m_Invites = new MySqlGroupsInvitesHandler(connectionString, realm + "_invites");
|
||||||
|
m_Notices = new MySqlGroupsNoticesHandler(connectionString, realm + "_notices");
|
||||||
|
m_Principals = new MySqlGroupsPrincipalsHandler(connectionString, realm + "_principals");
|
||||||
|
}
|
||||||
|
|
||||||
|
#region groups table
|
||||||
|
public bool StoreGroup(GroupData data)
|
||||||
|
{
|
||||||
|
return m_Groups.Store(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupData RetrieveGroup(UUID groupID)
|
||||||
|
{
|
||||||
|
GroupData[] groups = m_Groups.Get("GroupID", groupID.ToString());
|
||||||
|
if (groups.Length > 0)
|
||||||
|
return groups[0];
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupData RetrieveGroup(string name)
|
||||||
|
{
|
||||||
|
GroupData[] groups = m_Groups.Get("Name", name);
|
||||||
|
if (groups.Length > 0)
|
||||||
|
return groups[0];
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupData[] RetrieveGroups(string pattern)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(pattern))
|
||||||
|
pattern = "1 ORDER BY Name LIMIT 100";
|
||||||
|
else
|
||||||
|
pattern = string.Format("Name LIKE %{0}% ORDER BY Name LIMIT 100", pattern);
|
||||||
|
|
||||||
|
return m_Groups.Get(pattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool DeleteGroup(UUID groupID)
|
||||||
|
{
|
||||||
|
return m_Groups.Delete("GroupID", groupID.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GroupsCount()
|
||||||
|
{
|
||||||
|
return (int)m_Groups.GetCount("Location=\"\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region membership table
|
||||||
|
public MembershipData[] RetrieveMembers(UUID groupID)
|
||||||
|
{
|
||||||
|
return m_Membership.Get("GroupID", groupID.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public MembershipData RetrieveMember(UUID groupID, string pricipalID)
|
||||||
|
{
|
||||||
|
MembershipData[] m = m_Membership.Get(new string[] { "GroupID", "PrincipalID" },
|
||||||
|
new string[] { groupID.ToString(), pricipalID });
|
||||||
|
if (m != null && m.Length > 0)
|
||||||
|
return m[0];
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MembershipData[] RetrieveMemberships(string pricipalID)
|
||||||
|
{
|
||||||
|
return m_Membership.Get("PrincipalID", pricipalID.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool StoreMember(MembershipData data)
|
||||||
|
{
|
||||||
|
return m_Membership.Store(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool DeleteMember(UUID groupID, string pricipalID)
|
||||||
|
{
|
||||||
|
return m_Membership.Delete(new string[] { "GroupID", "PrincipalID" },
|
||||||
|
new string[] { groupID.ToString(), pricipalID });
|
||||||
|
}
|
||||||
|
|
||||||
|
public int MemberCount(UUID groupID)
|
||||||
|
{
|
||||||
|
return (int)m_Membership.GetCount("GroupID", groupID.ToString());
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region roles table
|
||||||
|
public bool StoreRole(RoleData data)
|
||||||
|
{
|
||||||
|
return m_Roles.Store(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RoleData RetrieveRole(UUID groupID, UUID roleID)
|
||||||
|
{
|
||||||
|
RoleData[] data = m_Roles.Get(new string[] { "GroupID", "RoleID" },
|
||||||
|
new string[] { groupID.ToString(), roleID.ToString() });
|
||||||
|
|
||||||
|
if (data != null && data.Length > 0)
|
||||||
|
return data[0];
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RoleData[] RetrieveRoles(UUID groupID)
|
||||||
|
{
|
||||||
|
//return m_Roles.RetrieveRoles(groupID);
|
||||||
|
return m_Roles.Get("GroupID", groupID.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool DeleteRole(UUID groupID, UUID roleID)
|
||||||
|
{
|
||||||
|
return m_Roles.Delete(new string[] { "GroupID", "RoleID" },
|
||||||
|
new string[] { groupID.ToString(), roleID.ToString() });
|
||||||
|
}
|
||||||
|
|
||||||
|
public int RoleCount(UUID groupID)
|
||||||
|
{
|
||||||
|
return (int)m_Roles.GetCount("GroupID", groupID.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region rolememberhip table
|
||||||
|
public RoleMembershipData[] RetrieveRolesMembers(UUID groupID)
|
||||||
|
{
|
||||||
|
RoleMembershipData[] data = m_RoleMembership.Get("GroupID", groupID.ToString());
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RoleMembershipData[] RetrieveRoleMembers(UUID groupID, UUID roleID)
|
||||||
|
{
|
||||||
|
RoleMembershipData[] data = m_RoleMembership.Get(new string[] { "GroupID", "RoleID" },
|
||||||
|
new string[] { groupID.ToString(), roleID.ToString() });
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RoleMembershipData[] RetrieveMemberRoles(UUID groupID, string principalID)
|
||||||
|
{
|
||||||
|
RoleMembershipData[] data = m_RoleMembership.Get(new string[] { "GroupID", "PrincipalID" },
|
||||||
|
new string[] { groupID.ToString(), principalID.ToString() });
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RoleMembershipData RetrieveRoleMember(UUID groupID, UUID roleID, string principalID)
|
||||||
|
{
|
||||||
|
RoleMembershipData[] data = m_RoleMembership.Get(new string[] { "GroupID", "RoleID", "PrincipalID" },
|
||||||
|
new string[] { groupID.ToString(), roleID.ToString(), principalID.ToString() });
|
||||||
|
|
||||||
|
if (data != null && data.Length > 0)
|
||||||
|
return data[0];
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int RoleMemberCount(UUID groupID, UUID roleID)
|
||||||
|
{
|
||||||
|
return (int)m_RoleMembership.GetCount(new string[] { "GroupID", "RoleID" },
|
||||||
|
new string[] { groupID.ToString(), roleID.ToString() });
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool StoreRoleMember(RoleMembershipData data)
|
||||||
|
{
|
||||||
|
return m_RoleMembership.Store(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool DeleteRoleMember(RoleMembershipData data)
|
||||||
|
{
|
||||||
|
return m_RoleMembership.Delete(new string[] { "GroupID", "RoleID", "PrincipalID"},
|
||||||
|
new string[] { data.GroupID.ToString(), data.RoleID.ToString(), data.PrincipalID });
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool DeleteMemberAllRoles(UUID groupID, string principalID)
|
||||||
|
{
|
||||||
|
return m_RoleMembership.Delete(new string[] { "GroupID", "PrincipalID" },
|
||||||
|
new string[] { groupID.ToString(), principalID });
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region principals table
|
||||||
|
public bool StorePrincipal(PrincipalData data)
|
||||||
|
{
|
||||||
|
return m_Principals.Store(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PrincipalData RetrievePrincipal(string principalID)
|
||||||
|
{
|
||||||
|
PrincipalData[] p = m_Principals.Get("PrincipalID", principalID);
|
||||||
|
if (p != null && p.Length > 0)
|
||||||
|
return p[0];
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool DeletePrincipal(string principalID)
|
||||||
|
{
|
||||||
|
return m_Principals.Delete("PrincipalID", principalID);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region invites table
|
||||||
|
|
||||||
|
public bool StoreInvitation(InvitationData data)
|
||||||
|
{
|
||||||
|
return m_Invites.Store(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public InvitationData RetrieveInvitation(UUID inviteID)
|
||||||
|
{
|
||||||
|
InvitationData[] invites = m_Invites.Get("InviteID", inviteID.ToString());
|
||||||
|
|
||||||
|
if (invites != null && invites.Length > 0)
|
||||||
|
return invites[0];
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InvitationData RetrieveInvitation(UUID groupID, string principalID)
|
||||||
|
{
|
||||||
|
InvitationData[] invites = m_Invites.Get(new string[] { "GroupID", "PrincipalID" },
|
||||||
|
new string[] { groupID.ToString(), principalID });
|
||||||
|
|
||||||
|
if (invites != null && invites.Length > 0)
|
||||||
|
return invites[0];
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool DeleteInvite(UUID inviteID)
|
||||||
|
{
|
||||||
|
return m_Invites.Delete("InviteID", inviteID.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DeleteOldInvites()
|
||||||
|
{
|
||||||
|
m_Invites.DeleteOld();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region notices table
|
||||||
|
|
||||||
|
public bool StoreNotice(NoticeData data)
|
||||||
|
{
|
||||||
|
return m_Notices.Store(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public NoticeData RetrieveNotice(UUID noticeID)
|
||||||
|
{
|
||||||
|
NoticeData[] notices = m_Notices.Get("NoticeID", noticeID.ToString());
|
||||||
|
|
||||||
|
if (notices != null && notices.Length > 0)
|
||||||
|
return notices[0];
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NoticeData[] RetrieveNotices(UUID groupID)
|
||||||
|
{
|
||||||
|
NoticeData[] notices = m_Notices.Get("GroupID", groupID.ToString());
|
||||||
|
|
||||||
|
return notices;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool DeleteNotice(UUID noticeID)
|
||||||
|
{
|
||||||
|
return m_Notices.Delete("NoticeID", noticeID.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DeleteOldNotices()
|
||||||
|
{
|
||||||
|
m_Notices.DeleteOld();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region combinations
|
||||||
|
public MembershipData RetrievePrincipalGroupMembership(string principalID, UUID groupID)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
public MembershipData[] RetrievePrincipalGroupMemberships(string principalID)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MySqlGroupsGroupsHandler : MySQLGenericTableHandler<GroupData>
|
||||||
|
{
|
||||||
|
protected override Assembly Assembly
|
||||||
|
{
|
||||||
|
// WARNING! Moving migrations to this assembly!!!
|
||||||
|
get { return GetType().Assembly; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public MySqlGroupsGroupsHandler(string connectionString, string realm, string store)
|
||||||
|
: base(connectionString, realm, store)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MySqlGroupsMembershipHandler : MySQLGenericTableHandler<MembershipData>
|
||||||
|
{
|
||||||
|
protected override Assembly Assembly
|
||||||
|
{
|
||||||
|
// WARNING! Moving migrations to this assembly!!!
|
||||||
|
get { return GetType().Assembly; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public MySqlGroupsMembershipHandler(string connectionString, string realm)
|
||||||
|
: base(connectionString, realm, string.Empty)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MySqlGroupsRolesHandler : MySQLGenericTableHandler<RoleData>
|
||||||
|
{
|
||||||
|
protected override Assembly Assembly
|
||||||
|
{
|
||||||
|
// WARNING! Moving migrations to this assembly!!!
|
||||||
|
get { return GetType().Assembly; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public MySqlGroupsRolesHandler(string connectionString, string realm)
|
||||||
|
: base(connectionString, realm, string.Empty)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MySqlGroupsRoleMembershipHandler : MySQLGenericTableHandler<RoleMembershipData>
|
||||||
|
{
|
||||||
|
protected override Assembly Assembly
|
||||||
|
{
|
||||||
|
// WARNING! Moving migrations to this assembly!!!
|
||||||
|
get { return GetType().Assembly; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public MySqlGroupsRoleMembershipHandler(string connectionString, string realm)
|
||||||
|
: base(connectionString, realm, string.Empty)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MySqlGroupsInvitesHandler : MySQLGenericTableHandler<InvitationData>
|
||||||
|
{
|
||||||
|
protected override Assembly Assembly
|
||||||
|
{
|
||||||
|
// WARNING! Moving migrations to this assembly!!!
|
||||||
|
get { return GetType().Assembly; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public MySqlGroupsInvitesHandler(string connectionString, string realm)
|
||||||
|
: base(connectionString, realm, string.Empty)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MySqlGroupsNoticesHandler : MySQLGenericTableHandler<NoticeData>
|
||||||
|
{
|
||||||
|
protected override Assembly Assembly
|
||||||
|
{
|
||||||
|
// WARNING! Moving migrations to this assembly!!!
|
||||||
|
get { return GetType().Assembly; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public MySqlGroupsNoticesHandler(string connectionString, string realm)
|
||||||
|
: base(connectionString, realm, string.Empty)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MySqlGroupsPrincipalsHandler : MySQLGenericTableHandler<PrincipalData>
|
||||||
|
{
|
||||||
|
protected override Assembly Assembly
|
||||||
|
{
|
||||||
|
// WARNING! Moving migrations to this assembly!!!
|
||||||
|
get { return GetType().Assembly; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public MySqlGroupsPrincipalsHandler(string connectionString, string realm)
|
||||||
|
: base(connectionString, realm, string.Empty)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,115 @@
|
||||||
|
:VERSION 1 # --------------------------
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
|
||||||
|
CREATE TABLE `os_groups_groups` (
|
||||||
|
`GroupID` char(36) NOT NULL default '',
|
||||||
|
`Location` varchar(255) NOT NULL default '',
|
||||||
|
`Name` varchar(255) NOT NULL default '',
|
||||||
|
`Charter` text NOT NULL,
|
||||||
|
`InsigniaID` char(36) NOT NULL default '',
|
||||||
|
`FounderID` char(36) NOT NULL default '',
|
||||||
|
`MembershipFee` int(11) NOT NULL default '0',
|
||||||
|
`OpenEnrollment` varchar(255) NOT NULL default '',
|
||||||
|
`ShowInList` int(4) NOT NULL default '0',
|
||||||
|
`AllowPublish` int(4) NOT NULL default '0',
|
||||||
|
`MaturePublish` int(4) NOT NULL default '0',
|
||||||
|
`OwnerRoleID` char(36) NOT NULL default '',
|
||||||
|
PRIMARY KEY (`GroupID`),
|
||||||
|
UNIQUE KEY `Name` (`Name`),
|
||||||
|
FULLTEXT KEY `Name_2` (`Name`)
|
||||||
|
) ENGINE=MyISAM;
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE `os_groups_membership` (
|
||||||
|
`GroupID`char(36) NOT NULL default '',
|
||||||
|
`PrincipalID` VARCHAR(255) NOT NULL default '',
|
||||||
|
`SelectedRoleID` char(36) NOT NULL default '',
|
||||||
|
`Contribution` int(11) NOT NULL default '0',
|
||||||
|
`ListInProfile` int(4) NOT NULL default '1',
|
||||||
|
`AcceptNotices` int(4) NOT NULL default '1',
|
||||||
|
`AccessToken` char(36) NOT NULL default '',
|
||||||
|
PRIMARY KEY (`GroupID`,`PrincipalID`),
|
||||||
|
KEY `PrincipalID` (`PrincipalID`)
|
||||||
|
) ENGINE=MyISAM;
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE `os_groups_roles` (
|
||||||
|
`GroupID` char(36) NOT NULL default '',
|
||||||
|
`RoleID` char(36) NOT NULL default '',
|
||||||
|
`Name` varchar(255) NOT NULL default '',
|
||||||
|
`Description` varchar(255) NOT NULL default '',
|
||||||
|
`Title` varchar(255) NOT NULL default '',
|
||||||
|
`Powers` bigint(20) unsigned NOT NULL default '0',
|
||||||
|
PRIMARY KEY (`GroupID`,`RoleID`),
|
||||||
|
KEY `GroupID` (`GroupID`)
|
||||||
|
) ENGINE=MyISAM;
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE `os_groups_rolemembership` (
|
||||||
|
`GroupID` char(36) NOT NULL default '',
|
||||||
|
`RoleID` char(36) NOT NULL default '',
|
||||||
|
`PrincipalID` VARCHAR(255) NOT NULL default '',
|
||||||
|
PRIMARY KEY (`GroupID`,`RoleID`,`PrincipalID`),
|
||||||
|
KEY `PrincipalID` (`PrincipalID`)
|
||||||
|
) ENGINE=MyISAM;
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE `os_groups_invites` (
|
||||||
|
`InviteID` char(36) NOT NULL default '',
|
||||||
|
`GroupID` char(36) NOT NULL default '',
|
||||||
|
`RoleID` char(36) NOT NULL default '',
|
||||||
|
`PrincipalID` VARCHAR(255) NOT NULL default '',
|
||||||
|
`TMStamp` timestamp NOT NULL,
|
||||||
|
PRIMARY KEY (`InviteID`),
|
||||||
|
UNIQUE KEY `PrincipalGroup` (`GroupID`,`PrincipalID`)
|
||||||
|
) ENGINE=MyISAM;
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE `os_groups_notices` (
|
||||||
|
`GroupID` char(36) NOT NULL default '',
|
||||||
|
`NoticeID` char(36) NOT NULL default '',
|
||||||
|
`TMStamp` int(10) unsigned NOT NULL default '0',
|
||||||
|
`FromName` varchar(255) NOT NULL default '',
|
||||||
|
`Subject` varchar(255) NOT NULL default '',
|
||||||
|
`Message` text NOT NULL,
|
||||||
|
`HasAttachment` int(4) NOT NULL default '0',
|
||||||
|
`AttachmentType` int(4) NOT NULL default '0',
|
||||||
|
`AttachmentName` varchar(128) NOT NULL default '',
|
||||||
|
`AttachmentItemID` char(36) NOT NULL default '',
|
||||||
|
`AttachmentOwnerID` varchar(255) NOT NULL default '',
|
||||||
|
PRIMARY KEY (`NoticeID`),
|
||||||
|
KEY `GroupID` (`GroupID`),
|
||||||
|
KEY `TMStamp` (`TMStamp`)
|
||||||
|
) ENGINE=MyISAM;
|
||||||
|
|
||||||
|
CREATE TABLE `os_groups_principals` (
|
||||||
|
`PrincipalID` VARCHAR(255) NOT NULL default '',
|
||||||
|
`ActiveGroupID` char(36) NOT NULL default '',
|
||||||
|
PRIMARY KEY (`PrincipalID`)
|
||||||
|
) ENGINE=MyISAM;
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
|
:VERSION 2 # --------------------------
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
|
||||||
|
INSERT INTO `os_groups_groups` SELECT * from `diva_groups_groups`;
|
||||||
|
DROP TABLE `diva_groups_groups`;
|
||||||
|
INSERT INTO `os_groups_membership` SELECT * from `diva_groups_membership`;
|
||||||
|
DROP TABLE `diva_groups_membership`;
|
||||||
|
INSERT INTO `os_groups_roles` SELECT * from `diva_groups_roles`;
|
||||||
|
DROP TABLE `diva_groups_roles`;
|
||||||
|
INSERT INTO `os_groups_rolemembership` SELECT * from `diva_groups_rolemembership`;
|
||||||
|
DROP TABLE `diva_groups_rolemembership`;
|
||||||
|
INSERT INTO `os_groups_invites` SELECT * from `diva_groups_invites`;
|
||||||
|
DROP TABLE `diva_groups_invites`;
|
||||||
|
INSERT INTO `os_groups_notices` SELECT * from `diva_groups_notices`;
|
||||||
|
DROP TABLE `diva_groups_notices`;
|
||||||
|
INSERT INTO `os_groups_principals` SELECT * from `diva_groups_principals`;
|
||||||
|
DROP TABLE `diva_groups_principals`;
|
||||||
|
|
||||||
|
DELETE FROM `migrations` WHERE name='diva_im_Store';
|
||||||
|
|
||||||
|
COMMIT;
|
|
@ -931,33 +931,47 @@
|
||||||
;; Enables the groups module
|
;; Enables the groups module
|
||||||
; Enabled = false
|
; Enabled = false
|
||||||
|
|
||||||
;# {Module} {Enabled:true} {Groups module to use? (Use GroupsModule to use Flotsam/Simian)} {} Default
|
;# {Module} {Enabled:true} {Groups module to use? (Use GroupsModule to use Flotsam/Simian)} {Default "Groups Module V2"} Default
|
||||||
;; This is the current groups stub in Region.CoreModules.Avatar.Groups.
|
;; The default module can use a PHP XmlRpc server from the Flotsam project at
|
||||||
;; All the other settings below only really apply to the Flotsam/SimianGrid
|
|
||||||
;; GroupsModule.
|
|
||||||
;; This module can use a PHP XmlRpc server from the Flotsam project at
|
|
||||||
;; http://code.google.com/p/flotsam/
|
;; http://code.google.com/p/flotsam/
|
||||||
;; or from the SimianGrid project at http://code.google.com/p/openmetaverse
|
;; or from the SimianGrid project at http://code.google.com/p/openmetaverse
|
||||||
; Module = Default
|
; Module = Default
|
||||||
|
;; or... use Groups Module V2, which works for standalones and robust grids
|
||||||
|
; Module = "Groups Module V2"
|
||||||
|
|
||||||
;# {MessagingEnabled} {Module:GroupsModule} {Is groups messaging enabled?} {true false} true
|
;# {StorageProvider} {Module:Groups Module V2} {The DLL that provides the storage for V2} {OpenSim.Data.MySQL.dll}
|
||||||
; MessagingEnabled = true
|
; StorageProvider = OpenSim.Data.MySQL.dll
|
||||||
|
|
||||||
;# {MessagingModule} {MessagingEnabled:true} {Module to use for groups messaging} {GroupsMessagingModule} GroupsMessagingModule
|
;# {ServicesConnectorModule} {Module:GroupsModule Module:Groups Module V2} {Service connector to use for groups} {XmlRpcGroupsServicesConnector SimianGroupsServicesConnector "Groups Local Service Connector" "Groups Remote Service Connector" "Groups HG Service Connector"} XmlRpcGroupsServicesConnector
|
||||||
; MessagingModule = GroupsMessagingModule
|
|
||||||
|
|
||||||
;# {ServicesConnectorModule} {Module:GroupsModule} {Service connector to use for groups} {XmlRpcGroupsServicesConnector SimianGroupsServicesConnector} XmlRpcGroupsServicesConnector
|
|
||||||
;; Service connectors to the Groups Service as used in the GroupsModule. Select one depending on
|
;; Service connectors to the Groups Service as used in the GroupsModule. Select one depending on
|
||||||
;; whether you're using a Flotsam XmlRpc backend or a SimianGrid backend
|
;; whether you're using a Flotsam XmlRpc backend or a SimianGrid backend or several flavours of V2, Hypergrided or not, standalone or grided.
|
||||||
; ServicesConnectorModule = XmlRpcGroupsServicesConnector
|
; ServicesConnectorModule = XmlRpcGroupsServicesConnector
|
||||||
|
|
||||||
;# {GroupsServerURI} {Module:GroupsModule} {Groups Server URI} {}
|
;# {LocalService} {ServicesConnectorModule:Groups HG Service Connector} {Is the group service in this process or elsewhere?} {local remote} local
|
||||||
;; URI for the groups services
|
;; Used for V2 in HG only. If standalone, set this to local; if grided sim, set this to remote
|
||||||
|
; LocalService = local
|
||||||
|
|
||||||
|
;# {GroupsServerURI} {Module:GroupsModule (ServicesConnectorModule:Groups Remote Service Connector or (ServicesConnectorModule:Groups HG Service Connector and LocalService:remote))} {Groups Server URI} {}
|
||||||
|
;; URI for the groups services of this grid
|
||||||
;; e.g. http://yourxmlrpcserver.com/xmlrpc.php for Flotsam XmlRpc
|
;; e.g. http://yourxmlrpcserver.com/xmlrpc.php for Flotsam XmlRpc
|
||||||
;; or http://mygridserver.com:82/Grid/ for SimianGrid
|
;; or http://mygridserver.com:82/Grid/ for SimianGrid
|
||||||
|
;; or http:://mygridserver.com:8003 for robust, V2
|
||||||
; GroupsServerURI = ""
|
; GroupsServerURI = ""
|
||||||
|
|
||||||
;# {NoticesEnabled} {Module:GroupsModule} {Enable group notices?} {true false} true
|
;# {HomeURI} {ServicesConnectorModule:Groups HG Service Connector} {What's the home address of this world?} {}
|
||||||
|
;; Used for V2 in HG only. For example
|
||||||
|
;; http://mygridserver.com:9000 or http://mygridserver.com:8002
|
||||||
|
; HomeURI = ""
|
||||||
|
|
||||||
|
;# {MessagingEnabled} {Module:GroupsModule Module:Groups Module V2} {Is groups messaging enabled?} {true false} true
|
||||||
|
; MessagingEnabled = true
|
||||||
|
|
||||||
|
;# {MessagingModule} {MessagingEnabled:true} {Module to use for groups messaging} {GroupsMessagingModule "Groups Messaging Module V2"} GroupsMessagingModule
|
||||||
|
; MessagingModule = GroupsMessagingModule
|
||||||
|
;; or use V2 for Groups V2
|
||||||
|
; MessagingModule = "Groups Messaging Module V2"
|
||||||
|
|
||||||
|
;# {NoticesEnabled} {Module:GroupsModule Module:Groups Module V2} {Enable group notices?} {true false} true
|
||||||
;; Enable Group Notices
|
;; Enable Group Notices
|
||||||
; NoticesEnabled = true
|
; NoticesEnabled = true
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,8 @@ MapAddServiceConnector = "8003/OpenSim.Server.Handlers.dll:MapAddServiceConnecto
|
||||||
MapGetServiceConnector = "8002/OpenSim.Server.Handlers.dll:MapGetServiceConnector"
|
MapGetServiceConnector = "8002/OpenSim.Server.Handlers.dll:MapGetServiceConnector"
|
||||||
;; Uncomment this if you want offline IM to work
|
;; Uncomment this if you want offline IM to work
|
||||||
;OfflineIMServiceConnector = "8003/OpenSim.Addons.OfflineIM.dll:OfflineIMServiceRobustConnector"
|
;OfflineIMServiceConnector = "8003/OpenSim.Addons.OfflineIM.dll:OfflineIMServiceRobustConnector"
|
||||||
|
;; Uncomment this if you want Groups V2 to work
|
||||||
|
;GroupsServiceConnector = "8003/OpenSim.Addons.Groups.dll:GroupsServiceRobustConnector"
|
||||||
|
|
||||||
;; Additions for Hypergrid
|
;; Additions for Hypergrid
|
||||||
|
|
||||||
|
@ -63,6 +65,8 @@ HGFriendsServerConnector = "8002/OpenSim.Server.Handlers.dll:HGFriendsServerConn
|
||||||
InstantMessageServerConnector = "8002/OpenSim.Server.Handlers.dll:InstantMessageServerConnector"
|
InstantMessageServerConnector = "8002/OpenSim.Server.Handlers.dll:InstantMessageServerConnector"
|
||||||
HGInventoryServiceConnector = "HGInventoryService@8002/OpenSim.Server.Handlers.dll:XInventoryInConnector"
|
HGInventoryServiceConnector = "HGInventoryService@8002/OpenSim.Server.Handlers.dll:XInventoryInConnector"
|
||||||
HGAssetServiceConnector = "HGAssetService@8002/OpenSim.Server.Handlers.dll:AssetServiceConnector"
|
HGAssetServiceConnector = "HGAssetService@8002/OpenSim.Server.Handlers.dll:AssetServiceConnector"
|
||||||
|
;; Uncomment this if you want Groups V2, HG to work
|
||||||
|
;HGGroupsServiceConnector = "8002/Diva.Groups.dll:HGGroupsServiceRobustConnector"
|
||||||
|
|
||||||
;; Additions for other add-on modules. For example:
|
;; Additions for other add-on modules. For example:
|
||||||
;; WifiServerConnector = "8002/Diva.Wifi.dll:WifiServerConnector"
|
;; WifiServerConnector = "8002/Diva.Wifi.dll:WifiServerConnector"
|
||||||
|
@ -550,3 +554,9 @@ HGAssetServiceConnector = "HGAssetService@8002/OpenSim.Server.Handlers.dll:Asset
|
||||||
; OfflineIM
|
; OfflineIM
|
||||||
OfflineIMService = "OpenSim.Addons.OfflineIM.dll:OfflineIMService"
|
OfflineIMService = "OpenSim.Addons.OfflineIM.dll:OfflineIMService"
|
||||||
|
|
||||||
|
[Groups]
|
||||||
|
;; for the HG Groups service
|
||||||
|
OfflineIMService = "OpenSim.Addons.OfflineIM.dll:OfflineIMService"
|
||||||
|
; What is the HomeURI of users associated with this grid?
|
||||||
|
HomeURI = "http://127.0.0.1:8002"
|
||||||
|
UserAccountService = "OpenSim.Services.UserAccountService.dll:UserAccountService"
|
||||||
|
|
|
@ -45,6 +45,8 @@ MapAddServiceConnector = "8003/OpenSim.Server.Handlers.dll:MapAddServiceConnecto
|
||||||
MapGetServiceConnector = "8002/OpenSim.Server.Handlers.dll:MapGetServiceConnector"
|
MapGetServiceConnector = "8002/OpenSim.Server.Handlers.dll:MapGetServiceConnector"
|
||||||
;; Uncomment this if you want offline IM to work
|
;; Uncomment this if you want offline IM to work
|
||||||
;OfflineIMServiceConnector = "8003/OpenSim.Addons.OfflineIM.dll:OfflineIMServiceRobustConnector"
|
;OfflineIMServiceConnector = "8003/OpenSim.Addons.OfflineIM.dll:OfflineIMServiceRobustConnector"
|
||||||
|
;; Uncomment this if you want Groups V2 to work
|
||||||
|
;GroupsServiceConnector = "8003/OpenSim.Addons.Groups.dll:GroupsServiceRobustConnector"
|
||||||
|
|
||||||
|
|
||||||
; * This is common for all services, it's the network setup for the entire
|
; * This is common for all services, it's the network setup for the entire
|
||||||
|
|
48
prebuild.xml
48
prebuild.xml
|
@ -2571,6 +2571,54 @@
|
||||||
</Files>
|
</Files>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
||||||
|
<Project frameworkVersion="v3_5" name="OpenSim.Addons.Groups" path="OpenSim/Addons/Groups" type="Library">
|
||||||
|
<Configuration name="Debug">
|
||||||
|
<Options>
|
||||||
|
<OutputPath>../../../bin/</OutputPath>
|
||||||
|
</Options>
|
||||||
|
</Configuration>
|
||||||
|
<Configuration name="Release">
|
||||||
|
<Options>
|
||||||
|
<OutputPath>../../../bin/</OutputPath>
|
||||||
|
</Options>
|
||||||
|
</Configuration>
|
||||||
|
|
||||||
|
<ReferencePath>../../bin/</ReferencePath>
|
||||||
|
<Reference name="System"/>
|
||||||
|
<Reference name="System.Core"/>
|
||||||
|
<Reference name="System.Data"/>
|
||||||
|
<Reference name="System.Web"/>
|
||||||
|
<Reference name="System.Xml"/>
|
||||||
|
|
||||||
|
<Reference name="Nini" path="../../../bin/"/>
|
||||||
|
<Reference name="Mono.Addins" path="../../../bin/"/>
|
||||||
|
<Reference name="log4net" path="../../../bin/"/>
|
||||||
|
<Reference name="OpenMetaverse" path="../../../bin/"/>
|
||||||
|
<Reference name="OpenMetaverseTypes" path="../../../bin/"/>
|
||||||
|
<Reference name="OpenMetaverse.StructuredData" path="../../../bin/"/>
|
||||||
|
|
||||||
|
<Reference name="OpenSim.Framework"/>
|
||||||
|
<Reference name="OpenSim.Data"/>
|
||||||
|
<Reference name="OpenSim.Framework.Servers"/>
|
||||||
|
<Reference name="OpenSim.Framework.Servers.HttpServer"/>
|
||||||
|
<Reference name="OpenSim.Services.Base"/>
|
||||||
|
<Reference name="OpenSim.Services.Interfaces"/>
|
||||||
|
<Reference name="OpenSim.Region.Framework"/>
|
||||||
|
<Reference name="OpenSim.Server.Base"/>
|
||||||
|
<Reference name="OpenSim.Server.Handlers"/>
|
||||||
|
|
||||||
|
<!-- To allow regions to have mono addins -->
|
||||||
|
<Reference name="Mono.Addins" path="../../../bin/" />
|
||||||
|
|
||||||
|
<Files>
|
||||||
|
<Match pattern="*.cs" recurse="true">
|
||||||
|
<Exclude pattern="Tests" />
|
||||||
|
</Match>
|
||||||
|
<Match buildAction="EmbeddedResource" path="Resources" pattern="*.migrations"/>
|
||||||
|
</Files>
|
||||||
|
|
||||||
|
</Project>
|
||||||
|
|
||||||
|
|
||||||
<!-- Tools -->
|
<!-- Tools -->
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue