OpenSim
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros
UserManagementModule.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 using System;
28 using System.Collections.Generic;
29 using System.IO;
30 using System.Reflection;
31 using System.Threading;
32 
33 using OpenSim.Framework;
34 using OpenSim.Framework.Console;
35 using OpenSim.Framework.Monitoring;
36 using OpenSim.Region.ClientStack.LindenUDP;
37 using OpenSim.Region.Framework;
38 using OpenSim.Region.Framework.Interfaces;
39 using OpenSim.Region.Framework.Scenes;
40 using OpenSim.Services.Interfaces;
41 using OpenSim.Services.Connectors.Hypergrid;
42 
43 using OpenMetaverse;
44 using OpenMetaverse.Packets;
45 using log4net;
46 using Nini.Config;
47 using Mono.Addins;
48 
50 
51 namespace OpenSim.Region.CoreModules.Framework.UserManagement
52 {
53  [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "UserManagementModule")]
55  {
56  private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
57 
58  protected bool m_Enabled;
59  protected List<Scene> m_Scenes = new List<Scene>();
60 
62  // The cache
63  protected Dictionary<UUID, UserData> m_UserCache = new Dictionary<UUID, UserData>();
64 
65  protected bool m_DisplayChangingHomeURI = false;
66 
67  #region ISharedRegionModule
68 
69  public void Initialise(IConfigSource config)
70  {
71  string umanmod = config.Configs["Modules"].GetString("UserManagementModule", Name);
72  if (umanmod == Name)
73  {
74  m_Enabled = true;
75  Init();
76  m_log.DebugFormat("[USER MANAGEMENT MODULE]: {0} is enabled", Name);
77  }
78 
79  if(!m_Enabled)
80  {
81  return;
82  }
83 
84  IConfig userManagementConfig = config.Configs["UserManagement"];
85  if (userManagementConfig == null)
86  return;
87 
88  m_DisplayChangingHomeURI = userManagementConfig.GetBoolean("DisplayChangingHomeURI", false);
89  }
90 
91  public bool IsSharedModule
92  {
93  get { return true; }
94  }
95 
96  public virtual string Name
97  {
98  get { return "BasicUserManagementModule"; }
99  }
100 
101  public Type ReplaceableInterface
102  {
103  get { return null; }
104  }
105 
106  public void AddRegion(Scene scene)
107  {
108  if (m_Enabled)
109  {
110  lock (m_Scenes)
111  {
112  m_Scenes.Add(scene);
113  }
114 
115  scene.RegisterModuleInterface<IUserManagement>(this);
116  scene.RegisterModuleInterface<IPeople>(this);
117  scene.EventManager.OnNewClient += new EventManager.OnNewClientDelegate(EventManager_OnNewClient);
118  scene.EventManager.OnPrimsLoaded += new EventManager.PrimsLoaded(EventManager_OnPrimsLoaded);
119  }
120  }
121 
122  public void RemoveRegion(Scene scene)
123  {
124  if (m_Enabled)
125  {
126  scene.UnregisterModuleInterface<IUserManagement>(this);
127  lock (m_Scenes)
128  {
129  m_Scenes.Remove(scene);
130  }
131  }
132  }
133 
134  public void RegionLoaded(Scene s)
135  {
136  if (m_Enabled && m_ServiceThrottle == null)
137  m_ServiceThrottle = s.RequestModuleInterface<IServiceThrottleModule>();
138  }
139 
140  public void PostInitialise()
141  {
142  }
143 
144  public void Close()
145  {
146  lock (m_Scenes)
147  {
148  m_Scenes.Clear();
149  }
150 
151  lock (m_UserCache)
152  m_UserCache.Clear();
153  }
154 
155  #endregion ISharedRegionModule
156 
157 
158  #region Event Handlers
159 
160  void EventManager_OnPrimsLoaded(Scene s)
161  {
162  // let's sniff all the user names referenced by objects in the scene
163  m_log.DebugFormat("[USER MANAGEMENT MODULE]: Caching creators' data from {0} ({1} objects)...", s.RegionInfo.RegionName, s.GetEntities().Length);
164  s.ForEachSOG(delegate(SceneObjectGroup sog) { CacheCreators(sog); });
165  }
166 
167  void EventManager_OnNewClient(IClientAPI client)
168  {
169  client.OnConnectionClosed += new Action<IClientAPI>(HandleConnectionClosed);
170  client.OnNameFromUUIDRequest += new UUIDNameRequest(HandleUUIDNameRequest);
171  client.OnAvatarPickerRequest += new AvatarPickerRequest(HandleAvatarPickerRequest);
172  }
173 
174  void HandleConnectionClosed(IClientAPI client)
175  {
176  client.OnNameFromUUIDRequest -= new UUIDNameRequest(HandleUUIDNameRequest);
177  client.OnAvatarPickerRequest -= new AvatarPickerRequest(HandleAvatarPickerRequest);
178  }
179 
180  void HandleUUIDNameRequest(UUID uuid, IClientAPI client)
181  {
182 // m_log.DebugFormat(
183 // "[USER MANAGEMENT MODULE]: Handling request for name binding of UUID {0} from {1}",
184 // uuid, remote_client.Name);
185  if(m_Scenes.Count <= 0)
186  return;
187 
188  if (m_Scenes[0].LibraryService != null && (m_Scenes[0].LibraryService.LibraryRootFolder.Owner == uuid))
189  {
190  client.SendNameReply(uuid, "Mr", "OpenSim");
191  }
192  else
193  {
194  UserData user;
195  /* bypass that continuation here when entry is already available */
196  lock (m_UserCache)
197  {
198  if (m_UserCache.TryGetValue(uuid, out user))
199  {
200  if (!user.IsUnknownUser && user.HasGridUserTried)
201  {
202  client.SendNameReply(uuid, user.FirstName, user.LastName);
203  return;
204  }
205  }
206  }
207 
208  // Not found in cache, queue continuation
209  m_ServiceThrottle.Enqueue("name", uuid.ToString(), delegate
210  {
211  //m_log.DebugFormat("[YYY]: Name request {0}", uuid);
212 
213  // As least upto September 2013, clients permanently cache UUID -> Name bindings. Some clients
214  // appear to clear this when the user asks it to clear the cache, but others may not.
215  //
216  // So to avoid clients
217  // (particularly Hypergrid clients) permanently binding "Unknown User" to a given UUID, we will
218  // instead drop the request entirely.
219  if (GetUser(uuid, out user))
220  {
221  client.SendNameReply(uuid, user.FirstName, user.LastName);
222  }
223 // else
224 // m_log.DebugFormat(
225 // "[USER MANAGEMENT MODULE]: No bound name for {0} found, ignoring request from {1}",
226 // uuid, client.Name);
227  });
228  }
229  }
230 
231  public void HandleAvatarPickerRequest(IClientAPI client, UUID avatarID, UUID RequestID, string query)
232  {
233  //EventManager.TriggerAvatarPickerRequest();
234 
235  m_log.DebugFormat("[USER MANAGEMENT MODULE]: HandleAvatarPickerRequest for {0}", query);
236 
237  List<UserData> users = GetUserData(query, 500, 1);
238 
239  AvatarPickerReplyPacket replyPacket = (AvatarPickerReplyPacket)PacketPool.Instance.GetPacket(PacketType.AvatarPickerReply);
240  // TODO: don't create new blocks if recycling an old packet
241 
242  AvatarPickerReplyPacket.DataBlock[] searchData =
243  new AvatarPickerReplyPacket.DataBlock[users.Count];
244  AvatarPickerReplyPacket.AgentDataBlock agentData = new AvatarPickerReplyPacket.AgentDataBlock();
245 
246  agentData.AgentID = avatarID;
247  agentData.QueryID = RequestID;
248  replyPacket.AgentData = agentData;
249  //byte[] bytes = new byte[AvatarResponses.Count*32];
250 
251  int i = 0;
252  foreach (UserData item in users)
253  {
254  UUID translatedIDtem = item.Id;
255  searchData[i] = new AvatarPickerReplyPacket.DataBlock();
256  searchData[i].AvatarID = translatedIDtem;
257  searchData[i].FirstName = Utils.StringToBytes((string)item.FirstName);
258  searchData[i].LastName = Utils.StringToBytes((string)item.LastName);
259  i++;
260  }
261  if (users.Count == 0)
262  {
263  searchData = new AvatarPickerReplyPacket.DataBlock[0];
264  }
265  replyPacket.Data = searchData;
266 
268  agent_data.AgentID = replyPacket.AgentData.AgentID;
269  agent_data.QueryID = replyPacket.AgentData.QueryID;
270 
271  List<AvatarPickerReplyDataArgs> data_args = new List<AvatarPickerReplyDataArgs>();
272  for (i = 0; i < replyPacket.Data.Length; i++)
273  {
275  data_arg.AvatarID = replyPacket.Data[i].AvatarID;
276  data_arg.FirstName = replyPacket.Data[i].FirstName;
277  data_arg.LastName = replyPacket.Data[i].LastName;
278  data_args.Add(data_arg);
279  }
280  client.SendAvatarPickerReply(agent_data, data_args);
281  }
282 
283  protected virtual void AddAdditionalUsers(string query, List<UserData> users)
284  {
285  }
286 
287  #endregion Event Handlers
288 
289  #region IPeople
290 
291  public List<UserData> GetUserData(string query, int page_size, int page_number)
292  {
293  if(m_Scenes.Count <= 0)
294  return new List<UserData>();;
295 
296  // search the user accounts service
297  List<UserAccount> accs = m_Scenes[0].UserAccountService.GetUserAccounts(m_Scenes[0].RegionInfo.ScopeID, query);
298 
299  List<UserData> users = new List<UserData>();
300  if (accs != null)
301  {
302  foreach (UserAccount acc in accs)
303  {
304  UserData ud = new UserData();
305  ud.FirstName = acc.FirstName;
306  ud.LastName = acc.LastName;
307  ud.Id = acc.PrincipalID;
308  ud.HasGridUserTried = true;
309  ud.IsUnknownUser = false;
310  users.Add(ud);
311  }
312  }
313 
314  // search the local cache
315  foreach (UserData data in m_UserCache.Values)
316  {
317  if (data.Id != UUID.Zero && !data.IsUnknownUser &&
318  users.Find(delegate(UserData d) { return d.Id == data.Id; }) == null &&
319  (data.FirstName.ToLower().StartsWith(query.ToLower()) || data.LastName.ToLower().StartsWith(query.ToLower())))
320  users.Add(data);
321  }
322 
323  AddAdditionalUsers(query, users);
324 
325  return users;
326 
327  }
328 
329  #endregion IPeople
330 
331  private void CacheCreators(SceneObjectGroup sog)
332  {
333  //m_log.DebugFormat("[USER MANAGEMENT MODULE]: processing {0} {1}; {2}", sog.RootPart.Name, sog.RootPart.CreatorData, sog.RootPart.CreatorIdentification);
334  AddUser(sog.RootPart.CreatorID, sog.RootPart.CreatorData);
335 
336  foreach (SceneObjectPart sop in sog.Parts)
337  {
338  AddUser(sop.CreatorID, sop.CreatorData);
339  foreach (TaskInventoryItem item in sop.TaskInventory.Values)
340  AddUser(item.CreatorID, item.CreatorData);
341  }
342  }
343 
350  private bool TryGetUserNames(UUID uuid, string[] names)
351  {
352  if (names == null)
353  names = new string[2];
354 
355  if (TryGetUserNamesFromCache(uuid, names))
356  return true;
357 
358  if (TryGetUserNamesFromServices(uuid, names))
359  return true;
360 
361  return false;
362  }
363 
364  private bool TryGetUserNamesFromCache(UUID uuid, string[] names)
365  {
366  lock (m_UserCache)
367  {
368  if (m_UserCache.ContainsKey(uuid))
369  {
370  names[0] = m_UserCache[uuid].FirstName;
371  names[1] = m_UserCache[uuid].LastName;
372 
373  return true;
374  }
375  }
376 
377  return false;
378  }
379 
386  private bool TryGetUserNamesFromServices(UUID uuid, string[] names)
387  {
388  if(m_Scenes.Count <= 0)
389  return false;
390 
391  UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(UUID.Zero, uuid);
392 
393  if (account != null)
394  {
395  names[0] = account.FirstName;
396  names[1] = account.LastName;
397 
398  UserData user = new UserData();
399  user.FirstName = account.FirstName;
400  user.LastName = account.LastName;
401 
402  lock (m_UserCache)
403  m_UserCache[uuid] = user;
404 
405  return true;
406  }
407  else
408  {
409  // Let's try the GridUser service
410  GridUserInfo uInfo = m_Scenes[0].GridUserService.GetGridUserInfo(uuid.ToString());
411  if (uInfo != null)
412  {
413  string url, first, last, tmp;
414  UUID u;
415  if (Util.ParseUniversalUserIdentifier(uInfo.UserID, out u, out url, out first, out last, out tmp))
416  {
417  AddUser(uuid, first, last, url);
418 
419  if (m_UserCache.ContainsKey(uuid))
420  {
421  names[0] = m_UserCache[uuid].FirstName;
422  names[1] = m_UserCache[uuid].LastName;
423 
424  return true;
425  }
426  }
427  else
428  m_log.DebugFormat("[USER MANAGEMENT MODULE]: Unable to parse UUI {0}", uInfo.UserID);
429  }
430 // else
431 // {
432 // m_log.DebugFormat("[USER MANAGEMENT MODULE]: No grid user found for {0}", uuid);
433 // }
434 
435  names[0] = "Unknown";
436  names[1] = "UserUMMTGUN9";
437 
438  return false;
439  }
440  }
441 
442 
443  #region IUserManagement
444 
445  public UUID GetUserIdByName(string name)
446  {
447  string[] parts = name.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
448  if (parts.Length < 2)
449  throw new Exception("Name must have 2 components");
450 
451  return GetUserIdByName(parts[0], parts[1]);
452  }
453 
454  public UUID GetUserIdByName(string firstName, string lastName)
455  {
456  if(m_Scenes.Count <= 0)
457  return UUID.Zero;
458 
459  // TODO: Optimize for reverse lookup if this gets used by non-console commands.
460  lock (m_UserCache)
461  {
462  foreach (UserData user in m_UserCache.Values)
463  {
464  if (user.FirstName == firstName && user.LastName == lastName)
465  return user.Id;
466  }
467  }
468 
469  UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(UUID.Zero, firstName, lastName);
470 
471  if (account != null)
472  return account.PrincipalID;
473 
474  return UUID.Zero;
475  }
476 
477  public string GetUserName(UUID uuid)
478  {
479  UserData user;
480  GetUser(uuid, out user);
481  return user.FirstName + " " + user.LastName;
482  }
483 
484  public string GetUserHomeURL(UUID userID)
485  {
486  UserData user;
487  if(GetUser(userID, out user))
488  {
489  return user.HomeURL;
490  }
491  return string.Empty;
492  }
493 
494  public string GetUserServerURL(UUID userID, string serverType)
495  {
496  UserData userdata;
497  if(!GetUser(userID, out userdata))
498  {
499  return string.Empty;
500  }
501 
502  if (userdata.ServerURLs != null && userdata.ServerURLs.ContainsKey(serverType) && userdata.ServerURLs[serverType] != null)
503  {
504  return userdata.ServerURLs[serverType].ToString();
505  }
506 
507  if (!string.IsNullOrEmpty(userdata.HomeURL))
508  {
509 // m_log.DebugFormat("[USER MANAGEMENT MODULE]: Requested url type {0} for {1}", serverType, userID);
510 
511  UserAgentServiceConnector uConn = new UserAgentServiceConnector(userdata.HomeURL);
512  try
513  {
514  userdata.ServerURLs = uConn.GetServerURLs(userID);
515  }
516  catch(System.Net.WebException e)
517  {
518  m_log.DebugFormat("[USER MANAGEMENT MODULE]: GetServerURLs call failed {0}", e.Message);
519  userdata.ServerURLs = new Dictionary<string, object>();
520  }
521  catch (Exception e)
522  {
523  m_log.Debug("[USER MANAGEMENT MODULE]: GetServerURLs call failed ", e);
524  userdata.ServerURLs = new Dictionary<string, object>();
525  }
526 
527  if (userdata.ServerURLs != null && userdata.ServerURLs.ContainsKey(serverType) && userdata.ServerURLs[serverType] != null)
528  return userdata.ServerURLs[serverType].ToString();
529  }
530 
531  return string.Empty;
532  }
533 
534  public string GetUserUUI(UUID userID)
535  {
536  string uui;
537  GetUserUUI(userID, out uui);
538  return uui;
539  }
540 
541  public bool GetUserUUI(UUID userID, out string uui)
542  {
543  UserData ud;
544  bool result = GetUser(userID, out ud);
545 
546  if (ud != null)
547  {
548  string homeURL = ud.HomeURL;
549  string first = ud.FirstName, last = ud.LastName;
550  if (ud.LastName.StartsWith("@"))
551  {
552  string[] parts = ud.FirstName.Split('.');
553  if (parts.Length >= 2)
554  {
555  first = parts[0];
556  last = parts[1];
557  }
558  uui = userID + ";" + homeURL + ";" + first + " " + last;
559  }
560  }
561 
562  uui = userID.ToString();
563  return result;
564  }
565 
566  #region Cache Management
567  public bool GetUser(UUID uuid, out UserData userdata)
568  {
569  if(m_Scenes.Count <= 0)
570  {
571  userdata = new UserData();
572  return false;
573  }
574 
575  lock (m_UserCache)
576  {
577  if (m_UserCache.TryGetValue(uuid, out userdata))
578  {
579  if (userdata.HasGridUserTried)
580  {
581  return true;
582  }
583  }
584  else
585  {
586  userdata = new UserData();
587  userdata.HasGridUserTried = false;
588  userdata.Id = uuid;
589  userdata.FirstName = "Unknown";
590  userdata.LastName = "UserUMMAU42";
591  userdata.HomeURL = string.Empty;
592  userdata.IsUnknownUser = true;
593  userdata.HasGridUserTried = false;
594  }
595  }
596 
597  /* BEGIN: do not wrap this code in any lock here
598  * There are HTTP calls in here.
599  */
600  if (!userdata.HasGridUserTried)
601  {
602  /* rewrite here */
603  UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, uuid);
604  if (account != null)
605  {
606  userdata.FirstName = account.FirstName;
607  userdata.LastName = account.LastName;
608  userdata.HomeURL = string.Empty;
609  userdata.IsUnknownUser = false;
610  userdata.HasGridUserTried = true;
611  }
612  }
613 
614  if (!userdata.HasGridUserTried)
615  {
616  GridUserInfo uInfo = null;
617  if (null != m_Scenes[0].GridUserService)
618  {
619  uInfo = m_Scenes[0].GridUserService.GetGridUserInfo(uuid.ToString());
620  }
621  if (uInfo != null)
622  {
623  string url, first, last, tmp;
624  UUID u;
625  if(uInfo.UserID.Length <= 36)
626  {
627  /* not a UUI */
628  }
629  else if (Util.ParseUniversalUserIdentifier(uInfo.UserID, out u, out url, out first, out last, out tmp))
630  {
631  if (url != string.Empty)
632  {
633  userdata.FirstName = first.Replace(" ", ".") + "." + last.Replace(" ", ".");
634  userdata.HomeURL = url;
635  try
636  {
637  userdata.LastName = "@" + new Uri(url).Authority;
638  userdata.IsUnknownUser = false;
639  }
640  catch
641  {
642  userdata.LastName = "@unknown";
643  }
644  userdata.HasGridUserTried = true;
645  }
646  }
647  else
648  m_log.DebugFormat("[USER MANAGEMENT MODULE]: Unable to parse UUI {0}", uInfo.UserID);
649  }
650  }
651  /* END: do not wrap this code in any lock here */
652 
653  lock (m_UserCache)
654  {
655  m_UserCache[uuid] = userdata;
656  }
657  return !userdata.IsUnknownUser;
658  }
659 
660  public void AddUser(UUID uuid, string first, string last)
661  {
662  lock(m_UserCache)
663  {
664  if(!m_UserCache.ContainsKey(uuid))
665  {
666  UserData user = new UserData();
667  user.Id = uuid;
668  user.FirstName = first;
669  user.LastName = last;
670  user.IsUnknownUser = false;
671  user.HasGridUserTried = false;
672  m_UserCache.Add(uuid, user);
673  }
674  }
675  }
676 
677  public void AddUser(UUID uuid, string first, string last, string homeURL)
678  {
679  //m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, first {1}, last {2}, url {3}", uuid, first, last, homeURL);
680 
681  UserData oldUser;
682  lock (m_UserCache)
683  {
684  if (m_UserCache.TryGetValue(uuid, out oldUser))
685  {
686  if (!oldUser.IsUnknownUser)
687  {
688  if (homeURL != oldUser.HomeURL && m_DisplayChangingHomeURI)
689  {
690  m_log.DebugFormat("[USER MANAGEMENT MODULE]: Different HomeURI for {0} {1} ({2}): {3} and {4}",
691  first, last, uuid.ToString(), homeURL, oldUser.HomeURL);
692  }
693  /* no update needed */
694  return;
695  }
696  }
697  else if(!m_UserCache.ContainsKey(uuid))
698  {
699  oldUser = new UserData();
700  oldUser.HasGridUserTried = false;
701  oldUser.IsUnknownUser = false;
702  if (homeURL != string.Empty)
703  {
704  oldUser.FirstName = first.Replace(" ", ".") + "." + last.Replace(" ", ".");
705  try
706  {
707  oldUser.LastName = "@" + new Uri(homeURL).Authority;
708  oldUser.IsUnknownUser = false;
709  }
710  catch
711  {
712  oldUser.LastName = "@unknown";
713  }
714  }
715  else
716  {
717  oldUser.FirstName = first;
718  oldUser.LastName = last;
719  }
720  oldUser.HomeURL = homeURL;
721  oldUser.Id = uuid;
722  m_UserCache.Add(uuid, oldUser);
723  }
724  }
725  }
726 
727  public void AddUser(UUID id, string creatorData)
728  {
729  // m_log.InfoFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, creatorData {1}", id, creatorData);
730 
731  if(string.IsNullOrEmpty(creatorData))
732  {
733  AddUser(id, string.Empty, string.Empty, string.Empty);
734  }
735  else
736  {
737  string homeURL;
738  string firstname = string.Empty;
739  string lastname = string.Empty;
740 
741  //creatorData = <endpoint>;<name>
742 
743  string[] parts = creatorData.Split(';');
744  if(parts.Length > 1)
745  {
746  string[] nameparts = parts[1].Split(' ');
747  firstname = nameparts[0];
748  for(int xi = 1; xi < nameparts.Length; ++xi)
749  {
750  if(xi != 1)
751  {
752  lastname += " ";
753  }
754  lastname += nameparts[xi];
755  }
756  }
757  else
758  {
759  firstname = "Unknown";
760  lastname = "UserUMMAU5";
761  }
762  if (parts.Length >= 1)
763  {
764  homeURL = parts[0];
765  if(Uri.IsWellFormedUriString(homeURL, UriKind.Absolute))
766  {
767  AddUser(id, firstname, lastname, homeURL);
768  }
769  else
770  {
771  m_log.DebugFormat("[SCENE]: Unable to parse Uri {0} for CreatorID {1}", parts[0], creatorData);
772 
773  lock (m_UserCache)
774  {
775  if(!m_UserCache.ContainsKey(id))
776  {
777  UserData newUser = new UserData();
778  newUser.Id = id;
779  newUser.FirstName = firstname + "." + lastname.Replace(' ', '.');
780  newUser.LastName = "@unknown";
781  newUser.HomeURL = string.Empty;
782  newUser.HasGridUserTried = false;
783  newUser.IsUnknownUser = true; /* we mark those users as Unknown user so a re-retrieve may be activated */
784  m_UserCache.Add(id, newUser);
785  }
786  }
787  }
788  }
789  else
790  {
791  lock(m_UserCache)
792  {
793  if(!m_UserCache.ContainsKey(id))
794  {
795  UserData newUser = new UserData();
796  newUser.Id = id;
797  newUser.FirstName = "Unknown";
798  newUser.LastName = "UserUMMAU4";
799  newUser.HomeURL = string.Empty;
800  newUser.IsUnknownUser = true;
801  newUser.HasGridUserTried = false;
802  m_UserCache.Add(id, newUser);
803  }
804  }
805  }
806  }
807  }
808  #endregion
809 
810  public bool IsLocalGridUser(UUID uuid)
811  {
812  UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, uuid);
813  if (account == null || (account != null && !account.LocalToGrid))
814  return false;
815 
816  return true;
817  }
818 
819  #endregion IUserManagement
820 
821  protected void Init()
822  {
823  AddUser(UUID.Zero, "Unknown", "User");
824  RegisterConsoleCmds();
825  }
826 
827  protected void RegisterConsoleCmds()
828  {
829  MainConsole.Instance.Commands.AddCommand("Users", true,
830  "show name",
831  "show name <uuid>",
832  "Show the bindings between a single user UUID and a user name",
833  String.Empty,
834  HandleShowUser);
835 
836  MainConsole.Instance.Commands.AddCommand("Users", true,
837  "show names",
838  "show names",
839  "Show the bindings between user UUIDs and user names",
840  String.Empty,
841  HandleShowUsers);
842 
843  MainConsole.Instance.Commands.AddCommand("Users", true,
844  "reset user cache",
845  "reset user cache",
846  "reset user cache to allow changed settings to be applied",
847  String.Empty,
848  HandleResetUserCache);
849  }
850 
851  private void HandleResetUserCache(string module, string[] cmd)
852  {
853  lock(m_UserCache)
854  {
855  m_UserCache.Clear();
856  }
857  }
858 
859  private void HandleShowUser(string module, string[] cmd)
860  {
861  if (cmd.Length < 3)
862  {
863  MainConsole.Instance.OutputFormat("Usage: show name <uuid>");
864  return;
865  }
866 
867  UUID userId;
868  if (!ConsoleUtil.TryParseConsoleUuid(MainConsole.Instance, cmd[2], out userId))
869  return;
870 
871  UserData ud;
872 
873  if(!GetUser(userId, out ud))
874  {
875  MainConsole.Instance.OutputFormat("No name known for user with id {0}", userId);
876  return;
877  }
878 
880  cdt.AddColumn("UUID", 36);
881  cdt.AddColumn("Name", 30);
882  cdt.AddColumn("HomeURL", 40);
883  cdt.AddRow(userId, string.Format("{0} {1}", ud.FirstName, ud.LastName), ud.HomeURL);
884 
885  MainConsole.Instance.Output(cdt.ToString());
886  }
887 
888  private void HandleShowUsers(string module, string[] cmd)
889  {
891  cdt.AddColumn("UUID", 36);
892  cdt.AddColumn("Name", 30);
893  cdt.AddColumn("HomeURL", 40);
894  cdt.AddColumn("Checked", 10);
895 
896  Dictionary<UUID, UserData> copyDict;
897  lock(m_UserCache)
898  {
899  copyDict = new Dictionary<UUID, UserData>(m_UserCache);
900  }
901 
902  foreach(KeyValuePair<UUID, UserData> kvp in copyDict)
903  {
904  cdt.AddRow(kvp.Key, string.Format("{0} {1}", kvp.Value.FirstName, kvp.Value.LastName), kvp.Value.HomeURL, kvp.Value.HasGridUserTried ? "yes" : "no");
905  }
906 
907  MainConsole.Instance.Output(cdt.ToString());
908  }
909 
910  }
911 
912 }
static bool TryParseConsoleUuid(ICommandConsole console, string rawUuid, out UUID uuid)
Try to parse a console UUID from the console.
Definition: ConsoleUtil.cs:95
void RemoveRegion(Scene scene)
This is called whenever a Scene is removed. For shared modules, this can happen several times...
void Initialise(IConfigSource config)
This is called to initialize the region module. For shared modules, this is called exactly once...
UUID GetUserIdByName(string firstName, string lastName)
Get user ID by the given name.
Used to generated a formatted table for the console.
void Close()
This is the inverse to Initialise. After a Close(), this instance won't be usable anymore...
void AddUser(UUID uuid, string first, string last)
Add a user.
A scene object group is conceptually an object in the scene. The object is constituted of SceneObject...
void AddRegion(Scene scene)
This is called whenever a Scene is added. For shared modules, this can happen several times...
Represents an item in a task inventory
Records user information specific to a grid but which is not part of a user's account.
string CreatorData
Data about the creator in the form home_url;name
List< UserData > GetUserData(string query, int page_size, int page_number)
static ICommandConsole Instance
Definition: MainConsole.cs:35
void HandleAvatarPickerRequest(IClientAPI client, UUID avatarID, UUID RequestID, string query)
void AddUser(UUID uuid, string first, string last, string homeURL)
Add a user.
Args to return to a client that queries picker data
virtual void AddAdditionalUsers(string query, List< UserData > users)
Packet GetPacket(PacketType type)
Gets a packet of the given type.
Definition: PacketPool.cs:116
OpenMetaverse.DirectoryManager.DirFindFlags DirFindFlags
This maintains the relationship between a UUID and a user name.
void RegionLoaded(Scene s)
This will be called once for every scene loaded. In a shared module this will be multiple times in on...
delegate void AvatarPickerRequest(IClientAPI remoteClient, UUID agentdata, UUID queryID, string UserQuery)
OpenMetaverse.DirectoryManager.DirFindFlags DirFindFlags
Definition: GroupsModule.cs:41
delegate void UUIDNameRequest(UUID id, IClientAPI remote_client)
void PostInitialise()
This is called exactly once after all the shared region-modules have been instanciated and IRegionMod...