clockwerk-opensim-stable – Blame information for rev 1

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