clockwerk-opensim – 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.Generic;
30 using System.Reflection;
31 using System.Timers;
32 using log4net;
33 using Nini.Config;
34  
35 using OpenMetaverse;
36 using OpenSim.Data;
37 using OpenSim.Framework;
38 using OpenSim.Services.Interfaces;
39  
40 namespace OpenSim.Groups
41 {
42 public class HGGroupsService : GroupsService
43 {
44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
45  
46 private IOfflineIMService m_OfflineIM;
47 private IUserAccountService m_UserAccounts;
48 private string m_HomeURI;
49  
50 public HGGroupsService(IConfigSource config, IOfflineIMService im, IUserAccountService users, string homeURI)
51 : base(config, string.Empty)
52 {
53 m_OfflineIM = im;
54 m_UserAccounts = users;
55 m_HomeURI = homeURI;
56 if (!m_HomeURI.EndsWith("/"))
57 m_HomeURI += "/";
58 }
59  
60  
61 #region HG specific operations
62  
63 public bool CreateGroupProxy(string RequestingAgentID, string agentID, string accessToken, UUID groupID, string serviceLocation, string name, out string reason)
64 {
65 reason = string.Empty;
66 Uri uri = null;
67 try
68 {
69 uri = new Uri(serviceLocation);
70 }
71 catch (UriFormatException)
72 {
73 reason = "Bad location for group proxy";
74 return false;
75 }
76  
77 // Check if it already exists
78 GroupData grec = m_Database.RetrieveGroup(groupID);
79 if (grec == null ||
80 (grec != null && grec.Data["Location"] != string.Empty && grec.Data["Location"].ToLower() != serviceLocation.ToLower()))
81 {
82 // Create the group
83 grec = new GroupData();
84 grec.GroupID = groupID;
85 grec.Data = new Dictionary<string, string>();
86 grec.Data["Name"] = name + " @ " + uri.Authority;
87 grec.Data["Location"] = serviceLocation;
88 grec.Data["Charter"] = string.Empty;
89 grec.Data["InsigniaID"] = UUID.Zero.ToString();
90 grec.Data["FounderID"] = UUID.Zero.ToString();
91 grec.Data["MembershipFee"] = "0";
92 grec.Data["OpenEnrollment"] = "0";
93 grec.Data["ShowInList"] = "0";
94 grec.Data["AllowPublish"] = "0";
95 grec.Data["MaturePublish"] = "0";
96 grec.Data["OwnerRoleID"] = UUID.Zero.ToString();
97  
98  
99 if (!m_Database.StoreGroup(grec))
100 return false;
101 }
102  
103 if (grec.Data["Location"] == string.Empty)
104 {
105 reason = "Cannot add proxy membership to non-proxy group";
106 return false;
107 }
108  
109 UUID uid = UUID.Zero;
110 string url = string.Empty, first = string.Empty, last = string.Empty, tmp = string.Empty;
111 Util.ParseUniversalUserIdentifier(RequestingAgentID, out uid, out url, out first, out last, out tmp);
112 string fromName = first + "." + last + "@" + url;
113  
114 // Invite to group again
115 InviteToGroup(fromName, groupID, new UUID(agentID), grec.Data["Name"]);
116  
117 // Stick the proxy membership in the DB already
118 // we'll delete it if the agent declines the invitation
119 MembershipData membership = new MembershipData();
120 membership.PrincipalID = agentID;
121 membership.GroupID = groupID;
122 membership.Data = new Dictionary<string, string>();
123 membership.Data["SelectedRoleID"] = UUID.Zero.ToString();
124 membership.Data["Contribution"] = "0";
125 membership.Data["ListInProfile"] = "1";
126 membership.Data["AcceptNotices"] = "1";
127 membership.Data["AccessToken"] = accessToken;
128  
129 m_Database.StoreMember(membership);
130  
131 return true;
132 }
133  
134 public bool RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID, string token)
135 {
136 // check the token
137 MembershipData membership = m_Database.RetrieveMember(GroupID, AgentID);
138 if (membership != null)
139 {
140 if (token != string.Empty && token.Equals(membership.Data["AccessToken"]))
141 {
142 return RemoveAgentFromGroup(RequestingAgentID, AgentID, GroupID);
143 }
144 else
145 {
146 m_log.DebugFormat("[Groups.HGGroupsService]: access token {0} did not match stored one {1}", token, membership.Data["AccessToken"]);
147 return false;
148 }
149 }
150 else
151 {
152 m_log.DebugFormat("[Groups.HGGroupsService]: membership not found for {0}", AgentID);
153 return false;
154 }
155 }
156  
157 public ExtendedGroupRecord GetGroupRecord(string RequestingAgentID, UUID GroupID, string groupName, string token)
158 {
159 // check the token
160 if (!VerifyToken(GroupID, RequestingAgentID, token))
161 return null;
162  
163 ExtendedGroupRecord grec;
164 if (GroupID == UUID.Zero)
165 grec = GetGroupRecord(RequestingAgentID, groupName);
166 else
167 grec = GetGroupRecord(RequestingAgentID, GroupID);
168  
169 if (grec != null)
170 FillFounderUUI(grec);
171  
172 return grec;
173 }
174  
175 public List<ExtendedGroupMembersData> GetGroupMembers(string RequestingAgentID, UUID GroupID, string token)
176 {
177 if (!VerifyToken(GroupID, RequestingAgentID, token))
178 return new List<ExtendedGroupMembersData>();
179  
180 List<ExtendedGroupMembersData> members = GetGroupMembers(RequestingAgentID, GroupID);
181  
182 // convert UUIDs to UUIs
183 members.ForEach(delegate (ExtendedGroupMembersData m)
184 {
185 if (m.AgentID.ToString().Length == 36) // UUID
186 {
187 UserAccount account = m_UserAccounts.GetUserAccount(UUID.Zero, new UUID(m.AgentID));
188 if (account != null)
189 m.AgentID = Util.UniversalIdentifier(account.PrincipalID, account.FirstName, account.LastName, m_HomeURI);
190 }
191 });
192  
193 return members;
194 }
195  
196 public List<GroupRolesData> GetGroupRoles(string RequestingAgentID, UUID GroupID, string token)
197 {
198 if (!VerifyToken(GroupID, RequestingAgentID, token))
199 return new List<GroupRolesData>();
200  
201 return GetGroupRoles(RequestingAgentID, GroupID);
202 }
203  
204 public List<ExtendedGroupRoleMembersData> GetGroupRoleMembers(string RequestingAgentID, UUID GroupID, string token)
205 {
206 if (!VerifyToken(GroupID, RequestingAgentID, token))
207 return new List<ExtendedGroupRoleMembersData>();
208  
209 List<ExtendedGroupRoleMembersData> rolemembers = GetGroupRoleMembers(RequestingAgentID, GroupID);
210  
211 // convert UUIDs to UUIs
212 rolemembers.ForEach(delegate(ExtendedGroupRoleMembersData m)
213 {
214 if (m.MemberID.ToString().Length == 36) // UUID
215 {
216 UserAccount account = m_UserAccounts.GetUserAccount(UUID.Zero, new UUID(m.MemberID));
217 if (account != null)
218 m.MemberID = Util.UniversalIdentifier(account.PrincipalID, account.FirstName, account.LastName, m_HomeURI);
219 }
220 });
221  
222 return rolemembers;
223 }
224  
225 public bool AddNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message,
226 bool hasAttachment, byte attType, string attName, UUID attItemID, string attOwnerID)
227 {
228 // check that the group proxy exists
229 ExtendedGroupRecord grec = GetGroupRecord(RequestingAgentID, groupID);
230 if (grec == null)
231 {
232 m_log.DebugFormat("[Groups.HGGroupsService]: attempt at adding notice to non-existent group proxy");
233 return false;
234 }
235  
236 // check that the group is remote
237 if (grec.ServiceLocation == string.Empty)
238 {
239 m_log.DebugFormat("[Groups.HGGroupsService]: attempt at adding notice to local (non-proxy) group");
240 return false;
241 }
242  
243 // check that there isn't already a notice with the same ID
244 if (GetGroupNotice(RequestingAgentID, noticeID) != null)
245 {
246 m_log.DebugFormat("[Groups.HGGroupsService]: a notice with the same ID already exists", grec.ServiceLocation);
247 return false;
248 }
249  
250 // This has good intentions (security) but it will potentially DDS the origin...
251 // We'll need to send a proof along with the message. Maybe encrypt the message
252 // using key pairs
253 //
254 //// check that the notice actually exists in the origin
255 //GroupsServiceHGConnector c = new GroupsServiceHGConnector(grec.ServiceLocation);
256 //if (!c.VerifyNotice(noticeID, groupID))
257 //{
258 // m_log.DebugFormat("[Groups.HGGroupsService]: notice does not exist at origin {0}", grec.ServiceLocation);
259 // return false;
260 //}
261  
262 // ok, we're good!
263 return _AddNotice(groupID, noticeID, fromName, subject, message, hasAttachment, attType, attName, attItemID, attOwnerID);
264 }
265  
266 public bool VerifyNotice(UUID noticeID, UUID groupID)
267 {
268 GroupNoticeInfo notice = GetGroupNotice(string.Empty, noticeID);
269  
270 if (notice == null)
271 return false;
272  
273 if (notice.GroupID != groupID)
274 return false;
275  
276 return true;
277 }
278  
279 #endregion
280  
281 private void InviteToGroup(string fromName, UUID groupID, UUID invitedAgentID, string groupName)
282 {
283 // Todo: Security check, probably also want to send some kind of notification
284 UUID InviteID = UUID.Random();
285  
286 if (AddAgentToGroupInvite(InviteID, groupID, invitedAgentID.ToString()))
287 {
288 Guid inviteUUID = InviteID.Guid;
289  
290 GridInstantMessage msg = new GridInstantMessage();
291  
292 msg.imSessionID = inviteUUID;
293  
294 // msg.fromAgentID = agentID.Guid;
295 msg.fromAgentID = groupID.Guid;
296 msg.toAgentID = invitedAgentID.Guid;
297 //msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
298 msg.timestamp = 0;
299 msg.fromAgentName = fromName;
300 msg.message = string.Format("Please confirm your acceptance to join group {0}.", groupName);
301 msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.GroupInvitation;
302 msg.fromGroup = true;
303 msg.offline = (byte)0;
304 msg.ParentEstateID = 0;
305 msg.Position = Vector3.Zero;
306 msg.RegionID = UUID.Zero.Guid;
307 msg.binaryBucket = new byte[20];
308  
309 string reason = string.Empty;
310 m_OfflineIM.StoreMessage(msg, out reason);
311  
312 }
313 }
314  
315 private bool AddAgentToGroupInvite(UUID inviteID, UUID groupID, string agentID)
316 {
317 // Check whether the invitee is already a member of the group
318 MembershipData m = m_Database.RetrieveMember(groupID, agentID);
319 if (m != null)
320 return false;
321  
322 // Check whether there are pending invitations and delete them
323 InvitationData invite = m_Database.RetrieveInvitation(groupID, agentID);
324 if (invite != null)
325 m_Database.DeleteInvite(invite.InviteID);
326  
327 invite = new InvitationData();
328 invite.InviteID = inviteID;
329 invite.PrincipalID = agentID;
330 invite.GroupID = groupID;
331 invite.RoleID = UUID.Zero;
332 invite.Data = new Dictionary<string, string>();
333  
334 return m_Database.StoreInvitation(invite);
335 }
336  
337 private void FillFounderUUI(ExtendedGroupRecord grec)
338 {
339 UserAccount account = m_UserAccounts.GetUserAccount(UUID.Zero, grec.FounderID);
340 if (account != null)
341 grec.FounderUUI = Util.UniversalIdentifier(account.PrincipalID, account.FirstName, account.LastName, m_HomeURI);
342 }
343  
344 private bool VerifyToken(UUID groupID, string agentID, string token)
345 {
346 // check the token
347 MembershipData membership = m_Database.RetrieveMember(groupID, agentID);
348 if (membership != null)
349 {
350 if (token != string.Empty && token.Equals(membership.Data["AccessToken"]))
351 return true;
352 else
353 m_log.DebugFormat("[Groups.HGGroupsService]: access token {0} did not match stored one {1}", token, membership.Data["AccessToken"]);
354 }
355 else
356 m_log.DebugFormat("[Groups.HGGroupsService]: membership not found for {0}", agentID);
357  
358 return false;
359 }
360 }
361 }