OpenSim
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros
XmlRpcGroupsServicesConnectorModule.cs
Go to the documentation of this file.
1 /*
2  * Copyright (c) Contributors, http://opensimulator.org/
3  * See CONTRIBUTORS.TXT for a full list of copyright holders.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of the OpenSimulator Project nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 using System;
29 using System.Collections;
30 using System.Collections.Generic;
31 using System.Reflection;
32 using System.Text;
33 
34 using Nwc.XmlRpc;
35 
36 using log4net;
37 using Mono.Addins;
38 using Nini.Config;
39 
40 using OpenMetaverse;
41 using OpenMetaverse.StructuredData;
42 
43 using OpenSim.Framework;
44 using OpenSim.Region.Framework.Interfaces;
45 using OpenSim.Services.Interfaces;
46 
47 namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
48 {
49  [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "XmlRpcGroupsServicesConnectorModule")]
51  {
52  private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53 
54  private bool m_debugEnabled = false;
55 
56  public const GroupPowers DefaultEveryonePowers
57  = GroupPowers.AllowSetHome
58  | GroupPowers.Accountable
59  | GroupPowers.JoinChat
60  | GroupPowers.AllowVoiceChat
61  | GroupPowers.ReceiveNotices
62  | GroupPowers.StartProposal
63  | GroupPowers.VoteOnProposal;
64 
65  // Would this be cleaner as (GroupPowers)ulong.MaxValue?
66  public const GroupPowers DefaultOwnerPowers
67  = GroupPowers.Accountable
68  | GroupPowers.AllowEditLand
69  | GroupPowers.AllowFly
70  | GroupPowers.AllowLandmark
71  | GroupPowers.AllowRez
72  | GroupPowers.AllowSetHome
73  | GroupPowers.AllowVoiceChat
74  | GroupPowers.AssignMember
75  | GroupPowers.AssignMemberLimited
76  | GroupPowers.ChangeActions
77  | GroupPowers.ChangeIdentity
78  | GroupPowers.ChangeMedia
79  | GroupPowers.ChangeOptions
80  | GroupPowers.CreateRole
81  | GroupPowers.DeedObject
82  | GroupPowers.DeleteRole
83  | GroupPowers.Eject
84  | GroupPowers.FindPlaces
85  | GroupPowers.Invite
86  | GroupPowers.JoinChat
87  | GroupPowers.LandChangeIdentity
88  | GroupPowers.LandDeed
89  | GroupPowers.LandDivideJoin
90  | GroupPowers.LandEdit
91  | GroupPowers.LandEjectAndFreeze
92  | GroupPowers.LandGardening
93  | GroupPowers.LandManageAllowed
94  | GroupPowers.LandManageBanned
95  | GroupPowers.LandManagePasses
96  | GroupPowers.LandOptions
97  | GroupPowers.LandRelease
98  | GroupPowers.LandSetSale
99  | GroupPowers.ModerateChat
100  | GroupPowers.ObjectManipulate
101  | GroupPowers.ObjectSetForSale
102  | GroupPowers.ReceiveNotices
103  | GroupPowers.RemoveMember
104  | GroupPowers.ReturnGroupOwned
105  | GroupPowers.ReturnGroupSet
106  | GroupPowers.ReturnNonGroup
107  | GroupPowers.RoleProperties
108  | GroupPowers.SendNotices
109  | GroupPowers.SetLandingPoint
110  | GroupPowers.StartProposal
111  | GroupPowers.VoteOnProposal;
112 
113  private bool m_connectorEnabled = false;
114 
115  private string m_groupsServerURI = string.Empty;
116 
117  private bool m_disableKeepAlive = true;
118 
119  private string m_groupReadKey = string.Empty;
120  private string m_groupWriteKey = string.Empty;
121 
122  private IUserAccountService m_accountService = null;
123 
124  private ExpiringCache<string, XmlRpcResponse> m_memoryCache;
125  private int m_cacheTimeout = 30;
126 
127  // Used to track which agents are have dropped from a group chat session
128  // Should be reset per agent, on logon
129  // TODO: move this to Flotsam XmlRpc Service
130  // SessionID, List<AgentID>
131  private Dictionary<UUID, List<UUID>> m_groupsAgentsDroppedFromChatSession = new Dictionary<UUID, List<UUID>>();
132  private Dictionary<UUID, List<UUID>> m_groupsAgentsInvitedToChatSession = new Dictionary<UUID, List<UUID>>();
133 
134  #region Region Module interfaceBase Members
135 
136  public string Name
137  {
138  get { return "XmlRpcGroupsServicesConnector"; }
139  }
140 
141  // this module is not intended to be replaced, but there should only be 1 of them.
142  public Type ReplaceableInterface
143  {
144  get { return null; }
145  }
146 
147  public void Initialise(IConfigSource config)
148  {
149  IConfig groupsConfig = config.Configs["Groups"];
150 
151  if (groupsConfig == null)
152  {
153  // Do not run this module by default.
154  return;
155  }
156  else
157  {
158  // if groups aren't enabled, we're not needed.
159  // if we're not specified as the connector to use, then we're not wanted
160  if ((groupsConfig.GetBoolean("Enabled", false) == false)
161  || (groupsConfig.GetString("ServicesConnectorModule", "XmlRpcGroupsServicesConnector") != Name))
162  {
163  m_connectorEnabled = false;
164  return;
165  }
166 
167  m_log.DebugFormat("[XMLRPC-GROUPS-CONNECTOR]: Initializing {0}", this.Name);
168 
169  m_groupsServerURI = groupsConfig.GetString("GroupsServerURI", string.Empty);
170  if (string.IsNullOrEmpty(m_groupsServerURI))
171  {
172  m_log.ErrorFormat("Please specify a valid URL for GroupsServerURI in OpenSim.ini, [Groups]");
173  m_connectorEnabled = false;
174  return;
175  }
176 
177  m_disableKeepAlive = groupsConfig.GetBoolean("XmlRpcDisableKeepAlive", true);
178 
179  m_groupReadKey = groupsConfig.GetString("XmlRpcServiceReadKey", string.Empty);
180  m_groupWriteKey = groupsConfig.GetString("XmlRpcServiceWriteKey", string.Empty);
181 
182  m_cacheTimeout = groupsConfig.GetInt("GroupsCacheTimeout", 30);
183  if (m_cacheTimeout == 0)
184  {
185  m_log.WarnFormat("[XMLRPC-GROUPS-CONNECTOR]: Groups Cache Disabled.");
186  }
187  else
188  {
189  m_log.InfoFormat("[XMLRPC-GROUPS-CONNECTOR]: Groups Cache Timeout set to {0}.", m_cacheTimeout);
190  }
191 
192  m_debugEnabled = groupsConfig.GetBoolean("DebugEnabled", false);
193 
194  // If we got all the config options we need, lets start'er'up
195  m_memoryCache = new ExpiringCache<string, XmlRpcResponse>();
196  m_connectorEnabled = true;
197  }
198  }
199 
200  public void Close()
201  {
202  m_log.DebugFormat("[XMLRPC-GROUPS-CONNECTOR]: Closing {0}", this.Name);
203  }
204 
205  public void AddRegion(OpenSim.Region.Framework.Scenes.Scene scene)
206  {
207  if (m_connectorEnabled)
208  {
209 
210  if (m_accountService == null)
211  {
212  m_accountService = scene.UserAccountService;
213  }
214 
215 
216  scene.RegisterModuleInterface<IGroupsServicesConnector>(this);
217  }
218  }
219 
220  public void RemoveRegion(OpenSim.Region.Framework.Scenes.Scene scene)
221  {
222  if (scene.RequestModuleInterface<IGroupsServicesConnector>() == this)
223  {
224  scene.UnregisterModuleInterface<IGroupsServicesConnector>(this);
225  }
226  }
227 
228  public void RegionLoaded(OpenSim.Region.Framework.Scenes.Scene scene)
229  {
230  // TODO: May want to consider listenning for Agent Connections so we can pre-cache group info
231  // scene.EventManager.OnNewClient += OnNewClient;
232  }
233 
234  #endregion
235 
236  #region ISharedRegionModule Members
237 
238  public void PostInitialise()
239  {
240  // NoOp
241  }
242 
243  #endregion
244 
245  #region IGroupsServicesConnector Members
246 
250  public UUID CreateGroup(UUID requestingAgentID, string name, string charter, bool showInList, UUID insigniaID,
251  int membershipFee, bool openEnrollment, bool allowPublish,
252  bool maturePublish, UUID founderID)
253  {
254  UUID GroupID = UUID.Random();
255  UUID OwnerRoleID = UUID.Random();
256 
257  Hashtable param = new Hashtable();
258  param["GroupID"] = GroupID.ToString();
259  param["Name"] = name;
260  param["Charter"] = charter;
261  param["ShowInList"] = showInList == true ? 1 : 0;
262  param["InsigniaID"] = insigniaID.ToString();
263  param["MembershipFee"] = membershipFee;
264  param["OpenEnrollment"] = openEnrollment == true ? 1 : 0;
265  param["AllowPublish"] = allowPublish == true ? 1 : 0;
266  param["MaturePublish"] = maturePublish == true ? 1 : 0;
267  param["FounderID"] = founderID.ToString();
268  param["EveryonePowers"] = ((ulong)DefaultEveryonePowers).ToString();
269  param["OwnerRoleID"] = OwnerRoleID.ToString();
270  param["OwnersPowers"] = ((ulong)DefaultOwnerPowers).ToString();
271 
272  Hashtable respData = XmlRpcCall(requestingAgentID, "groups.createGroup", param);
273 
274  if (respData.Contains("error"))
275  {
276  // UUID is not nullable
277 
278  return UUID.Zero;
279  }
280 
281  return UUID.Parse((string)respData["GroupID"]);
282  }
283 
284  public void UpdateGroup(UUID requestingAgentID, UUID groupID, string charter, bool showInList,
285  UUID insigniaID, int membershipFee, bool openEnrollment,
286  bool allowPublish, bool maturePublish)
287  {
288  Hashtable param = new Hashtable();
289  param["GroupID"] = groupID.ToString();
290  param["Charter"] = charter;
291  param["ShowInList"] = showInList == true ? 1 : 0;
292  param["InsigniaID"] = insigniaID.ToString();
293  param["MembershipFee"] = membershipFee;
294  param["OpenEnrollment"] = openEnrollment == true ? 1 : 0;
295  param["AllowPublish"] = allowPublish == true ? 1 : 0;
296  param["MaturePublish"] = maturePublish == true ? 1 : 0;
297 
298  XmlRpcCall(requestingAgentID, "groups.updateGroup", param);
299  }
300 
301  public void AddGroupRole(UUID requestingAgentID, UUID groupID, UUID roleID, string name, string description,
302  string title, ulong powers)
303  {
304  Hashtable param = new Hashtable();
305  param["GroupID"] = groupID.ToString();
306  param["RoleID"] = roleID.ToString();
307  param["Name"] = name;
308  param["Description"] = description;
309  param["Title"] = title;
310  param["Powers"] = powers.ToString();
311 
312  XmlRpcCall(requestingAgentID, "groups.addRoleToGroup", param);
313  }
314 
315  public void RemoveGroupRole(UUID requestingAgentID, UUID groupID, UUID roleID)
316  {
317  Hashtable param = new Hashtable();
318  param["GroupID"] = groupID.ToString();
319  param["RoleID"] = roleID.ToString();
320 
321  XmlRpcCall(requestingAgentID, "groups.removeRoleFromGroup", param);
322  }
323 
324  public void UpdateGroupRole(UUID requestingAgentID, UUID groupID, UUID roleID, string name, string description,
325  string title, ulong powers)
326  {
327  Hashtable param = new Hashtable();
328  param["GroupID"] = groupID.ToString();
329  param["RoleID"] = roleID.ToString();
330  if (name != null)
331  {
332  param["Name"] = name;
333  }
334  if (description != null)
335  {
336  param["Description"] = description;
337  }
338  if (title != null)
339  {
340  param["Title"] = title;
341  }
342  param["Powers"] = powers.ToString();
343 
344  XmlRpcCall(requestingAgentID, "groups.updateGroupRole", param);
345  }
346 
347  public GroupRecord GetGroupRecord(UUID requestingAgentID, UUID GroupID, string GroupName)
348  {
349  Hashtable param = new Hashtable();
350  if (GroupID != UUID.Zero)
351  {
352  param["GroupID"] = GroupID.ToString();
353  }
354  if (!string.IsNullOrEmpty(GroupName))
355  {
356  param["Name"] = GroupName.ToString();
357  }
358 
359  Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getGroup", param);
360 
361  if (respData.Contains("error"))
362  {
363  return null;
364  }
365 
366  return GroupProfileHashtableToGroupRecord(respData);
367 
368  }
369 
370  public GroupProfileData GetMemberGroupProfile(UUID requestingAgentID, UUID GroupID, UUID AgentID)
371  {
372  Hashtable param = new Hashtable();
373  param["GroupID"] = GroupID.ToString();
374 
375  Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getGroup", param);
376 
377  if (respData.Contains("error"))
378  {
379  // GroupProfileData is not nullable
380  return new GroupProfileData();
381  }
382 
383  GroupMembershipData MemberInfo = GetAgentGroupMembership(requestingAgentID, AgentID, GroupID);
384  GroupProfileData MemberGroupProfile = GroupProfileHashtableToGroupProfileData(respData);
385 
386  MemberGroupProfile.MemberTitle = MemberInfo.GroupTitle;
387  MemberGroupProfile.PowersMask = MemberInfo.GroupPowers;
388 
389  return MemberGroupProfile;
390  }
391 
392  public void SetAgentActiveGroup(UUID requestingAgentID, UUID AgentID, UUID GroupID)
393  {
394  Hashtable param = new Hashtable();
395  param["AgentID"] = AgentID.ToString();
396  param["GroupID"] = GroupID.ToString();
397 
398  XmlRpcCall(requestingAgentID, "groups.setAgentActiveGroup", param);
399  }
400 
401  public void SetAgentActiveGroupRole(UUID requestingAgentID, UUID AgentID, UUID GroupID, UUID RoleID)
402  {
403  Hashtable param = new Hashtable();
404  param["AgentID"] = AgentID.ToString();
405  param["GroupID"] = GroupID.ToString();
406  param["SelectedRoleID"] = RoleID.ToString();
407 
408  XmlRpcCall(requestingAgentID, "groups.setAgentGroupInfo", param);
409  }
410 
411  public void SetAgentGroupInfo(UUID requestingAgentID, UUID AgentID, UUID GroupID, bool AcceptNotices, bool ListInProfile)
412  {
413  Hashtable param = new Hashtable();
414  param["AgentID"] = AgentID.ToString();
415  param["GroupID"] = GroupID.ToString();
416  param["AcceptNotices"] = AcceptNotices ? "1" : "0";
417  param["ListInProfile"] = ListInProfile ? "1" : "0";
418 
419  XmlRpcCall(requestingAgentID, "groups.setAgentGroupInfo", param);
420 
421  }
422 
423  public void AddAgentToGroupInvite(UUID requestingAgentID, UUID inviteID, UUID groupID, UUID roleID, UUID agentID)
424  {
425  Hashtable param = new Hashtable();
426  param["InviteID"] = inviteID.ToString();
427  param["AgentID"] = agentID.ToString();
428  param["RoleID"] = roleID.ToString();
429  param["GroupID"] = groupID.ToString();
430 
431  XmlRpcCall(requestingAgentID, "groups.addAgentToGroupInvite", param);
432 
433  }
434 
435  public GroupInviteInfo GetAgentToGroupInvite(UUID requestingAgentID, UUID inviteID)
436  {
437  Hashtable param = new Hashtable();
438  param["InviteID"] = inviteID.ToString();
439 
440  Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getAgentToGroupInvite", param);
441 
442  if (respData.Contains("error"))
443  {
444  return null;
445  }
446 
447  GroupInviteInfo inviteInfo = new GroupInviteInfo();
448  inviteInfo.InviteID = inviteID;
449  inviteInfo.GroupID = UUID.Parse((string)respData["GroupID"]);
450  inviteInfo.RoleID = UUID.Parse((string)respData["RoleID"]);
451  inviteInfo.AgentID = UUID.Parse((string)respData["AgentID"]);
452 
453  return inviteInfo;
454  }
455 
456  public void RemoveAgentToGroupInvite(UUID requestingAgentID, UUID inviteID)
457  {
458  Hashtable param = new Hashtable();
459  param["InviteID"] = inviteID.ToString();
460 
461  XmlRpcCall(requestingAgentID, "groups.removeAgentToGroupInvite", param);
462  }
463 
464  public void AddAgentToGroup(UUID requestingAgentID, UUID AgentID, UUID GroupID, UUID RoleID)
465  {
466  Hashtable param = new Hashtable();
467  param["AgentID"] = AgentID.ToString();
468  param["GroupID"] = GroupID.ToString();
469  param["RoleID"] = RoleID.ToString();
470 
471  XmlRpcCall(requestingAgentID, "groups.addAgentToGroup", param);
472  }
473 
474  public void RemoveAgentFromGroup(UUID requestingAgentID, UUID AgentID, UUID GroupID)
475  {
476  Hashtable param = new Hashtable();
477  param["AgentID"] = AgentID.ToString();
478  param["GroupID"] = GroupID.ToString();
479 
480  XmlRpcCall(requestingAgentID, "groups.removeAgentFromGroup", param);
481  }
482 
483  public void AddAgentToGroupRole(UUID requestingAgentID, UUID AgentID, UUID GroupID, UUID RoleID)
484  {
485  Hashtable param = new Hashtable();
486  param["AgentID"] = AgentID.ToString();
487  param["GroupID"] = GroupID.ToString();
488  param["RoleID"] = RoleID.ToString();
489 
490  XmlRpcCall(requestingAgentID, "groups.addAgentToGroupRole", param);
491  }
492 
493  public void RemoveAgentFromGroupRole(UUID requestingAgentID, UUID AgentID, UUID GroupID, UUID RoleID)
494  {
495  Hashtable param = new Hashtable();
496  param["AgentID"] = AgentID.ToString();
497  param["GroupID"] = GroupID.ToString();
498  param["RoleID"] = RoleID.ToString();
499 
500  XmlRpcCall(requestingAgentID, "groups.removeAgentFromGroupRole", param);
501  }
502 
503  public List<DirGroupsReplyData> FindGroups(UUID requestingAgentID, string search)
504  {
505  Hashtable param = new Hashtable();
506  param["Search"] = search;
507 
508  Hashtable respData = XmlRpcCall(requestingAgentID, "groups.findGroups", param);
509 
510  List<DirGroupsReplyData> findings = new List<DirGroupsReplyData>();
511 
512  if (!respData.Contains("error"))
513  {
514  Hashtable results = (Hashtable)respData["results"];
515  foreach (Hashtable groupFind in results.Values)
516  {
518  data.groupID = new UUID((string)groupFind["GroupID"]); ;
519  data.groupName = (string)groupFind["Name"];
520  data.members = int.Parse((string)groupFind["Members"]);
521  // data.searchOrder = order;
522 
523  findings.Add(data);
524  }
525  }
526 
527  return findings;
528  }
529 
530  public GroupMembershipData GetAgentGroupMembership(UUID requestingAgentID, UUID AgentID, UUID GroupID)
531  {
532  Hashtable param = new Hashtable();
533  param["AgentID"] = AgentID.ToString();
534  param["GroupID"] = GroupID.ToString();
535 
536  Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getAgentGroupMembership", param);
537 
538  if (respData.Contains("error"))
539  {
540  return null;
541  }
542 
543  GroupMembershipData data = HashTableToGroupMembershipData(respData);
544 
545  return data;
546  }
547 
548  public GroupMembershipData GetAgentActiveMembership(UUID requestingAgentID, UUID AgentID)
549  {
550  Hashtable param = new Hashtable();
551  param["AgentID"] = AgentID.ToString();
552 
553  Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getAgentActiveMembership", param);
554 
555  if (respData.Contains("error"))
556  {
557  return null;
558  }
559 
560  return HashTableToGroupMembershipData(respData);
561  }
562 
563  public List<GroupMembershipData> GetAgentGroupMemberships(UUID requestingAgentID, UUID AgentID)
564  {
565  Hashtable param = new Hashtable();
566  param["AgentID"] = AgentID.ToString();
567 
568  Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getAgentGroupMemberships", param);
569 
570  List<GroupMembershipData> memberships = new List<GroupMembershipData>();
571 
572  if (!respData.Contains("error"))
573  {
574  foreach (object membership in respData.Values)
575  {
576  memberships.Add(HashTableToGroupMembershipData((Hashtable)membership));
577  }
578  }
579 
580  return memberships;
581  }
582 
583  public List<GroupRolesData> GetAgentGroupRoles(UUID requestingAgentID, UUID AgentID, UUID GroupID)
584  {
585  Hashtable param = new Hashtable();
586  param["AgentID"] = AgentID.ToString();
587  param["GroupID"] = GroupID.ToString();
588 
589  Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getAgentRoles", param);
590 
591  List<GroupRolesData> Roles = new List<GroupRolesData>();
592 
593  if (respData.Contains("error"))
594  {
595  return Roles;
596  }
597 
598  foreach (Hashtable role in respData.Values)
599  {
600  GroupRolesData data = new GroupRolesData();
601  data.RoleID = new UUID((string)role["RoleID"]);
602  data.Name = (string)role["Name"];
603  data.Description = (string)role["Description"];
604  data.Powers = ulong.Parse((string)role["Powers"]);
605  data.Title = (string)role["Title"];
606 
607  Roles.Add(data);
608  }
609 
610  return Roles;
611  }
612 
613  public List<GroupRolesData> GetGroupRoles(UUID requestingAgentID, UUID GroupID)
614  {
615  Hashtable param = new Hashtable();
616  param["GroupID"] = GroupID.ToString();
617 
618  Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getGroupRoles", param);
619 
620  List<GroupRolesData> Roles = new List<GroupRolesData>();
621 
622  if (respData.Contains("error"))
623  {
624  return Roles;
625  }
626 
627  foreach (Hashtable role in respData.Values)
628  {
629  GroupRolesData data = new GroupRolesData();
630  data.Description = (string)role["Description"];
631  data.Members = int.Parse((string)role["Members"]);
632  data.Name = (string)role["Name"];
633  data.Powers = ulong.Parse((string)role["Powers"]);
634  data.RoleID = new UUID((string)role["RoleID"]);
635  data.Title = (string)role["Title"];
636 
637  Roles.Add(data);
638  }
639 
640  return Roles;
641  }
642 
643  public List<GroupMembersData> GetGroupMembers(UUID requestingAgentID, UUID GroupID)
644  {
645  Hashtable param = new Hashtable();
646  param["GroupID"] = GroupID.ToString();
647 
648  Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getGroupMembers", param);
649 
650  List<GroupMembersData> members = new List<GroupMembersData>();
651 
652  if (respData.Contains("error"))
653  {
654  return members;
655  }
656 
657  foreach (Hashtable membership in respData.Values)
658  {
659  GroupMembersData data = new GroupMembersData();
660 
661  data.AcceptNotices = ((string)membership["AcceptNotices"]) == "1";
662  data.AgentID = new UUID((string)membership["AgentID"]);
663  data.Contribution = int.Parse((string)membership["Contribution"]);
664  data.IsOwner = ((string)membership["IsOwner"]) == "1";
665  data.ListInProfile = ((string)membership["ListInProfile"]) == "1";
666  data.AgentPowers = ulong.Parse((string)membership["AgentPowers"]);
667  data.Title = (string)membership["Title"];
668 
669  members.Add(data);
670  }
671 
672  return members;
673  }
674 
675  public List<GroupRoleMembersData> GetGroupRoleMembers(UUID requestingAgentID, UUID GroupID)
676  {
677  Hashtable param = new Hashtable();
678  param["GroupID"] = GroupID.ToString();
679 
680  Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getGroupRoleMembers", param);
681 
682  List<GroupRoleMembersData> members = new List<GroupRoleMembersData>();
683 
684  if (!respData.Contains("error"))
685  {
686  foreach (Hashtable membership in respData.Values)
687  {
689 
690  data.MemberID = new UUID((string)membership["AgentID"]);
691  data.RoleID = new UUID((string)membership["RoleID"]);
692 
693  members.Add(data);
694  }
695  }
696  return members;
697  }
698 
699  public List<GroupNoticeData> GetGroupNotices(UUID requestingAgentID, UUID GroupID)
700  {
701  Hashtable param = new Hashtable();
702  param["GroupID"] = GroupID.ToString();
703 
704  Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getGroupNotices", param);
705 
706  List<GroupNoticeData> values = new List<GroupNoticeData>();
707 
708  if (!respData.Contains("error"))
709  {
710  foreach (Hashtable value in respData.Values)
711  {
712  GroupNoticeData data = new GroupNoticeData();
713  data.NoticeID = UUID.Parse((string)value["NoticeID"]);
714  data.Timestamp = uint.Parse((string)value["Timestamp"]);
715  data.FromName = (string)value["FromName"];
716  data.Subject = (string)value["Subject"];
717  data.HasAttachment = false;
718  data.AssetType = 0;
719 
720  values.Add(data);
721  }
722  }
723 
724  return values;
725  }
726 
727  public GroupNoticeInfo GetGroupNotice(UUID requestingAgentID, UUID noticeID)
728  {
729  Hashtable param = new Hashtable();
730  param["NoticeID"] = noticeID.ToString();
731 
732  Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getGroupNotice", param);
733 
734  if (respData.Contains("error"))
735  {
736  return null;
737  }
738 
739  GroupNoticeInfo data = new GroupNoticeInfo();
740  data.GroupID = UUID.Parse((string)respData["GroupID"]);
741  data.Message = (string)respData["Message"];
742  data.BinaryBucket = Utils.HexStringToBytes((string)respData["BinaryBucket"], true);
743  data.noticeData.NoticeID = UUID.Parse((string)respData["NoticeID"]);
744  data.noticeData.Timestamp = uint.Parse((string)respData["Timestamp"]);
745  data.noticeData.FromName = (string)respData["FromName"];
746  data.noticeData.Subject = (string)respData["Subject"];
747  data.noticeData.HasAttachment = false;
748  data.noticeData.AssetType = 0;
749 
750  if (data.Message == null)
751  {
752  data.Message = string.Empty;
753  }
754 
755  return data;
756  }
757 
758  public void AddGroupNotice(UUID requestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message, byte[] binaryBucket)
759  {
760  string binBucket = OpenMetaverse.Utils.BytesToHexString(binaryBucket, "");
761 
762  Hashtable param = new Hashtable();
763  param["GroupID"] = groupID.ToString();
764  param["NoticeID"] = noticeID.ToString();
765  param["FromName"] = fromName;
766  param["Subject"] = subject;
767  param["Message"] = message;
768  param["BinaryBucket"] = binBucket;
769  param["TimeStamp"] = ((uint)Util.UnixTimeSinceEpoch()).ToString();
770 
771  XmlRpcCall(requestingAgentID, "groups.addGroupNotice", param);
772  }
773 
774  #endregion
775 
776  #region GroupSessionTracking
777 
778  public void ResetAgentGroupChatSessions(UUID agentID)
779  {
780  foreach (List<UUID> agentList in m_groupsAgentsDroppedFromChatSession.Values)
781  {
782  agentList.Remove(agentID);
783  }
784  }
785 
786  public bool hasAgentBeenInvitedToGroupChatSession(UUID agentID, UUID groupID)
787  {
788  // If we're tracking this group, and we can find them in the tracking, then they've been invited
789  return m_groupsAgentsInvitedToChatSession.ContainsKey(groupID)
790  && m_groupsAgentsInvitedToChatSession[groupID].Contains(agentID);
791  }
792 
793  public bool hasAgentDroppedGroupChatSession(UUID agentID, UUID groupID)
794  {
795  // If we're tracking drops for this group,
796  // and we find them, well... then they've dropped
797  return m_groupsAgentsDroppedFromChatSession.ContainsKey(groupID)
798  && m_groupsAgentsDroppedFromChatSession[groupID].Contains(agentID);
799  }
800 
801  public void AgentDroppedFromGroupChatSession(UUID agentID, UUID groupID)
802  {
803  if (m_groupsAgentsDroppedFromChatSession.ContainsKey(groupID))
804  {
805  // If not in dropped list, add
806  if (!m_groupsAgentsDroppedFromChatSession[groupID].Contains(agentID))
807  {
808  m_groupsAgentsDroppedFromChatSession[groupID].Add(agentID);
809  }
810  }
811  }
812 
813  public void AgentInvitedToGroupChatSession(UUID agentID, UUID groupID)
814  {
815  // Add Session Status if it doesn't exist for this session
816  CreateGroupChatSessionTracking(groupID);
817 
818  // If nessesary, remove from dropped list
819  if (m_groupsAgentsDroppedFromChatSession[groupID].Contains(agentID))
820  {
821  m_groupsAgentsDroppedFromChatSession[groupID].Remove(agentID);
822  }
823  }
824 
825  private void CreateGroupChatSessionTracking(UUID groupID)
826  {
827  if (!m_groupsAgentsDroppedFromChatSession.ContainsKey(groupID))
828  {
829  m_groupsAgentsDroppedFromChatSession.Add(groupID, new List<UUID>());
830  m_groupsAgentsInvitedToChatSession.Add(groupID, new List<UUID>());
831  }
832 
833  }
834  #endregion
835 
836  #region XmlRpcHashtableMarshalling
837  private GroupProfileData GroupProfileHashtableToGroupProfileData(Hashtable groupProfile)
838  {
839  GroupProfileData group = new GroupProfileData();
840  group.GroupID = UUID.Parse((string)groupProfile["GroupID"]);
841  group.Name = (string)groupProfile["Name"];
842 
843  if (groupProfile["Charter"] != null)
844  {
845  group.Charter = (string)groupProfile["Charter"];
846  }
847 
848  group.ShowInList = ((string)groupProfile["ShowInList"]) == "1";
849  group.InsigniaID = UUID.Parse((string)groupProfile["InsigniaID"]);
850  group.MembershipFee = int.Parse((string)groupProfile["MembershipFee"]);
851  group.OpenEnrollment = ((string)groupProfile["OpenEnrollment"]) == "1";
852  group.AllowPublish = ((string)groupProfile["AllowPublish"]) == "1";
853  group.MaturePublish = ((string)groupProfile["MaturePublish"]) == "1";
854  group.FounderID = UUID.Parse((string)groupProfile["FounderID"]);
855  group.OwnerRole = UUID.Parse((string)groupProfile["OwnerRoleID"]);
856 
857  group.GroupMembershipCount = int.Parse((string)groupProfile["GroupMembershipCount"]);
858  group.GroupRolesCount = int.Parse((string)groupProfile["GroupRolesCount"]);
859 
860  return group;
861  }
862 
863  private GroupRecord GroupProfileHashtableToGroupRecord(Hashtable groupProfile)
864  {
865  GroupRecord group = new GroupRecord();
866  group.GroupID = UUID.Parse((string)groupProfile["GroupID"]);
867  group.GroupName = groupProfile["Name"].ToString();
868  if (groupProfile["Charter"] != null)
869  {
870  group.Charter = (string)groupProfile["Charter"];
871  }
872  group.ShowInList = ((string)groupProfile["ShowInList"]) == "1";
873  group.GroupPicture = UUID.Parse((string)groupProfile["InsigniaID"]);
874  group.MembershipFee = int.Parse((string)groupProfile["MembershipFee"]);
875  group.OpenEnrollment = ((string)groupProfile["OpenEnrollment"]) == "1";
876  group.AllowPublish = ((string)groupProfile["AllowPublish"]) == "1";
877  group.MaturePublish = ((string)groupProfile["MaturePublish"]) == "1";
878  group.FounderID = UUID.Parse((string)groupProfile["FounderID"]);
879  group.OwnerRoleID = UUID.Parse((string)groupProfile["OwnerRoleID"]);
880 
881  return group;
882  }
883 
884  private static GroupMembershipData HashTableToGroupMembershipData(Hashtable respData)
885  {
887  data.AcceptNotices = ((string)respData["AcceptNotices"] == "1");
888  data.Contribution = int.Parse((string)respData["Contribution"]);
889  data.ListInProfile = ((string)respData["ListInProfile"] == "1");
890 
891  data.ActiveRole = new UUID((string)respData["SelectedRoleID"]);
892  data.GroupTitle = (string)respData["Title"];
893 
894  data.GroupPowers = ulong.Parse((string)respData["GroupPowers"]);
895 
896  // Is this group the agent's active group
897 
898  data.GroupID = new UUID((string)respData["GroupID"]);
899 
900  UUID ActiveGroup = new UUID((string)respData["ActiveGroupID"]);
901  data.Active = data.GroupID.Equals(ActiveGroup);
902 
903  data.AllowPublish = ((string)respData["AllowPublish"] == "1");
904  if (respData["Charter"] != null)
905  {
906  data.Charter = (string)respData["Charter"];
907  }
908  data.FounderID = new UUID((string)respData["FounderID"]);
909  data.GroupID = new UUID((string)respData["GroupID"]);
910  data.GroupName = (string)respData["GroupName"];
911  data.GroupPicture = new UUID((string)respData["InsigniaID"]);
912  data.MaturePublish = ((string)respData["MaturePublish"] == "1");
913  data.MembershipFee = int.Parse((string)respData["MembershipFee"]);
914  data.OpenEnrollment = ((string)respData["OpenEnrollment"] == "1");
915  data.ShowInList = ((string)respData["ShowInList"] == "1");
916 
917  return data;
918  }
919 
920  #endregion
921 
925  private Hashtable XmlRpcCall(UUID requestingAgentID, string function, Hashtable param)
926  {
927  XmlRpcResponse resp = null;
928  string CacheKey = null;
929 
930  // Only bother with the cache if it isn't disabled.
931  if (m_cacheTimeout > 0)
932  {
933  if (!function.StartsWith("groups.get"))
934  {
935  // Any and all updates cause the cache to clear
936  m_memoryCache.Clear();
937  }
938  else
939  {
940  StringBuilder sb = new StringBuilder(requestingAgentID + function);
941  foreach (object key in param.Keys)
942  {
943  if (param[key] != null)
944  {
945  sb.AppendFormat(",{0}:{1}", key.ToString(), param[key].ToString());
946  }
947  }
948 
949  CacheKey = sb.ToString();
950  m_memoryCache.TryGetValue(CacheKey, out resp);
951  }
952  }
953 
954  if (resp == null)
955  {
956  if (m_debugEnabled)
957  m_log.DebugFormat("[XMLRPC-GROUPS-CONNECTOR]: Cache miss for key {0}", CacheKey);
958 
959  string UserService;
960  UUID SessionID;
961  GetClientGroupRequestID(requestingAgentID, out UserService, out SessionID);
962 
963  param.Add("RequestingAgentID", requestingAgentID.ToString());
964  param.Add("RequestingAgentUserService", UserService);
965  param.Add("RequestingSessionID", SessionID.ToString());
966  param.Add("ReadKey", m_groupReadKey);
967  param.Add("WriteKey", m_groupWriteKey);
968 
969  IList parameters = new ArrayList();
970  parameters.Add(param);
971 
973  req = new ConfigurableKeepAliveXmlRpcRequest(function, parameters, m_disableKeepAlive);
974 
975  try
976  {
977  resp = req.Send(m_groupsServerURI, 10000);
978 
979  if ((m_cacheTimeout > 0) && (CacheKey != null))
980  {
981  m_memoryCache.AddOrUpdate(CacheKey, resp, TimeSpan.FromSeconds(m_cacheTimeout));
982  }
983  }
984  catch (Exception e)
985  {
986  m_log.ErrorFormat(
987  "[XMLRPC-GROUPS-CONNECTOR]: An error has occured while attempting to access the XmlRpcGroups server method {0} at {1}: {2}",
988  function, m_groupsServerURI, e.Message);
989 
990  if(m_debugEnabled)
991  {
992  m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: {0}", e.StackTrace);
993 
994  foreach (string ResponseLine in req.RequestResponse.Split(new string[] { Environment.NewLine }, StringSplitOptions.None))
995  {
996  m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: {0} ", ResponseLine);
997  }
998 
999  foreach (string key in param.Keys)
1000  {
1001  m_log.WarnFormat("[XMLRPC-GROUPS-CONNECTOR]: {0} :: {1}", key, param[key].ToString());
1002  }
1003  }
1004  Hashtable respData = new Hashtable();
1005  respData.Add("error", e.ToString());
1006  return respData;
1007  }
1008  }
1009 
1010  if (resp.Value is Hashtable)
1011  {
1012  Hashtable respData = (Hashtable)resp.Value;
1013  if (respData.Contains("error") && !respData.Contains("succeed"))
1014  {
1015  LogRespDataToConsoleError(requestingAgentID, function, param, respData);
1016  }
1017 
1018  return respData;
1019  }
1020 
1021  m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: The XmlRpc server returned a {1} instead of a hashtable for {0}", function, resp.Value.GetType().ToString());
1022 
1023  if (resp.Value is ArrayList)
1024  {
1025  ArrayList al = (ArrayList)resp.Value;
1026  m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: Contains {0} elements", al.Count);
1027 
1028  foreach (object o in al)
1029  {
1030  m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: {0} :: {1}", o.GetType().ToString(), o.ToString());
1031  }
1032  }
1033  else
1034  {
1035  m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: Function returned: {0}", resp.Value.ToString());
1036  }
1037 
1038  Hashtable error = new Hashtable();
1039  error.Add("error", "invalid return value");
1040  return error;
1041  }
1042 
1043  private void LogRespDataToConsoleError(UUID requestingAgentID, string function, Hashtable param, Hashtable respData)
1044  {
1045  m_log.ErrorFormat(
1046  "[XMLRPC-GROUPS-CONNECTOR]: Error when calling {0} for {1} with params {2}. Response params are {3}",
1047  function, requestingAgentID, Util.PrettyFormatToSingleLine(param), Util.PrettyFormatToSingleLine(respData));
1048  }
1049 
1057  private void GetClientGroupRequestID(UUID AgentID, out string UserServiceURL, out UUID SessionID)
1058  {
1059  UserServiceURL = "";
1060  SessionID = UUID.Zero;
1061 
1062 
1063  // Need to rework this based on changes to User Services
1064  /*
1065  UserAccount userAccount = m_accountService.GetUserAccount(UUID.Zero,AgentID);
1066  if (userAccount == null)
1067  {
1068  // This should be impossible. If I've been passed a reference to a client
1069  // that client should be registered with the UserService. So something
1070  // is horribly wrong somewhere.
1071 
1072  m_log.WarnFormat("[GROUPS]: Could not find a UserServiceURL for {0}", AgentID);
1073 
1074  }
1075  else if (userProfile is ForeignUserProfileData)
1076  {
1077  // They aren't from around here
1078  ForeignUserProfileData fupd = (ForeignUserProfileData)userProfile;
1079  UserServiceURL = fupd.UserServerURI;
1080  SessionID = fupd.CurrentAgent.SessionID;
1081 
1082  }
1083  else
1084  {
1085  // They're a local user, use this:
1086  UserServiceURL = m_commManager.NetworkServersInfo.UserURL;
1087  SessionID = userProfile.CurrentAgent.SessionID;
1088  }
1089  */
1090  }
1091 
1092  }
1093 }
1094 
1095 namespace Nwc.XmlRpc
1096 {
1097  using System;
1098  using System.Collections;
1099  using System.IO;
1100  using System.Xml;
1101  using System.Net;
1102  using System.Text;
1103  using System.Reflection;
1104 
1106  public class ConfigurableKeepAliveXmlRpcRequest : XmlRpcRequest
1107  {
1108  private XmlRpcRequestSerializer _serializer = new XmlRpcRequestSerializer();
1109  private XmlRpcResponseDeserializer _deserializer = new XmlRpcResponseDeserializer();
1110  private bool _disableKeepAlive = true;
1111 
1112  public string RequestResponse = String.Empty;
1113 
1118  public ConfigurableKeepAliveXmlRpcRequest(String methodName, IList parameters, bool disableKeepAlive)
1119  {
1120  MethodName = methodName;
1121  _params = parameters;
1122  _disableKeepAlive = disableKeepAlive;
1123  }
1124 
1128  public XmlRpcResponse Send(String url)
1129  {
1130  HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
1131  if (request == null)
1132  throw new XmlRpcException(XmlRpcErrorCodes.TRANSPORT_ERROR,
1133  XmlRpcErrorCodes.TRANSPORT_ERROR_MSG + ": Could not create request with " + url);
1134  request.Method = "POST";
1135  request.ContentType = "text/xml";
1136  request.AllowWriteStreamBuffering = true;
1137  request.KeepAlive = !_disableKeepAlive;
1138 
1139  using (Stream stream = request.GetRequestStream())
1140  {
1141  using (XmlTextWriter xml = new XmlTextWriter(stream, Encoding.ASCII))
1142  {
1143  _serializer.Serialize(xml, this);
1144  xml.Flush();
1145  }
1146  }
1147 
1148  XmlRpcResponse resp;
1149 
1150  using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
1151  {
1152  using (Stream s = response.GetResponseStream())
1153  {
1154  using (StreamReader input = new StreamReader(s))
1155  {
1156  string inputXml = input.ReadToEnd();
1157 
1158  try
1159  {
1160  resp = (XmlRpcResponse)_deserializer.Deserialize(inputXml);
1161  }
1162  catch (Exception e)
1163  {
1164  RequestResponse = inputXml;
1165  throw e;
1166  }
1167  }
1168  }
1169  }
1170 
1171  return resp;
1172  }
1173  }
1174 }
Class supporting the request side of an XML-RPC transaction.
List< GroupMembershipData > GetAgentGroupMemberships(UUID requestingAgentID, UUID AgentID)
Get information about the groups to which a user belongs.
UUID CreateGroup(UUID requestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish, UUID founderID)
Create a Group, including Everyone and Owners Role, place FounderID in both groups, select Owner as selected role, and newly created group as agent's active role.
void AddAgentToGroupInvite(UUID requestingAgentID, UUID inviteID, UUID groupID, UUID roleID, UUID agentID)
void SetAgentActiveGroupRole(UUID requestingAgentID, UUID AgentID, UUID GroupID, UUID RoleID)
void Initialise(IConfigSource config)
This is called to initialize the region module. For shared modules, this is called exactly once...
void AddGroupRole(UUID requestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers)
OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString key
Definition: ICM_Api.cs:31
void UpdateGroupRole(UUID requestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers)
void AddAgentToGroup(UUID requestingAgentID, UUID AgentID, UUID GroupID, UUID RoleID)
XmlRpcResponse Send(String url)
Send the request to the server.
void AddAgentToGroupRole(UUID requestingAgentID, UUID AgentID, UUID GroupID, UUID RoleID)
GroupRecord GetGroupRecord(UUID requestingAgentID, UUID GroupID, string GroupName)
Get the group record.
void UpdateGroup(UUID requestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish)
Interactive OpenSim region server
Definition: OpenSim.cs:55
GroupProfileData GetMemberGroupProfile(UUID requestingAgentID, UUID GroupID, UUID AgentID)
void SetAgentGroupInfo(UUID requestingAgentID, UUID AgentID, UUID GroupID, bool AcceptNotices, bool ListInProfile)
void PostInitialise()
This is called exactly once after all the shared region-modules have been instanciated and IRegionMod...
void AddGroupNotice(UUID requestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message, byte[] binaryBucket)
void Close()
This is the inverse to Initialise. After a Close(), this instance won't be usable anymore...
GroupMembershipData GetAgentGroupMembership(UUID requestingAgentID, UUID AgentID, UUID GroupID)
Get information about a specific group to which the user belongs.
List< GroupRolesData > GetAgentGroupRoles(UUID requestingAgentID, UUID AgentID, UUID GroupID)
void RemoveAgentFromGroupRole(UUID requestingAgentID, UUID AgentID, UUID GroupID, UUID RoleID)
ConfigurableKeepAliveXmlRpcRequest(String methodName, IList parameters, bool disableKeepAlive)
Instantiate an XmlRpcRequest for a specified method and parameters.