aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsModule.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsModule.cs')
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsModule.cs1039
1 files changed, 1039 insertions, 0 deletions
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsModule.cs
new file mode 100644
index 0000000..ca08fe2
--- /dev/null
+++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsModule.cs
@@ -0,0 +1,1039 @@
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 OpenSim 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
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31
32using System.Collections;
33//using Nwc.XmlRpc;
34
35using log4net;
36using Nini.Config;
37
38using OpenMetaverse;
39using OpenMetaverse.StructuredData;
40
41using OpenSim.Framework;
42using OpenSim.Region.CoreModules.Framework.EventQueue;
43using OpenSim.Region.Framework.Interfaces;
44using OpenSim.Region.Framework.Scenes;
45
46using Caps = OpenSim.Framework.Communications.Capabilities.Caps;
47using DirFindFlags = OpenMetaverse.DirectoryManager.DirFindFlags;
48
49
50
51namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
52{
53 public class XmlRpcGroupsModule : INonSharedRegionModule, IGroupsModule
54 {
55 /// <summary>
56 /// To use this module, you must specify the following in your OpenSim.ini
57 /// [GROUPS]
58 /// Enabled = true
59 /// Module = XmlRpcGroups
60 /// XmlRpcMessagingEnabled = true
61 /// XmlRpcNoticesEnabled = true
62 /// XmlRpcDebugEnabled = true
63 ///
64 /// </summary>
65
66 private static readonly ILog m_log =
67 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
68
69 private List<Scene> m_SceneList = new List<Scene>();
70
71 // This only works when running as non-Shared, in shared, there may be multiple IClientAPIs for a single client
72 private Dictionary<UUID, IClientAPI> m_ActiveClients = new Dictionary<UUID, IClientAPI>();
73
74 private IMessageTransferModule m_MsgTransferModule = null;
75
76 private IGroupDataProvider m_groupData = null;
77
78 // Configuration settings
79 private const string m_defaultXmlRpcServiceURL = "http://osflotsam.org/xmlrpc.php";
80 private bool m_GroupsEnabled = false;
81 private bool m_GroupNoticesEnabled = true;
82 private bool m_debugEnabled = true;
83
84 #region IRegionModule Members
85
86 public void Initialise(IConfigSource config)
87 {
88 IConfig groupsConfig = config.Configs["Groups"];
89
90 m_log.Info("[GROUPS]: Initializing XmlRpcGroups");
91
92 if (groupsConfig == null)
93 {
94 // Do not run this module by default.
95 m_log.Info("[GROUPS]: No config found in OpenSim.ini -- not enabling XmlRpcGroups");
96 return;
97 }
98 else
99 {
100 m_GroupsEnabled = groupsConfig.GetBoolean("Enabled", false);
101 if (!m_GroupsEnabled)
102 {
103 m_log.Info("[GROUPS]: Groups disabled in configuration");
104 return;
105 }
106
107 if (groupsConfig.GetString("Module", "Default") != "XmlRpcGroups")
108 {
109 m_log.Info("[GROUPS]: Config Groups Module not set to XmlRpcGroups");
110
111 return;
112 }
113
114 string ServiceURL = groupsConfig.GetString("XmlRpcServiceURL", m_defaultXmlRpcServiceURL);
115 m_groupData = new XmlRpcGroupDataProvider(ServiceURL);
116 m_log.InfoFormat("[GROUPS]: XmlRpc Service URL set to: {0}", ServiceURL);
117
118 m_GroupNoticesEnabled = groupsConfig.GetBoolean("XmlRpcNoticesEnabled", true);
119 m_debugEnabled = groupsConfig.GetBoolean("XmlRpcDebugEnabled", true);
120
121 }
122 }
123
124 public void AddRegion(Scene scene)
125 {
126 scene.RegisterModuleInterface<IGroupsModule>(this);
127 }
128 public void RegionLoaded(Scene scene)
129 {
130 if (m_debugEnabled) m_log.InfoFormat("[GROUPS] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
131
132 if (!m_GroupsEnabled)
133 return;
134
135
136 m_MsgTransferModule = scene.RequestModuleInterface<IMessageTransferModule>();
137
138 // No message transfer module, no notices, group invites, rejects, ejects, etc
139 if (m_MsgTransferModule == null)
140 {
141 m_GroupsEnabled = false;
142 m_log.Info("[GROUPS]: Could not get MessageTransferModule");
143 Close();
144 return;
145 }
146
147
148 m_SceneList.Add(scene);
149
150 scene.EventManager.OnNewClient += OnNewClient;
151 scene.EventManager.OnClientClosed += OnClientClosed;
152 scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage;
153
154 }
155
156 public void RemoveRegion(Scene scene)
157 {
158 if (m_debugEnabled) m_log.InfoFormat("[GROUPS] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
159
160 m_SceneList.Remove(scene);
161 }
162
163 public void Close()
164 {
165 m_log.Debug("[GROUPS]: Shutting down XmlRpcGroups module.");
166 }
167
168 public string Name
169 {
170 get { return "XmlRpcGroupsModule"; }
171 }
172
173 #endregion
174
175 private void UpdateAllClientsWithGroupInfo()
176 {
177 if (m_debugEnabled) m_log.InfoFormat("[GROUPS] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
178 foreach (IClientAPI client in m_ActiveClients.Values)
179 {
180 UpdateClientWithGroupInfo(client);
181 }
182 }
183
184 private void UpdateClientWithGroupInfo(IClientAPI client)
185 {
186 m_log.InfoFormat("[GROUPS] {0} called for {1}", System.Reflection.MethodBase.GetCurrentMethod().Name, client.Name);
187 OnAgentDataUpdateRequest(client, client.AgentId, UUID.Zero);
188
189
190 // Need to send a group membership update to the client
191 // UDP version doesn't seem to behave nicely
192 // client.SendGroupMembership(GetMembershipData(client.AgentId));
193
194 GroupMembershipData[] membershipData = m_groupData.GetAgentGroupMemberships(client.AgentId).ToArray();
195
196 SendGroupMembershipInfoViaCaps(client, membershipData);
197 client.SendAvatarGroupsReply(client.AgentId, membershipData);
198
199 }
200
201 #region EventHandlers
202 private void OnNewClient(IClientAPI client)
203 {
204 if (m_debugEnabled) m_log.InfoFormat("[GROUPS] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
205
206
207 lock (m_ActiveClients)
208 {
209 if (!m_ActiveClients.ContainsKey(client.AgentId))
210 {
211 client.OnUUIDGroupNameRequest += HandleUUIDGroupNameRequest;
212 client.OnAgentDataUpdateRequest += OnAgentDataUpdateRequest;
213 client.OnDirFindQuery += OnDirFindQuery;
214 client.OnInstantMessage += OnInstantMessage;
215
216 m_ActiveClients.Add(client.AgentId, client);
217 }
218 }
219
220 UpdateClientWithGroupInfo(client);
221 }
222 private void OnClientClosed(UUID AgentId)
223 {
224 if (m_debugEnabled) m_log.InfoFormat("[GROUPS] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
225
226 lock (m_ActiveClients)
227 {
228 if (m_ActiveClients.ContainsKey(AgentId))
229 {
230 IClientAPI client = m_ActiveClients[AgentId];
231 client.OnUUIDGroupNameRequest -= HandleUUIDGroupNameRequest;
232 client.OnAgentDataUpdateRequest -= OnAgentDataUpdateRequest;
233 client.OnDirFindQuery -= OnDirFindQuery;
234 client.OnInstantMessage -= OnInstantMessage;
235
236 m_ActiveClients.Remove(AgentId);
237 }
238 else
239 {
240 m_log.InfoFormat("[GROUPS] Client closed that wasn't registered here.");
241 }
242
243
244 }
245
246 }
247
248
249 void OnDirFindQuery(IClientAPI remoteClient, UUID queryID, string queryText, uint queryFlags, int queryStart)
250 {
251 if (((DirFindFlags)queryFlags & DirFindFlags.Groups) == DirFindFlags.Groups)
252 {
253 m_log.InfoFormat("[GROUPS] {0} called with queryText({1}) queryFlags({2}) queryStart({3})", System.Reflection.MethodBase.GetCurrentMethod().Name, queryText, (DirFindFlags)queryFlags, queryStart);
254
255 remoteClient.SendDirGroupsReply(queryID, m_groupData.FindGroups(queryText).ToArray());
256 }
257
258 }
259
260 private void OnAgentDataUpdateRequest(IClientAPI remoteClient,
261 UUID AgentID, UUID SessionID)
262 {
263 m_log.InfoFormat("[GROUPS] {0} called with SessionID :: {1}", System.Reflection.MethodBase.GetCurrentMethod().Name, SessionID);
264
265
266 UUID ActiveGroupID = UUID.Zero;
267 string ActiveGroupTitle = string.Empty;
268 string ActiveGroupName = string.Empty;
269 ulong ActiveGroupPowers = (ulong)GroupPowers.None;
270
271 GroupMembershipData membership = m_groupData.GetAgentActiveMembership(AgentID);
272 if (membership != null)
273 {
274 ActiveGroupID = membership.GroupID;
275 ActiveGroupTitle = membership.GroupTitle;
276 ActiveGroupPowers = membership.GroupPowers;
277 }
278
279 string firstname, lastname;
280 IClientAPI agent;
281 if( m_ActiveClients.TryGetValue(AgentID, out agent) )
282 {
283 firstname = agent.FirstName;
284 lastname = agent.LastName;
285 } else {
286 firstname = "Unknown";
287 lastname = "Unknown";
288 }
289
290 UpdateScenePresenceWithTitle(AgentID, ActiveGroupTitle);
291
292 remoteClient.SendAgentDataUpdate(AgentID, ActiveGroupID, firstname,
293 lastname, ActiveGroupPowers, ActiveGroupName,
294 ActiveGroupTitle);
295 }
296
297 private void HandleUUIDGroupNameRequest(UUID GroupID,IClientAPI remote_client)
298 {
299 if (m_debugEnabled) m_log.InfoFormat("[GROUPS] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
300
301 string GroupName;
302
303 GroupRecord group = m_groupData.GetGroupRecord(GroupID, null);
304 if (group != null)
305 {
306 GroupName = group.GroupName;
307 }
308 else
309 {
310 GroupName = "Unknown";
311 }
312
313
314 remote_client.SendGroupNameReply(GroupID, GroupName);
315 }
316
317
318 private void OnInstantMessage(IClientAPI remoteClient, GridInstantMessage im)
319 {
320 if (m_debugEnabled) m_log.InfoFormat("[GROUPS] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
321
322
323 // Group invitations
324 if ((im.dialog == (byte)InstantMessageDialog.GroupInvitationAccept) || (im.dialog == (byte)InstantMessageDialog.GroupInvitationDecline))
325 {
326 m_log.WarnFormat("[GROUPS] Received an IIM for {0}.", ((InstantMessageDialog)im.dialog).ToString());
327
328
329 UUID inviteID = new UUID(im.imSessionID);
330 GroupInviteInfo inviteInfo = m_groupData.GetAgentToGroupInvite(inviteID);
331
332 m_log.WarnFormat("[GROUPS] Invite is for Agent {0} to Group {1}.", inviteInfo.AgentID, inviteInfo.GroupID);
333
334 UUID fromAgentID = new UUID(im.fromAgentID);
335 if ((inviteInfo != null) && (fromAgentID == inviteInfo.AgentID))
336 {
337
338 // Accept
339 if (im.dialog == (byte)InstantMessageDialog.GroupInvitationAccept)
340 {
341 m_log.WarnFormat("[GROUPS] Received an accept invite notice.");
342
343 // and the sessionid is the role
344 m_groupData.AddAgentToGroup(inviteInfo.AgentID, inviteInfo.GroupID, inviteInfo.RoleID);
345
346 if (m_MsgTransferModule != null)
347 {
348 GridInstantMessage msg = new GridInstantMessage();
349 msg.imSessionID = UUID.Zero.Guid;
350 msg.fromAgentID = UUID.Zero.Guid;
351 msg.toAgentID = inviteInfo.AgentID.Guid;
352 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
353 msg.fromAgentName = "Groups";
354 msg.message = string.Format("You have been added to the group.");
355 msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.MessageBox;
356 msg.fromGroup = false;
357 msg.offline = (byte)0;
358 msg.ParentEstateID = 0;
359 msg.Position = Vector3.Zero;
360 msg.RegionID = UUID.Zero.Guid;
361 msg.binaryBucket = new byte[0];
362
363 m_MsgTransferModule.SendInstantMessage(msg, delegate(bool success) { });
364 }
365
366 UpdateAllClientsWithGroupInfo();
367
368 m_groupData.RemoveAgentToGroupInvite(inviteID);
369 }
370
371 // Reject
372 if (im.dialog == (byte)InstantMessageDialog.GroupInvitationDecline)
373 {
374 m_log.WarnFormat("[GROUPS] Received a reject invite notice.");
375 m_groupData.RemoveAgentToGroupInvite(inviteID);
376
377 }
378
379
380 }
381 }
382
383 // Group notices
384 if ((im.dialog == (byte)InstantMessageDialog.GroupNotice))
385 {
386 if (!m_GroupNoticesEnabled)
387 {
388 return;
389 }
390
391 UUID GroupID = new UUID(im.toAgentID);
392 if( m_groupData.GetGroupRecord(GroupID, null) != null)
393 {
394 UUID NoticeID = UUID.Random();
395 string Subject = im.message.Substring(0, im.message.IndexOf('|'));
396 string Message = im.message.Substring(Subject.Length + 1);
397
398 byte[] bucket;
399
400 if ((im.binaryBucket.Length == 1) && (im.binaryBucket[0] == 0))
401 {
402 bucket = new byte[19];
403 bucket[0] = 0; //dunno
404 bucket[1] = 0; //dunno
405 GroupID.ToBytes(bucket, 2);
406 bucket[18] = 0; //dunno
407 }
408 else
409 {
410 string binBucket = OpenMetaverse.Utils.BytesToString(im.binaryBucket);
411 binBucket = binBucket.Remove(0, 14).Trim();
412 m_log.WarnFormat("I don't understand a group notice binary bucket of: {0}", binBucket);
413
414 OSDMap binBucketOSD = (OSDMap)OSDParser.DeserializeLLSDXml(binBucket);
415
416 foreach (string key in binBucketOSD.Keys)
417 {
418 m_log.WarnFormat("{0}: {1}", key, binBucketOSD[key].ToString());
419 }
420
421 // treat as if no attachment
422 bucket = new byte[19];
423 bucket[0] = 0; //dunno
424 bucket[1] = 0; //dunno
425 GroupID.ToBytes(bucket, 2);
426 bucket[18] = 0; //dunno
427 }
428
429
430 m_groupData.AddGroupNotice(GroupID, NoticeID, im.fromAgentName, Subject, Message, bucket);
431 if (OnNewGroupNotice != null)
432 {
433 OnNewGroupNotice(GroupID, NoticeID);
434 }
435
436 // Build notice IIM
437 GridInstantMessage msg = CreateGroupNoticeIM(UUID.Zero, NoticeID, (byte)OpenMetaverse.InstantMessageDialog.GroupNotice);
438
439 // Send notice out to everyone that wants notices
440 foreach( GroupMembersData member in m_groupData.GetGroupMembers(GroupID) )
441 {
442 if( member.AcceptNotices )
443 {
444 msg.toAgentID = member.AgentID.Guid;
445 m_MsgTransferModule.SendInstantMessage(msg, delegate(bool success) { });
446
447 }
448 }
449
450
451
452 }
453 }
454
455 // Interop, received special 210 code for ejecting a group member
456 // this only works within the comms servers domain, and won't work hypergrid
457 // TODO:FIXME: Use a presense server of some kind to find out where the
458 // client actually is, and try contacting that region directly to notify them,
459 // or provide the notification via xmlrpc update queue
460 if ((im.dialog == 210))
461 {
462 // This is sent from the region that the ejectee was ejected from
463 // if it's being delivered here, then the ejectee is here
464 // so we need to send local updates to the agent.
465
466
467 if (m_MsgTransferModule != null)
468 {
469 im.dialog = (byte)InstantMessageDialog.MessageFromAgent;
470 m_MsgTransferModule.SendInstantMessage(im, delegate(bool success) { });
471 }
472
473 UUID ejecteeID = new UUID(im.toAgentID);
474 UUID groupID = new UUID(im.toAgentID);
475 if (m_ActiveClients.ContainsKey(ejecteeID))
476 {
477 m_ActiveClients[ejecteeID].SendAgentDropGroup(groupID);
478 }
479
480 }
481
482
483
484 }
485
486 private void OnGridInstantMessage(GridInstantMessage msg)
487 {
488 if (m_debugEnabled) m_log.InfoFormat("[GROUPS] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
489
490 // Trigger the above event handler
491 OnInstantMessage(null, msg);
492 }
493
494
495 #endregion
496
497
498 private void UpdateScenePresenceWithTitle(UUID AgentID, string Title)
499 {
500 m_log.DebugFormat("[GROUPS] Updating scene title for {0} with title: {1}", AgentID, Title);
501 ScenePresence presence = null;
502 lock (m_SceneList)
503 {
504 foreach (Scene scene in m_SceneList)
505 {
506 presence = scene.GetScenePresence(AgentID);
507 if (presence != null)
508 {
509 presence.Grouptitle = Title;
510
511 // FixMe: Ter suggests a "Schedule" method that I can't find.
512 presence.SendFullUpdateToAllClients();
513 }
514 }
515 }
516 }
517
518
519 #region IGroupsModule Members
520
521 public event NewGroupNotice OnNewGroupNotice;
522
523 public GroupRecord GetGroupRecord(UUID GroupID)
524 {
525 return m_groupData.GetGroupRecord(GroupID, null);
526 }
527
528 public void ActivateGroup(IClientAPI remoteClient, UUID groupID)
529 {
530 if (m_debugEnabled) m_log.InfoFormat("[GROUPS] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
531
532 m_groupData.SetAgentActiveGroup(remoteClient.AgentId, groupID);
533
534 // UpdateClientWithGroupInfo(remoteClient);
535 UpdateAllClientsWithGroupInfo();
536 }
537
538 /// <summary>
539 /// Get the Role Titles for an Agent, for a specific group
540 /// </summary>
541 public List<GroupTitlesData> GroupTitlesRequest(IClientAPI remoteClient, UUID groupID)
542 {
543 if (m_debugEnabled) m_log.InfoFormat("[GROUPS] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
544
545 List<GroupRolesData> agentRoles = m_groupData.GetAgentGroupRoles(remoteClient.AgentId, groupID);
546 GroupMembershipData agentMembership = m_groupData.GetAgentGroupMembership(remoteClient.AgentId, groupID);
547
548 List<GroupTitlesData> titles = new List<GroupTitlesData>();
549 foreach (GroupRolesData role in agentRoles)
550 {
551 GroupTitlesData title = new GroupTitlesData();
552 title.Name = role.Name;
553 title.Selected = agentMembership.ActiveRole == role.RoleID;
554 title.UUID = role.RoleID;
555 }
556
557 return titles;
558 }
559
560 public List<GroupMembersData> GroupMembersRequest(IClientAPI remoteClient, UUID groupID)
561 {
562 if (m_debugEnabled) m_log.InfoFormat("[GROUPS] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
563
564 List<GroupMembersData> data = m_groupData.GetGroupMembers(groupID);
565
566 foreach (GroupMembersData member in data)
567 {
568 m_log.InfoFormat("[GROUPS] {0} {1}", member.AgentID, member.Title);
569 }
570
571 return data;
572
573 }
574
575 public List<GroupRolesData> GroupRoleDataRequest(IClientAPI remoteClient, UUID groupID)
576 {
577 if (m_debugEnabled) m_log.InfoFormat("[GROUPS] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
578
579 List<GroupRolesData> data = m_groupData.GetGroupRoles(groupID);
580
581 foreach (GroupRolesData member in data)
582 {
583 m_log.InfoFormat("[GROUPS] {0} {1}", member.Title, member.Members);
584 }
585
586 return data;
587
588 }
589
590 public List<GroupRoleMembersData> GroupRoleMembersRequest(IClientAPI remoteClient, UUID groupID)
591 {
592 if (m_debugEnabled) m_log.InfoFormat("[GROUPS] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
593
594 List<GroupRoleMembersData> data = m_groupData.GetGroupRoleMembers(groupID);
595
596 foreach (GroupRoleMembersData member in data)
597 {
598 m_log.InfoFormat("[GROUPS] Av: {0} Role: {1}", member.MemberID, member.RoleID);
599 }
600
601 return data;
602
603
604 }
605
606 public GroupProfileData GroupProfileRequest(IClientAPI remoteClient, UUID groupID)
607 {
608 if (m_debugEnabled) m_log.InfoFormat("[GROUPS] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
609
610 GroupProfileData profile = new GroupProfileData();
611
612 GroupRecord groupInfo = m_groupData.GetGroupRecord(groupID, null);
613 if (groupInfo != null)
614 {
615 profile.AllowPublish = groupInfo.AllowPublish;
616 profile.Charter = groupInfo.Charter;
617 profile.FounderID = groupInfo.FounderID;
618 profile.GroupID = groupID;
619 profile.GroupMembershipCount = m_groupData.GetGroupMembers(groupID).Count;
620 profile.GroupRolesCount = m_groupData.GetGroupRoles(groupID).Count;
621 profile.InsigniaID = groupInfo.GroupPicture;
622 profile.MaturePublish = groupInfo.MaturePublish;
623 profile.MembershipFee = groupInfo.MembershipFee;
624 profile.Money = 0; // TODO: Get this from the currency server?
625 profile.Name = groupInfo.GroupName;
626 profile.OpenEnrollment = groupInfo.OpenEnrollment;
627 profile.OwnerRole = groupInfo.OwnerRoleID;
628 profile.ShowInList = groupInfo.ShowInList;
629 }
630
631 GroupMembershipData memberInfo = m_groupData.GetAgentGroupMembership(remoteClient.AgentId, groupID);
632 if (memberInfo != null)
633 {
634 profile.MemberTitle = memberInfo.GroupTitle;
635 profile.PowersMask = memberInfo.GroupPowers;
636 }
637
638 return profile;
639 }
640
641 public GroupMembershipData[] GetMembershipData(UUID UserID)
642 {
643 if (m_debugEnabled) m_log.InfoFormat("[GROUPS] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
644
645 return m_groupData.GetAgentGroupMemberships(UserID).ToArray();
646 }
647
648 public GroupMembershipData GetMembershipData(UUID GroupID, UUID UserID)
649 {
650 if (m_debugEnabled) m_log.InfoFormat("[GROUPS] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
651
652 return m_groupData.GetAgentGroupMembership(UserID, GroupID);
653 }
654
655 public void UpdateGroupInfo(IClientAPI remoteClient, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish)
656 {
657 if (m_debugEnabled) m_log.InfoFormat("[GROUPS] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
658
659 // TODO: Security Check?
660
661 m_groupData.UpdateGroup(groupID, charter, showInList, insigniaID, membershipFee, openEnrollment, allowPublish, maturePublish);
662 }
663
664 public void SetGroupAcceptNotices(IClientAPI remoteClient, UUID groupID, bool acceptNotices, bool listInProfile)
665 {
666 // TODO: Security Check?
667 if (m_debugEnabled) m_log.InfoFormat("[GROUPS] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
668
669 m_groupData.SetAgentGroupInfo(remoteClient.AgentId, groupID, acceptNotices, listInProfile);
670 }
671
672 public UUID CreateGroup(IClientAPI remoteClient, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish)
673 {
674 if (m_debugEnabled) m_log.InfoFormat("[GROUPS] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
675
676 if( m_groupData.GetGroupRecord(UUID.Zero, name) != null )
677 {
678 remoteClient.SendCreateGroupReply(UUID.Zero, false, "A group with the same name already exists.");
679 return UUID.Zero;
680 }
681
682 UUID GroupID = m_groupData.CreateGroup(name, charter, showInList, insigniaID, membershipFee, openEnrollment, allowPublish, maturePublish, remoteClient.AgentId);
683
684 remoteClient.SendCreateGroupReply(GroupID, true, "Group created successfullly");
685
686 UpdateClientWithGroupInfo(remoteClient);
687
688 return GroupID;
689 }
690
691 public GroupNoticeData[] GroupNoticesListRequest(IClientAPI remoteClient, UUID GroupID)
692 {
693 if (m_debugEnabled) m_log.InfoFormat("[GROUPS] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
694
695 // ToDo: check if agent is a member of group and is allowed to see notices?
696
697 return m_groupData.GetGroupNotices(GroupID).ToArray();
698 }
699
700 /// <summary>
701 /// Get the title of the agent's current role.
702 /// </summary>
703 public string GetGroupTitle(UUID avatarID)
704 {
705 if (m_debugEnabled) m_log.InfoFormat("[GROUPS] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
706
707 GroupMembershipData membership = m_groupData.GetAgentActiveMembership(avatarID);
708 if (membership != null)
709 {
710 return membership.GroupTitle;
711 }
712 return string.Empty;
713 }
714
715 /// <summary>
716 /// Change the current Active Group Role for Agent
717 /// </summary>
718 public void GroupTitleUpdate(IClientAPI remoteClient, UUID GroupID, UUID TitleRoleID)
719 {
720 if (m_debugEnabled) m_log.InfoFormat("[GROUPS] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
721
722 m_groupData.SetAgentActiveGroupRole(remoteClient.AgentId, GroupID, TitleRoleID);
723
724 UpdateAllClientsWithGroupInfo();
725 }
726
727
728 public void GroupRoleUpdate(IClientAPI remoteClient, UUID groupID, UUID roleID, string name, string description, string title, ulong powers, byte updateType)
729 {
730 if (m_debugEnabled) m_log.InfoFormat("[GROUPS] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
731
732 // TODO: Security Checks?
733
734 switch ((OpenMetaverse.GroupRoleUpdate)updateType)
735 {
736 case OpenMetaverse.GroupRoleUpdate.Create:
737 m_groupData.AddGroupRole(groupID, UUID.Random(), name, description, title, powers);
738 break;
739
740 case OpenMetaverse.GroupRoleUpdate.Delete:
741 m_groupData.RemoveGroupRole(groupID, roleID);
742 break;
743
744 case OpenMetaverse.GroupRoleUpdate.UpdateAll:
745 case OpenMetaverse.GroupRoleUpdate.UpdateData:
746 case OpenMetaverse.GroupRoleUpdate.UpdatePowers:
747 m_groupData.UpdateGroupRole(groupID, roleID, name, description, title, powers);
748 break;
749
750 case OpenMetaverse.GroupRoleUpdate.NoUpdate:
751 default:
752 // No Op
753 break;
754
755 }
756
757 UpdateClientWithGroupInfo(remoteClient);
758 }
759
760 public void GroupRoleChanges(IClientAPI remoteClient, UUID groupID, UUID roleID, UUID memberID, uint changes)
761 {
762 if (m_debugEnabled) m_log.InfoFormat("[GROUPS] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
763 // Todo: Security check
764
765 switch (changes)
766 {
767 case 0:
768 // Add
769 m_groupData.AddAgentToGroupRole(memberID, groupID, roleID);
770
771 break;
772 case 1:
773 // Remove
774 m_groupData.RemoveAgentFromGroupRole(memberID, groupID, roleID);
775
776 break;
777 default:
778 m_log.ErrorFormat("[GROUPS] {0} does not understand changes == {1}", System.Reflection.MethodBase.GetCurrentMethod().Name, changes);
779 break;
780 }
781 UpdateClientWithGroupInfo(remoteClient);
782 }
783
784 public void GroupNoticeRequest(IClientAPI remoteClient, UUID groupNoticeID)
785 {
786 if (m_debugEnabled) m_log.InfoFormat("[GROUPS] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
787
788
789 GroupNoticeInfo data = m_groupData.GetGroupNotice(groupNoticeID);
790
791 if (data != null)
792 {
793 if (m_MsgTransferModule != null)
794 {
795 GridInstantMessage msg = new GridInstantMessage();
796 msg.imSessionID = UUID.Zero.Guid;
797 msg.fromAgentID = data.GroupID.Guid;
798 msg.toAgentID = remoteClient.AgentId.Guid;
799 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
800 msg.fromAgentName = "Group Notice From";
801 msg.message = data.noticeData.Subject + "|" + data.Message;
802 msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.GroupNoticeRequested;
803 msg.fromGroup = true;
804 msg.offline = (byte)0;
805 msg.ParentEstateID = 0;
806 msg.Position = Vector3.Zero;
807 msg.RegionID = UUID.Zero.Guid;
808 msg.binaryBucket = data.BinaryBucket;
809
810 m_MsgTransferModule.SendInstantMessage(msg, delegate(bool success) { });
811 }
812 }
813
814 }
815
816 public GridInstantMessage CreateGroupNoticeIM(UUID agentID, UUID groupNoticeID, byte dialog)
817 {
818 m_log.WarnFormat("[GROUPS] {0} is probably not properly implemented", System.Reflection.MethodBase.GetCurrentMethod().Name);
819
820 GridInstantMessage msg = new GridInstantMessage();
821 msg.imSessionID = UUID.Zero.Guid;
822 msg.toAgentID = agentID.Guid;
823 msg.dialog = dialog;
824 // msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.GroupNotice;
825 msg.fromGroup = true;
826 msg.offline = (byte)0;
827 msg.ParentEstateID = 0;
828 msg.Position = Vector3.Zero;
829 msg.RegionID = UUID.Zero.Guid;
830
831 GroupNoticeInfo info = m_groupData.GetGroupNotice(groupNoticeID);
832 if (info != null)
833 {
834 msg.fromAgentID = info.GroupID.Guid;
835 msg.timestamp = info.noticeData.Timestamp;
836 msg.fromAgentName = info.noticeData.FromName;
837 msg.message = info.noticeData.Subject + "|" + info.Message;
838 msg.binaryBucket = info.BinaryBucket;
839 }
840
841 return msg;
842 }
843
844 public void SendAgentGroupDataUpdate(IClientAPI remoteClient)
845 {
846 if (m_debugEnabled) m_log.InfoFormat("[GROUPS] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
847
848 UpdateClientWithGroupInfo(remoteClient);
849 }
850
851 public void JoinGroupRequest(IClientAPI remoteClient, UUID groupID)
852 {
853 if (m_debugEnabled) m_log.InfoFormat("[GROUPS] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
854
855 // Should check to see if OpenEnrollment, or if there's an outstanding invitation
856 m_groupData.AddAgentToGroup(remoteClient.AgentId, groupID, UUID.Zero);
857
858 remoteClient.SendJoinGroupReply(groupID, true);
859
860 UpdateClientWithGroupInfo(remoteClient);
861 }
862
863 public void LeaveGroupRequest(IClientAPI remoteClient, UUID GroupID)
864 {
865 if (m_debugEnabled) m_log.InfoFormat("[GROUPS] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
866
867 m_groupData.RemoveAgentFromGroup(remoteClient.AgentId, GroupID);
868
869 remoteClient.SendLeaveGroupReply(GroupID, true);
870
871 remoteClient.SendAgentDropGroup(GroupID);
872
873 UpdateClientWithGroupInfo(remoteClient);
874 }
875
876 public void EjectGroupMemberRequest(IClientAPI remoteClient, UUID GroupID, UUID EjecteeID)
877 {
878 if (m_debugEnabled) m_log.InfoFormat("[GROUPS] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
879
880 // Todo: Security check?
881 m_groupData.RemoveAgentFromGroup(EjecteeID, GroupID);
882
883 remoteClient.SendEjectGroupMemberReply(remoteClient.AgentId, GroupID, true);
884
885 if (m_MsgTransferModule != null)
886 {
887 GroupRecord groupInfo = m_groupData.GetGroupRecord(GroupID, null);
888 UserProfileData userProfile = m_SceneList[0].CommsManager.UserService.GetUserProfile(EjecteeID);
889
890 if ((groupInfo == null) || (userProfile == null))
891 {
892 return;
893 }
894
895
896 // Send Message to Ejectee
897 GridInstantMessage msg = new GridInstantMessage();
898
899 msg.imSessionID = UUID.Zero.Guid;
900 msg.fromAgentID = remoteClient.AgentId.Guid;
901 // msg.fromAgentID = info.GroupID;
902 msg.toAgentID = EjecteeID.Guid;
903 //msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
904 msg.timestamp = 0;
905 msg.fromAgentName = remoteClient.Name;
906 msg.message = string.Format("You have been ejected from '{1}' by {0}.", remoteClient.Name, groupInfo.GroupName);
907 msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.MessageFromAgent;
908 msg.fromGroup = false;
909 msg.offline = (byte)0;
910 msg.ParentEstateID = 0;
911 msg.Position = Vector3.Zero;
912 msg.RegionID = remoteClient.Scene.RegionInfo.RegionID.Guid;
913 msg.binaryBucket = new byte[0];
914 m_MsgTransferModule.SendInstantMessage(msg, delegate(bool success) { m_log.DebugFormat("[GROUPS] Message Sent Success: {0}", success,ToString()); });
915
916
917 // Message to ejector
918 // Interop, received special 210 code for ejecting a group member
919 // this only works within the comms servers domain, and won't work hypergrid
920 // TODO:FIXME: Use a presense server of some kind to find out where the
921 // client actually is, and try contacting that region directly to notify them,
922 // or provide the notification via xmlrpc update queue
923
924 msg = new GridInstantMessage();
925 msg.imSessionID = UUID.Zero.Guid;
926 msg.fromAgentID = remoteClient.AgentId.Guid;
927 msg.toAgentID = remoteClient.AgentId.Guid;
928 msg.timestamp = 0;
929 msg.fromAgentName = remoteClient.Name;
930 if (userProfile != null)
931 {
932 msg.message = string.Format("{2} has been ejected from '{1}' by {0}.", remoteClient.Name, groupInfo.GroupName, userProfile.Name);
933 }
934 else
935 {
936 msg.message = string.Format("{2} has been ejected from '{1}' by {0}.", remoteClient.Name, groupInfo.GroupName, "Unknown member");
937 }
938 msg.dialog = (byte)210; //interop
939 msg.fromGroup = false;
940 msg.offline = (byte)0;
941 msg.ParentEstateID = 0;
942 msg.Position = Vector3.Zero;
943 msg.RegionID = remoteClient.Scene.RegionInfo.RegionID.Guid;
944 msg.binaryBucket = new byte[0];
945 m_MsgTransferModule.SendInstantMessage(msg, delegate(bool success) { m_log.DebugFormat("[GROUPS] Message Sent Success: {0}", success, ToString()); });
946
947
948
949 }
950
951
952 UpdateAllClientsWithGroupInfo();
953 }
954
955 public void InviteGroupRequest(IClientAPI remoteClient, UUID GroupID, UUID InvitedAgentID, UUID RoleID)
956 {
957 if (m_debugEnabled) m_log.InfoFormat("[GROUPS] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
958 m_log.WarnFormat("[GROUPS] GID {0}, AID {1}, RID {2} ", GroupID, InvitedAgentID, RoleID);
959
960 // Todo: Security check, probably also want to send some kind of notification
961 UUID InviteID = UUID.Random();
962 m_log.WarnFormat("[GROUPS] Invite ID: {0}", InviteID);
963 m_groupData.AddAgentToGroupInvite(InviteID, GroupID, RoleID, InvitedAgentID);
964
965 if (m_MsgTransferModule != null)
966 {
967 Guid inviteUUID = InviteID.Guid;
968
969 GridInstantMessage msg = new GridInstantMessage();
970
971 msg.imSessionID = inviteUUID;
972
973 // msg.fromAgentID = remoteClient.AgentId.Guid;
974 msg.fromAgentID = GroupID.Guid;
975 msg.toAgentID = InvitedAgentID.Guid;
976 //msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
977 msg.timestamp = 0;
978 msg.fromAgentName = remoteClient.Name;
979 msg.message = string.Format("{0} has invited you to join a group. There is no cost to join this group.", remoteClient.Name);
980 msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.GroupInvitation;
981 msg.fromGroup = true;
982 msg.offline = (byte)0;
983 msg.ParentEstateID = 0;
984 msg.Position = Vector3.Zero;
985 msg.RegionID = remoteClient.Scene.RegionInfo.RegionID.Guid;
986 msg.binaryBucket = new byte[20];
987
988 m_MsgTransferModule.SendInstantMessage(msg, delegate(bool success) { m_log.DebugFormat("[GROUPS] Message Sent Success: {0}", success,ToString()); });
989 }
990 }
991
992 #endregion
993
994 void SendGroupMembershipInfoViaCaps(IClientAPI remoteClient, GroupMembershipData[] data)
995 {
996 if (m_debugEnabled) m_log.InfoFormat("[GROUPS] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
997
998 OSDArray AgentData = new OSDArray(1);
999 OSDMap AgentDataMap = new OSDMap(1);
1000 AgentDataMap.Add("AgentID", OSD.FromUUID(remoteClient.AgentId));
1001 AgentData.Add(AgentDataMap);
1002
1003
1004 OSDArray GroupData = new OSDArray(data.Length);
1005 OSDArray NewGroupData = new OSDArray(data.Length);
1006
1007 foreach (GroupMembershipData membership in data)
1008 {
1009 OSDMap GroupDataMap = new OSDMap(6);
1010 OSDMap NewGroupDataMap = new OSDMap(1);
1011
1012 GroupDataMap.Add("GroupID", OSD.FromUUID(membership.GroupID));
1013 GroupDataMap.Add("GroupPowers", OSD.FromBinary(membership.GroupPowers));
1014 GroupDataMap.Add("AcceptNotices", OSD.FromBoolean(membership.AcceptNotices));
1015 GroupDataMap.Add("GroupInsigniaID", OSD.FromUUID(membership.GroupPicture));
1016 GroupDataMap.Add("Contribution", OSD.FromInteger(membership.Contribution));
1017 GroupDataMap.Add("GroupName", OSD.FromString(membership.GroupName));
1018 NewGroupDataMap.Add("ListInProfile", OSD.FromBoolean(membership.ListInProfile));
1019
1020 GroupData.Add(GroupDataMap);
1021 NewGroupData.Add(NewGroupDataMap);
1022 }
1023
1024 OSDMap llDataStruct = new OSDMap(3);
1025 llDataStruct.Add("AgentData", AgentData);
1026 llDataStruct.Add("GroupData", GroupData);
1027 llDataStruct.Add("NewGroupData", NewGroupData);
1028
1029 IEventQueue queue = remoteClient.Scene.RequestModuleInterface<IEventQueue>();
1030
1031 if (queue != null)
1032 {
1033 queue.Enqueue(EventQueueHelper.buildEvent("AgentGroupDataUpdate", llDataStruct), remoteClient.AgentId);
1034 }
1035
1036 }
1037 }
1038
1039}