aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/Communications
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Framework/Communications')
-rw-r--r--OpenSim/Framework/Communications/Cache/CachedUserInfo.cs847
-rw-r--r--OpenSim/Framework/Communications/Cache/LibraryRootFolder.cs257
-rw-r--r--OpenSim/Framework/Communications/Cache/UserProfileCacheService.cs277
-rw-r--r--OpenSim/Framework/Communications/Clients/AuthClient.cs151
-rw-r--r--OpenSim/Framework/Communications/Clients/GridClient.cs392
-rw-r--r--OpenSim/Framework/Communications/Clients/InventoryClient.cs79
-rw-r--r--OpenSim/Framework/Communications/Clients/RegionClient.cs755
-rw-r--r--OpenSim/Framework/Communications/CommunicationsManager.cs264
-rw-r--r--OpenSim/Framework/Communications/IAuthentication.cs39
-rw-r--r--OpenSim/Framework/Communications/IAvatarService.cs48
-rw-r--r--OpenSim/Framework/Communications/IInterServiceInventoryServices.cs64
-rw-r--r--OpenSim/Framework/Communications/IMessagingService.cs37
-rw-r--r--OpenSim/Framework/Communications/IUserAdminService.cs71
-rw-r--r--OpenSim/Framework/Communications/Osp/OspInventoryWrapperPlugin.cs10
-rw-r--r--OpenSim/Framework/Communications/Osp/OspResolver.cs27
-rw-r--r--OpenSim/Framework/Communications/Services/GridInfoService.cs176
-rw-r--r--OpenSim/Framework/Communications/Services/HGLoginAuthService.cs339
-rw-r--r--OpenSim/Framework/Communications/Services/LoginResponse.cs823
-rw-r--r--OpenSim/Framework/Communications/Services/LoginService.cs1241
-rw-r--r--OpenSim/Framework/Communications/TemporaryUserProfilePlugin.cs104
-rw-r--r--OpenSim/Framework/Communications/Tests/Cache/UserProfileCacheServiceTests.cs345
-rw-r--r--OpenSim/Framework/Communications/Tests/LoginServiceTests.cs453
-rw-r--r--OpenSim/Framework/Communications/UserManagerBase.cs930
23 files changed, 21 insertions, 7708 deletions
diff --git a/OpenSim/Framework/Communications/Cache/CachedUserInfo.cs b/OpenSim/Framework/Communications/Cache/CachedUserInfo.cs
deleted file mode 100644
index 6648c36..0000000
--- a/OpenSim/Framework/Communications/Cache/CachedUserInfo.cs
+++ /dev/null
@@ -1,847 +0,0 @@
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
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using log4net;
32using OpenMetaverse;
33using OpenSim.Services.Interfaces;
34
35namespace OpenSim.Framework.Communications.Cache
36{
37 internal delegate void AddItemDelegate(InventoryItemBase itemInfo);
38 internal delegate void UpdateItemDelegate(InventoryItemBase itemInfo);
39 internal delegate void DeleteItemDelegate(UUID itemID);
40 internal delegate void QueryItemDelegate(UUID itemID);
41 internal delegate void QueryFolderDelegate(UUID folderID);
42
43 internal delegate void CreateFolderDelegate(string folderName, UUID folderID, ushort folderType, UUID parentID);
44 internal delegate void MoveFolderDelegate(UUID folderID, UUID parentID);
45 internal delegate void PurgeFolderDelegate(UUID folderID);
46 internal delegate void UpdateFolderDelegate(string name, UUID folderID, ushort type, UUID parentID);
47
48 internal delegate void SendInventoryDescendentsDelegate(
49 IClientAPI client, UUID folderID, bool fetchFolders, bool fetchItems);
50
51 public delegate void OnItemReceivedDelegate(UUID itemID);
52 public delegate void OnInventoryReceivedDelegate(UUID userID);
53
54 /// <summary>
55 /// Stores user profile and inventory data received from backend services for a particular user.
56 /// </summary>
57 public class CachedUserInfo
58 {
59 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
60
61 //// <value>
62 /// Fired when a particular item has been received from the inventory service
63 /// </value>
64 public event OnItemReceivedDelegate OnItemReceived;
65
66 /// <value>
67 /// Fired once the entire inventory has been received for the user
68 /// </value>
69 public event OnInventoryReceivedDelegate OnInventoryReceived;
70
71 /// <summary>
72 /// The comms manager holds references to services (user, grid, inventory, etc.)
73 /// </summary>
74 private readonly IInventoryService m_InventoryService;
75
76 public UserProfileData UserProfile { get { return m_userProfile; } }
77 private UserProfileData m_userProfile;
78
79 /// <summary>
80 /// Have we received the user's inventory from the inventory service?
81 /// </summary>
82 public bool HasReceivedInventory { get { return m_hasReceivedInventory; } }
83 private bool m_hasReceivedInventory;
84
85 /// <summary>
86 /// Inventory requests waiting for receipt of this user's inventory from the inventory service.
87 /// </summary>
88 private readonly IList<IInventoryRequest> m_pendingRequests = new List<IInventoryRequest>();
89
90 /// <summary>
91 /// The root folder of this user's inventory. Returns null if the root folder has not yet been received.
92 /// </summary>
93 public InventoryFolderImpl RootFolder { get { return m_rootFolder; } }
94 private InventoryFolderImpl m_rootFolder;
95
96 public UUID SessionID
97 {
98 get { return m_session_id; }
99 set { m_session_id = value; }
100 }
101 private UUID m_session_id = UUID.Zero;
102
103 /// <summary>
104 /// Constructor
105 /// </summary>
106 /// <param name="commsManager"></param>
107 /// <param name="userProfile"></param>
108 public CachedUserInfo(IInventoryService invService, UserProfileData userProfile)
109 {
110 m_userProfile = userProfile;
111 m_InventoryService = invService;
112 }
113
114 /// <summary>
115 /// This allows a request to be added to be processed once we receive a user's inventory
116 /// from the inventory service. If we already have the inventory, the request
117 /// is executed immediately instead.
118 /// </summary>
119 /// <param name="parent"></param>
120 protected void AddRequest(IInventoryRequest request)
121 {
122 lock (m_pendingRequests)
123 {
124 if (HasReceivedInventory)
125 {
126 request.Execute();
127 }
128 else
129 {
130 m_pendingRequests.Add(request);
131 }
132 }
133 }
134
135 /// <summary>
136 /// Helper function for InventoryReceive() - Store a folder temporarily until we've received entire folder list
137 /// </summary>
138 /// <param name="folder"></param>
139 private void AddFolderToDictionary(InventoryFolderImpl folder, IDictionary<UUID, IList<InventoryFolderImpl>> dictionary)
140 {
141 UUID parentFolderId = folder.ParentID;
142
143 if (dictionary.ContainsKey(parentFolderId))
144 {
145 dictionary[parentFolderId].Add(folder);
146 }
147 else
148 {
149 IList<InventoryFolderImpl> folders = new List<InventoryFolderImpl>();
150 folders.Add(folder);
151 dictionary[parentFolderId] = folders;
152 }
153 }
154
155 /// <summary>
156 /// Recursively, in depth-first order, add all the folders we've received (stored
157 /// in a dictionary indexed by parent ID) into the tree that describes user folder
158 /// heirarchy
159 /// Any folder that is resolved into the tree is also added to resolvedFolderDictionary,
160 /// indexed by folder ID.
161 /// </summary>
162 /// <param name="parentId">
163 /// A <see cref="UUID"/>
164 /// </param>
165 private void ResolveReceivedFolders(InventoryFolderImpl parentFolder,
166 IDictionary<UUID, IList<InventoryFolderImpl>> receivedFolderDictionary,
167 IDictionary<UUID, InventoryFolderImpl> resolvedFolderDictionary)
168 {
169 if (receivedFolderDictionary.ContainsKey(parentFolder.ID))
170 {
171 List<InventoryFolderImpl> resolvedFolders = new List<InventoryFolderImpl>(); // Folders we've resolved with this invocation
172 foreach (InventoryFolderImpl folder in receivedFolderDictionary[parentFolder.ID])
173 {
174 if (parentFolder.ContainsChildFolder(folder.ID))
175 {
176 m_log.WarnFormat(
177 "[INVENTORY CACHE]: Received folder {0} {1} from inventory service which has already been received",
178 folder.Name, folder.ID);
179 }
180 else
181 {
182 if (resolvedFolderDictionary.ContainsKey(folder.ID))
183 {
184 m_log.WarnFormat(
185 "[INVENTORY CACHE]: Received folder {0} {1} from inventory service has already been received but with different parent",
186 folder.Name, folder.ID);
187 }
188 else
189 {
190 resolvedFolders.Add(folder);
191 resolvedFolderDictionary[folder.ID] = folder;
192 parentFolder.AddChildFolder(folder);
193 }
194 }
195 } // foreach (folder in pendingCategorizationFolders[parentFolder.ID])
196
197 receivedFolderDictionary.Remove(parentFolder.ID);
198 foreach (InventoryFolderImpl folder in resolvedFolders)
199 ResolveReceivedFolders(folder, receivedFolderDictionary, resolvedFolderDictionary);
200 } // if (receivedFolderDictionary.ContainsKey(parentFolder.ID))
201 }
202
203 /// <summary>
204 /// Drop all cached inventory.
205 /// </summary>
206 public void DropInventory()
207 {
208 m_log.Debug("[INVENTORY CACHE]: DropInventory called");
209 // Make sure there aren't pending requests around when we do this
210 // FIXME: There is still a race condition where an inventory operation can be requested (since these aren't being locked).
211 // Will have to extend locking to exclude this very soon.
212 lock (m_pendingRequests)
213 {
214 m_hasReceivedInventory = false;
215 m_rootFolder = null;
216 }
217 }
218
219 /// <summary>
220 /// Fetch inventory for this user.
221 /// </summary>
222 /// This has to be executed as a separate step once user information is retreived.
223 /// This will occur synchronously if the inventory service is in the same process as this class, and
224 /// asynchronously otherwise.
225 public void FetchInventory()
226 {
227 m_InventoryService.GetUserInventory(UserProfile.ID, InventoryReceive);
228 }
229
230 /// <summary>
231 /// Callback invoked when the inventory is received from an async request to the inventory service
232 /// </summary>
233 /// <param name="userID"></param>
234 /// <param name="inventoryCollection"></param>
235 public void InventoryReceive(ICollection<InventoryFolderImpl> folders, ICollection<InventoryItemBase> items)
236 {
237 // FIXME: Exceptions thrown upwards never appear on the console. Could fix further up if these
238 // are simply being swallowed
239
240 try
241 {
242 // collection of all received folders, indexed by their parent ID
243 IDictionary<UUID, IList<InventoryFolderImpl>> receivedFolders =
244 new Dictionary<UUID, IList<InventoryFolderImpl>>();
245
246 // collection of all folders that have been placed into the folder heirarchy starting at m_rootFolder
247 // This dictonary exists so we don't have to do an InventoryFolderImpl.FindFolder(), which is O(n) on the
248 // number of folders in our inventory.
249 // Maybe we should make this structure a member so we can skip InventoryFolderImpl.FindFolder() calls later too?
250 IDictionary<UUID, InventoryFolderImpl> resolvedFolders =
251 new Dictionary<UUID, InventoryFolderImpl>();
252
253 // Take all received folders, find the root folder, and put ther rest into
254 // the pendingCategorizationFolders collection
255 foreach (InventoryFolderImpl folder in folders)
256 AddFolderToDictionary(folder, receivedFolders);
257
258 if (!receivedFolders.ContainsKey(UUID.Zero))
259 throw new Exception("Database did not return a root inventory folder");
260 else
261 {
262 IList<InventoryFolderImpl> rootFolderList = receivedFolders[UUID.Zero];
263 m_rootFolder = rootFolderList[0];
264 resolvedFolders[m_rootFolder.ID] = m_rootFolder;
265 if (rootFolderList.Count > 1)
266 {
267 for (int i = 1; i < rootFolderList.Count; i++)
268 {
269 m_log.WarnFormat(
270 "[INVENTORY CACHE]: Discarding extra root folder {0}. Using previously received root folder {1}",
271 rootFolderList[i].ID, RootFolder.ID);
272 }
273 }
274 receivedFolders.Remove(UUID.Zero);
275 }
276
277 // Now take the pendingCategorizationFolders collection, and turn that into a tree,
278 // with the root being RootFolder
279 if (RootFolder != null)
280 ResolveReceivedFolders(RootFolder, receivedFolders, resolvedFolders);
281
282 // Generate a warning for folders that are not part of the heirarchy
283 foreach (KeyValuePair<UUID, IList<InventoryFolderImpl>> folderList in receivedFolders)
284 {
285 foreach (InventoryFolderImpl folder in folderList.Value)
286 m_log.WarnFormat("[INVENTORY CACHE]: Malformed Database: Unresolved Pending Folder {0}", folder.Name);
287 }
288
289 // Take all ther received items and put them into the folder tree heirarchy
290 foreach (InventoryItemBase item in items) {
291 InventoryFolderImpl folder = resolvedFolders.ContainsKey(item.Folder) ? resolvedFolders[item.Folder] : null;
292 ItemReceive(item, folder);
293 }
294 }
295 catch (Exception e)
296 {
297 m_log.ErrorFormat("[INVENTORY CACHE]: Error processing inventory received from inventory service, {0}", e);
298 }
299
300 // Deal with pending requests
301 lock (m_pendingRequests)
302 {
303 // We're going to change inventory status within the lock to avoid a race condition
304 // where requests are processed after the AddRequest() method has been called.
305 m_hasReceivedInventory = true;
306
307 foreach (IInventoryRequest request in m_pendingRequests)
308 {
309 request.Execute();
310 }
311 }
312
313 if (OnInventoryReceived != null)
314 OnInventoryReceived(UserProfile.ID);
315 }
316
317 /// <summary>
318 /// Callback invoked when an item is received from an async request to the inventory service.
319 ///
320 /// We're assuming here that items are always received after all the folders
321 /// received.
322 /// If folder is null, we will search for it starting from RootFolder (an O(n) operation),
323 /// otherwise we'll just put it into folder
324 /// </summary>
325 /// <param name="folderInfo"></param>
326 private void ItemReceive(InventoryItemBase itemInfo, InventoryFolderImpl folder)
327 {
328 // m_log.DebugFormat(
329 // "[INVENTORY CACHE]: Received item {0} {1} for user {2}",
330 // itemInfo.Name, itemInfo.ID, userID);
331
332 if (folder == null && RootFolder != null)
333 folder = RootFolder.FindFolder(itemInfo.Folder);
334
335 if (null == folder)
336 {
337 m_log.WarnFormat(
338 "Received item {0} {1} but its folder {2} does not exist",
339 itemInfo.Name, itemInfo.ID, itemInfo.Folder);
340
341 return;
342 }
343
344 lock (folder.Items)
345 {
346 folder.Items[itemInfo.ID] = itemInfo;
347 }
348
349 if (OnItemReceived != null)
350 OnItemReceived(itemInfo.ID);
351 }
352
353 /// <summary>
354 /// Create a folder in this agent's inventory.
355 /// </summary>
356 ///
357 /// If the inventory service has not yet delievered the inventory
358 /// for this user then the request will be queued.
359 ///
360 /// <param name="parentID"></param>
361 /// <returns></returns>
362 public bool CreateFolder(string folderName, UUID folderID, ushort folderType, UUID parentID)
363 {
364 // m_log.DebugFormat(
365 // "[AGENT INVENTORY]: Creating inventory folder {0} {1} for {2} {3}", folderID, folderName, remoteClient.Name, remoteClient.AgentId);
366
367 if (m_hasReceivedInventory)
368 {
369 InventoryFolderImpl parentFolder = RootFolder.FindFolder(parentID);
370
371 if (null == parentFolder)
372 {
373 m_log.WarnFormat(
374 "[AGENT INVENTORY]: Tried to create folder {0} {1} but the parent {2} does not exist",
375 folderName, folderID, parentID);
376
377 return false;
378 }
379
380 InventoryFolderImpl createdFolder = parentFolder.CreateChildFolder(folderID, folderName, folderType);
381
382 if (createdFolder != null)
383 {
384 InventoryFolderBase createdBaseFolder = new InventoryFolderBase();
385 createdBaseFolder.Owner = createdFolder.Owner;
386 createdBaseFolder.ID = createdFolder.ID;
387 createdBaseFolder.Name = createdFolder.Name;
388 createdBaseFolder.ParentID = createdFolder.ParentID;
389 createdBaseFolder.Type = createdFolder.Type;
390 createdBaseFolder.Version = createdFolder.Version;
391
392 m_InventoryService.AddFolder(createdBaseFolder);
393
394 return true;
395 }
396 else
397 {
398 m_log.WarnFormat(
399 "[AGENT INVENTORY]: Tried to create folder {0} {1} but the folder already exists",
400 folderName, folderID);
401
402 return false;
403 }
404 }
405 else
406 {
407 AddRequest(
408 new InventoryRequest(
409 Delegate.CreateDelegate(typeof(CreateFolderDelegate), this, "CreateFolder"),
410 new object[] { folderName, folderID, folderType, parentID }));
411
412 return true;
413 }
414 }
415
416 /// <summary>
417 /// Handle a client request to update the inventory folder
418 /// </summary>
419 ///
420 /// If the inventory service has not yet delievered the inventory
421 /// for this user then the request will be queued.
422 ///
423 /// FIXME: We call add new inventory folder because in the data layer, we happen to use an SQL REPLACE
424 /// so this will work to rename an existing folder. Needless to say, to rely on this is very confusing,
425 /// and needs to be changed.
426 ///
427 /// <param name="folderID"></param>
428 /// <param name="type"></param>
429 /// <param name="name"></param>
430 /// <param name="parentID"></param>
431 public bool UpdateFolder(string name, UUID folderID, ushort type, UUID parentID)
432 {
433 // m_log.DebugFormat(
434 // "[AGENT INVENTORY]: Updating inventory folder {0} {1} for {2} {3}", folderID, name, remoteClient.Name, remoteClient.AgentId);
435
436 if (m_hasReceivedInventory)
437 {
438 InventoryFolderImpl folder = RootFolder.FindFolder(folderID);
439
440 // Delegate movement if updated parent id isn't the same as the existing parentId
441 if (folder.ParentID != parentID)
442 MoveFolder(folderID, parentID);
443
444 InventoryFolderBase baseFolder = new InventoryFolderBase();
445 baseFolder.Owner = m_userProfile.ID;
446 baseFolder.ID = folderID;
447 baseFolder.Name = name;
448 baseFolder.ParentID = parentID;
449 baseFolder.Type = (short)type;
450 baseFolder.Version = RootFolder.Version;
451
452 m_InventoryService.UpdateFolder(baseFolder);
453
454 folder.Name = name;
455 folder.Type = (short)type;
456 }
457 else
458 {
459 AddRequest(
460 new InventoryRequest(
461 Delegate.CreateDelegate(typeof(UpdateFolderDelegate), this, "UpdateFolder"),
462 new object[] { name, folderID, type, parentID }));
463 }
464
465 return true;
466 }
467
468 /// <summary>
469 /// Handle an inventory folder move request from the client.
470 ///
471 /// If the inventory service has not yet delievered the inventory
472 /// for this user then the request will be queued.
473 /// </summary>
474 ///
475 /// <param name="folderID"></param>
476 /// <param name="parentID"></param>
477 /// <returns>
478 /// true if the delete was successful, or if it was queued pending folder receipt
479 /// false if the folder to be deleted did not exist.
480 /// </returns>
481 public bool MoveFolder(UUID folderID, UUID parentID)
482 {
483 // m_log.DebugFormat(
484 // "[AGENT INVENTORY]: Moving inventory folder {0} into folder {1} for {2} {3}",
485 // parentID, remoteClient.Name, remoteClient.Name, remoteClient.AgentId);
486
487 if (m_hasReceivedInventory)
488 {
489 InventoryFolderBase baseFolder = new InventoryFolderBase();
490 baseFolder.Owner = m_userProfile.ID;
491 baseFolder.ID = folderID;
492 baseFolder.ParentID = parentID;
493
494 m_InventoryService.MoveFolder(baseFolder);
495
496 InventoryFolderImpl folder = RootFolder.FindFolder(folderID);
497 InventoryFolderImpl parentFolder = RootFolder.FindFolder(parentID);
498 if (parentFolder != null && folder != null)
499 {
500 InventoryFolderImpl oldParentFolder = RootFolder.FindFolder(folder.ParentID);
501
502 if (oldParentFolder != null)
503 {
504 oldParentFolder.RemoveChildFolder(folderID);
505 parentFolder.AddChildFolder(folder);
506 }
507 else
508 {
509 return false;
510 }
511 }
512 else
513 {
514 return false;
515 }
516
517 return true;
518 }
519 else
520 {
521 AddRequest(
522 new InventoryRequest(
523 Delegate.CreateDelegate(typeof(MoveFolderDelegate), this, "MoveFolder"),
524 new object[] { folderID, parentID }));
525
526 return true;
527 }
528 }
529
530 /// <summary>
531 /// This method will delete all the items and folders in the given folder.
532 /// </summary>
533 /// If the inventory service has not yet delievered the inventory
534 /// for this user then the request will be queued.
535 ///
536 /// <param name="folderID"></param>
537 public bool PurgeFolder(UUID folderID)
538 {
539 // m_log.InfoFormat("[AGENT INVENTORY]: Purging folder {0} for {1} uuid {2}",
540 // folderID, remoteClient.Name, remoteClient.AgentId);
541
542 if (m_hasReceivedInventory)
543 {
544 InventoryFolderImpl purgedFolder = RootFolder.FindFolder(folderID);
545
546 if (purgedFolder != null)
547 {
548 // XXX Nasty - have to create a new object to hold details we already have
549 InventoryFolderBase purgedBaseFolder = new InventoryFolderBase();
550 purgedBaseFolder.Owner = purgedFolder.Owner;
551 purgedBaseFolder.ID = purgedFolder.ID;
552 purgedBaseFolder.Name = purgedFolder.Name;
553 purgedBaseFolder.ParentID = purgedFolder.ParentID;
554 purgedBaseFolder.Type = purgedFolder.Type;
555 purgedBaseFolder.Version = purgedFolder.Version;
556
557 m_InventoryService.PurgeFolder(purgedBaseFolder);
558
559 purgedFolder.Purge();
560
561 return true;
562 }
563 }
564 else
565 {
566 AddRequest(
567 new InventoryRequest(
568 Delegate.CreateDelegate(typeof(PurgeFolderDelegate), this, "PurgeFolder"),
569 new object[] { folderID }));
570
571 return true;
572 }
573
574 return false;
575 }
576
577 /// <summary>
578 /// Add an item to the user's inventory.
579 /// </summary>
580 /// If the item has no folder set (i.e. it is UUID.Zero), then it is placed in the most appropriate folder
581 /// for that type.
582 /// <param name="itemInfo"></param>
583 public void AddItem(InventoryItemBase item)
584 {
585 if (m_hasReceivedInventory)
586 {
587 if (item.Folder == UUID.Zero)
588 {
589 InventoryFolderImpl f = FindFolderForType(item.AssetType);
590 if (f != null)
591 item.Folder = f.ID;
592 else
593 item.Folder = RootFolder.ID;
594 }
595 ItemReceive(item, null);
596
597 m_InventoryService.AddItem(item);
598 }
599 else
600 {
601 AddRequest(
602 new InventoryRequest(
603 Delegate.CreateDelegate(typeof(AddItemDelegate), this, "AddItem"),
604 new object[] { item }));
605 }
606 }
607
608 /// <summary>
609 /// Update an item in the user's inventory
610 /// </summary>
611 /// <param name="userID"></param>
612 /// <param name="itemInfo"></param>
613 public void UpdateItem(InventoryItemBase item)
614 {
615 if (m_hasReceivedInventory)
616 {
617 m_InventoryService.UpdateItem(item);
618 }
619 else
620 {
621 AddRequest(
622 new InventoryRequest(
623 Delegate.CreateDelegate(typeof(UpdateItemDelegate), this, "UpdateItem"),
624 new object[] { item }));
625 }
626 }
627
628 /// <summary>
629 /// Delete an item from the user's inventory
630 ///
631 /// If the inventory service has not yet delievered the inventory
632 /// for this user then the request will be queued.
633 /// </summary>
634 /// <param name="itemID"></param>
635 /// <returns>
636 /// true on a successful delete or a if the request is queued.
637 /// Returns false on an immediate failure
638 /// </returns>
639 public bool DeleteItem(UUID itemID)
640 {
641 if (m_hasReceivedInventory)
642 {
643 // XXX For historical reasons (grid comms), we need to retrieve the whole item in order to delete, even though
644 // really only the item id is required.
645 InventoryItemBase item = RootFolder.FindItem(itemID);
646
647 if (null == item)
648 {
649 m_log.WarnFormat("[AGENT INVENTORY]: Tried to delete item {0} which does not exist", itemID);
650
651 return false;
652 }
653
654 if (RootFolder.DeleteItem(item.ID))
655 {
656 List<UUID> uuids = new List<UUID>();
657 uuids.Add(itemID);
658 return m_InventoryService.DeleteItems(this.UserProfile.ID, uuids);
659 }
660 }
661 else
662 {
663 AddRequest(
664 new InventoryRequest(
665 Delegate.CreateDelegate(typeof(DeleteItemDelegate), this, "DeleteItem"),
666 new object[] { itemID }));
667
668 return true;
669 }
670
671 return false;
672 }
673
674 /// <summary>
675 /// Send details of the inventory items and/or folders in a given folder to the client.
676 /// </summary>
677 /// <param name="client"></param>
678 /// <param name="folderID"></param>
679 /// <param name="fetchFolders"></param>
680 /// <param name="fetchItems"></param>
681 /// <returns>true if the request was queued or successfully processed, false otherwise</returns>
682 public bool SendInventoryDecendents(IClientAPI client, UUID folderID, int version, bool fetchFolders, bool fetchItems)
683 {
684 if (m_hasReceivedInventory)
685 {
686 InventoryFolderImpl folder;
687
688 if ((folder = RootFolder.FindFolder(folderID)) != null)
689 {
690 // m_log.DebugFormat(
691 // "[AGENT INVENTORY]: Found folder {0} for client {1}",
692 // folderID, remoteClient.AgentId);
693
694 client.SendInventoryFolderDetails(
695 client.AgentId, folderID, folder.RequestListOfItems(),
696 folder.RequestListOfFolders(), version, fetchFolders, fetchItems);
697
698 return true;
699 }
700 else
701 {
702 m_log.WarnFormat(
703 "[AGENT INVENTORY]: Could not find folder {0} requested by user {1} {2}",
704 folderID, client.Name, client.AgentId);
705
706 return false;
707 }
708 }
709 else
710 {
711 AddRequest(
712 new InventoryRequest(
713 Delegate.CreateDelegate(typeof(SendInventoryDescendentsDelegate), this, "SendInventoryDecendents", false, false),
714 new object[] { client, folderID, fetchFolders, fetchItems }));
715
716 return true;
717 }
718 }
719
720 /// <summary>
721 /// Find an appropriate folder for the given asset type
722 /// </summary>
723 /// <param name="type"></param>
724 /// <returns>null if no appropriate folder exists</returns>
725 public InventoryFolderImpl FindFolderForType(int type)
726 {
727 if (RootFolder == null)
728 return null;
729
730 return RootFolder.FindFolderForType(type);
731 }
732
733 // Load additional items that other regions have put into the database
734 // The item will be added tot he local cache. Returns true if the item
735 // was found and can be sent to the client
736 //
737 public bool QueryItem(InventoryItemBase item)
738 {
739 if (m_hasReceivedInventory)
740 {
741 InventoryItemBase invItem = RootFolder.FindItem(item.ID);
742
743 if (invItem != null)
744 {
745 // Item is in local cache, just update client
746 //
747 return true;
748 }
749
750 InventoryItemBase itemInfo = null;
751
752 itemInfo = m_InventoryService.GetItem(item);
753
754 if (itemInfo != null)
755 {
756 InventoryFolderImpl folder = RootFolder.FindFolder(itemInfo.Folder);
757 ItemReceive(itemInfo, folder);
758 return true;
759 }
760
761 return false;
762 }
763 else
764 {
765 AddRequest(
766 new InventoryRequest(
767 Delegate.CreateDelegate(typeof(QueryItemDelegate), this, "QueryItem"),
768 new object[] { item.ID }));
769
770 return true;
771 }
772 }
773
774 public bool QueryFolder(InventoryFolderBase folder)
775 {
776 if (m_hasReceivedInventory)
777 {
778 InventoryFolderBase invFolder = RootFolder.FindFolder(folder.ID);
779
780 if (invFolder != null)
781 {
782 // Folder is in local cache, just update client
783 //
784 return true;
785 }
786
787 InventoryFolderBase folderInfo = null;
788
789 folderInfo = m_InventoryService.GetFolder(folder);
790
791 if (folderInfo != null)
792 {
793 InventoryFolderImpl createdFolder = RootFolder.CreateChildFolder(folderInfo.ID, folderInfo.Name, (ushort)folderInfo.Type);
794
795 createdFolder.Version = folderInfo.Version;
796 createdFolder.Owner = folderInfo.Owner;
797 createdFolder.ParentID = folderInfo.ParentID;
798
799 return true;
800 }
801
802 return false;
803 }
804 else
805 {
806 AddRequest(
807 new InventoryRequest(
808 Delegate.CreateDelegate(typeof(QueryFolderDelegate), this, "QueryFolder"),
809 new object[] { folder.ID }));
810
811 return true;
812 }
813 }
814 }
815
816 /// <summary>
817 /// Should be implemented by callers which require a callback when the user's inventory is received
818 /// </summary>
819 public interface IInventoryRequest
820 {
821 /// <summary>
822 /// This is the method executed once we have received the user's inventory by which the request can be fulfilled.
823 /// </summary>
824 void Execute();
825 }
826
827 /// <summary>
828 /// Generic inventory request
829 /// </summary>
830 class InventoryRequest : IInventoryRequest
831 {
832 private Delegate m_delegate;
833 private Object[] m_args;
834
835 internal InventoryRequest(Delegate delegat, Object[] args)
836 {
837 m_delegate = delegat;
838 m_args = args;
839 }
840
841 public void Execute()
842 {
843 if (m_delegate != null)
844 m_delegate.DynamicInvoke(m_args);
845 }
846 }
847}
diff --git a/OpenSim/Framework/Communications/Cache/LibraryRootFolder.cs b/OpenSim/Framework/Communications/Cache/LibraryRootFolder.cs
deleted file mode 100644
index 74ba0a5..0000000
--- a/OpenSim/Framework/Communications/Cache/LibraryRootFolder.cs
+++ /dev/null
@@ -1,257 +0,0 @@
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
28using System;
29using System.Collections.Generic;
30using System.IO;
31using System.Reflection;
32using System.Xml;
33using log4net;
34using Nini.Config;
35using OpenMetaverse;
36
37namespace OpenSim.Framework.Communications.Cache
38{
39 /// <summary>
40 /// Basically a hack to give us a Inventory library while we don't have a inventory server
41 /// once the server is fully implemented then should read the data from that
42 /// </summary>
43 public class LibraryRootFolder : InventoryFolderImpl
44 {
45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46
47 private UUID libOwner = new UUID("11111111-1111-0000-0000-000100bba000");
48
49 /// <summary>
50 /// Holds the root library folder and all its descendents. This is really only used during inventory
51 /// setup so that we don't have to repeatedly search the tree of library folders.
52 /// </summary>
53 protected Dictionary<UUID, InventoryFolderImpl> libraryFolders
54 = new Dictionary<UUID, InventoryFolderImpl>();
55
56 public LibraryRootFolder(string pLibrariesLocation)
57 {
58 Owner = libOwner;
59 ID = new UUID("00000112-000f-0000-0000-000100bba000");
60 Name = "OpenSim Library";
61 ParentID = UUID.Zero;
62 Type = (short) 8;
63 Version = (ushort) 1;
64
65 libraryFolders.Add(ID, this);
66
67 LoadLibraries(pLibrariesLocation);
68 }
69
70 public InventoryItemBase CreateItem(UUID inventoryID, UUID assetID, string name, string description,
71 int assetType, int invType, UUID parentFolderID)
72 {
73 InventoryItemBase item = new InventoryItemBase();
74 item.Owner = libOwner;
75 item.CreatorId = libOwner.ToString();
76 item.ID = inventoryID;
77 item.AssetID = assetID;
78 item.Description = description;
79 item.Name = name;
80 item.AssetType = assetType;
81 item.InvType = invType;
82 item.Folder = parentFolderID;
83 item.BasePermissions = 0x7FFFFFFF;
84 item.EveryOnePermissions = 0x7FFFFFFF;
85 item.CurrentPermissions = 0x7FFFFFFF;
86 item.NextPermissions = 0x7FFFFFFF;
87 return item;
88 }
89
90 /// <summary>
91 /// Use the asset set information at path to load assets
92 /// </summary>
93 /// <param name="path"></param>
94 /// <param name="assets"></param>
95 protected void LoadLibraries(string librariesControlPath)
96 {
97 m_log.InfoFormat("[LIBRARY INVENTORY]: Loading library control file {0}", librariesControlPath);
98 LoadFromFile(librariesControlPath, "Libraries control", ReadLibraryFromConfig);
99 }
100
101 /// <summary>
102 /// Read a library set from config
103 /// </summary>
104 /// <param name="config"></param>
105 protected void ReadLibraryFromConfig(IConfig config, string path)
106 {
107 string basePath = Path.GetDirectoryName(path);
108 string foldersPath
109 = Path.Combine(
110 basePath, config.GetString("foldersFile", String.Empty));
111
112 LoadFromFile(foldersPath, "Library folders", ReadFolderFromConfig);
113
114 string itemsPath
115 = Path.Combine(
116 basePath, config.GetString("itemsFile", String.Empty));
117
118 LoadFromFile(itemsPath, "Library items", ReadItemFromConfig);
119 }
120
121 /// <summary>
122 /// Read a library inventory folder from a loaded configuration
123 /// </summary>
124 /// <param name="source"></param>
125 private void ReadFolderFromConfig(IConfig config, string path)
126 {
127 InventoryFolderImpl folderInfo = new InventoryFolderImpl();
128
129 folderInfo.ID = new UUID(config.GetString("folderID", ID.ToString()));
130 folderInfo.Name = config.GetString("name", "unknown");
131 folderInfo.ParentID = new UUID(config.GetString("parentFolderID", ID.ToString()));
132 folderInfo.Type = (short)config.GetInt("type", 8);
133
134 folderInfo.Owner = libOwner;
135 folderInfo.Version = 1;
136
137 if (libraryFolders.ContainsKey(folderInfo.ParentID))
138 {
139 InventoryFolderImpl parentFolder = libraryFolders[folderInfo.ParentID];
140
141 libraryFolders.Add(folderInfo.ID, folderInfo);
142 parentFolder.AddChildFolder(folderInfo);
143
144// m_log.InfoFormat("[LIBRARY INVENTORY]: Adding folder {0} ({1})", folderInfo.name, folderInfo.folderID);
145 }
146 else
147 {
148 m_log.WarnFormat(
149 "[LIBRARY INVENTORY]: Couldn't add folder {0} ({1}) since parent folder with ID {2} does not exist!",
150 folderInfo.Name, folderInfo.ID, folderInfo.ParentID);
151 }
152 }
153
154 /// <summary>
155 /// Read a library inventory item metadata from a loaded configuration
156 /// </summary>
157 /// <param name="source"></param>
158 private void ReadItemFromConfig(IConfig config, string path)
159 {
160 InventoryItemBase item = new InventoryItemBase();
161 item.Owner = libOwner;
162 item.CreatorId = libOwner.ToString();
163 item.ID = new UUID(config.GetString("inventoryID", ID.ToString()));
164 item.AssetID = new UUID(config.GetString("assetID", item.ID.ToString()));
165 item.Folder = new UUID(config.GetString("folderID", ID.ToString()));
166 item.Name = config.GetString("name", String.Empty);
167 item.Description = config.GetString("description", item.Name);
168 item.InvType = config.GetInt("inventoryType", 0);
169 item.AssetType = config.GetInt("assetType", item.InvType);
170 item.CurrentPermissions = (uint)config.GetLong("currentPermissions", 0x7FFFFFFF);
171 item.NextPermissions = (uint)config.GetLong("nextPermissions", 0x7FFFFFFF);
172 item.EveryOnePermissions = (uint)config.GetLong("everyonePermissions", 0x7FFFFFFF);
173 item.BasePermissions = (uint)config.GetLong("basePermissions", 0x7FFFFFFF);
174 item.Flags = (uint)config.GetInt("flags", 0);
175
176 if (libraryFolders.ContainsKey(item.Folder))
177 {
178 InventoryFolderImpl parentFolder = libraryFolders[item.Folder];
179 try
180 {
181 parentFolder.Items.Add(item.ID, item);
182 }
183 catch (Exception)
184 {
185 m_log.WarnFormat("[LIBRARY INVENTORY] Item {1} [{0}] not added, duplicate item", item.ID, item.Name);
186 }
187 }
188 else
189 {
190 m_log.WarnFormat(
191 "[LIBRARY INVENTORY]: Couldn't add item {0} ({1}) since parent folder with ID {2} does not exist!",
192 item.Name, item.ID, item.Folder);
193 }
194 }
195
196 private delegate void ConfigAction(IConfig config, string path);
197
198 /// <summary>
199 /// Load the given configuration at a path and perform an action on each Config contained within it
200 /// </summary>
201 /// <param name="path"></param>
202 /// <param name="fileDescription"></param>
203 /// <param name="action"></param>
204 private static void LoadFromFile(string path, string fileDescription, ConfigAction action)
205 {
206 if (File.Exists(path))
207 {
208 try
209 {
210 XmlConfigSource source = new XmlConfigSource(path);
211
212 for (int i = 0; i < source.Configs.Count; i++)
213 {
214 action(source.Configs[i], path);
215 }
216 }
217 catch (XmlException e)
218 {
219 m_log.ErrorFormat("[LIBRARY INVENTORY]: Error loading {0} : {1}", path, e);
220 }
221 }
222 else
223 {
224 m_log.ErrorFormat("[LIBRARY INVENTORY]: {0} file {1} does not exist!", fileDescription, path);
225 }
226 }
227
228 /// <summary>
229 /// Looks like a simple getter, but is written like this for some consistency with the other Request
230 /// methods in the superclass
231 /// </summary>
232 /// <returns></returns>
233 public Dictionary<UUID, InventoryFolderImpl> RequestSelfAndDescendentFolders()
234 {
235 Dictionary<UUID, InventoryFolderImpl> fs = new Dictionary<UUID, InventoryFolderImpl>();
236 fs.Add(ID, this);
237 List<InventoryFolderImpl> fis = TraverseFolder(this);
238 foreach (InventoryFolderImpl f in fis)
239 {
240 fs.Add(f.ID, f);
241 }
242 //return libraryFolders;
243 return fs;
244 }
245
246 private List<InventoryFolderImpl> TraverseFolder(InventoryFolderImpl node)
247 {
248 List<InventoryFolderImpl> folders = node.RequestListOfFolderImpls();
249 List<InventoryFolderImpl> subs = new List<InventoryFolderImpl>();
250 foreach (InventoryFolderImpl f in folders)
251 subs.AddRange(TraverseFolder(f));
252
253 folders.AddRange(subs);
254 return folders;
255 }
256 }
257}
diff --git a/OpenSim/Framework/Communications/Cache/UserProfileCacheService.cs b/OpenSim/Framework/Communications/Cache/UserProfileCacheService.cs
deleted file mode 100644
index acae4b1..0000000
--- a/OpenSim/Framework/Communications/Cache/UserProfileCacheService.cs
+++ /dev/null
@@ -1,277 +0,0 @@
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
28using System.Collections.Generic;
29using System.Reflection;
30using log4net;
31using OpenMetaverse;
32using OpenSim.Services.Interfaces;
33
34namespace OpenSim.Framework.Communications.Cache
35{
36 /// <summary>
37 /// Holds user profile information and retrieves it from backend services.
38 /// </summary>
39 public class UserProfileCacheService
40 {
41 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
42
43 /// <value>
44 /// Standard format for names.
45 /// </value>
46 public const string NAME_FORMAT = "{0} {1}";
47
48 /// <summary>
49 /// The comms manager holds references to services (user, grid, inventory, etc.)
50 /// </summary>
51 private readonly CommunicationsManager m_commsManager;
52
53 /// <summary>
54 /// User profiles indexed by UUID
55 /// </summary>
56 private readonly Dictionary<UUID, CachedUserInfo> m_userProfilesById
57 = new Dictionary<UUID, CachedUserInfo>();
58
59 /// <summary>
60 /// User profiles indexed by name
61 /// </summary>
62 private readonly Dictionary<string, CachedUserInfo> m_userProfilesByName
63 = new Dictionary<string, CachedUserInfo>();
64
65 /// <summary>
66 /// The root library folder.
67 /// </summary>
68 public readonly InventoryFolderImpl LibraryRoot;
69
70 private IInventoryService m_InventoryService;
71
72 /// <summary>
73 /// Constructor
74 /// </summary>
75 /// <param name="commsManager"></param>
76 /// <param name="libraryRootFolder"></param>
77 public UserProfileCacheService(CommunicationsManager commsManager, LibraryRootFolder libraryRootFolder)
78 {
79 m_commsManager = commsManager;
80 LibraryRoot = libraryRootFolder;
81 }
82
83 public void SetInventoryService(IInventoryService invService)
84 {
85 m_InventoryService = invService;
86 }
87
88 /// <summary>
89 /// A new user has moved into a region in this instance so retrieve their profile from the user service.
90 /// </summary>
91 ///
92 /// It isn't strictly necessary to make this call since user data can be lazily requested later on. However,
93 /// it might be helpful in order to avoid an initial response delay later on
94 ///
95 /// <param name="userID"></param>
96 public void AddNewUser(UUID userID)
97 {
98 if (userID == UUID.Zero)
99 return;
100
101 //m_log.DebugFormat("[USER CACHE]: Adding user profile for {0}", userID);
102 GetUserDetails(userID);
103 }
104
105 /// <summary>
106 /// Remove this user's profile cache.
107 /// </summary>
108 /// <param name="userID"></param>
109 /// <returns>true if the user was successfully removed, false otherwise</returns>
110 public bool RemoveUser(UUID userId)
111 {
112 if (!RemoveFromCaches(userId))
113 {
114 m_log.WarnFormat(
115 "[USER CACHE]: Tried to remove the profile of user {0}, but this was not in the scene", userId);
116
117 return false;
118 }
119
120 return true;
121 }
122
123 /// <summary>
124 /// Get details of the given user.
125 /// </summary>
126 /// If the user isn't in cache then the user is requested from the profile service.
127 /// <param name="userID"></param>
128 /// <returns>null if no user details are found</returns>
129 public CachedUserInfo GetUserDetails(string fname, string lname)
130 {
131 lock (m_userProfilesByName)
132 {
133 CachedUserInfo userInfo;
134
135 if (m_userProfilesByName.TryGetValue(string.Format(NAME_FORMAT, fname, lname), out userInfo))
136 {
137 return userInfo;
138 }
139 else
140 {
141 UserProfileData userProfile = m_commsManager.UserService.GetUserProfile(fname, lname);
142
143 if (userProfile != null)
144 {
145
146 if ((userProfile.UserAssetURI == null || userProfile.UserAssetURI == "") && m_commsManager.NetworkServersInfo != null)
147 userProfile.UserAssetURI = m_commsManager.NetworkServersInfo.AssetURL;
148 if ((userProfile.UserInventoryURI == null || userProfile.UserInventoryURI == "") && m_commsManager.NetworkServersInfo != null)
149 userProfile.UserInventoryURI = m_commsManager.NetworkServersInfo.InventoryURL;
150
151 return AddToCaches(userProfile);
152 }
153 else
154 return null;
155 }
156 }
157 }
158
159 /// <summary>
160 /// Get details of the given user.
161 /// </summary>
162 /// If the user isn't in cache then the user is requested from the profile service.
163 /// <param name="userID"></param>
164 /// <returns>null if no user details are found</returns>
165 public CachedUserInfo GetUserDetails(UUID userID)
166 {
167 if (userID == UUID.Zero)
168 return null;
169
170 lock (m_userProfilesById)
171 {
172 if (m_userProfilesById.ContainsKey(userID))
173 {
174 return m_userProfilesById[userID];
175 }
176 else
177 {
178 UserProfileData userProfile = m_commsManager.UserService.GetUserProfile(userID);
179 if (userProfile != null)
180 {
181
182 if ((userProfile.UserAssetURI == null || userProfile.UserAssetURI == "") && m_commsManager.NetworkServersInfo != null)
183 userProfile.UserAssetURI = m_commsManager.NetworkServersInfo.AssetURL;
184 if ((userProfile.UserInventoryURI == null || userProfile.UserInventoryURI == "") && m_commsManager.NetworkServersInfo != null)
185 userProfile.UserInventoryURI = m_commsManager.NetworkServersInfo.InventoryURL;
186
187 return AddToCaches(userProfile);
188 }
189 else
190 return null;
191 }
192 }
193 }
194
195 /// <summary>
196 /// Update an existing profile
197 /// </summary>
198 /// <param name="userProfile"></param>
199 /// <returns>true if a user profile was found to update, false otherwise</returns>
200 // Commented out for now. The implementation needs to be improved by protecting against race conditions,
201 // probably by making sure that the update doesn't use the UserCacheInfo.UserProfile directly (possibly via
202 // returning a read only class from the cache).
203// public bool StoreProfile(UserProfileData userProfile)
204// {
205// lock (m_userProfilesById)
206// {
207// CachedUserInfo userInfo = GetUserDetails(userProfile.ID);
208//
209// if (userInfo != null)
210// {
211// userInfo.m_userProfile = userProfile;
212// m_commsManager.UserService.UpdateUserProfile(userProfile);
213//
214// return true;
215// }
216// }
217//
218// return false;
219// }
220
221 /// <summary>
222 /// Populate caches with the given user profile
223 /// </summary>
224 /// <param name="userProfile"></param>
225 protected CachedUserInfo AddToCaches(UserProfileData userProfile)
226 {
227 CachedUserInfo createdUserInfo = new CachedUserInfo(m_InventoryService, userProfile);
228
229 lock (m_userProfilesById)
230 {
231 m_userProfilesById[createdUserInfo.UserProfile.ID] = createdUserInfo;
232
233 lock (m_userProfilesByName)
234 {
235 m_userProfilesByName[createdUserInfo.UserProfile.Name] = createdUserInfo;
236 }
237 }
238
239 return createdUserInfo;
240 }
241
242 /// <summary>
243 /// Remove profile belong to the given uuid from the caches
244 /// </summary>
245 /// <param name="userUuid"></param>
246 /// <returns>true if there was a profile to remove, false otherwise</returns>
247 protected bool RemoveFromCaches(UUID userId)
248 {
249 lock (m_userProfilesById)
250 {
251 if (m_userProfilesById.ContainsKey(userId))
252 {
253 CachedUserInfo userInfo = m_userProfilesById[userId];
254 m_userProfilesById.Remove(userId);
255
256 lock (m_userProfilesByName)
257 {
258 m_userProfilesByName.Remove(userInfo.UserProfile.Name);
259 }
260
261 return true;
262 }
263 }
264
265 return false;
266 }
267
268 /// <summary>
269 /// Preloads User data into the region cache. Modules may use this service to add non-standard clients
270 /// </summary>
271 /// <param name="userData"></param>
272 public void PreloadUserCache(UserProfileData userData)
273 {
274 AddToCaches(userData);
275 }
276 }
277}
diff --git a/OpenSim/Framework/Communications/Clients/AuthClient.cs b/OpenSim/Framework/Communications/Clients/AuthClient.cs
deleted file mode 100644
index adae637..0000000
--- a/OpenSim/Framework/Communications/Clients/AuthClient.cs
+++ /dev/null
@@ -1,151 +0,0 @@
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
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using Nwc.XmlRpc;
32using OpenMetaverse;
33
34namespace OpenSim.Framework.Communications.Clients
35{
36 public class AuthClient
37 {
38 public static string GetNewKey(string authurl, UUID userID, UUID authToken)
39 {
40 //Hashtable keyParams = new Hashtable();
41 //keyParams["user_id"] = userID;
42 //keyParams["auth_token"] = authKey;
43
44 List<string> SendParams = new List<string>();
45 SendParams.Add(userID.ToString());
46 SendParams.Add(authToken.ToString());
47
48 XmlRpcRequest request = new XmlRpcRequest("hg_new_auth_key", SendParams);
49 XmlRpcResponse reply;
50 try
51 {
52 reply = request.Send(authurl, 6000);
53 }
54 catch (Exception e)
55 {
56 System.Console.WriteLine("[HGrid]: Failed to get new key. Reason: " + e.Message);
57 return string.Empty;
58 }
59
60 if (!reply.IsFault)
61 {
62 string newKey = string.Empty;
63 if (reply.Value != null)
64 newKey = (string)reply.Value;
65
66 return newKey;
67 }
68 else
69 {
70 System.Console.WriteLine("[HGrid]: XmlRpc request to get auth key failed with message {0}" + reply.FaultString + ", code " + reply.FaultCode);
71 return string.Empty;
72 }
73
74 }
75
76 public static bool VerifyKey(string authurl, UUID userID, string authKey)
77 {
78 List<string> SendParams = new List<string>();
79 SendParams.Add(userID.ToString());
80 SendParams.Add(authKey);
81
82 System.Console.WriteLine("[HGrid]: Verifying user key with authority " + authurl);
83
84 XmlRpcRequest request = new XmlRpcRequest("hg_verify_auth_key", SendParams);
85 XmlRpcResponse reply;
86 try
87 {
88 reply = request.Send(authurl, 10000);
89 }
90 catch (Exception e)
91 {
92 System.Console.WriteLine("[HGrid]: Failed to verify key. Reason: " + e.Message);
93 return false;
94 }
95
96 if (reply != null)
97 {
98 if (!reply.IsFault)
99 {
100 bool success = false;
101 if (reply.Value != null)
102 success = (bool)reply.Value;
103
104 return success;
105 }
106 else
107 {
108 System.Console.WriteLine("[HGrid]: XmlRpc request to verify key failed with message {0}" + reply.FaultString + ", code " + reply.FaultCode);
109 return false;
110 }
111 }
112 else
113 {
114 System.Console.WriteLine("[HGrid]: XmlRpc request to verify key returned null reply");
115 return false;
116 }
117 }
118
119 public static bool VerifySession(string authurl, UUID userID, UUID sessionID)
120 {
121 Hashtable requestData = new Hashtable();
122 requestData["avatar_uuid"] = userID.ToString();
123 requestData["session_id"] = sessionID.ToString();
124 ArrayList SendParams = new ArrayList();
125 SendParams.Add(requestData);
126 XmlRpcRequest UserReq = new XmlRpcRequest("check_auth_session", SendParams);
127 XmlRpcResponse UserResp = null;
128 try
129 {
130 UserResp = UserReq.Send(authurl, 3000);
131 }
132 catch (Exception e)
133 {
134 System.Console.WriteLine("[Session Auth]: VerifySession XmlRpc: " + e.Message);
135 return false;
136 }
137
138 Hashtable responseData = (Hashtable)UserResp.Value;
139 if (responseData != null && responseData.ContainsKey("auth_session") && responseData["auth_session"] != null && responseData["auth_session"].ToString() == "TRUE")
140 {
141 //System.Console.WriteLine("[Authorization]: userserver reported authorized session for user " + userID);
142 return true;
143 }
144 else
145 {
146 //System.Console.WriteLine("[Authorization]: userserver reported unauthorized session for user " + userID);
147 return false;
148 }
149 }
150 }
151}
diff --git a/OpenSim/Framework/Communications/Clients/GridClient.cs b/OpenSim/Framework/Communications/Clients/GridClient.cs
deleted file mode 100644
index 4836556..0000000
--- a/OpenSim/Framework/Communications/Clients/GridClient.cs
+++ /dev/null
@@ -1,392 +0,0 @@
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
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Net;
32using System.Reflection;
33
34using log4net;
35using OpenMetaverse;
36using Nwc.XmlRpc;
37
38namespace OpenSim.Framework.Communications.Clients
39{
40 public class GridClient
41 {
42 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
43
44 public bool RegisterRegion(
45 string gridServerURL, string sendKey, string receiveKey, RegionInfo regionInfo, out bool forcefulBanLines)
46 {
47 m_log.InfoFormat(
48 "[GRID CLIENT]: Registering region {0} with grid at {1}", regionInfo.RegionName, gridServerURL);
49
50 forcefulBanLines = true;
51
52 Hashtable GridParams = new Hashtable();
53 // Login / Authentication
54
55 GridParams["authkey"] = sendKey;
56 GridParams["recvkey"] = receiveKey;
57 GridParams["UUID"] = regionInfo.RegionID.ToString();
58 GridParams["sim_ip"] = regionInfo.ExternalHostName;
59 GridParams["sim_port"] = regionInfo.InternalEndPoint.Port.ToString();
60 GridParams["region_locx"] = regionInfo.RegionLocX.ToString();
61 GridParams["region_locy"] = regionInfo.RegionLocY.ToString();
62 GridParams["sim_name"] = regionInfo.RegionName;
63 GridParams["http_port"] = regionInfo.HttpPort.ToString();
64 GridParams["remoting_port"] = ConfigSettings.DefaultRegionRemotingPort.ToString();
65 GridParams["map-image-id"] = regionInfo.RegionSettings.TerrainImageID.ToString();
66 GridParams["originUUID"] = regionInfo.originRegionID.ToString();
67 GridParams["server_uri"] = regionInfo.ServerURI;
68 GridParams["region_secret"] = regionInfo.regionSecret;
69 GridParams["major_interface_version"] = VersionInfo.MajorInterfaceVersion.ToString();
70
71 if (regionInfo.MasterAvatarAssignedUUID != UUID.Zero)
72 GridParams["master_avatar_uuid"] = regionInfo.MasterAvatarAssignedUUID.ToString();
73 else
74 GridParams["master_avatar_uuid"] = regionInfo.EstateSettings.EstateOwner.ToString();
75
76 // Package into an XMLRPC Request
77 ArrayList SendParams = new ArrayList();
78 SendParams.Add(GridParams);
79
80 // Send Request
81 XmlRpcRequest GridReq = new XmlRpcRequest("simulator_login", SendParams);
82 XmlRpcResponse GridResp;
83
84 try
85 {
86 // The timeout should always be significantly larger than the timeout for the grid server to request
87 // the initial status of the region before confirming registration.
88 GridResp = GridReq.Send(gridServerURL, 90000);
89 }
90 catch (Exception e)
91 {
92 Exception e2
93 = new Exception(
94 String.Format(
95 "Unable to register region with grid at {0}. Grid service not running?",
96 gridServerURL),
97 e);
98
99 throw e2;
100 }
101
102 Hashtable GridRespData = (Hashtable)GridResp.Value;
103 // Hashtable griddatahash = GridRespData;
104
105 // Process Response
106 if (GridRespData.ContainsKey("error"))
107 {
108 string errorstring = (string)GridRespData["error"];
109
110 Exception e = new Exception(
111 String.Format("Unable to connect to grid at {0}: {1}", gridServerURL, errorstring));
112
113 throw e;
114 }
115 else
116 {
117 // m_knownRegions = RequestNeighbours(regionInfo.RegionLocX, regionInfo.RegionLocY);
118 if (GridRespData.ContainsKey("allow_forceful_banlines"))
119 {
120 if ((string)GridRespData["allow_forceful_banlines"] != "TRUE")
121 {
122 forcefulBanLines = false;
123 }
124 }
125
126 }
127 return true;
128 }
129
130 public bool DeregisterRegion(string gridServerURL, string sendKey, string receiveKey, RegionInfo regionInfo, out string errorMsg)
131 {
132 errorMsg = "";
133 Hashtable GridParams = new Hashtable();
134
135 GridParams["UUID"] = regionInfo.RegionID.ToString();
136
137 // Package into an XMLRPC Request
138 ArrayList SendParams = new ArrayList();
139 SendParams.Add(GridParams);
140
141 // Send Request
142 XmlRpcRequest GridReq = new XmlRpcRequest("simulator_after_region_moved", SendParams);
143 XmlRpcResponse GridResp = null;
144
145 try
146 {
147 GridResp = GridReq.Send(gridServerURL, 10000);
148 }
149 catch (Exception e)
150 {
151 Exception e2
152 = new Exception(
153 String.Format(
154 "Unable to deregister region with grid at {0}. Grid service not running?",
155 gridServerURL),
156 e);
157
158 throw e2;
159 }
160
161 Hashtable GridRespData = (Hashtable)GridResp.Value;
162
163 // Hashtable griddatahash = GridRespData;
164
165 // Process Response
166 if (GridRespData != null && GridRespData.ContainsKey("error"))
167 {
168 errorMsg = (string)GridRespData["error"];
169 return false;
170 }
171
172 return true;
173 }
174
175 public bool RequestNeighborInfo(
176 string gridServerURL, string sendKey, string receiveKey, UUID regionUUID,
177 out RegionInfo regionInfo, out string errorMsg)
178 {
179 // didn't find it so far, we have to go the long way
180 regionInfo = null;
181 errorMsg = string.Empty;
182 Hashtable requestData = new Hashtable();
183 requestData["region_UUID"] = regionUUID.ToString();
184 requestData["authkey"] = sendKey;
185 ArrayList SendParams = new ArrayList();
186 SendParams.Add(requestData);
187 XmlRpcRequest gridReq = new XmlRpcRequest("simulator_data_request", SendParams);
188 XmlRpcResponse gridResp = null;
189
190 try
191 {
192 gridResp = gridReq.Send(gridServerURL, 3000);
193 }
194 catch (Exception e)
195 {
196 errorMsg = e.Message;
197 return false;
198 }
199
200 Hashtable responseData = (Hashtable)gridResp.Value;
201
202 if (responseData.ContainsKey("error"))
203 {
204 errorMsg = (string)responseData["error"];
205 return false; ;
206 }
207
208 regionInfo = BuildRegionInfo(responseData, String.Empty);
209
210 return true;
211 }
212
213 public bool RequestNeighborInfo(
214 string gridServerURL, string sendKey, string receiveKey, ulong regionHandle,
215 out RegionInfo regionInfo, out string errorMsg)
216 {
217 // didn't find it so far, we have to go the long way
218 regionInfo = null;
219 errorMsg = string.Empty;
220
221 try
222 {
223 Hashtable requestData = new Hashtable();
224 requestData["region_handle"] = regionHandle.ToString();
225 requestData["authkey"] = sendKey;
226 ArrayList SendParams = new ArrayList();
227 SendParams.Add(requestData);
228 XmlRpcRequest GridReq = new XmlRpcRequest("simulator_data_request", SendParams);
229 XmlRpcResponse GridResp = GridReq.Send(gridServerURL, 3000);
230
231 Hashtable responseData = (Hashtable)GridResp.Value;
232
233 if (responseData.ContainsKey("error"))
234 {
235 errorMsg = (string)responseData["error"];
236 return false;
237 }
238
239 uint regX = Convert.ToUInt32((string)responseData["region_locx"]);
240 uint regY = Convert.ToUInt32((string)responseData["region_locy"]);
241 string externalHostName = (string)responseData["sim_ip"];
242 uint simPort = Convert.ToUInt32(responseData["sim_port"]);
243 string regionName = (string)responseData["region_name"];
244 UUID regionID = new UUID((string)responseData["region_UUID"]);
245 uint remotingPort = Convert.ToUInt32((string)responseData["remoting_port"]);
246
247 uint httpPort = 9000;
248 if (responseData.ContainsKey("http_port"))
249 {
250 httpPort = Convert.ToUInt32((string)responseData["http_port"]);
251 }
252
253 // Ok, so this is definitively the wrong place to do this, way too hard coded, but it doesn't seem we GET this info?
254
255 string simURI = "http://" + externalHostName + ":" + simPort;
256
257 // string externalUri = (string) responseData["sim_uri"];
258
259 //IPEndPoint neighbourInternalEndPoint = new IPEndPoint(IPAddress.Parse(internalIpStr), (int) port);
260 regionInfo = RegionInfo.Create(regionID, regionName, regX, regY, externalHostName, httpPort, simPort, remotingPort, simURI);
261 }
262 catch (Exception e)
263 {
264 errorMsg = e.Message;
265 return false;
266 }
267
268 return true;
269 }
270
271 public bool RequestClosestRegion(
272 string gridServerURL, string sendKey, string receiveKey, string regionName,
273 out RegionInfo regionInfo, out string errorMsg)
274 {
275 regionInfo = null;
276 errorMsg = string.Empty;
277 try
278 {
279 Hashtable requestData = new Hashtable();
280 requestData["region_name_search"] = regionName;
281 requestData["authkey"] = sendKey;
282 ArrayList SendParams = new ArrayList();
283 SendParams.Add(requestData);
284 XmlRpcRequest GridReq = new XmlRpcRequest("simulator_data_request", SendParams);
285 XmlRpcResponse GridResp = GridReq.Send(gridServerURL, 3000);
286
287 Hashtable responseData = (Hashtable)GridResp.Value;
288
289 if (responseData.ContainsKey("error"))
290 {
291 errorMsg = (string)responseData["error"];
292 return false;
293 }
294
295 regionInfo = BuildRegionInfo(responseData, "");
296
297 }
298 catch (Exception e)
299 {
300 errorMsg = e.Message;
301 return false;
302 }
303 return true;
304 }
305
306 /// <summary>
307 /// Performs a XML-RPC query against the grid server returning mapblock information in the specified coordinates
308 /// </summary>
309 /// <remarks>REDUNDANT - OGS1 is to be phased out in favour of OGS2</remarks>
310 /// <param name="minX">Minimum X value</param>
311 /// <param name="minY">Minimum Y value</param>
312 /// <param name="maxX">Maximum X value</param>
313 /// <param name="maxY">Maximum Y value</param>
314 /// <returns>Hashtable of hashtables containing map data elements</returns>
315 public bool MapBlockQuery(
316 string gridServerURL, int minX, int minY, int maxX, int maxY, out Hashtable respData, out string errorMsg)
317 {
318 respData = new Hashtable();
319 errorMsg = string.Empty;
320
321 Hashtable param = new Hashtable();
322 param["xmin"] = minX;
323 param["ymin"] = minY;
324 param["xmax"] = maxX;
325 param["ymax"] = maxY;
326 IList parameters = new ArrayList();
327 parameters.Add(param);
328
329 try
330 {
331 XmlRpcRequest req = new XmlRpcRequest("map_block", parameters);
332 XmlRpcResponse resp = req.Send(gridServerURL, 10000);
333 respData = (Hashtable)resp.Value;
334 return true;
335 }
336 catch (Exception e)
337 {
338 errorMsg = e.Message;
339 return false;
340 }
341 }
342
343 public bool SearchRegionByName(string gridServerURL, IList parameters, out Hashtable respData, out string errorMsg)
344 {
345 respData = null;
346 errorMsg = string.Empty;
347 try
348 {
349 XmlRpcRequest request = new XmlRpcRequest("search_for_region_by_name", parameters);
350 XmlRpcResponse resp = request.Send(gridServerURL, 10000);
351 respData = (Hashtable)resp.Value;
352 if (respData != null && respData.Contains("faultCode"))
353 {
354 errorMsg = (string)respData["faultString"];
355 return false;
356 }
357
358 return true;
359 }
360 catch (Exception e)
361 {
362 errorMsg = e.Message;
363 return false;
364 }
365 }
366
367 public RegionInfo BuildRegionInfo(Hashtable responseData, string prefix)
368 {
369 uint regX = Convert.ToUInt32((string)responseData[prefix + "region_locx"]);
370 uint regY = Convert.ToUInt32((string)responseData[prefix + "region_locy"]);
371 string internalIpStr = (string)responseData[prefix + "sim_ip"];
372 uint port = Convert.ToUInt32(responseData[prefix + "sim_port"]);
373
374 IPEndPoint neighbourInternalEndPoint = new IPEndPoint(Util.GetHostFromDNS(internalIpStr), (int)port);
375
376 RegionInfo regionInfo = new RegionInfo(regX, regY, neighbourInternalEndPoint, internalIpStr);
377 regionInfo.RemotingPort = Convert.ToUInt32((string)responseData[prefix + "remoting_port"]);
378 regionInfo.RemotingAddress = internalIpStr;
379
380 if (responseData.ContainsKey(prefix + "http_port"))
381 {
382 regionInfo.HttpPort = Convert.ToUInt32((string)responseData[prefix + "http_port"]);
383 }
384
385 regionInfo.RegionID = new UUID((string)responseData[prefix + "region_UUID"]);
386 regionInfo.RegionName = (string)responseData[prefix + "region_name"];
387
388 regionInfo.RegionSettings.TerrainImageID = new UUID((string)responseData[prefix + "map_UUID"]);
389 return regionInfo;
390 }
391 }
392}
diff --git a/OpenSim/Framework/Communications/Clients/InventoryClient.cs b/OpenSim/Framework/Communications/Clients/InventoryClient.cs
deleted file mode 100644
index e4f5e2a..0000000
--- a/OpenSim/Framework/Communications/Clients/InventoryClient.cs
+++ /dev/null
@@ -1,79 +0,0 @@
1/**
2 * Copyright (c), Contributors. All rights reserved.
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * * Neither the name of the Organizations nor the names of Individual
14 * Contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
20 * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
22 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
25 * OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 */
28
29using System;
30using OpenSim.Framework.Servers;
31using OpenSim.Framework.Servers.HttpServer;
32
33using OpenMetaverse;
34
35namespace OpenSim.Framework.Communications.Clients
36{
37 public class InventoryClient
38 {
39 private string ServerURL;
40
41 public InventoryClient(string url)
42 {
43 ServerURL = url;
44 }
45
46 public void GetInventoryItemAsync(InventoryItemBase item, ReturnResponse<InventoryItemBase> callBack)
47 {
48 System.Console.WriteLine("[HGrid] GetInventory from " + ServerURL);
49 try
50 {
51 RestSessionObjectPosterResponse<InventoryItemBase, InventoryItemBase> requester
52 = new RestSessionObjectPosterResponse<InventoryItemBase, InventoryItemBase>();
53 requester.ResponseCallback = callBack;
54
55 requester.BeginPostObject(ServerURL + "/GetItem/", item, string.Empty, string.Empty);
56 }
57 catch (Exception e)
58 {
59 System.Console.WriteLine("[HGrid]: Exception posting to inventory: " + e);
60 }
61 }
62
63 public InventoryItemBase GetInventoryItem(InventoryItemBase item)
64 {
65 System.Console.WriteLine("[HGrid] GetInventory " + item.ID + " from " + ServerURL);
66 try
67 {
68 item = SynchronousRestSessionObjectPoster<Guid, InventoryItemBase>.BeginPostObject("POST", ServerURL + "/GetItem/", item.ID.Guid, "", "");
69 return item;
70 }
71 catch (Exception e)
72 {
73 System.Console.WriteLine("[HGrid]: Exception posting to inventory: " + e);
74 }
75 return null;
76 }
77
78 }
79}
diff --git a/OpenSim/Framework/Communications/Clients/RegionClient.cs b/OpenSim/Framework/Communications/Clients/RegionClient.cs
deleted file mode 100644
index ee7dec8..0000000
--- a/OpenSim/Framework/Communications/Clients/RegionClient.cs
+++ /dev/null
@@ -1,755 +0,0 @@
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
28using System;
29using System.Collections.Generic;
30using System.IO;
31using System.Net;
32using System.Reflection;
33using System.Text;
34
35using OpenMetaverse;
36using OpenMetaverse.StructuredData;
37
38using GridRegion = OpenSim.Services.Interfaces.GridRegion;
39
40using log4net;
41
42namespace OpenSim.Framework.Communications.Clients
43{
44 public class RegionClient
45 {
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47
48 public bool DoCreateChildAgentCall(GridRegion region, AgentCircuitData aCircuit, string authKey, uint teleportFlags, out string reason)
49 {
50 reason = String.Empty;
51
52 // Eventually, we want to use a caps url instead of the agentID
53 string uri = string.Empty;
54 try
55 {
56 uri = "http://" + region.ExternalEndPoint.Address + ":" + region.HttpPort + "/agent/" + aCircuit.AgentID + "/";
57 }
58 catch (Exception e)
59 {
60 m_log.Debug("[REST COMMS]: Unable to resolve external endpoint on agent create. Reason: " + e.Message);
61 reason = e.Message;
62 return false;
63 }
64
65 //Console.WriteLine(" >>> DoCreateChildAgentCall <<< " + uri);
66
67 HttpWebRequest AgentCreateRequest = (HttpWebRequest)WebRequest.Create(uri);
68 AgentCreateRequest.Method = "POST";
69 AgentCreateRequest.ContentType = "application/json";
70 AgentCreateRequest.Timeout = 10000;
71 //AgentCreateRequest.KeepAlive = false;
72 AgentCreateRequest.Headers.Add("Authorization", authKey);
73
74 // Fill it in
75 OSDMap args = null;
76 try
77 {
78 args = aCircuit.PackAgentCircuitData();
79 }
80 catch (Exception e)
81 {
82 m_log.Debug("[REST COMMS]: PackAgentCircuitData failed with exception: " + e.Message);
83 }
84 // Add the regionhandle of the destination region
85 ulong regionHandle = GetRegionHandle(region.RegionHandle);
86 args["destination_handle"] = OSD.FromString(regionHandle.ToString());
87 args["teleport_flags"] = OSD.FromString(teleportFlags.ToString());
88
89 string strBuffer = "";
90 byte[] buffer = new byte[1];
91 try
92 {
93 strBuffer = OSDParser.SerializeJsonString(args);
94 Encoding str = Util.UTF8;
95 buffer = str.GetBytes(strBuffer);
96
97 }
98 catch (Exception e)
99 {
100 m_log.WarnFormat("[REST COMMS]: Exception thrown on serialization of ChildCreate: {0}", e.Message);
101 // ignore. buffer will be empty, caller should check.
102 }
103
104 Stream os = null;
105 try
106 { // send the Post
107 AgentCreateRequest.ContentLength = buffer.Length; //Count bytes to send
108 os = AgentCreateRequest.GetRequestStream();
109 os.Write(buffer, 0, strBuffer.Length); //Send it
110 //m_log.InfoFormat("[REST COMMS]: Posted CreateChildAgent request to remote sim {0}", uri);
111 }
112 //catch (WebException ex)
113 catch
114 {
115 //m_log.InfoFormat("[REST COMMS]: Bad send on ChildAgentUpdate {0}", ex.Message);
116 reason = "cannot contact remote region";
117 return false;
118 }
119 finally
120 {
121 if (os != null)
122 os.Close();
123 }
124
125 // Let's wait for the response
126 //m_log.Info("[REST COMMS]: Waiting for a reply after DoCreateChildAgentCall");
127
128 WebResponse webResponse = null;
129 StreamReader sr = null;
130 try
131 {
132 webResponse = AgentCreateRequest.GetResponse();
133 if (webResponse == null)
134 {
135 m_log.Info("[REST COMMS]: Null reply on DoCreateChildAgentCall post");
136 }
137 else
138 {
139
140 sr = new StreamReader(webResponse.GetResponseStream());
141 string response = sr.ReadToEnd().Trim();
142 m_log.InfoFormat("[REST COMMS]: DoCreateChildAgentCall reply was {0} ", response);
143
144 if (!String.IsNullOrEmpty(response))
145 {
146 try
147 {
148 // we assume we got an OSDMap back
149 OSDMap r = GetOSDMap(response);
150 bool success = r["success"].AsBoolean();
151 reason = r["reason"].AsString();
152 return success;
153 }
154 catch (NullReferenceException e)
155 {
156 m_log.InfoFormat("[REST COMMS]: exception on reply of DoCreateChildAgentCall {0}", e.Message);
157
158 // check for old style response
159 if (response.ToLower().StartsWith("true"))
160 return true;
161
162 return false;
163 }
164 }
165 }
166 }
167 catch (WebException ex)
168 {
169 m_log.InfoFormat("[REST COMMS]: exception on reply of DoCreateChildAgentCall {0}", ex.Message);
170 // ignore, really
171 }
172 finally
173 {
174 if (sr != null)
175 sr.Close();
176 }
177
178 return true;
179
180 }
181
182 public bool DoChildAgentUpdateCall(GridRegion region, IAgentData cAgentData)
183 {
184 // Eventually, we want to use a caps url instead of the agentID
185 string uri = string.Empty;
186 try
187 {
188 uri = "http://" + region.ExternalEndPoint.Address + ":" + region.HttpPort + "/agent/" + cAgentData.AgentID + "/";
189 }
190 catch (Exception e)
191 {
192 m_log.Debug("[REST COMMS]: Unable to resolve external endpoint on agent update. Reason: " + e.Message);
193 return false;
194 }
195 //Console.WriteLine(" >>> DoChildAgentUpdateCall <<< " + uri);
196
197 HttpWebRequest ChildUpdateRequest = (HttpWebRequest)WebRequest.Create(uri);
198 ChildUpdateRequest.Method = "PUT";
199 ChildUpdateRequest.ContentType = "application/json";
200 ChildUpdateRequest.Timeout = 10000;
201 //ChildUpdateRequest.KeepAlive = false;
202
203 // Fill it in
204 OSDMap args = null;
205 try
206 {
207 args = cAgentData.Pack();
208 }
209 catch (Exception e)
210 {
211 m_log.Debug("[REST COMMS]: PackUpdateMessage failed with exception: " + e.Message);
212 }
213 // Add the regionhandle of the destination region
214 ulong regionHandle = GetRegionHandle(region.RegionHandle);
215 args["destination_handle"] = OSD.FromString(regionHandle.ToString());
216
217 string strBuffer = "";
218 byte[] buffer = new byte[1];
219 try
220 {
221 strBuffer = OSDParser.SerializeJsonString(args);
222 Encoding str = Util.UTF8;
223 buffer = str.GetBytes(strBuffer);
224
225 }
226 catch (Exception e)
227 {
228 m_log.WarnFormat("[REST COMMS]: Exception thrown on serialization of ChildUpdate: {0}", e.Message);
229 // ignore. buffer will be empty, caller should check.
230 }
231
232 Stream os = null;
233 try
234 { // send the Post
235 ChildUpdateRequest.ContentLength = buffer.Length; //Count bytes to send
236 os = ChildUpdateRequest.GetRequestStream();
237 os.Write(buffer, 0, strBuffer.Length); //Send it
238 //m_log.InfoFormat("[REST COMMS]: Posted ChildAgentUpdate request to remote sim {0}", uri);
239 }
240 //catch (WebException ex)
241 catch
242 {
243 //m_log.InfoFormat("[REST COMMS]: Bad send on ChildAgentUpdate {0}", ex.Message);
244
245 return false;
246 }
247 finally
248 {
249 if (os != null)
250 os.Close();
251 }
252
253 // Let's wait for the response
254 //m_log.Info("[REST COMMS]: Waiting for a reply after ChildAgentUpdate");
255
256 WebResponse webResponse = null;
257 StreamReader sr = null;
258 try
259 {
260 webResponse = ChildUpdateRequest.GetResponse();
261 if (webResponse == null)
262 {
263 m_log.Info("[REST COMMS]: Null reply on ChilAgentUpdate post");
264 }
265
266 sr = new StreamReader(webResponse.GetResponseStream());
267 //reply = sr.ReadToEnd().Trim();
268 sr.ReadToEnd().Trim();
269 sr.Close();
270 //m_log.InfoFormat("[REST COMMS]: ChilAgentUpdate reply was {0} ", reply);
271
272 }
273 catch (WebException ex)
274 {
275 m_log.InfoFormat("[REST COMMS]: exception on reply of ChilAgentUpdate {0}", ex.Message);
276 // ignore, really
277 }
278 finally
279 {
280 if (sr != null)
281 sr.Close();
282 }
283
284 return true;
285 }
286
287 public bool DoRetrieveRootAgentCall(GridRegion region, UUID id, out IAgentData agent)
288 {
289 agent = null;
290 // Eventually, we want to use a caps url instead of the agentID
291 string uri = "http://" + region.ExternalEndPoint.Address + ":" + region.HttpPort + "/agent/" + id + "/" + region.RegionHandle.ToString() + "/";
292 //Console.WriteLine(" >>> DoRetrieveRootAgentCall <<< " + uri);
293
294 HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
295 request.Method = "GET";
296 request.Timeout = 10000;
297 //request.Headers.Add("authorization", ""); // coming soon
298
299 HttpWebResponse webResponse = null;
300 string reply = string.Empty;
301 StreamReader sr = null;
302 try
303 {
304 webResponse = (HttpWebResponse)request.GetResponse();
305 if (webResponse == null)
306 {
307 m_log.Info("[REST COMMS]: Null reply on agent get ");
308 }
309
310 sr = new StreamReader(webResponse.GetResponseStream());
311 reply = sr.ReadToEnd().Trim();
312
313 //Console.WriteLine("[REST COMMS]: ChilAgentUpdate reply was " + reply);
314
315 }
316 catch (WebException ex)
317 {
318 m_log.InfoFormat("[REST COMMS]: exception on reply of agent get {0}", ex.Message);
319 // ignore, really
320 return false;
321 }
322 finally
323 {
324 if (sr != null)
325 sr.Close();
326 }
327
328 if (webResponse.StatusCode == HttpStatusCode.OK)
329 {
330 // we know it's jason
331 OSDMap args = GetOSDMap(reply);
332 if (args == null)
333 {
334 //Console.WriteLine("[REST COMMS]: Error getting OSDMap from reply");
335 return false;
336 }
337
338 agent = new CompleteAgentData();
339 agent.Unpack(args);
340 return true;
341 }
342
343 //Console.WriteLine("[REST COMMS]: DoRetrieveRootAgentCall returned status " + webResponse.StatusCode);
344 return false;
345 }
346
347 public bool DoReleaseAgentCall(ulong regionHandle, UUID id, string uri)
348 {
349 //m_log.Debug(" >>> DoReleaseAgentCall <<< " + uri);
350
351 WebRequest request = WebRequest.Create(uri);
352 request.Method = "DELETE";
353 request.Timeout = 10000;
354
355 StreamReader sr = null;
356 try
357 {
358 WebResponse webResponse = request.GetResponse();
359 if (webResponse == null)
360 {
361 m_log.Info("[REST COMMS]: Null reply on agent delete ");
362 }
363
364 sr = new StreamReader(webResponse.GetResponseStream());
365 //reply = sr.ReadToEnd().Trim();
366 sr.ReadToEnd().Trim();
367 sr.Close();
368 //m_log.InfoFormat("[REST COMMS]: ChilAgentUpdate reply was {0} ", reply);
369
370 }
371 catch (WebException ex)
372 {
373 m_log.InfoFormat("[REST COMMS]: exception on reply of agent delete {0}", ex.Message);
374 // ignore, really
375 }
376 finally
377 {
378 if (sr != null)
379 sr.Close();
380 }
381
382 return true;
383 }
384
385
386 public bool DoCloseAgentCall(GridRegion region, UUID id)
387 {
388 string uri = string.Empty;
389 try
390 {
391 uri = "http://" + region.ExternalEndPoint.Address + ":" + region.HttpPort + "/agent/" + id + "/" + region.RegionHandle.ToString() + "/";
392 }
393 catch (Exception e)
394 {
395 m_log.Debug("[REST COMMS]: Unable to resolve external endpoint on agent close. Reason: " + e.Message);
396 return false;
397 }
398
399 //Console.WriteLine(" >>> DoCloseAgentCall <<< " + uri);
400
401 WebRequest request = WebRequest.Create(uri);
402 request.Method = "DELETE";
403 request.Timeout = 10000;
404
405 StreamReader sr = null;
406 try
407 {
408 WebResponse webResponse = request.GetResponse();
409 if (webResponse == null)
410 {
411 m_log.Info("[REST COMMS]: Null reply on agent delete ");
412 }
413
414 sr = new StreamReader(webResponse.GetResponseStream());
415 //reply = sr.ReadToEnd().Trim();
416 sr.ReadToEnd().Trim();
417 sr.Close();
418 //m_log.InfoFormat("[REST COMMS]: ChilAgentUpdate reply was {0} ", reply);
419
420 }
421 catch (WebException ex)
422 {
423 m_log.InfoFormat("[REST COMMS]: exception on reply of agent delete {0}", ex.Message);
424 // ignore, really
425 }
426 finally
427 {
428 if (sr != null)
429 sr.Close();
430 }
431
432 return true;
433 }
434
435 public bool DoCreateObjectCall(GridRegion region, ISceneObject sog, string sogXml2, bool allowScriptCrossing)
436 {
437 ulong regionHandle = GetRegionHandle(region.RegionHandle);
438 string uri
439 = "http://" + region.ExternalEndPoint.Address + ":" + region.HttpPort
440 + "/object/" + sog.UUID + "/" + regionHandle.ToString() + "/";
441 //m_log.Debug(" >>> DoCreateChildAgentCall <<< " + uri);
442
443 WebRequest ObjectCreateRequest = WebRequest.Create(uri);
444 ObjectCreateRequest.Method = "POST";
445 ObjectCreateRequest.ContentType = "application/json";
446 ObjectCreateRequest.Timeout = 10000;
447
448 OSDMap args = new OSDMap(2);
449 args["sog"] = OSD.FromString(sogXml2);
450 args["extra"] = OSD.FromString(sog.ExtraToXmlString());
451 if (allowScriptCrossing)
452 {
453 string state = sog.GetStateSnapshot();
454 if (state.Length > 0)
455 args["state"] = OSD.FromString(state);
456 }
457
458 string strBuffer = "";
459 byte[] buffer = new byte[1];
460 try
461 {
462 strBuffer = OSDParser.SerializeJsonString(args);
463 Encoding str = Util.UTF8;
464 buffer = str.GetBytes(strBuffer);
465
466 }
467 catch (Exception e)
468 {
469 m_log.WarnFormat("[REST COMMS]: Exception thrown on serialization of CreateObject: {0}", e.Message);
470 // ignore. buffer will be empty, caller should check.
471 }
472
473 Stream os = null;
474 try
475 { // send the Post
476 ObjectCreateRequest.ContentLength = buffer.Length; //Count bytes to send
477 os = ObjectCreateRequest.GetRequestStream();
478 os.Write(buffer, 0, strBuffer.Length); //Send it
479 m_log.InfoFormat("[REST COMMS]: Posted ChildAgentUpdate request to remote sim {0}", uri);
480 }
481 //catch (WebException ex)
482 catch
483 {
484 // m_log.InfoFormat("[REST COMMS]: Bad send on CreateObject {0}", ex.Message);
485
486 return false;
487 }
488 finally
489 {
490 if (os != null)
491 os.Close();
492 }
493
494 // Let's wait for the response
495 //m_log.Info("[REST COMMS]: Waiting for a reply after DoCreateChildAgentCall");
496
497 StreamReader sr = null;
498 try
499 {
500 WebResponse webResponse = ObjectCreateRequest.GetResponse();
501 if (webResponse == null)
502 {
503 m_log.Info("[REST COMMS]: Null reply on DoCreateObjectCall post");
504 }
505
506 sr = new StreamReader(webResponse.GetResponseStream());
507 //reply = sr.ReadToEnd().Trim();
508 sr.ReadToEnd().Trim();
509 //m_log.InfoFormat("[REST COMMS]: DoCreateChildAgentCall reply was {0} ", reply);
510
511 }
512 catch (WebException ex)
513 {
514 m_log.InfoFormat("[REST COMMS]: exception on reply of DoCreateObjectCall {0}", ex.Message);
515 // ignore, really
516 }
517 finally
518 {
519 if (sr != null)
520 sr.Close();
521 }
522
523 return true;
524
525 }
526
527 public bool DoCreateObjectCall(GridRegion region, UUID userID, UUID itemID)
528 {
529 ulong regionHandle = GetRegionHandle(region.RegionHandle);
530 string uri = "http://" + region.ExternalEndPoint.Address + ":" + region.HttpPort + "/object/" + UUID.Zero + "/" + regionHandle.ToString() + "/";
531 //m_log.Debug(" >>> DoCreateChildAgentCall <<< " + uri);
532
533 WebRequest ObjectCreateRequest = WebRequest.Create(uri);
534 ObjectCreateRequest.Method = "PUT";
535 ObjectCreateRequest.ContentType = "application/json";
536 ObjectCreateRequest.Timeout = 10000;
537
538 OSDMap args = new OSDMap(2);
539 args["userid"] = OSD.FromUUID(userID);
540 args["itemid"] = OSD.FromUUID(itemID);
541
542 string strBuffer = "";
543 byte[] buffer = new byte[1];
544 try
545 {
546 strBuffer = OSDParser.SerializeJsonString(args);
547 Encoding str = Util.UTF8;
548 buffer = str.GetBytes(strBuffer);
549
550 }
551 catch (Exception e)
552 {
553 m_log.WarnFormat("[REST COMMS]: Exception thrown on serialization of CreateObject: {0}", e.Message);
554 // ignore. buffer will be empty, caller should check.
555 }
556
557 Stream os = null;
558 try
559 { // send the Post
560 ObjectCreateRequest.ContentLength = buffer.Length; //Count bytes to send
561 os = ObjectCreateRequest.GetRequestStream();
562 os.Write(buffer, 0, strBuffer.Length); //Send it
563 //m_log.InfoFormat("[REST COMMS]: Posted CreateObject request to remote sim {0}", uri);
564 }
565 //catch (WebException ex)
566 catch
567 {
568 // m_log.InfoFormat("[REST COMMS]: Bad send on CreateObject {0}", ex.Message);
569
570 return false;
571 }
572 finally
573 {
574 if (os != null)
575 os.Close();
576 }
577
578 // Let's wait for the response
579 //m_log.Info("[REST COMMS]: Waiting for a reply after DoCreateChildAgentCall");
580
581 StreamReader sr = null;
582 try
583 {
584 WebResponse webResponse = ObjectCreateRequest.GetResponse();
585 if (webResponse == null)
586 {
587 m_log.Info("[REST COMMS]: Null reply on DoCreateObjectCall post");
588 }
589
590 sr = new StreamReader(webResponse.GetResponseStream());
591 sr.ReadToEnd().Trim();
592 sr.ReadToEnd().Trim();
593
594 //m_log.InfoFormat("[REST COMMS]: DoCreateChildAgentCall reply was {0} ", reply);
595
596 }
597 catch (WebException ex)
598 {
599 m_log.InfoFormat("[REST COMMS]: exception on reply of DoCreateObjectCall {0}", ex.Message);
600 // ignore, really
601 }
602 finally
603 {
604 if (sr != null)
605 sr.Close();
606 }
607
608 return true;
609
610 }
611
612 public bool DoHelloNeighbourCall(RegionInfo region, RegionInfo thisRegion)
613 {
614 string uri = "http://" + region.ExternalEndPoint.Address + ":" + region.HttpPort + "/region/" + thisRegion.RegionID + "/";
615 //m_log.Debug(" >>> DoHelloNeighbourCall <<< " + uri);
616
617 WebRequest HelloNeighbourRequest = WebRequest.Create(uri);
618 HelloNeighbourRequest.Method = "POST";
619 HelloNeighbourRequest.ContentType = "application/json";
620 HelloNeighbourRequest.Timeout = 10000;
621
622 // Fill it in
623 OSDMap args = null;
624 try
625 {
626 args = thisRegion.PackRegionInfoData();
627 }
628 catch (Exception e)
629 {
630 m_log.Debug("[REST COMMS]: PackRegionInfoData failed with exception: " + e.Message);
631 }
632 // Add the regionhandle of the destination region
633 ulong regionHandle = GetRegionHandle(region.RegionHandle);
634 args["destination_handle"] = OSD.FromString(regionHandle.ToString());
635
636 string strBuffer = "";
637 byte[] buffer = new byte[1];
638 try
639 {
640 strBuffer = OSDParser.SerializeJsonString(args);
641 Encoding str = Util.UTF8;
642 buffer = str.GetBytes(strBuffer);
643
644 }
645 catch (Exception e)
646 {
647 m_log.WarnFormat("[REST COMMS]: Exception thrown on serialization of HelloNeighbour: {0}", e.Message);
648 // ignore. buffer will be empty, caller should check.
649 }
650
651 Stream os = null;
652 try
653 { // send the Post
654 HelloNeighbourRequest.ContentLength = buffer.Length; //Count bytes to send
655 os = HelloNeighbourRequest.GetRequestStream();
656 os.Write(buffer, 0, strBuffer.Length); //Send it
657 //m_log.InfoFormat("[REST COMMS]: Posted HelloNeighbour request to remote sim {0}", uri);
658 }
659 //catch (WebException ex)
660 catch
661 {
662 //m_log.InfoFormat("[REST COMMS]: Bad send on HelloNeighbour {0}", ex.Message);
663
664 return false;
665 }
666 finally
667 {
668 if (os != null)
669 os.Close();
670 }
671 // Let's wait for the response
672 //m_log.Info("[REST COMMS]: Waiting for a reply after DoHelloNeighbourCall");
673
674 StreamReader sr = null;
675 try
676 {
677 WebResponse webResponse = HelloNeighbourRequest.GetResponse();
678 if (webResponse == null)
679 {
680 m_log.Info("[REST COMMS]: Null reply on DoHelloNeighbourCall post");
681 }
682
683 sr = new StreamReader(webResponse.GetResponseStream());
684 //reply = sr.ReadToEnd().Trim();
685 sr.ReadToEnd().Trim();
686 //m_log.InfoFormat("[REST COMMS]: DoHelloNeighbourCall reply was {0} ", reply);
687
688 }
689 catch (WebException ex)
690 {
691 m_log.InfoFormat("[REST COMMS]: exception on reply of DoHelloNeighbourCall {0}", ex.Message);
692 // ignore, really
693 }
694 finally
695 {
696 if (sr != null)
697 sr.Close();
698 }
699
700 return true;
701
702 }
703
704 #region Hyperlinks
705
706 public virtual ulong GetRegionHandle(ulong handle)
707 {
708 return handle;
709 }
710
711 public virtual bool IsHyperlink(ulong handle)
712 {
713 return false;
714 }
715
716 public virtual void SendUserInformation(GridRegion regInfo, AgentCircuitData aCircuit)
717 {
718 }
719
720 public virtual void AdjustUserInformation(AgentCircuitData aCircuit)
721 {
722 }
723
724 #endregion /* Hyperlinks */
725
726 public static OSDMap GetOSDMap(string data)
727 {
728 OSDMap args = null;
729 try
730 {
731 OSD buffer;
732 // We should pay attention to the content-type, but let's assume we know it's Json
733 buffer = OSDParser.DeserializeJson(data);
734 if (buffer.Type == OSDType.Map)
735 {
736 args = (OSDMap)buffer;
737 return args;
738 }
739 else
740 {
741 // uh?
742 System.Console.WriteLine("[REST COMMS]: Got OSD of type " + buffer.Type.ToString());
743 return null;
744 }
745 }
746 catch (Exception ex)
747 {
748 System.Console.WriteLine("[REST COMMS]: exception on parse of REST message " + ex.Message);
749 return null;
750 }
751 }
752
753
754 }
755}
diff --git a/OpenSim/Framework/Communications/CommunicationsManager.cs b/OpenSim/Framework/Communications/CommunicationsManager.cs
deleted file mode 100644
index 4bf9018..0000000
--- a/OpenSim/Framework/Communications/CommunicationsManager.cs
+++ /dev/null
@@ -1,264 +0,0 @@
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
28using System;
29using System.Collections.Generic;
30using OpenMetaverse;
31using OpenSim.Framework.Communications.Cache;
32
33namespace OpenSim.Framework.Communications
34{
35 /// <summary>
36 /// This class manages references to OpenSim non-region services (inventory, user, etc.)
37 /// </summary>
38 ///
39 /// TODO: Service retrieval needs to be managed via plugin and interfaces requests, as happens for region
40 /// modules from scene. Among other things, this will allow this class to be used in many different contexts
41 /// (from a grid service executable, to provide services on a region) without lots of messy nulls and confusion.
42 /// Also, a post initialize step on the plugins will be needed so that we don't get tortuous problems with
43 /// circular dependencies between plugins.
44 public class CommunicationsManager
45 {
46 //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47
48 protected Dictionary<UUID, string[]> m_nameRequestCache = new Dictionary<UUID, string[]>();
49
50 public IUserService UserService
51 {
52 get { return m_userService; }
53 }
54 protected IUserService m_userService;
55
56 public IMessagingService MessageService
57 {
58 get { return m_messageService; }
59 }
60 protected IMessagingService m_messageService;
61
62
63 public UserProfileCacheService UserProfileCacheService
64 {
65 get { return m_userProfileCacheService; }
66 }
67 protected UserProfileCacheService m_userProfileCacheService;
68
69 public IAvatarService AvatarService
70 {
71 get { return m_avatarService; }
72 }
73 protected IAvatarService m_avatarService;
74
75 public IInterServiceInventoryServices InterServiceInventoryService
76 {
77 get { return m_interServiceInventoryService; }
78 }
79 protected IInterServiceInventoryServices m_interServiceInventoryService;
80
81 public NetworkServersInfo NetworkServersInfo
82 {
83 get { return m_networkServersInfo; }
84 }
85 protected NetworkServersInfo m_networkServersInfo;
86
87 /// <summary>
88 /// Interface to user service for administrating users.
89 /// </summary>
90 public IUserAdminService UserAdminService
91 {
92 get { return m_userAdminService; }
93 }
94 protected IUserAdminService m_userAdminService;
95
96 /// <summary>
97 /// Constructor
98 /// </summary>
99 /// <param name="serversInfo"></param>
100 public CommunicationsManager(NetworkServersInfo serversInfo,
101 LibraryRootFolder libraryRootFolder)
102 {
103 m_networkServersInfo = serversInfo;
104 m_userProfileCacheService = new UserProfileCacheService(this, libraryRootFolder);
105 }
106
107
108 #region Friend Methods
109
110 /// <summary>
111 /// Adds a new friend to the database for XUser
112 /// </summary>
113 /// <param name="friendlistowner">The agent that who's friends list is being added to</param>
114 /// <param name="friend">The agent that being added to the friends list of the friends list owner</param>
115 /// <param name="perms">A uint bit vector for set perms that the friend being added has; 0 = none, 1=This friend can see when they sign on, 2 = map, 4 edit objects </param>
116 public void AddNewUserFriend(UUID friendlistowner, UUID friend, uint perms)
117 {
118 m_userService.AddNewUserFriend(friendlistowner, friend, perms);
119 }
120
121 /// <summary>
122 /// Logs off a user and does the appropriate communications
123 /// </summary>
124 /// <param name="userid"></param>
125 /// <param name="regionid"></param>
126 /// <param name="regionhandle"></param>
127 /// <param name="position"></param>
128 /// <param name="lookat"></param>
129 public void LogOffUser(UUID userid, UUID regionid, ulong regionhandle, Vector3 position, Vector3 lookat)
130 {
131 m_userService.LogOffUser(userid, regionid, regionhandle, position, lookat);
132 }
133
134 /// <summary>
135 /// Logs off a user and does the appropriate communications (deprecated as of 2008-08-27)
136 /// </summary>
137 /// <param name="userid"></param>
138 /// <param name="regionid"></param>
139 /// <param name="regionhandle"></param>
140 /// <param name="posx"></param>
141 /// <param name="posy"></param>
142 /// <param name="posz"></param>
143 public void LogOffUser(UUID userid, UUID regionid, ulong regionhandle, float posx, float posy, float posz)
144 {
145 m_userService.LogOffUser(userid, regionid, regionhandle, posx, posy, posz);
146 }
147
148 /// <summary>
149 /// Delete friend on friendlistowner's friendlist.
150 /// </summary>
151 /// <param name="friendlistowner">The agent that who's friends list is being updated</param>
152 /// <param name="friend">The Ex-friend agent</param>
153 public void RemoveUserFriend(UUID friendlistowner, UUID friend)
154 {
155 m_userService.RemoveUserFriend(friendlistowner, friend);
156 }
157
158 /// <summary>
159 /// Update permissions for friend on friendlistowner's friendlist.
160 /// </summary>
161 /// <param name="friendlistowner">The agent that who's friends list is being updated</param>
162 /// <param name="friend">The agent that is getting or loosing permissions</param>
163 /// <param name="perms">A uint bit vector for set perms that the friend being added has; 0 = none, 1=This friend can see when they sign on, 2 = map, 4 edit objects </param>
164 public void UpdateUserFriendPerms(UUID friendlistowner, UUID friend, uint perms)
165 {
166 m_userService.UpdateUserFriendPerms(friendlistowner, friend, perms);
167 }
168
169 /// <summary>
170 /// Returns a list of FriendsListItems that describe the friends and permissions in the friend relationship for UUID friendslistowner
171 /// </summary>
172 /// <param name="friendlistowner">The agent that we're retreiving the friends Data.</param>
173 public List<FriendListItem> GetUserFriendList(UUID friendlistowner)
174 {
175 return m_userService.GetUserFriendList(friendlistowner);
176 }
177
178 public Dictionary<UUID, FriendRegionInfo> GetFriendRegionInfos(List<UUID> uuids)
179 {
180 return m_messageService.GetFriendRegionInfos(uuids);
181 }
182
183 #endregion
184
185 #region Packet Handlers
186
187 public void UpdateAvatarPropertiesRequest(IClientAPI remote_client, UserProfileData UserProfile)
188 {
189 m_userService.UpdateUserProfile(UserProfile);
190 return;
191 }
192
193 public void HandleUUIDNameRequest(UUID uuid, IClientAPI remote_client)
194 {
195 if (uuid == m_userProfileCacheService.LibraryRoot.Owner)
196 {
197 remote_client.SendNameReply(uuid, "Mr", "OpenSim");
198 }
199 else
200 {
201 string[] names = doUUIDNameRequest(uuid);
202 if (names.Length == 2)
203 {
204 remote_client.SendNameReply(uuid, names[0], names[1]);
205 }
206
207 }
208 }
209
210 private string[] doUUIDNameRequest(UUID uuid)
211 {
212 lock (m_nameRequestCache)
213 {
214 if (m_nameRequestCache.ContainsKey(uuid))
215 return m_nameRequestCache[uuid];
216 }
217
218 string[] returnstring = new string[0];
219 CachedUserInfo uinfo = UserProfileCacheService.GetUserDetails(uuid);
220
221 if ((uinfo != null) && (uinfo.UserProfile != null))
222 {
223 returnstring = new string[2];
224 returnstring[0] = uinfo.UserProfile.FirstName;
225 returnstring[1] = uinfo.UserProfile.SurName;
226 lock (m_nameRequestCache)
227 {
228 if (!m_nameRequestCache.ContainsKey(uuid))
229 m_nameRequestCache.Add(uuid, returnstring);
230 }
231 }
232
233 return returnstring;
234 }
235
236 public bool UUIDNameCachedTest(UUID uuid)
237 {
238 lock (m_nameRequestCache)
239 return m_nameRequestCache.ContainsKey(uuid);
240 }
241
242 public string UUIDNameRequestString(UUID uuid)
243 {
244 string[] names = doUUIDNameRequest(uuid);
245 if (names.Length == 2)
246 {
247 string firstname = names[0];
248 string lastname = names[1];
249
250 return firstname + " " + lastname;
251
252 }
253 return "(hippos)";
254 }
255
256 public List<AvatarPickerAvatar> GenerateAgentPickerRequestResponse(UUID queryID, string query)
257 {
258 List<AvatarPickerAvatar> pickerlist = m_userService.GenerateAgentPickerRequestResponse(queryID, query);
259 return pickerlist;
260 }
261
262 #endregion
263 }
264}
diff --git a/OpenSim/Framework/Communications/IAuthentication.cs b/OpenSim/Framework/Communications/IAuthentication.cs
deleted file mode 100644
index bd568e4..0000000
--- a/OpenSim/Framework/Communications/IAuthentication.cs
+++ /dev/null
@@ -1,39 +0,0 @@
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
28using System;
29using OpenMetaverse;
30
31namespace OpenSim.Framework.Communications
32{
33 public interface IAuthentication
34 {
35 string GetNewKey(string url, UUID userID, UUID authToken);
36 bool VerifyKey(UUID userID, string key);
37 bool VerifySession(UUID iserID, UUID sessionID);
38 }
39}
diff --git a/OpenSim/Framework/Communications/IAvatarService.cs b/OpenSim/Framework/Communications/IAvatarService.cs
deleted file mode 100644
index 760aa62..0000000
--- a/OpenSim/Framework/Communications/IAvatarService.cs
+++ /dev/null
@@ -1,48 +0,0 @@
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
28using OpenMetaverse;
29
30namespace OpenSim.Framework.Communications
31{
32 public interface IAvatarService
33 {
34 /// <summary>
35 /// Get avatar appearance information
36 /// </summary>
37 /// <param name="user"></param>
38 /// <returns></returns>
39 AvatarAppearance GetUserAppearance(UUID user);
40
41 /// <summary>
42 /// Update avatar appearance information
43 /// </summary>
44 /// <param name="user"></param>
45 /// <param name="appearance"></param>
46 void UpdateUserAppearance(UUID user, AvatarAppearance appearance);
47 }
48}
diff --git a/OpenSim/Framework/Communications/IInterServiceInventoryServices.cs b/OpenSim/Framework/Communications/IInterServiceInventoryServices.cs
deleted file mode 100644
index 7f17872..0000000
--- a/OpenSim/Framework/Communications/IInterServiceInventoryServices.cs
+++ /dev/null
@@ -1,64 +0,0 @@
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
28using System.Collections.Generic;
29using OpenMetaverse;
30
31namespace OpenSim.Framework.Communications
32{
33 /// <summary>
34 /// Inventory operations used between grid services.
35 /// </summary>
36 public interface IInterServiceInventoryServices
37 {
38 /// <summary>
39 /// Create a new inventory for the given user.
40 /// </summary>
41 /// <param name="user"></param>
42 /// <returns>true if the inventory was successfully created, false otherwise</returns>
43 bool CreateNewUserInventory(UUID user);
44
45 /// <summary>
46 /// Returns a list of all the folders in a given user's inventory.
47 /// </summary>
48 /// <param name="userId"></param>
49 /// <returns>A flat list of the user's inventory folder tree,
50 /// null if there is no inventory for this user</returns>
51 List<InventoryFolderBase> GetInventorySkeleton(UUID userId);
52
53 /// <summary>
54 /// Returns a list of all the active gestures in a user's inventory.
55 /// </summary>
56 /// <param name="userId">
57 /// The <see cref="UUID"/> of the user
58 /// </param>
59 /// <returns>
60 /// A flat list of the gesture items.
61 /// </returns>
62 List<InventoryItemBase> GetActiveGestures(UUID userId);
63 }
64}
diff --git a/OpenSim/Framework/Communications/IMessagingService.cs b/OpenSim/Framework/Communications/IMessagingService.cs
deleted file mode 100644
index 5d65f19..0000000
--- a/OpenSim/Framework/Communications/IMessagingService.cs
+++ /dev/null
@@ -1,37 +0,0 @@
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
28using System.Collections.Generic;
29using OpenMetaverse;
30
31namespace OpenSim.Framework.Communications
32{
33 public interface IMessagingService
34 {
35 Dictionary<UUID, FriendRegionInfo> GetFriendRegionInfos (List<UUID> uuids);
36 }
37}
diff --git a/OpenSim/Framework/Communications/IUserAdminService.cs b/OpenSim/Framework/Communications/IUserAdminService.cs
deleted file mode 100644
index 423b49b..0000000
--- a/OpenSim/Framework/Communications/IUserAdminService.cs
+++ /dev/null
@@ -1,71 +0,0 @@
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
28using OpenMetaverse;
29
30namespace OpenSim.Framework.Communications
31{
32 /// <summary>
33 /// Interface for the service for administrating users
34 /// </summary>
35 public interface IUserAdminService
36 {
37 /// <summary>
38 /// Add a new user
39 /// </summary>
40 /// <param name="firstName">The first name</param>
41 /// <param name="lastName">The last name</param>
42 /// <param name="pass">password of avatar</param>
43 /// <param name="email">email of user</param>
44 /// <param name="regX">region X</param>
45 /// <param name="regY">region Y</param>
46 /// <returns>The UUID of the created user profile. On failure, returns UUID.Zero</returns>
47 UUID AddUser(string firstName, string lastName, string pass, string email, uint regX, uint regY);
48
49 /// <summary>
50 /// Add a new user with a specified UUID. SHOULD ONLY BE USED in very special circumstances from modules!
51 /// </summary>
52 /// <param name="firstName">The first name</param>
53 /// <param name="lastName">The last name</param>
54 /// <param name="pass">password of avatar</param>
55 /// <param name="email">email of user</param>
56 /// <param name="regX">region X</param>
57 /// <param name="regY">region Y</param>
58 /// <param name="setUUID">The set UUID</param>
59 /// <returns>The UUID of the created user profile. On failure, returns UUID.Zero</returns>
60 UUID AddUser(string firstName, string lastName, string pass, string email, uint regX, uint regY, UUID setUUID);
61
62 /// <summary>
63 /// Reset a user password
64 /// </summary>
65 /// <param name="firstName"></param>
66 /// <param name="lastName"></param>
67 /// <param name="newPassword"></param>
68 /// <returns>true if the update was successful, false otherwise</returns>
69 bool ResetUserPassword(string firstName, string lastName, string newPassword);
70 }
71}
diff --git a/OpenSim/Framework/Communications/Osp/OspInventoryWrapperPlugin.cs b/OpenSim/Framework/Communications/Osp/OspInventoryWrapperPlugin.cs
index e96c5e8..bcd1eee 100644
--- a/OpenSim/Framework/Communications/Osp/OspInventoryWrapperPlugin.cs
+++ b/OpenSim/Framework/Communications/Osp/OspInventoryWrapperPlugin.cs
@@ -28,6 +28,7 @@
28using System.Collections.Generic; 28using System.Collections.Generic;
29using OpenSim.Data; 29using OpenSim.Data;
30using OpenMetaverse; 30using OpenMetaverse;
31using OpenSim.Services.Interfaces;
31 32
32namespace OpenSim.Framework.Communications.Osp 33namespace OpenSim.Framework.Communications.Osp
33{ 34{
@@ -37,12 +38,13 @@ namespace OpenSim.Framework.Communications.Osp
37 public class OspInventoryWrapperPlugin : IInventoryDataPlugin 38 public class OspInventoryWrapperPlugin : IInventoryDataPlugin
38 { 39 {
39 protected IInventoryDataPlugin m_wrappedPlugin; 40 protected IInventoryDataPlugin m_wrappedPlugin;
40 protected CommunicationsManager m_commsManager; 41 //protected CommunicationsManager m_commsManager;
42 protected IUserAccountService m_userAccountService;
41 43
42 public OspInventoryWrapperPlugin(IInventoryDataPlugin wrappedPlugin, CommunicationsManager commsManager) 44 public OspInventoryWrapperPlugin(IInventoryDataPlugin wrappedPlugin, IUserAccountService userService)
43 { 45 {
44 m_wrappedPlugin = wrappedPlugin; 46 m_wrappedPlugin = wrappedPlugin;
45 m_commsManager = commsManager; 47 m_userAccountService = userService;
46 } 48 }
47 49
48 public string Name { get { return "OspInventoryWrapperPlugin"; } } 50 public string Name { get { return "OspInventoryWrapperPlugin"; } }
@@ -81,7 +83,7 @@ namespace OpenSim.Framework.Communications.Osp
81 83
82 protected InventoryItemBase PostProcessItem(InventoryItemBase item) 84 protected InventoryItemBase PostProcessItem(InventoryItemBase item)
83 { 85 {
84 item.CreatorIdAsUuid = OspResolver.ResolveOspa(item.CreatorId, m_commsManager); 86 item.CreatorIdAsUuid = OspResolver.ResolveOspa(item.CreatorId, m_userAccountService);
85 return item; 87 return item;
86 } 88 }
87 89
diff --git a/OpenSim/Framework/Communications/Osp/OspResolver.cs b/OpenSim/Framework/Communications/Osp/OspResolver.cs
index 4013896..24ea64d 100644
--- a/OpenSim/Framework/Communications/Osp/OspResolver.cs
+++ b/OpenSim/Framework/Communications/Osp/OspResolver.cs
@@ -30,7 +30,7 @@ using System.Text;
30using log4net; 30using log4net;
31using OpenMetaverse; 31using OpenMetaverse;
32using OpenSim.Framework; 32using OpenSim.Framework;
33using OpenSim.Framework.Communications.Cache; 33using OpenSim.Services.Interfaces;
34 34
35namespace OpenSim.Framework.Communications.Osp 35namespace OpenSim.Framework.Communications.Osp
36{ 36{
@@ -55,11 +55,11 @@ namespace OpenSim.Framework.Communications.Osp
55 /// <param name="userId"></param> 55 /// <param name="userId"></param>
56 /// <param name="commsManager"></param> 56 /// <param name="commsManager"></param>
57 /// <returns>The OSPA. Null if a user with the given UUID could not be found.</returns> 57 /// <returns>The OSPA. Null if a user with the given UUID could not be found.</returns>
58 public static string MakeOspa(UUID userId, CommunicationsManager commsManager) 58 public static string MakeOspa(UUID userId, IUserAccountService userService)
59 { 59 {
60 CachedUserInfo userInfo = commsManager.UserProfileCacheService.GetUserDetails(userId); 60 UserAccount account = userService.GetUserAccount(UUID.Zero, userId);
61 if (userInfo != null) 61 if (account != null)
62 return MakeOspa(userInfo.UserProfile.FirstName, userInfo.UserProfile.SurName); 62 return MakeOspa(account.FirstName, account.LastName);
63 63
64 return null; 64 return null;
65 } 65 }
@@ -88,7 +88,7 @@ namespace OpenSim.Framework.Communications.Osp
88 /// A suitable UUID for use in Second Life client communication. If the string was not a valid ospa, then UUID.Zero 88 /// A suitable UUID for use in Second Life client communication. If the string was not a valid ospa, then UUID.Zero
89 /// is returned. 89 /// is returned.
90 /// </returns> 90 /// </returns>
91 public static UUID ResolveOspa(string ospa, CommunicationsManager commsManager) 91 public static UUID ResolveOspa(string ospa, IUserAccountService userService)
92 { 92 {
93 if (!ospa.StartsWith(OSPA_PREFIX)) 93 if (!ospa.StartsWith(OSPA_PREFIX))
94 return UUID.Zero; 94 return UUID.Zero;
@@ -112,7 +112,7 @@ namespace OpenSim.Framework.Communications.Osp
112 string value = tuple.Substring(tupleSeparatorIndex + 1).Trim(); 112 string value = tuple.Substring(tupleSeparatorIndex + 1).Trim();
113 113
114 if (OSPA_NAME_KEY == key) 114 if (OSPA_NAME_KEY == key)
115 return ResolveOspaName(value, commsManager); 115 return ResolveOspaName(value, userService);
116 } 116 }
117 117
118 return UUID.Zero; 118 return UUID.Zero;
@@ -137,8 +137,11 @@ namespace OpenSim.Framework.Communications.Osp
137 /// <returns> 137 /// <returns>
138 /// An OpenSim internal identifier for the name given. Returns null if the name was not valid 138 /// An OpenSim internal identifier for the name given. Returns null if the name was not valid
139 /// </returns> 139 /// </returns>
140 protected static UUID ResolveOspaName(string name, CommunicationsManager commsManager) 140 protected static UUID ResolveOspaName(string name, IUserAccountService userService)
141 { 141 {
142 if (userService == null)
143 return UUID.Zero;
144
142 int nameSeparatorIndex = name.IndexOf(OSPA_NAME_VALUE_SEPARATOR); 145 int nameSeparatorIndex = name.IndexOf(OSPA_NAME_VALUE_SEPARATOR);
143 146
144 if (nameSeparatorIndex < 0) 147 if (nameSeparatorIndex < 0)
@@ -149,10 +152,10 @@ namespace OpenSim.Framework.Communications.Osp
149 152
150 string firstName = name.Remove(nameSeparatorIndex).TrimEnd(); 153 string firstName = name.Remove(nameSeparatorIndex).TrimEnd();
151 string lastName = name.Substring(nameSeparatorIndex + 1).TrimStart(); 154 string lastName = name.Substring(nameSeparatorIndex + 1).TrimStart();
152 155
153 CachedUserInfo userInfo = commsManager.UserProfileCacheService.GetUserDetails(firstName, lastName); 156 UserAccount account = userService.GetUserAccount(UUID.Zero, firstName, lastName);
154 if (userInfo != null) 157 if (account != null)
155 return userInfo.UserProfile.ID; 158 return account.PrincipalID;
156 159
157 // XXX: Disable temporary user profile creation for now as implementation is incomplete - justincc 160 // XXX: Disable temporary user profile creation for now as implementation is incomplete - justincc
158 /* 161 /*
diff --git a/OpenSim/Framework/Communications/Services/GridInfoService.cs b/OpenSim/Framework/Communications/Services/GridInfoService.cs
deleted file mode 100644
index cd2a152..0000000
--- a/OpenSim/Framework/Communications/Services/GridInfoService.cs
+++ /dev/null
@@ -1,176 +0,0 @@
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
28using System;
29using System.Collections;
30using System.IO;
31using System.Net;
32using System.Reflection;
33using System.Text;
34using log4net;
35using Nini.Config;
36using Nwc.XmlRpc;
37using OpenSim.Framework.Servers.HttpServer;
38
39namespace OpenSim.Framework.Communications.Services
40{
41 public class GridInfoService
42 {
43 private static readonly ILog _log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
44
45 private Hashtable _info = new Hashtable();
46
47 /// <summary>
48 /// Instantiate a GridInfoService object.
49 /// </summary>
50 /// <param name="configPath">path to config path containing
51 /// grid information</param>
52 /// <remarks>
53 /// GridInfoService uses the [GridInfo] section of the
54 /// standard OpenSim.ini file --- which is not optimal, but
55 /// anything else requires a general redesign of the config
56 /// system.
57 /// </remarks>
58 public GridInfoService(IConfigSource configSource)
59 {
60 loadGridInfo(configSource);
61 }
62
63 /// <summary>
64 /// Default constructor, uses OpenSim.ini.
65 /// </summary>
66 public GridInfoService()
67 {
68 try
69 {
70 IConfigSource configSource = new IniConfigSource(Path.Combine(Util.configDir(), "OpenSim.ini"));
71 loadGridInfo(configSource);
72 }
73 catch (FileNotFoundException)
74 {
75 _log.Warn(
76 "[GRID INFO SERVICE]: No OpenSim.ini file found --- GridInfoServices WILL NOT BE AVAILABLE to your users");
77 }
78 }
79
80 private void loadGridInfo(IConfigSource configSource)
81 {
82 _info["platform"] = "OpenSim";
83 try
84 {
85 IConfig startupCfg = configSource.Configs["Startup"];
86 IConfig gridCfg = configSource.Configs["GridInfo"];
87 IConfig netCfg = configSource.Configs["Network"];
88
89 bool grid = startupCfg.GetBoolean("gridmode", false);
90
91 if (grid)
92 _info["mode"] = "grid";
93 else
94 _info["mode"] = "standalone";
95
96
97 if (null != gridCfg)
98 {
99 foreach (string k in gridCfg.GetKeys())
100 {
101 _info[k] = gridCfg.GetString(k);
102 }
103 }
104 else if (null != netCfg)
105 {
106 if (grid)
107 _info["login"]
108 = netCfg.GetString(
109 "user_server_url", "http://127.0.0.1:" + ConfigSettings.DefaultUserServerHttpPort.ToString());
110 else
111 _info["login"]
112 = String.Format(
113 "http://127.0.0.1:{0}/",
114 netCfg.GetString(
115 "http_listener_port", ConfigSettings.DefaultRegionHttpPort.ToString()));
116
117 IssueWarning();
118 }
119 else
120 {
121 _info["login"] = "http://127.0.0.1:9000/";
122 IssueWarning();
123 }
124 }
125 catch (Exception)
126 {
127 _log.Debug("[GRID INFO SERVICE]: Cannot get grid info from config source, using minimal defaults");
128 }
129
130 _log.DebugFormat("[GRID INFO SERVICE]: Grid info service initialized with {0} keys", _info.Count);
131
132 }
133
134 private void IssueWarning()
135 {
136 _log.Warn("[GRID INFO SERVICE]: found no [GridInfo] section in your OpenSim.ini");
137 _log.Warn("[GRID INFO SERVICE]: trying to guess sensible defaults, you might want to provide better ones:");
138
139 foreach (string k in _info.Keys)
140 {
141 _log.WarnFormat("[GRID INFO SERVICE]: {0}: {1}", k, _info[k]);
142 }
143 }
144
145 public XmlRpcResponse XmlRpcGridInfoMethod(XmlRpcRequest request, IPEndPoint remoteClient)
146 {
147 XmlRpcResponse response = new XmlRpcResponse();
148 Hashtable responseData = new Hashtable();
149
150 _log.Info("[GRID INFO SERVICE]: Request for grid info");
151
152 foreach (string k in _info.Keys)
153 {
154 responseData[k] = _info[k];
155 }
156 response.Value = responseData;
157
158 return response;
159 }
160
161 public string RestGetGridInfoMethod(string request, string path, string param,
162 OSHttpRequest httpRequest, OSHttpResponse httpResponse)
163 {
164 StringBuilder sb = new StringBuilder();
165
166 sb.Append("<gridinfo>\n");
167 foreach (string k in _info.Keys)
168 {
169 sb.AppendFormat("<{0}>{1}</{0}>\n", k, _info[k]);
170 }
171 sb.Append("</gridinfo>\n");
172
173 return sb.ToString();
174 }
175 }
176}
diff --git a/OpenSim/Framework/Communications/Services/HGLoginAuthService.cs b/OpenSim/Framework/Communications/Services/HGLoginAuthService.cs
deleted file mode 100644
index d3f813e..0000000
--- a/OpenSim/Framework/Communications/Services/HGLoginAuthService.cs
+++ /dev/null
@@ -1,339 +0,0 @@
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
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Net;
32using System.Reflection;
33using System.Text.RegularExpressions;
34using OpenSim.Framework;
35using OpenSim.Framework.Communications.Cache;
36using OpenSim.Framework.Capabilities;
37using OpenSim.Framework.Servers;
38
39using OpenMetaverse;
40
41using log4net;
42using Nini.Config;
43using Nwc.XmlRpc;
44
45namespace OpenSim.Framework.Communications.Services
46{
47 public class HGLoginAuthService : LoginService
48 {
49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50
51 protected NetworkServersInfo m_serversInfo;
52 protected bool m_authUsers = false;
53
54 /// <summary>
55 /// Used by the login service to make requests to the inventory service.
56 /// </summary>
57 protected IInterServiceInventoryServices m_interServiceInventoryService;
58
59 /// <summary>
60 /// Used to make requests to the local regions.
61 /// </summary>
62 protected ILoginServiceToRegionsConnector m_regionsConnector;
63
64 public HGLoginAuthService(
65 UserManagerBase userManager, string welcomeMess,
66 IInterServiceInventoryServices interServiceInventoryService,
67 NetworkServersInfo serversInfo,
68 bool authenticate, LibraryRootFolder libraryRootFolder, ILoginServiceToRegionsConnector regionsConnector)
69 : base(userManager, libraryRootFolder, welcomeMess)
70 {
71 this.m_serversInfo = serversInfo;
72 if (m_serversInfo != null)
73 {
74 m_defaultHomeX = this.m_serversInfo.DefaultHomeLocX;
75 m_defaultHomeY = this.m_serversInfo.DefaultHomeLocY;
76 }
77 m_authUsers = authenticate;
78
79 m_interServiceInventoryService = interServiceInventoryService;
80 m_regionsConnector = regionsConnector;
81 m_interInventoryService = interServiceInventoryService;
82 }
83
84 public void SetServersInfo(NetworkServersInfo sinfo)
85 {
86 m_serversInfo = sinfo;
87 }
88
89 public override XmlRpcResponse XmlRpcLoginMethod(XmlRpcRequest request, IPEndPoint remoteClient)
90 {
91 m_log.Info("[HGLOGIN]: HGLogin called " + request.MethodName);
92 XmlRpcResponse response = base.XmlRpcLoginMethod(request, remoteClient);
93 Hashtable responseData = (Hashtable)response.Value;
94
95 responseData["grid_service"] = m_serversInfo.GridURL;
96 responseData["grid_service_send_key"] = m_serversInfo.GridSendKey;
97 responseData["inventory_service"] = m_serversInfo.InventoryURL;
98 responseData["asset_service"] = m_serversInfo.AssetURL;
99 responseData["asset_service_send_key"] = m_serversInfo.AssetSendKey;
100 int x = (Int32)responseData["region_x"];
101 int y = (Int32)responseData["region_y"];
102 uint ux = (uint)(x / Constants.RegionSize);
103 uint uy = (uint)(y / Constants.RegionSize);
104 ulong regionHandle = Util.UIntsToLong(ux, uy);
105 responseData["region_handle"] = regionHandle.ToString();
106
107 // Let's remove the seed cap from the login
108 //responseData.Remove("seed_capability");
109
110 // Let's add the appearance
111 UUID userID = UUID.Zero;
112 UUID.TryParse((string)responseData["agent_id"], out userID);
113 AvatarAppearance appearance = m_userManager.GetUserAppearance(userID);
114 if (appearance == null)
115 {
116 m_log.WarnFormat("[INTER]: Appearance not found for {0}. Creating default.", userID);
117 appearance = new AvatarAppearance();
118 }
119
120 responseData["appearance"] = appearance.ToHashTable();
121
122 // Let's also send the auth token
123 UUID token = UUID.Random();
124 responseData["auth_token"] = token.ToString();
125 UserProfileData userProfile = m_userManager.GetUserProfile(userID);
126 if (userProfile != null)
127 {
128 userProfile.WebLoginKey = token;
129 m_userManager.CommitAgent(ref userProfile);
130 }
131 m_log.Warn("[HGLOGIN]: Auth token: " + token);
132
133
134 return response;
135 }
136
137 public XmlRpcResponse XmlRpcGenerateKeyMethod(XmlRpcRequest request, IPEndPoint remoteClient)
138 {
139 // Verify the key of who's calling
140 UUID userID = UUID.Zero;
141 UUID authKey = UUID.Zero;
142 UUID.TryParse((string)request.Params[0], out userID);
143 UUID.TryParse((string)request.Params[1], out authKey);
144
145 m_log.InfoFormat("[HGLOGIN] HGGenerateKey called with authToken ", authKey);
146 string newKey = string.Empty;
147
148 if (!(m_userManager is IAuthentication))
149 {
150 m_log.Debug("[HGLOGIN]: UserManager is not IAuthentication service. Returning empty key.");
151 }
152 else
153 {
154 newKey = ((IAuthentication)m_userManager).GetNewKey(m_serversInfo.UserURL, userID, authKey);
155 }
156
157 XmlRpcResponse response = new XmlRpcResponse();
158 response.Value = (string) newKey;
159 return response;
160 }
161
162 public XmlRpcResponse XmlRpcVerifyKeyMethod(XmlRpcRequest request, IPEndPoint remoteClient)
163 {
164 bool success = false;
165
166 if (request.Params.Count >= 2)
167 {
168 // Verify the key of who's calling
169 UUID userID = UUID.Zero;
170 string authKey = string.Empty;
171 if (UUID.TryParse((string)request.Params[0], out userID))
172 {
173 authKey = (string)request.Params[1];
174
175 m_log.InfoFormat("[HGLOGIN] HGVerifyKey called with key {0}", authKey);
176
177 if (!(m_userManager is IAuthentication))
178 {
179 m_log.Debug("[HGLOGIN]: UserManager is not IAuthentication service. Denying.");
180 }
181 else
182 {
183 success = ((IAuthentication)m_userManager).VerifyKey(userID, authKey);
184 }
185 }
186 }
187
188 m_log.DebugFormat("[HGLOGIN]: Response to VerifyKey is {0}", success);
189 XmlRpcResponse response = new XmlRpcResponse();
190 response.Value = success;
191 return response;
192 }
193
194 public override UserProfileData GetTheUser(string firstname, string lastname)
195 {
196 UserProfileData profile = m_userManager.GetUserProfile(firstname, lastname);
197 if (profile != null)
198 {
199 return profile;
200 }
201
202 if (!m_authUsers)
203 {
204 //no current user account so make one
205 m_log.Info("[LOGIN]: No user account found so creating a new one.");
206
207 m_userManager.AddUser(firstname, lastname, "test", "", m_defaultHomeX, m_defaultHomeY);
208
209 return m_userManager.GetUserProfile(firstname, lastname);
210 }
211
212 return null;
213 }
214
215 public override bool AuthenticateUser(UserProfileData profile, string password)
216 {
217 if (!m_authUsers)
218 {
219 //for now we will accept any password in sandbox mode
220 m_log.Info("[LOGIN]: Authorising user (no actual password check)");
221
222 return true;
223 }
224 else
225 {
226 m_log.Info(
227 "[LOGIN]: Authenticating " + profile.FirstName + " " + profile.SurName);
228
229 if (!password.StartsWith("$1$"))
230 password = "$1$" + Util.Md5Hash(password);
231
232 password = password.Remove(0, 3); //remove $1$
233
234 string s = Util.Md5Hash(password + ":" + profile.PasswordSalt);
235
236 bool loginresult = (profile.PasswordHash.Equals(s.ToString(), StringComparison.InvariantCultureIgnoreCase)
237 || profile.PasswordHash.Equals(password, StringComparison.InvariantCulture));
238 return loginresult;
239 }
240 }
241
242 protected override RegionInfo RequestClosestRegion(string region)
243 {
244 return m_regionsConnector.RequestClosestRegion(region);
245 }
246
247 protected override RegionInfo GetRegionInfo(ulong homeRegionHandle)
248 {
249 return m_regionsConnector.RequestNeighbourInfo(homeRegionHandle);
250 }
251
252 protected override RegionInfo GetRegionInfo(UUID homeRegionId)
253 {
254 return m_regionsConnector.RequestNeighbourInfo(homeRegionId);
255 }
256
257 /// <summary>
258 /// Not really informing the region. Just filling out the response fields related to the region.
259 /// </summary>
260 /// <param name="sim"></param>
261 /// <param name="user"></param>
262 /// <param name="response"></param>
263 /// <returns>true if the region was successfully contacted, false otherwise</returns>
264 protected override bool PrepareLoginToRegion(RegionInfo regionInfo, UserProfileData user, LoginResponse response, IPEndPoint remoteClient)
265 {
266 IPEndPoint endPoint = regionInfo.ExternalEndPoint;
267 response.SimAddress = endPoint.Address.ToString();
268 response.SimPort = (uint)endPoint.Port;
269 response.RegionX = regionInfo.RegionLocX;
270 response.RegionY = regionInfo.RegionLocY;
271 response.SimHttpPort = regionInfo.HttpPort;
272
273 string capsPath = CapsUtil.GetRandomCapsObjectPath();
274 string capsSeedPath = CapsUtil.GetCapsSeedPath(capsPath);
275
276 // Don't use the following! It Fails for logging into any region not on the same port as the http server!
277 // Kept here so it doesn't happen again!
278 // response.SeedCapability = regionInfo.ServerURI + capsSeedPath;
279
280 string seedcap = "http://";
281
282 if (m_serversInfo.HttpUsesSSL)
283 {
284 // For NAT
285 string host = NetworkUtil.GetHostFor(remoteClient.Address, m_serversInfo.HttpSSLCN);
286
287 seedcap = "https://" + host + ":" + m_serversInfo.httpSSLPort + capsSeedPath;
288 }
289 else
290 {
291 // For NAT
292 string host = NetworkUtil.GetHostFor(remoteClient.Address, regionInfo.ExternalHostName);
293
294 seedcap = "http://" + host + ":" + m_serversInfo.HttpListenerPort + capsSeedPath;
295 }
296
297 response.SeedCapability = seedcap;
298
299 // Notify the target of an incoming user
300 m_log.InfoFormat(
301 "[LOGIN]: Telling {0} @ {1},{2} ({3}) to prepare for client connection",
302 regionInfo.RegionName, response.RegionX, response.RegionY, regionInfo.ServerURI);
303
304 // Update agent with target sim
305 user.CurrentAgent.Region = regionInfo.RegionID;
306 user.CurrentAgent.Handle = regionInfo.RegionHandle;
307
308 return true;
309 }
310
311 public override void LogOffUser(UserProfileData theUser, string message)
312 {
313 RegionInfo SimInfo;
314 try
315 {
316 SimInfo = this.m_regionsConnector.RequestNeighbourInfo(theUser.CurrentAgent.Handle);
317
318 if (SimInfo == null)
319 {
320 m_log.Error("[LOCAL LOGIN]: Region user was in isn't currently logged in");
321 return;
322 }
323 }
324 catch (Exception)
325 {
326 m_log.Error("[LOCAL LOGIN]: Unable to look up region to log user off");
327 return;
328 }
329
330 m_regionsConnector.LogOffUserFromGrid(SimInfo.RegionHandle, theUser.ID, theUser.CurrentAgent.SecureSessionID, "Logging you off");
331 }
332
333 protected override bool AllowLoginWithoutInventory()
334 {
335 return true;
336 }
337
338 }
339}
diff --git a/OpenSim/Framework/Communications/Services/LoginResponse.cs b/OpenSim/Framework/Communications/Services/LoginResponse.cs
deleted file mode 100644
index ec5f428..0000000
--- a/OpenSim/Framework/Communications/Services/LoginResponse.cs
+++ /dev/null
@@ -1,823 +0,0 @@
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
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Reflection;
32using log4net;
33using Nwc.XmlRpc;
34using OpenMetaverse;
35using OpenMetaverse.StructuredData;
36
37namespace OpenSim.Framework.Communications.Services
38{
39 /// <summary>
40 /// A temp class to handle login response.
41 /// Should make use of UserProfileManager where possible.
42 /// </summary>
43 public class LoginResponse
44 {
45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46
47 private Hashtable loginFlagsHash;
48 private Hashtable globalTexturesHash;
49 private Hashtable loginError;
50 private Hashtable uiConfigHash;
51
52 private ArrayList loginFlags;
53 private ArrayList globalTextures;
54 private ArrayList eventCategories;
55 private ArrayList uiConfig;
56 private ArrayList classifiedCategories;
57 private ArrayList inventoryRoot;
58 private ArrayList initialOutfit;
59 private ArrayList agentInventory;
60 private ArrayList inventoryLibraryOwner;
61 private ArrayList inventoryLibRoot;
62 private ArrayList inventoryLibrary;
63 private ArrayList activeGestures;
64
65 private UserInfo userProfile;
66
67 private UUID agentID;
68 private UUID sessionID;
69 private UUID secureSessionID;
70
71 // Login Flags
72 private string dst;
73 private string stipendSinceLogin;
74 private string gendered;
75 private string everLoggedIn;
76 private string login;
77 private uint simPort;
78 private uint simHttpPort;
79 private string simAddress;
80 private string agentAccess;
81 private string agentAccessMax;
82 private Int32 circuitCode;
83 private uint regionX;
84 private uint regionY;
85
86 // Login
87 private string firstname;
88 private string lastname;
89
90 // Global Textures
91 private string sunTexture;
92 private string cloudTexture;
93 private string moonTexture;
94
95 // Error Flags
96 private string errorReason;
97 private string errorMessage;
98
99 // Response
100 private XmlRpcResponse xmlRpcResponse;
101 // private XmlRpcResponse defaultXmlRpcResponse;
102
103 private string welcomeMessage;
104 private string startLocation;
105 private string allowFirstLife;
106 private string home;
107 private string seedCapability;
108 private string lookAt;
109
110 private BuddyList m_buddyList = null;
111
112 public LoginResponse()
113 {
114 loginFlags = new ArrayList();
115 globalTextures = new ArrayList();
116 eventCategories = new ArrayList();
117 uiConfig = new ArrayList();
118 classifiedCategories = new ArrayList();
119
120 loginError = new Hashtable();
121 uiConfigHash = new Hashtable();
122
123 // defaultXmlRpcResponse = new XmlRpcResponse();
124 userProfile = new UserInfo();
125 inventoryRoot = new ArrayList();
126 initialOutfit = new ArrayList();
127 agentInventory = new ArrayList();
128 inventoryLibrary = new ArrayList();
129 inventoryLibraryOwner = new ArrayList();
130 activeGestures = new ArrayList();
131
132 xmlRpcResponse = new XmlRpcResponse();
133 // defaultXmlRpcResponse = new XmlRpcResponse();
134
135 SetDefaultValues();
136 }
137
138 private void SetDefaultValues()
139 {
140 DST = TimeZone.CurrentTimeZone.IsDaylightSavingTime(DateTime.Now) ? "Y" : "N";
141 StipendSinceLogin = "N";
142 Gendered = "Y";
143 EverLoggedIn = "Y";
144 login = "false";
145 firstname = "Test";
146 lastname = "User";
147 agentAccess = "M";
148 agentAccessMax = "A";
149 startLocation = "last";
150 allowFirstLife = "Y";
151
152 SunTexture = "cce0f112-878f-4586-a2e2-a8f104bba271";
153 CloudTexture = "dc4b9f0b-d008-45c6-96a4-01dd947ac621";
154 MoonTexture = "ec4b9f0b-d008-45c6-96a4-01dd947ac621";
155
156 ErrorMessage = "You have entered an invalid name/password combination. Check Caps/lock.";
157 ErrorReason = "key";
158 welcomeMessage = "Welcome to OpenSim!";
159 seedCapability = String.Empty;
160 home = "{'region_handle':[r" + (1000*Constants.RegionSize).ToString() + ",r" + (1000*Constants.RegionSize).ToString() + "], 'position':[r" +
161 userProfile.homepos.X.ToString() + ",r" + userProfile.homepos.Y.ToString() + ",r" +
162 userProfile.homepos.Z.ToString() + "], 'look_at':[r" + userProfile.homelookat.X.ToString() + ",r" +
163 userProfile.homelookat.Y.ToString() + ",r" + userProfile.homelookat.Z.ToString() + "]}";
164 lookAt = "[r0.99949799999999999756,r0.03166859999999999814,r0]";
165 RegionX = (uint) 255232;
166 RegionY = (uint) 254976;
167
168 // Classifieds;
169 AddClassifiedCategory((Int32) 1, "Shopping");
170 AddClassifiedCategory((Int32) 2, "Land Rental");
171 AddClassifiedCategory((Int32) 3, "Property Rental");
172 AddClassifiedCategory((Int32) 4, "Special Attraction");
173 AddClassifiedCategory((Int32) 5, "New Products");
174 AddClassifiedCategory((Int32) 6, "Employment");
175 AddClassifiedCategory((Int32) 7, "Wanted");
176 AddClassifiedCategory((Int32) 8, "Service");
177 AddClassifiedCategory((Int32) 9, "Personal");
178
179 SessionID = UUID.Random();
180 SecureSessionID = UUID.Random();
181 AgentID = UUID.Random();
182
183 Hashtable InitialOutfitHash = new Hashtable();
184 InitialOutfitHash["folder_name"] = "Nightclub Female";
185 InitialOutfitHash["gender"] = "female";
186 initialOutfit.Add(InitialOutfitHash);
187 }
188
189 #region Login Failure Methods
190
191 public XmlRpcResponse GenerateFailureResponse(string reason, string message, string login)
192 {
193 // Overwrite any default values;
194 xmlRpcResponse = new XmlRpcResponse();
195
196 // Ensure Login Failed message/reason;
197 ErrorMessage = message;
198 ErrorReason = reason;
199
200 loginError["reason"] = ErrorReason;
201 loginError["message"] = ErrorMessage;
202 loginError["login"] = login;
203 xmlRpcResponse.Value = loginError;
204 return (xmlRpcResponse);
205 }
206
207 public OSD GenerateFailureResponseLLSD(string reason, string message, string login)
208 {
209 OSDMap map = new OSDMap();
210
211 // Ensure Login Failed message/reason;
212 ErrorMessage = message;
213 ErrorReason = reason;
214
215 map["reason"] = OSD.FromString(ErrorReason);
216 map["message"] = OSD.FromString(ErrorMessage);
217 map["login"] = OSD.FromString(login);
218
219 return map;
220 }
221
222 public XmlRpcResponse CreateFailedResponse()
223 {
224 return (CreateLoginFailedResponse());
225 }
226
227 public OSD CreateFailedResponseLLSD()
228 {
229 return CreateLoginFailedResponseLLSD();
230 }
231
232 public XmlRpcResponse CreateLoginFailedResponse()
233 {
234 return
235 (GenerateFailureResponse("key",
236 "Could not authenticate your avatar. Please check your username and password, and check the grid if problems persist.",
237 "false"));
238 }
239
240 public OSD CreateLoginFailedResponseLLSD()
241 {
242 return GenerateFailureResponseLLSD(
243 "key",
244 "Could not authenticate your avatar. Please check your username and password, and check the grid if problems persist.",
245 "false");
246 }
247
248 /// <summary>
249 /// Response to indicate that login failed because the agent's inventory was not available.
250 /// </summary>
251 /// <returns></returns>
252 public XmlRpcResponse CreateLoginInventoryFailedResponse()
253 {
254 return GenerateFailureResponse(
255 "key",
256 "The avatar inventory service is not responding. Please notify your login region operator.",
257 "false");
258 }
259
260 public XmlRpcResponse CreateAlreadyLoggedInResponse()
261 {
262 return
263 (GenerateFailureResponse("presence",
264 "You appear to be already logged in. " +
265 "If this is not the case please wait for your session to timeout. " +
266 "If this takes longer than a few minutes please contact the grid owner. " +
267 "Please wait 5 minutes if you are going to connect to a region nearby to the region you were at previously.",
268 "false"));
269 }
270
271 public OSD CreateAlreadyLoggedInResponseLLSD()
272 {
273 return GenerateFailureResponseLLSD(
274 "presence",
275 "You appear to be already logged in. " +
276 "If this is not the case please wait for your session to timeout. " +
277 "If this takes longer than a few minutes please contact the grid owner",
278 "false");
279 }
280
281 public XmlRpcResponse CreateLoginBlockedResponse()
282 {
283 return
284 (GenerateFailureResponse("presence",
285 "Logins are currently restricted. Please try again later",
286 "false"));
287 }
288
289 public OSD CreateLoginBlockedResponseLLSD()
290 {
291 return GenerateFailureResponseLLSD(
292 "presence",
293 "Logins are currently restricted. Please try again later",
294 "false");
295 }
296
297 public XmlRpcResponse CreateDeadRegionResponse()
298 {
299 return
300 (GenerateFailureResponse("key",
301 "The region you are attempting to log into is not responding. Please select another region and try again.",
302 "false"));
303 }
304
305 public OSD CreateDeadRegionResponseLLSD()
306 {
307 return GenerateFailureResponseLLSD(
308 "key",
309 "The region you are attempting to log into is not responding. Please select another region and try again.",
310 "false");
311 }
312
313 public XmlRpcResponse CreateGridErrorResponse()
314 {
315 return
316 (GenerateFailureResponse("key",
317 "Error connecting to grid. Could not percieve credentials from login XML.",
318 "false"));
319 }
320
321 public OSD CreateGridErrorResponseLLSD()
322 {
323 return GenerateFailureResponseLLSD(
324 "key",
325 "Error connecting to grid. Could not perceive credentials from login XML.",
326 "false");
327 }
328
329 #endregion
330
331 public virtual XmlRpcResponse ToXmlRpcResponse()
332 {
333 try
334 {
335 Hashtable responseData = new Hashtable();
336
337 loginFlagsHash = new Hashtable();
338 loginFlagsHash["daylight_savings"] = DST;
339 loginFlagsHash["stipend_since_login"] = StipendSinceLogin;
340 loginFlagsHash["gendered"] = Gendered;
341 loginFlagsHash["ever_logged_in"] = EverLoggedIn;
342 loginFlags.Add(loginFlagsHash);
343
344 responseData["first_name"] = Firstname;
345 responseData["last_name"] = Lastname;
346 responseData["agent_access"] = agentAccess;
347 responseData["agent_access_max"] = agentAccessMax;
348
349 globalTexturesHash = new Hashtable();
350 globalTexturesHash["sun_texture_id"] = SunTexture;
351 globalTexturesHash["cloud_texture_id"] = CloudTexture;
352 globalTexturesHash["moon_texture_id"] = MoonTexture;
353 globalTextures.Add(globalTexturesHash);
354 // this.eventCategories.Add(this.eventCategoriesHash);
355
356 AddToUIConfig("allow_first_life", allowFirstLife);
357 uiConfig.Add(uiConfigHash);
358
359 responseData["sim_port"] = (Int32) SimPort;
360 responseData["sim_ip"] = SimAddress;
361 responseData["http_port"] = (Int32)SimHttpPort;
362
363 responseData["agent_id"] = AgentID.ToString();
364 responseData["session_id"] = SessionID.ToString();
365 responseData["secure_session_id"] = SecureSessionID.ToString();
366 responseData["circuit_code"] = CircuitCode;
367 responseData["seconds_since_epoch"] = (Int32) (DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds;
368 responseData["login-flags"] = loginFlags;
369 responseData["global-textures"] = globalTextures;
370 responseData["seed_capability"] = seedCapability;
371
372 responseData["event_categories"] = eventCategories;
373 responseData["event_notifications"] = new ArrayList(); // todo
374 responseData["classified_categories"] = classifiedCategories;
375 responseData["ui-config"] = uiConfig;
376
377 if (agentInventory != null)
378 {
379 responseData["inventory-skeleton"] = agentInventory;
380 responseData["inventory-root"] = inventoryRoot;
381 }
382 responseData["inventory-skel-lib"] = inventoryLibrary;
383 responseData["inventory-lib-root"] = inventoryLibRoot;
384 responseData["gestures"] = activeGestures;
385 responseData["inventory-lib-owner"] = inventoryLibraryOwner;
386 responseData["initial-outfit"] = initialOutfit;
387 responseData["start_location"] = startLocation;
388 responseData["seed_capability"] = seedCapability;
389 responseData["home"] = home;
390 responseData["look_at"] = lookAt;
391 responseData["message"] = welcomeMessage;
392 responseData["region_x"] = (Int32)(RegionX * Constants.RegionSize);
393 responseData["region_y"] = (Int32)(RegionY * Constants.RegionSize);
394
395 if (m_buddyList != null)
396 {
397 responseData["buddy-list"] = m_buddyList.ToArray();
398 }
399
400 responseData["login"] = "true";
401 xmlRpcResponse.Value = responseData;
402
403 return (xmlRpcResponse);
404 }
405 catch (Exception e)
406 {
407 m_log.Warn("[CLIENT]: LoginResponse: Error creating XML-RPC Response: " + e.Message);
408
409 return (GenerateFailureResponse("Internal Error", "Error generating Login Response", "false"));
410 }
411 }
412
413 public OSD ToLLSDResponse()
414 {
415 try
416 {
417 OSDMap map = new OSDMap();
418
419 map["first_name"] = OSD.FromString(Firstname);
420 map["last_name"] = OSD.FromString(Lastname);
421 map["agent_access"] = OSD.FromString(agentAccess);
422 map["agent_access_max"] = OSD.FromString(agentAccessMax);
423
424 map["sim_port"] = OSD.FromInteger(SimPort);
425 map["sim_ip"] = OSD.FromString(SimAddress);
426
427 map["agent_id"] = OSD.FromUUID(AgentID);
428 map["session_id"] = OSD.FromUUID(SessionID);
429 map["secure_session_id"] = OSD.FromUUID(SecureSessionID);
430 map["circuit_code"] = OSD.FromInteger(CircuitCode);
431 map["seconds_since_epoch"] = OSD.FromInteger((int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds);
432
433 #region Login Flags
434
435 OSDMap loginFlagsLLSD = new OSDMap();
436 loginFlagsLLSD["daylight_savings"] = OSD.FromString(DST);
437 loginFlagsLLSD["stipend_since_login"] = OSD.FromString(StipendSinceLogin);
438 loginFlagsLLSD["gendered"] = OSD.FromString(Gendered);
439 loginFlagsLLSD["ever_logged_in"] = OSD.FromString(EverLoggedIn);
440 map["login-flags"] = WrapOSDMap(loginFlagsLLSD);
441
442 #endregion Login Flags
443
444 #region Global Textures
445
446 OSDMap globalTexturesLLSD = new OSDMap();
447 globalTexturesLLSD["sun_texture_id"] = OSD.FromString(SunTexture);
448 globalTexturesLLSD["cloud_texture_id"] = OSD.FromString(CloudTexture);
449 globalTexturesLLSD["moon_texture_id"] = OSD.FromString(MoonTexture);
450
451 map["global-textures"] = WrapOSDMap(globalTexturesLLSD);
452
453 #endregion Global Textures
454
455 map["seed_capability"] = OSD.FromString(seedCapability);
456
457 map["event_categories"] = ArrayListToOSDArray(eventCategories);
458 //map["event_notifications"] = new OSDArray(); // todo
459 map["classified_categories"] = ArrayListToOSDArray(classifiedCategories);
460
461 #region UI Config
462
463 OSDMap uiConfigLLSD = new OSDMap();
464 uiConfigLLSD["allow_first_life"] = OSD.FromString(allowFirstLife);
465 map["ui-config"] = WrapOSDMap(uiConfigLLSD);
466
467 #endregion UI Config
468
469 #region Inventory
470
471 map["inventory-skeleton"] = ArrayListToOSDArray(agentInventory);
472
473 map["inventory-skel-lib"] = ArrayListToOSDArray(inventoryLibrary);
474 map["inventory-root"] = ArrayListToOSDArray(inventoryRoot); ;
475 map["inventory-lib-root"] = ArrayListToOSDArray(inventoryLibRoot);
476 map["inventory-lib-owner"] = ArrayListToOSDArray(inventoryLibraryOwner);
477
478 #endregion Inventory
479
480 map["gestures"] = ArrayListToOSDArray(activeGestures);
481
482 map["initial-outfit"] = ArrayListToOSDArray(initialOutfit);
483 map["start_location"] = OSD.FromString(startLocation);
484
485 map["seed_capability"] = OSD.FromString(seedCapability);
486 map["home"] = OSD.FromString(home);
487 map["look_at"] = OSD.FromString(lookAt);
488 map["message"] = OSD.FromString(welcomeMessage);
489 map["region_x"] = OSD.FromInteger(RegionX * Constants.RegionSize);
490 map["region_y"] = OSD.FromInteger(RegionY * Constants.RegionSize);
491
492 if (m_buddyList != null)
493 {
494 map["buddy-list"] = ArrayListToOSDArray(m_buddyList.ToArray());
495 }
496
497 map["login"] = OSD.FromString("true");
498
499 return map;
500 }
501 catch (Exception e)
502 {
503 m_log.Warn("[CLIENT]: LoginResponse: Error creating LLSD Response: " + e.Message);
504
505 return GenerateFailureResponseLLSD("Internal Error", "Error generating Login Response", "false");
506 }
507 }
508
509 public OSDArray ArrayListToOSDArray(ArrayList arrlst)
510 {
511 OSDArray llsdBack = new OSDArray();
512 foreach (Hashtable ht in arrlst)
513 {
514 OSDMap mp = new OSDMap();
515 foreach (DictionaryEntry deHt in ht)
516 {
517 mp.Add((string)deHt.Key, OSDString.FromObject(deHt.Value));
518 }
519 llsdBack.Add(mp);
520 }
521 return llsdBack;
522 }
523
524 private static OSDArray WrapOSDMap(OSDMap wrapMe)
525 {
526 OSDArray array = new OSDArray();
527 array.Add(wrapMe);
528 return array;
529 }
530
531 public void SetEventCategories(string category, string value)
532 {
533 // this.eventCategoriesHash[category] = value;
534 //TODO
535 }
536
537 public void AddToUIConfig(string itemName, string item)
538 {
539 uiConfigHash[itemName] = item;
540 }
541
542 public void AddClassifiedCategory(Int32 ID, string categoryName)
543 {
544 Hashtable hash = new Hashtable();
545 hash["category_name"] = categoryName;
546 hash["category_id"] = ID;
547 classifiedCategories.Add(hash);
548 // this.classifiedCategoriesHash.Clear();
549 }
550
551 #region Properties
552
553 public string Login
554 {
555 get { return login; }
556 set { login = value; }
557 }
558
559 public string DST
560 {
561 get { return dst; }
562 set { dst = value; }
563 }
564
565 public string StipendSinceLogin
566 {
567 get { return stipendSinceLogin; }
568 set { stipendSinceLogin = value; }
569 }
570
571 public string Gendered
572 {
573 get { return gendered; }
574 set { gendered = value; }
575 }
576
577 public string EverLoggedIn
578 {
579 get { return everLoggedIn; }
580 set { everLoggedIn = value; }
581 }
582
583 public uint SimPort
584 {
585 get { return simPort; }
586 set { simPort = value; }
587 }
588
589 public uint SimHttpPort
590 {
591 get { return simHttpPort; }
592 set { simHttpPort = value; }
593 }
594
595 public string SimAddress
596 {
597 get { return simAddress; }
598 set { simAddress = value; }
599 }
600
601 public UUID AgentID
602 {
603 get { return agentID; }
604 set { agentID = value; }
605 }
606
607 public UUID SessionID
608 {
609 get { return sessionID; }
610 set { sessionID = value; }
611 }
612
613 public UUID SecureSessionID
614 {
615 get { return secureSessionID; }
616 set { secureSessionID = value; }
617 }
618
619 public Int32 CircuitCode
620 {
621 get { return circuitCode; }
622 set { circuitCode = value; }
623 }
624
625 public uint RegionX
626 {
627 get { return regionX; }
628 set { regionX = value; }
629 }
630
631 public uint RegionY
632 {
633 get { return regionY; }
634 set { regionY = value; }
635 }
636
637 public string SunTexture
638 {
639 get { return sunTexture; }
640 set { sunTexture = value; }
641 }
642
643 public string CloudTexture
644 {
645 get { return cloudTexture; }
646 set { cloudTexture = value; }
647 }
648
649 public string MoonTexture
650 {
651 get { return moonTexture; }
652 set { moonTexture = value; }
653 }
654
655 public string Firstname
656 {
657 get { return firstname; }
658 set { firstname = value; }
659 }
660
661 public string Lastname
662 {
663 get { return lastname; }
664 set { lastname = value; }
665 }
666
667 public string AgentAccess
668 {
669 get { return agentAccess; }
670 set { agentAccess = value; }
671 }
672
673 public string AgentAccessMax
674 {
675 get { return agentAccessMax; }
676 set { agentAccessMax = value; }
677 }
678
679 public string StartLocation
680 {
681 get { return startLocation; }
682 set { startLocation = value; }
683 }
684
685 public string LookAt
686 {
687 get { return lookAt; }
688 set { lookAt = value; }
689 }
690
691 public string SeedCapability
692 {
693 get { return seedCapability; }
694 set { seedCapability = value; }
695 }
696
697 public string ErrorReason
698 {
699 get { return errorReason; }
700 set { errorReason = value; }
701 }
702
703 public string ErrorMessage
704 {
705 get { return errorMessage; }
706 set { errorMessage = value; }
707 }
708
709 public ArrayList InventoryRoot
710 {
711 get { return inventoryRoot; }
712 set { inventoryRoot = value; }
713 }
714
715 public ArrayList InventorySkeleton
716 {
717 get { return agentInventory; }
718 set { agentInventory = value; }
719 }
720
721 public ArrayList InventoryLibrary
722 {
723 get { return inventoryLibrary; }
724 set { inventoryLibrary = value; }
725 }
726
727 public ArrayList InventoryLibraryOwner
728 {
729 get { return inventoryLibraryOwner; }
730 set { inventoryLibraryOwner = value; }
731 }
732
733 public ArrayList InventoryLibRoot
734 {
735 get { return inventoryLibRoot; }
736 set { inventoryLibRoot = value; }
737 }
738
739 public ArrayList ActiveGestures
740 {
741 get { return activeGestures; }
742 set { activeGestures = value; }
743 }
744
745 public string Home
746 {
747 get { return home; }
748 set { home = value; }
749 }
750
751 public string Message
752 {
753 get { return welcomeMessage; }
754 set { welcomeMessage = value; }
755 }
756
757 public BuddyList BuddList
758 {
759 get { return m_buddyList; }
760 set { m_buddyList = value; }
761 }
762
763 #endregion
764
765 public class UserInfo
766 {
767 public string firstname;
768 public string lastname;
769 public ulong homeregionhandle;
770 public Vector3 homepos;
771 public Vector3 homelookat;
772 }
773
774 public class BuddyList
775 {
776 public List<BuddyInfo> Buddies = new List<BuddyInfo>();
777
778 public void AddNewBuddy(BuddyInfo buddy)
779 {
780 if (!Buddies.Contains(buddy))
781 {
782 Buddies.Add(buddy);
783 }
784 }
785
786 public ArrayList ToArray()
787 {
788 ArrayList buddyArray = new ArrayList();
789 foreach (BuddyInfo buddy in Buddies)
790 {
791 buddyArray.Add(buddy.ToHashTable());
792 }
793 return buddyArray;
794 }
795
796 public class BuddyInfo
797 {
798 public int BuddyRightsHave = 1;
799 public int BuddyRightsGiven = 1;
800 public UUID BuddyID;
801
802 public BuddyInfo(string buddyID)
803 {
804 BuddyID = new UUID(buddyID);
805 }
806
807 public BuddyInfo(UUID buddyID)
808 {
809 BuddyID = buddyID;
810 }
811
812 public Hashtable ToHashTable()
813 {
814 Hashtable hTable = new Hashtable();
815 hTable["buddy_rights_has"] = BuddyRightsHave;
816 hTable["buddy_rights_given"] = BuddyRightsGiven;
817 hTable["buddy_id"] = BuddyID.ToString();
818 return hTable;
819 }
820 }
821 }
822 }
823}
diff --git a/OpenSim/Framework/Communications/Services/LoginService.cs b/OpenSim/Framework/Communications/Services/LoginService.cs
deleted file mode 100644
index 824cc57..0000000
--- a/OpenSim/Framework/Communications/Services/LoginService.cs
+++ /dev/null
@@ -1,1241 +0,0 @@
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
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.IO;
32using System.Net;
33using System.Reflection;
34using System.Text.RegularExpressions;
35using System.Threading;
36using System.Web;
37using log4net;
38using Nwc.XmlRpc;
39using OpenMetaverse;
40using OpenMetaverse.StructuredData;
41using OpenSim.Framework;
42using OpenSim.Framework.Communications.Cache;
43using OpenSim.Framework.Statistics;
44using OpenSim.Services.Interfaces;
45
46namespace OpenSim.Framework.Communications.Services
47{
48 public abstract class LoginService
49 {
50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51
52 protected string m_welcomeMessage = "Welcome to OpenSim";
53 protected int m_minLoginLevel = 0;
54 protected UserManagerBase m_userManager = null;
55 protected Mutex m_loginMutex = new Mutex(false);
56
57 /// <summary>
58 /// Used during login to send the skeleton of the OpenSim Library to the client.
59 /// </summary>
60 protected LibraryRootFolder m_libraryRootFolder;
61
62 protected uint m_defaultHomeX;
63 protected uint m_defaultHomeY;
64
65 protected bool m_warn_already_logged = true;
66
67 /// <summary>
68 /// Used by the login service to make requests to the inventory service.
69 /// </summary>
70 protected IInterServiceInventoryServices m_interInventoryService;
71 // Hack
72 protected IInventoryService m_InventoryService;
73
74 /// <summary>
75 /// Constructor
76 /// </summary>
77 /// <param name="userManager"></param>
78 /// <param name="libraryRootFolder"></param>
79 /// <param name="welcomeMess"></param>
80 public LoginService(UserManagerBase userManager, LibraryRootFolder libraryRootFolder,
81 string welcomeMess)
82 {
83 m_userManager = userManager;
84 m_libraryRootFolder = libraryRootFolder;
85
86 if (welcomeMess != String.Empty)
87 {
88 m_welcomeMessage = welcomeMess;
89 }
90 }
91
92 /// <summary>
93 /// Called when we receive the client's initial XMLRPC login_to_simulator request message
94 /// </summary>
95 /// <param name="request">The XMLRPC request</param>
96 /// <returns>The response to send</returns>
97 public virtual XmlRpcResponse XmlRpcLoginMethod(XmlRpcRequest request, IPEndPoint remoteClient)
98 {
99 // Temporary fix
100 m_loginMutex.WaitOne();
101
102 try
103 {
104 //CFK: CustomizeResponse contains sufficient strings to alleviate the need for this.
105 //CKF: m_log.Info("[LOGIN]: Attempting login now...");
106 XmlRpcResponse response = new XmlRpcResponse();
107 Hashtable requestData = (Hashtable)request.Params[0];
108
109 SniffLoginKey((Uri)request.Params[2], requestData);
110
111 bool GoodXML = (requestData.Contains("first") && requestData.Contains("last") &&
112 (requestData.Contains("passwd") || requestData.Contains("web_login_key")));
113
114 string startLocationRequest = "last";
115
116 UserProfileData userProfile;
117 LoginResponse logResponse = new LoginResponse();
118
119 string firstname;
120 string lastname;
121
122 if (GoodXML)
123 {
124 if (requestData.Contains("start"))
125 {
126 startLocationRequest = (string)requestData["start"];
127 }
128
129 firstname = (string)requestData["first"];
130 lastname = (string)requestData["last"];
131
132 m_log.InfoFormat(
133 "[LOGIN BEGIN]: XMLRPC Received login request message from user '{0}' '{1}'",
134 firstname, lastname);
135
136 string clientVersion = "Unknown";
137
138 if (requestData.Contains("version"))
139 {
140 clientVersion = (string)requestData["version"];
141 }
142
143 m_log.DebugFormat(
144 "[LOGIN]: XMLRPC Client is {0}, start location is {1}", clientVersion, startLocationRequest);
145
146 if (!TryAuthenticateXmlRpcLogin(request, firstname, lastname, out userProfile))
147 {
148 return logResponse.CreateLoginFailedResponse();
149 }
150 }
151 else
152 {
153 m_log.Info(
154 "[LOGIN END]: XMLRPC login_to_simulator login message did not contain all the required data");
155
156 return logResponse.CreateGridErrorResponse();
157 }
158
159 if (userProfile.GodLevel < m_minLoginLevel)
160 {
161 return logResponse.CreateLoginBlockedResponse();
162 }
163 else
164 {
165 // If we already have a session...
166 if (userProfile.CurrentAgent != null && userProfile.CurrentAgent.AgentOnline)
167 {
168 //TODO: The following statements can cause trouble:
169 // If agentOnline could not turn from true back to false normally
170 // because of some problem, for instance, the crashment of server or client,
171 // the user cannot log in any longer.
172 userProfile.CurrentAgent.AgentOnline = false;
173
174 m_userManager.CommitAgent(ref userProfile);
175
176 // try to tell the region that their user is dead.
177 LogOffUser(userProfile, " XMLRPC You were logged off because you logged in from another location");
178
179 if (m_warn_already_logged)
180 {
181 // This is behavior for for grid, reject login
182 m_log.InfoFormat(
183 "[LOGIN END]: XMLRPC Notifying user {0} {1} that they are already logged in",
184 firstname, lastname);
185
186 return logResponse.CreateAlreadyLoggedInResponse();
187 }
188 else
189 {
190 // This is behavior for standalone (silent logout of last hung session)
191 m_log.InfoFormat(
192 "[LOGIN]: XMLRPC User {0} {1} is already logged in, not notifying user, kicking old presence and starting new login.",
193 firstname, lastname);
194 }
195 }
196
197 // Otherwise...
198 // Create a new agent session
199
200 // XXYY we don't need this
201 //m_userManager.ResetAttachments(userProfile.ID);
202
203 CreateAgent(userProfile, request);
204
205 // We need to commit the agent right here, even though the userProfile info is not complete
206 // at this point. There is another commit further down.
207 // This is for the new sessionID to be stored so that the region can check it for session authentication.
208 // CustomiseResponse->PrepareLoginToRegion
209 CommitAgent(ref userProfile);
210
211 try
212 {
213 UUID agentID = userProfile.ID;
214 InventoryData inventData = null;
215
216 try
217 {
218 inventData = GetInventorySkeleton(agentID);
219 }
220 catch (Exception e)
221 {
222 m_log.ErrorFormat(
223 "[LOGIN END]: Error retrieving inventory skeleton of agent {0} - {1}",
224 agentID, e);
225
226 // Let's not panic
227 if (!AllowLoginWithoutInventory())
228 return logResponse.CreateLoginInventoryFailedResponse();
229 }
230
231 if (inventData != null)
232 {
233 ArrayList AgentInventoryArray = inventData.InventoryArray;
234
235 Hashtable InventoryRootHash = new Hashtable();
236 InventoryRootHash["folder_id"] = inventData.RootFolderID.ToString();
237 ArrayList InventoryRoot = new ArrayList();
238 InventoryRoot.Add(InventoryRootHash);
239
240 logResponse.InventoryRoot = InventoryRoot;
241 logResponse.InventorySkeleton = AgentInventoryArray;
242 }
243
244 // Inventory Library Section
245 Hashtable InventoryLibRootHash = new Hashtable();
246 InventoryLibRootHash["folder_id"] = "00000112-000f-0000-0000-000100bba000";
247 ArrayList InventoryLibRoot = new ArrayList();
248 InventoryLibRoot.Add(InventoryLibRootHash);
249
250 logResponse.InventoryLibRoot = InventoryLibRoot;
251 logResponse.InventoryLibraryOwner = GetLibraryOwner();
252 logResponse.InventoryLibrary = GetInventoryLibrary();
253
254 logResponse.CircuitCode = Util.RandomClass.Next();
255 logResponse.Lastname = userProfile.SurName;
256 logResponse.Firstname = userProfile.FirstName;
257 logResponse.AgentID = agentID;
258 logResponse.SessionID = userProfile.CurrentAgent.SessionID;
259 logResponse.SecureSessionID = userProfile.CurrentAgent.SecureSessionID;
260 logResponse.Message = GetMessage();
261 logResponse.BuddList = ConvertFriendListItem(m_userManager.GetUserFriendList(agentID));
262 logResponse.StartLocation = startLocationRequest;
263
264 if (CustomiseResponse(logResponse, userProfile, startLocationRequest, remoteClient))
265 {
266 userProfile.LastLogin = userProfile.CurrentAgent.LoginTime;
267 CommitAgent(ref userProfile);
268
269 // If we reach this point, then the login has successfully logged onto the grid
270 if (StatsManager.UserStats != null)
271 StatsManager.UserStats.AddSuccessfulLogin();
272
273 m_log.DebugFormat(
274 "[LOGIN END]: XMLRPC Authentication of user {0} {1} successful. Sending response to client.",
275 firstname, lastname);
276
277 return logResponse.ToXmlRpcResponse();
278 }
279 else
280 {
281 m_log.ErrorFormat("[LOGIN END]: XMLRPC informing user {0} {1} that login failed due to an unavailable region", firstname, lastname);
282 return logResponse.CreateDeadRegionResponse();
283 }
284 }
285 catch (Exception e)
286 {
287 m_log.Error("[LOGIN END]: XMLRPC Login failed, " + e);
288 m_log.Error(e.StackTrace);
289 }
290 }
291
292 m_log.Info("[LOGIN END]: XMLRPC Login failed. Sending back blank XMLRPC response");
293 return response;
294 }
295 finally
296 {
297 m_loginMutex.ReleaseMutex();
298 }
299 }
300
301 protected virtual bool TryAuthenticateXmlRpcLogin(
302 XmlRpcRequest request, string firstname, string lastname, out UserProfileData userProfile)
303 {
304 Hashtable requestData = (Hashtable)request.Params[0];
305
306 userProfile = GetTheUser(firstname, lastname);
307 if (userProfile == null)
308 {
309 m_log.Debug("[LOGIN END]: XMLRPC Could not find a profile for " + firstname + " " + lastname);
310 return false;
311 }
312 else
313 {
314 if (requestData.Contains("passwd"))
315 {
316 string passwd = (string)requestData["passwd"];
317 bool authenticated = AuthenticateUser(userProfile, passwd);
318
319 if (!authenticated)
320 m_log.DebugFormat("[LOGIN END]: XMLRPC User {0} {1} failed password authentication",
321 firstname, lastname);
322
323 return authenticated;
324 }
325
326 if (requestData.Contains("web_login_key"))
327 {
328 try
329 {
330 UUID webloginkey = new UUID((string)requestData["web_login_key"]);
331 bool authenticated = AuthenticateUser(userProfile, webloginkey);
332
333 if (!authenticated)
334 m_log.DebugFormat("[LOGIN END]: XMLRPC User {0} {1} failed web login key authentication",
335 firstname, lastname);
336
337 return authenticated;
338 }
339 catch (Exception e)
340 {
341 m_log.DebugFormat(
342 "[LOGIN END]: XMLRPC Bad web_login_key: {0} for user {1} {2}, exception {3}",
343 requestData["web_login_key"], firstname, lastname, e);
344
345 return false;
346 }
347 }
348
349 m_log.DebugFormat(
350 "[LOGIN END]: XMLRPC login request for {0} {1} contained neither a password nor a web login key",
351 firstname, lastname);
352 }
353
354 return false;
355 }
356
357 protected virtual bool TryAuthenticateLLSDLogin(string firstname, string lastname, string passwd, out UserProfileData userProfile)
358 {
359 bool GoodLogin = false;
360 userProfile = GetTheUser(firstname, lastname);
361 if (userProfile == null)
362 {
363 m_log.Info("[LOGIN]: LLSD Could not find a profile for " + firstname + " " + lastname);
364
365 return false;
366 }
367
368 GoodLogin = AuthenticateUser(userProfile, passwd);
369 return GoodLogin;
370 }
371
372 /// <summary>
373 /// Called when we receive the client's initial LLSD login_to_simulator request message
374 /// </summary>
375 /// <param name="request">The LLSD request</param>
376 /// <returns>The response to send</returns>
377 public OSD LLSDLoginMethod(OSD request, IPEndPoint remoteClient)
378 {
379 // Temporary fix
380 m_loginMutex.WaitOne();
381
382 try
383 {
384 // bool GoodLogin = false;
385
386 string startLocationRequest = "last";
387
388 UserProfileData userProfile = null;
389 LoginResponse logResponse = new LoginResponse();
390
391 if (request.Type == OSDType.Map)
392 {
393 OSDMap map = (OSDMap)request;
394
395 if (map.ContainsKey("first") && map.ContainsKey("last") && map.ContainsKey("passwd"))
396 {
397 string firstname = map["first"].AsString();
398 string lastname = map["last"].AsString();
399 string passwd = map["passwd"].AsString();
400
401 if (map.ContainsKey("start"))
402 {
403 m_log.Info("[LOGIN]: LLSD StartLocation Requested: " + map["start"].AsString());
404 startLocationRequest = map["start"].AsString();
405 }
406 m_log.Info("[LOGIN]: LLSD Login Requested for: '" + firstname + "' '" + lastname + "' / " + passwd);
407
408 if (!TryAuthenticateLLSDLogin(firstname, lastname, passwd, out userProfile))
409 {
410 return logResponse.CreateLoginFailedResponseLLSD();
411 }
412 }
413 else
414 return logResponse.CreateLoginFailedResponseLLSD();
415 }
416 else
417 return logResponse.CreateLoginFailedResponseLLSD();
418
419
420 if (userProfile.GodLevel < m_minLoginLevel)
421 {
422 return logResponse.CreateLoginBlockedResponseLLSD();
423 }
424 else
425 {
426 // If we already have a session...
427 if (userProfile.CurrentAgent != null && userProfile.CurrentAgent.AgentOnline)
428 {
429 userProfile.CurrentAgent.AgentOnline = false;
430
431 m_userManager.CommitAgent(ref userProfile);
432 // try to tell the region that their user is dead.
433 LogOffUser(userProfile, " LLSD You were logged off because you logged in from another location");
434
435 if (m_warn_already_logged)
436 {
437 // This is behavior for for grid, reject login
438 m_log.InfoFormat(
439 "[LOGIN END]: LLSD Notifying user {0} {1} that they are already logged in",
440 userProfile.FirstName, userProfile.SurName);
441
442 userProfile.CurrentAgent = null;
443 return logResponse.CreateAlreadyLoggedInResponseLLSD();
444 }
445 else
446 {
447 // This is behavior for standalone (silent logout of last hung session)
448 m_log.InfoFormat(
449 "[LOGIN]: LLSD User {0} {1} is already logged in, not notifying user, kicking old presence and starting new login.",
450 userProfile.FirstName, userProfile.SurName);
451 }
452 }
453
454 // Otherwise...
455 // Create a new agent session
456
457 // XXYY We don't need this
458 //m_userManager.ResetAttachments(userProfile.ID);
459
460 CreateAgent(userProfile, request);
461
462 // We need to commit the agent right here, even though the userProfile info is not complete
463 // at this point. There is another commit further down.
464 // This is for the new sessionID to be stored so that the region can check it for session authentication.
465 // CustomiseResponse->PrepareLoginToRegion
466 CommitAgent(ref userProfile);
467
468 try
469 {
470 UUID agentID = userProfile.ID;
471
472 //InventoryData inventData = GetInventorySkeleton(agentID);
473 InventoryData inventData = null;
474
475 try
476 {
477 inventData = GetInventorySkeleton(agentID);
478 }
479 catch (Exception e)
480 {
481 m_log.ErrorFormat(
482 "[LOGIN END]: LLSD Error retrieving inventory skeleton of agent {0}, {1} - {2}",
483 agentID, e.GetType(), e.Message);
484
485 return logResponse.CreateLoginFailedResponseLLSD();// .CreateLoginInventoryFailedResponseLLSD ();
486 }
487
488
489 ArrayList AgentInventoryArray = inventData.InventoryArray;
490
491 Hashtable InventoryRootHash = new Hashtable();
492 InventoryRootHash["folder_id"] = inventData.RootFolderID.ToString();
493 ArrayList InventoryRoot = new ArrayList();
494 InventoryRoot.Add(InventoryRootHash);
495
496
497 // Inventory Library Section
498 Hashtable InventoryLibRootHash = new Hashtable();
499 InventoryLibRootHash["folder_id"] = "00000112-000f-0000-0000-000100bba000";
500 ArrayList InventoryLibRoot = new ArrayList();
501 InventoryLibRoot.Add(InventoryLibRootHash);
502
503 logResponse.InventoryLibRoot = InventoryLibRoot;
504 logResponse.InventoryLibraryOwner = GetLibraryOwner();
505 logResponse.InventoryRoot = InventoryRoot;
506 logResponse.InventorySkeleton = AgentInventoryArray;
507 logResponse.InventoryLibrary = GetInventoryLibrary();
508
509 logResponse.CircuitCode = (Int32)Util.RandomClass.Next();
510 logResponse.Lastname = userProfile.SurName;
511 logResponse.Firstname = userProfile.FirstName;
512 logResponse.AgentID = agentID;
513 logResponse.SessionID = userProfile.CurrentAgent.SessionID;
514 logResponse.SecureSessionID = userProfile.CurrentAgent.SecureSessionID;
515 logResponse.Message = GetMessage();
516 logResponse.BuddList = ConvertFriendListItem(m_userManager.GetUserFriendList(agentID));
517 logResponse.StartLocation = startLocationRequest;
518
519 try
520 {
521 CustomiseResponse(logResponse, userProfile, startLocationRequest, remoteClient);
522 }
523 catch (Exception ex)
524 {
525 m_log.Info("[LOGIN]: LLSD " + ex.ToString());
526 return logResponse.CreateDeadRegionResponseLLSD();
527 }
528
529 userProfile.LastLogin = userProfile.CurrentAgent.LoginTime;
530 CommitAgent(ref userProfile);
531
532 // If we reach this point, then the login has successfully logged onto the grid
533 if (StatsManager.UserStats != null)
534 StatsManager.UserStats.AddSuccessfulLogin();
535
536 m_log.DebugFormat(
537 "[LOGIN END]: LLSD Authentication of user {0} {1} successful. Sending response to client.",
538 userProfile.FirstName, userProfile.SurName);
539
540 return logResponse.ToLLSDResponse();
541 }
542 catch (Exception ex)
543 {
544 m_log.Info("[LOGIN]: LLSD " + ex.ToString());
545 return logResponse.CreateFailedResponseLLSD();
546 }
547 }
548 }
549 finally
550 {
551 m_loginMutex.ReleaseMutex();
552 }
553 }
554
555 public Hashtable ProcessHTMLLogin(Hashtable keysvals)
556 {
557 // Matches all unspecified characters
558 // Currently specified,; lowercase letters, upper case letters, numbers, underline
559 // period, space, parens, and dash.
560
561 Regex wfcut = new Regex("[^a-zA-Z0-9_\\.\\$ \\(\\)\\-]");
562
563 Hashtable returnactions = new Hashtable();
564 int statuscode = 200;
565
566 string firstname = String.Empty;
567 string lastname = String.Empty;
568 string location = String.Empty;
569 string region = String.Empty;
570 string grid = String.Empty;
571 string channel = String.Empty;
572 string version = String.Empty;
573 string lang = String.Empty;
574 string password = String.Empty;
575 string errormessages = String.Empty;
576
577 // the client requires the HTML form field be named 'username'
578 // however, the data it sends when it loads the first time is 'firstname'
579 // another one of those little nuances.
580
581 if (keysvals.Contains("firstname"))
582 firstname = wfcut.Replace((string)keysvals["firstname"], String.Empty, 99999);
583
584 if (keysvals.Contains("username"))
585 firstname = wfcut.Replace((string)keysvals["username"], String.Empty, 99999);
586
587 if (keysvals.Contains("lastname"))
588 lastname = wfcut.Replace((string)keysvals["lastname"], String.Empty, 99999);
589
590 if (keysvals.Contains("location"))
591 location = wfcut.Replace((string)keysvals["location"], String.Empty, 99999);
592
593 if (keysvals.Contains("region"))
594 region = wfcut.Replace((string)keysvals["region"], String.Empty, 99999);
595
596 if (keysvals.Contains("grid"))
597 grid = wfcut.Replace((string)keysvals["grid"], String.Empty, 99999);
598
599 if (keysvals.Contains("channel"))
600 channel = wfcut.Replace((string)keysvals["channel"], String.Empty, 99999);
601
602 if (keysvals.Contains("version"))
603 version = wfcut.Replace((string)keysvals["version"], String.Empty, 99999);
604
605 if (keysvals.Contains("lang"))
606 lang = wfcut.Replace((string)keysvals["lang"], String.Empty, 99999);
607
608 if (keysvals.Contains("password"))
609 password = wfcut.Replace((string)keysvals["password"], String.Empty, 99999);
610
611 // load our login form.
612 string loginform = GetLoginForm(firstname, lastname, location, region, grid, channel, version, lang, password, errormessages);
613
614 if (keysvals.ContainsKey("show_login_form"))
615 {
616 UserProfileData user = GetTheUser(firstname, lastname);
617 bool goodweblogin = false;
618
619 if (user != null)
620 goodweblogin = AuthenticateUser(user, password);
621
622 if (goodweblogin)
623 {
624 UUID webloginkey = UUID.Random();
625 m_userManager.StoreWebLoginKey(user.ID, webloginkey);
626 //statuscode = 301;
627
628 // string redirectURL = "about:blank?redirect-http-hack=" +
629 // HttpUtility.UrlEncode("secondlife:///app/login?first_name=" + firstname + "&last_name=" +
630 // lastname +
631 // "&location=" + location + "&grid=Other&web_login_key=" + webloginkey.ToString());
632 //m_log.Info("[WEB]: R:" + redirectURL);
633 returnactions["int_response_code"] = statuscode;
634 //returnactions["str_redirect_location"] = redirectURL;
635 //returnactions["str_response_string"] = "<HTML><BODY>GoodLogin</BODY></HTML>";
636 returnactions["str_response_string"] = webloginkey.ToString();
637 }
638 else
639 {
640 errormessages = "The Username and password supplied did not match our records. Check your caps lock and try again";
641
642 loginform = GetLoginForm(firstname, lastname, location, region, grid, channel, version, lang, password, errormessages);
643 returnactions["int_response_code"] = statuscode;
644 returnactions["str_response_string"] = loginform;
645 }
646 }
647 else
648 {
649 returnactions["int_response_code"] = statuscode;
650 returnactions["str_response_string"] = loginform;
651 }
652 return returnactions;
653 }
654
655 public string GetLoginForm(string firstname, string lastname, string location, string region,
656 string grid, string channel, string version, string lang,
657 string password, string errormessages)
658 {
659 // inject our values in the form at the markers
660
661 string loginform = String.Empty;
662 string file = Path.Combine(Util.configDir(), "http_loginform.html");
663 if (!File.Exists(file))
664 {
665 loginform = GetDefaultLoginForm();
666 }
667 else
668 {
669 StreamReader sr = File.OpenText(file);
670 loginform = sr.ReadToEnd();
671 sr.Close();
672 }
673
674 loginform = loginform.Replace("[$firstname]", firstname);
675 loginform = loginform.Replace("[$lastname]", lastname);
676 loginform = loginform.Replace("[$location]", location);
677 loginform = loginform.Replace("[$region]", region);
678 loginform = loginform.Replace("[$grid]", grid);
679 loginform = loginform.Replace("[$channel]", channel);
680 loginform = loginform.Replace("[$version]", version);
681 loginform = loginform.Replace("[$lang]", lang);
682 loginform = loginform.Replace("[$password]", password);
683 loginform = loginform.Replace("[$errors]", errormessages);
684
685 return loginform;
686 }
687
688 public string GetDefaultLoginForm()
689 {
690 string responseString =
691 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">";
692 responseString += "<html xmlns=\"http://www.w3.org/1999/xhtml\">";
693 responseString += "<head>";
694 responseString += "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />";
695 responseString += "<meta http-equiv=\"cache-control\" content=\"no-cache\">";
696 responseString += "<meta http-equiv=\"Pragma\" content=\"no-cache\">";
697 responseString += "<title>OpenSim Login</title>";
698 responseString += "<body><br />";
699 responseString += "<div id=\"login_box\">";
700
701 responseString += "<form action=\"/go.cgi\" method=\"GET\" id=\"login-form\">";
702
703 responseString += "<div id=\"message\">[$errors]</div>";
704 responseString += "<fieldset id=\"firstname\">";
705 responseString += "<legend>First Name:</legend>";
706 responseString += "<input type=\"text\" id=\"firstname_input\" size=\"15\" maxlength=\"100\" name=\"username\" value=\"[$firstname]\" />";
707 responseString += "</fieldset>";
708 responseString += "<fieldset id=\"lastname\">";
709 responseString += "<legend>Last Name:</legend>";
710 responseString += "<input type=\"text\" size=\"15\" maxlength=\"100\" name=\"lastname\" value=\"[$lastname]\" />";
711 responseString += "</fieldset>";
712 responseString += "<fieldset id=\"password\">";
713 responseString += "<legend>Password:</legend>";
714 responseString += "<table cellspacing=\"0\" cellpadding=\"0\" border=\"0\">";
715 responseString += "<tr>";
716 responseString += "<td colspan=\"2\"><input type=\"password\" size=\"15\" maxlength=\"100\" name=\"password\" value=\"[$password]\" /></td>";
717 responseString += "</tr>";
718 responseString += "<tr>";
719 responseString += "<td valign=\"middle\"><input type=\"checkbox\" name=\"remember_password\" id=\"remember_password\" [$remember_password] style=\"margin-left:0px;\"/></td>";
720 responseString += "<td><label for=\"remember_password\">Remember password</label></td>";
721 responseString += "</tr>";
722 responseString += "</table>";
723 responseString += "</fieldset>";
724 responseString += "<input type=\"hidden\" name=\"show_login_form\" value=\"FALSE\" />";
725 responseString += "<input type=\"hidden\" name=\"method\" value=\"login\" />";
726 responseString += "<input type=\"hidden\" id=\"grid\" name=\"grid\" value=\"[$grid]\" />";
727 responseString += "<input type=\"hidden\" id=\"region\" name=\"region\" value=\"[$region]\" />";
728 responseString += "<input type=\"hidden\" id=\"location\" name=\"location\" value=\"[$location]\" />";
729 responseString += "<input type=\"hidden\" id=\"channel\" name=\"channel\" value=\"[$channel]\" />";
730 responseString += "<input type=\"hidden\" id=\"version\" name=\"version\" value=\"[$version]\" />";
731 responseString += "<input type=\"hidden\" id=\"lang\" name=\"lang\" value=\"[$lang]\" />";
732 responseString += "<div id=\"submitbtn\">";
733 responseString += "<input class=\"input_over\" type=\"submit\" value=\"Connect\" />";
734 responseString += "</div>";
735 responseString += "<div id=\"connecting\" style=\"visibility:hidden\"> Connecting...</div>";
736
737 responseString += "<div id=\"helplinks\"><!---";
738 responseString += "<a href=\"#join now link\" target=\"_blank\"></a> | ";
739 responseString += "<a href=\"#forgot password link\" target=\"_blank\"></a>";
740 responseString += "---></div>";
741
742 responseString += "<div id=\"channelinfo\"> [$channel] | [$version]=[$lang]</div>";
743 responseString += "</form>";
744 responseString += "<script language=\"JavaScript\">";
745 responseString += "document.getElementById('firstname_input').focus();";
746 responseString += "</script>";
747 responseString += "</div>";
748 responseString += "</div>";
749 responseString += "</body>";
750 responseString += "</html>";
751
752 return responseString;
753 }
754
755 /// <summary>
756 /// Saves a target agent to the database
757 /// </summary>
758 /// <param name="profile">The users profile</param>
759 /// <returns>Successful?</returns>
760 public bool CommitAgent(ref UserProfileData profile)
761 {
762 return m_userManager.CommitAgent(ref profile);
763 }
764
765 /// <summary>
766 /// Checks a user against it's password hash
767 /// </summary>
768 /// <param name="profile">The users profile</param>
769 /// <param name="password">The supplied password</param>
770 /// <returns>Authenticated?</returns>
771 public virtual bool AuthenticateUser(UserProfileData profile, string password)
772 {
773 bool passwordSuccess = false;
774 //m_log.InfoFormat("[LOGIN]: Authenticating {0} {1} ({2})", profile.FirstName, profile.SurName, profile.ID);
775
776 // Web Login method seems to also occasionally send the hashed password itself
777
778 // we do this to get our hash in a form that the server password code can consume
779 // when the web-login-form submits the password in the clear (supposed to be over SSL!)
780 if (!password.StartsWith("$1$"))
781 password = "$1$" + Util.Md5Hash(password);
782
783 password = password.Remove(0, 3); //remove $1$
784
785 string s = Util.Md5Hash(password + ":" + profile.PasswordSalt);
786 // Testing...
787 //m_log.Info("[LOGIN]: SubHash:" + s + " userprofile:" + profile.passwordHash);
788 //m_log.Info("[LOGIN]: userprofile:" + profile.passwordHash + " SubCT:" + password);
789
790 passwordSuccess = (profile.PasswordHash.Equals(s.ToString(), StringComparison.InvariantCultureIgnoreCase)
791 || profile.PasswordHash.Equals(password, StringComparison.InvariantCulture));
792
793 return passwordSuccess;
794 }
795
796 public virtual bool AuthenticateUser(UserProfileData profile, UUID webloginkey)
797 {
798 bool passwordSuccess = false;
799 m_log.InfoFormat("[LOGIN]: Authenticating {0} {1} ({2})", profile.FirstName, profile.SurName, profile.ID);
800
801 // Match web login key unless it's the default weblogin key UUID.Zero
802 passwordSuccess = ((profile.WebLoginKey == webloginkey) && profile.WebLoginKey != UUID.Zero);
803
804 return passwordSuccess;
805 }
806
807 /// <summary>
808 ///
809 /// </summary>
810 /// <param name="profile"></param>
811 /// <param name="request"></param>
812 public void CreateAgent(UserProfileData profile, XmlRpcRequest request)
813 {
814 m_userManager.CreateAgent(profile, request);
815 }
816
817 public void CreateAgent(UserProfileData profile, OSD request)
818 {
819 m_userManager.CreateAgent(profile, request);
820 }
821
822 /// <summary>
823 ///
824 /// </summary>
825 /// <param name="firstname"></param>
826 /// <param name="lastname"></param>
827 /// <returns></returns>
828 public virtual UserProfileData GetTheUser(string firstname, string lastname)
829 {
830 return m_userManager.GetUserProfile(firstname, lastname);
831 }
832
833 /// <summary>
834 ///
835 /// </summary>
836 /// <returns></returns>
837 public virtual string GetMessage()
838 {
839 return m_welcomeMessage;
840 }
841
842 private static LoginResponse.BuddyList ConvertFriendListItem(List<FriendListItem> LFL)
843 {
844 LoginResponse.BuddyList buddylistreturn = new LoginResponse.BuddyList();
845 foreach (FriendListItem fl in LFL)
846 {
847 LoginResponse.BuddyList.BuddyInfo buddyitem = new LoginResponse.BuddyList.BuddyInfo(fl.Friend);
848 buddyitem.BuddyID = fl.Friend;
849 buddyitem.BuddyRightsHave = (int)fl.FriendListOwnerPerms;
850 buddyitem.BuddyRightsGiven = (int)fl.FriendPerms;
851 buddylistreturn.AddNewBuddy(buddyitem);
852 }
853 return buddylistreturn;
854 }
855
856 /// <summary>
857 /// Converts the inventory library skeleton into the form required by the rpc request.
858 /// </summary>
859 /// <returns></returns>
860 protected virtual ArrayList GetInventoryLibrary()
861 {
862 Dictionary<UUID, InventoryFolderImpl> rootFolders
863 = m_libraryRootFolder.RequestSelfAndDescendentFolders();
864 ArrayList folderHashes = new ArrayList();
865
866 foreach (InventoryFolderBase folder in rootFolders.Values)
867 {
868 Hashtable TempHash = new Hashtable();
869 TempHash["name"] = folder.Name;
870 TempHash["parent_id"] = folder.ParentID.ToString();
871 TempHash["version"] = (Int32)folder.Version;
872 TempHash["type_default"] = (Int32)folder.Type;
873 TempHash["folder_id"] = folder.ID.ToString();
874 folderHashes.Add(TempHash);
875 }
876
877 return folderHashes;
878 }
879
880 /// <summary>
881 ///
882 /// </summary>
883 /// <returns></returns>
884 protected virtual ArrayList GetLibraryOwner()
885 {
886 //for now create random inventory library owner
887 Hashtable TempHash = new Hashtable();
888 TempHash["agent_id"] = "11111111-1111-0000-0000-000100bba000";
889 ArrayList inventoryLibOwner = new ArrayList();
890 inventoryLibOwner.Add(TempHash);
891 return inventoryLibOwner;
892 }
893
894 public class InventoryData
895 {
896 public ArrayList InventoryArray = null;
897 public UUID RootFolderID = UUID.Zero;
898
899 public InventoryData(ArrayList invList, UUID rootID)
900 {
901 InventoryArray = invList;
902 RootFolderID = rootID;
903 }
904 }
905
906 protected void SniffLoginKey(Uri uri, Hashtable requestData)
907 {
908 string uri_str = uri.ToString();
909 string[] parts = uri_str.Split(new char[] { '=' });
910 if (parts.Length > 1)
911 {
912 string web_login_key = parts[1];
913 requestData.Add("web_login_key", web_login_key);
914 m_log.InfoFormat("[LOGIN]: Login with web_login_key {0}", web_login_key);
915 }
916 }
917
918 /// <summary>
919 /// Customises the login response and fills in missing values. This method also tells the login region to
920 /// expect a client connection.
921 /// </summary>
922 /// <param name="response">The existing response</param>
923 /// <param name="theUser">The user profile</param>
924 /// <param name="startLocationRequest">The requested start location</param>
925 /// <returns>true on success, false if the region was not successfully told to expect a user connection</returns>
926 public bool CustomiseResponse(LoginResponse response, UserProfileData theUser, string startLocationRequest, IPEndPoint client)
927 {
928 // add active gestures to login-response
929 AddActiveGestures(response, theUser);
930
931 // HomeLocation
932 RegionInfo homeInfo = null;
933
934 // use the homeRegionID if it is stored already. If not, use the regionHandle as before
935 UUID homeRegionId = theUser.HomeRegionID;
936 ulong homeRegionHandle = theUser.HomeRegion;
937 if (homeRegionId != UUID.Zero)
938 {
939 homeInfo = GetRegionInfo(homeRegionId);
940 }
941 else
942 {
943 homeInfo = GetRegionInfo(homeRegionHandle);
944 }
945
946 if (homeInfo != null)
947 {
948 response.Home =
949 string.Format(
950 "{{'region_handle':[r{0},r{1}], 'position':[r{2},r{3},r{4}], 'look_at':[r{5},r{6},r{7}]}}",
951 (homeInfo.RegionLocX * Constants.RegionSize),
952 (homeInfo.RegionLocY * Constants.RegionSize),
953 theUser.HomeLocation.X, theUser.HomeLocation.Y, theUser.HomeLocation.Z,
954 theUser.HomeLookAt.X, theUser.HomeLookAt.Y, theUser.HomeLookAt.Z);
955 }
956 else
957 {
958 m_log.InfoFormat("not found the region at {0} {1}", theUser.HomeRegionX, theUser.HomeRegionY);
959 // Emergency mode: Home-region isn't available, so we can't request the region info.
960 // Use the stored home regionHandle instead.
961 // NOTE: If the home-region moves, this will be wrong until the users update their user-profile again
962 ulong regionX = homeRegionHandle >> 32;
963 ulong regionY = homeRegionHandle & 0xffffffff;
964 response.Home =
965 string.Format(
966 "{{'region_handle':[r{0},r{1}], 'position':[r{2},r{3},r{4}], 'look_at':[r{5},r{6},r{7}]}}",
967 regionX, regionY,
968 theUser.HomeLocation.X, theUser.HomeLocation.Y, theUser.HomeLocation.Z,
969 theUser.HomeLookAt.X, theUser.HomeLookAt.Y, theUser.HomeLookAt.Z);
970
971 m_log.InfoFormat("[LOGIN] Home region of user {0} {1} is not available; using computed region position {2} {3}",
972 theUser.FirstName, theUser.SurName,
973 regionX, regionY);
974 }
975
976 // StartLocation
977 RegionInfo regionInfo = null;
978 if (startLocationRequest == "home")
979 {
980 regionInfo = homeInfo;
981 theUser.CurrentAgent.Position = theUser.HomeLocation;
982 response.LookAt = String.Format("[r{0},r{1},r{2}]", theUser.HomeLookAt.X.ToString(),
983 theUser.HomeLookAt.Y.ToString(), theUser.HomeLookAt.Z.ToString());
984 }
985 else if (startLocationRequest == "last")
986 {
987 UUID lastRegion = theUser.CurrentAgent.Region;
988 regionInfo = GetRegionInfo(lastRegion);
989 response.LookAt = String.Format("[r{0},r{1},r{2}]", theUser.CurrentAgent.LookAt.X.ToString(),
990 theUser.CurrentAgent.LookAt.Y.ToString(), theUser.CurrentAgent.LookAt.Z.ToString());
991 }
992 else
993 {
994 Regex reURI = new Regex(@"^uri:(?<region>[^&]+)&(?<x>\d+)&(?<y>\d+)&(?<z>\d+)$");
995 Match uriMatch = reURI.Match(startLocationRequest);
996 if (uriMatch == null)
997 {
998 m_log.InfoFormat("[LOGIN]: Got Custom Login URL {0}, but can't process it", startLocationRequest);
999 }
1000 else
1001 {
1002 string region = uriMatch.Groups["region"].ToString();
1003 regionInfo = RequestClosestRegion(region);
1004 if (regionInfo == null)
1005 {
1006 m_log.InfoFormat("[LOGIN]: Got Custom Login URL {0}, can't locate region {1}", startLocationRequest, region);
1007 }
1008 else
1009 {
1010 theUser.CurrentAgent.Position = new Vector3(float.Parse(uriMatch.Groups["x"].Value, Culture.NumberFormatInfo),
1011 float.Parse(uriMatch.Groups["y"].Value, Culture.NumberFormatInfo), float.Parse(uriMatch.Groups["z"].Value, Culture.NumberFormatInfo));
1012 }
1013 }
1014 response.LookAt = "[r0,r1,r0]";
1015 // can be: last, home, safe, url
1016 response.StartLocation = "url";
1017 }
1018
1019 if ((regionInfo != null) && (PrepareLoginToRegion(regionInfo, theUser, response, client)))
1020 {
1021 return true;
1022 }
1023
1024 // Get the default region handle
1025 ulong defaultHandle = Utils.UIntsToLong(m_defaultHomeX * Constants.RegionSize, m_defaultHomeY * Constants.RegionSize);
1026
1027 // If we haven't already tried the default region, reset regionInfo
1028 if (regionInfo != null && defaultHandle != regionInfo.RegionHandle)
1029 regionInfo = null;
1030
1031 if (regionInfo == null)
1032 {
1033 m_log.Error("[LOGIN]: Sending user to default region " + defaultHandle + " instead");
1034 regionInfo = GetRegionInfo(defaultHandle);
1035 }
1036
1037 if (regionInfo == null)
1038 {
1039 m_log.ErrorFormat("[LOGIN]: Sending user to any region");
1040 regionInfo = RequestClosestRegion(String.Empty);
1041 }
1042
1043 theUser.CurrentAgent.Position = new Vector3(128f, 128f, 0f);
1044 response.StartLocation = "safe";
1045
1046 return PrepareLoginToRegion(regionInfo, theUser, response, client);
1047 }
1048
1049 protected abstract RegionInfo RequestClosestRegion(string region);
1050 protected abstract RegionInfo GetRegionInfo(ulong homeRegionHandle);
1051 protected abstract RegionInfo GetRegionInfo(UUID homeRegionId);
1052
1053 /// <summary>
1054 /// If the user is already logged in, try to notify the region that the user they've got is dead.
1055 /// </summary>
1056 /// <param name="theUser"></param>
1057 public abstract void LogOffUser(UserProfileData theUser, string message);
1058
1059 /// <summary>
1060 /// Prepare a login to the given region. This involves both telling the region to expect a connection
1061 /// and appropriately customising the response to the user.
1062 /// </summary>
1063 /// <param name="sim"></param>
1064 /// <param name="user"></param>
1065 /// <param name="response"></param>
1066 /// <param name="remoteClient"></param>
1067 /// <returns>true if the region was successfully contacted, false otherwise</returns>
1068 protected abstract bool PrepareLoginToRegion(
1069 RegionInfo regionInfo, UserProfileData user, LoginResponse response, IPEndPoint client);
1070
1071 /// <summary>
1072 /// Add active gestures of the user to the login response.
1073 /// </summary>
1074 /// <param name="response">
1075 /// A <see cref="LoginResponse"/>
1076 /// </param>
1077 /// <param name="theUser">
1078 /// A <see cref="UserProfileData"/>
1079 /// </param>
1080 protected void AddActiveGestures(LoginResponse response, UserProfileData theUser)
1081 {
1082 List<InventoryItemBase> gestures = null;
1083 try
1084 {
1085 if (m_InventoryService != null)
1086 gestures = m_InventoryService.GetActiveGestures(theUser.ID);
1087 else
1088 gestures = m_interInventoryService.GetActiveGestures(theUser.ID);
1089 }
1090 catch (Exception e)
1091 {
1092 m_log.Debug("[LOGIN]: Unable to retrieve active gestures from inventory server. Reason: " + e.Message);
1093 }
1094 //m_log.DebugFormat("[LOGIN]: AddActiveGestures, found {0}", gestures == null ? 0 : gestures.Count);
1095 ArrayList list = new ArrayList();
1096 if (gestures != null)
1097 {
1098 foreach (InventoryItemBase gesture in gestures)
1099 {
1100 Hashtable item = new Hashtable();
1101 item["item_id"] = gesture.ID.ToString();
1102 item["asset_id"] = gesture.AssetID.ToString();
1103 list.Add(item);
1104 }
1105 }
1106 response.ActiveGestures = list;
1107 }
1108
1109 /// <summary>
1110 /// Get the initial login inventory skeleton (in other words, the folder structure) for the given user.
1111 /// </summary>
1112 /// <param name="userID"></param>
1113 /// <returns></returns>
1114 /// <exception cref='System.Exception'>This will be thrown if there is a problem with the inventory service</exception>
1115 protected InventoryData GetInventorySkeleton(UUID userID)
1116 {
1117 List<InventoryFolderBase> folders = null;
1118 if (m_InventoryService != null)
1119 {
1120 folders = m_InventoryService.GetInventorySkeleton(userID);
1121 }
1122 else
1123 {
1124 folders = m_interInventoryService.GetInventorySkeleton(userID);
1125 }
1126
1127 // If we have user auth but no inventory folders for some reason, create a new set of folders.
1128 if (folders == null || folders.Count == 0)
1129 {
1130 m_log.InfoFormat(
1131 "[LOGIN]: A root inventory folder for user {0} was not found. Requesting creation.", userID);
1132
1133 // Although the create user function creates a new agent inventory along with a new user profile, some
1134 // tools are creating the user profile directly in the database without creating the inventory. At
1135 // this time we'll accomodate them by lazily creating the user inventory now if it doesn't already
1136 // exist.
1137 if (m_interInventoryService != null)
1138 {
1139 if (!m_interInventoryService.CreateNewUserInventory(userID))
1140 {
1141 throw new Exception(
1142 String.Format(
1143 "The inventory creation request for user {0} did not succeed."
1144 + " Please contact your inventory service provider for more information.",
1145 userID));
1146 }
1147 }
1148 else if ((m_InventoryService != null) && !m_InventoryService.CreateUserInventory(userID))
1149 {
1150 throw new Exception(
1151 String.Format(
1152 "The inventory creation request for user {0} did not succeed."
1153 + " Please contact your inventory service provider for more information.",
1154 userID));
1155 }
1156
1157
1158 m_log.InfoFormat("[LOGIN]: A new inventory skeleton was successfully created for user {0}", userID);
1159
1160 if (m_InventoryService != null)
1161 folders = m_InventoryService.GetInventorySkeleton(userID);
1162 else
1163 folders = m_interInventoryService.GetInventorySkeleton(userID);
1164
1165 if (folders == null || folders.Count == 0)
1166 {
1167 throw new Exception(
1168 String.Format(
1169 "A root inventory folder for user {0} could not be retrieved from the inventory service",
1170 userID));
1171 }
1172 }
1173
1174 UUID rootID = UUID.Zero;
1175 ArrayList AgentInventoryArray = new ArrayList();
1176 Hashtable TempHash;
1177 foreach (InventoryFolderBase InvFolder in folders)
1178 {
1179 if (InvFolder.ParentID == UUID.Zero)
1180 {
1181 rootID = InvFolder.ID;
1182 }
1183 TempHash = new Hashtable();
1184 TempHash["name"] = InvFolder.Name;
1185 TempHash["parent_id"] = InvFolder.ParentID.ToString();
1186 TempHash["version"] = (Int32)InvFolder.Version;
1187 TempHash["type_default"] = (Int32)InvFolder.Type;
1188 TempHash["folder_id"] = InvFolder.ID.ToString();
1189 AgentInventoryArray.Add(TempHash);
1190 }
1191
1192 return new InventoryData(AgentInventoryArray, rootID);
1193 }
1194
1195 protected virtual bool AllowLoginWithoutInventory()
1196 {
1197 return false;
1198 }
1199
1200 public XmlRpcResponse XmlRPCCheckAuthSession(XmlRpcRequest request, IPEndPoint remoteClient)
1201 {
1202 XmlRpcResponse response = new XmlRpcResponse();
1203 Hashtable requestData = (Hashtable)request.Params[0];
1204
1205 string authed = "FALSE";
1206 if (requestData.Contains("avatar_uuid") && requestData.Contains("session_id"))
1207 {
1208 UUID guess_aid;
1209 UUID guess_sid;
1210
1211 UUID.TryParse((string)requestData["avatar_uuid"], out guess_aid);
1212 if (guess_aid == UUID.Zero)
1213 {
1214 return Util.CreateUnknownUserErrorResponse();
1215 }
1216
1217 UUID.TryParse((string)requestData["session_id"], out guess_sid);
1218 if (guess_sid == UUID.Zero)
1219 {
1220 return Util.CreateUnknownUserErrorResponse();
1221 }
1222
1223 if (m_userManager.VerifySession(guess_aid, guess_sid))
1224 {
1225 authed = "TRUE";
1226 m_log.InfoFormat("[UserManager]: CheckAuthSession TRUE for user {0}", guess_aid);
1227 }
1228 else
1229 {
1230 m_log.InfoFormat("[UserManager]: CheckAuthSession FALSE");
1231 return Util.CreateUnknownUserErrorResponse();
1232 }
1233 }
1234
1235 Hashtable responseData = new Hashtable();
1236 responseData["auth_session"] = authed;
1237 response.Value = responseData;
1238 return response;
1239 }
1240 }
1241} \ No newline at end of file
diff --git a/OpenSim/Framework/Communications/TemporaryUserProfilePlugin.cs b/OpenSim/Framework/Communications/TemporaryUserProfilePlugin.cs
deleted file mode 100644
index 2413055..0000000
--- a/OpenSim/Framework/Communications/TemporaryUserProfilePlugin.cs
+++ /dev/null
@@ -1,104 +0,0 @@
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
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using log4net;
32using OpenMetaverse;
33using OpenSim.Data;
34
35namespace OpenSim.Framework.Communications
36{
37 /// <summary>
38 /// Plugin for managing temporary user profiles.
39 /// </summary>
40 public class TemporaryUserProfilePlugin : IUserDataPlugin
41 {
42 //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
43
44 protected Dictionary<UUID, UserProfileData> m_profiles = new Dictionary<UUID, UserProfileData>();
45
46 public string Name { get { return "TemporaryUserProfilePlugin"; } }
47 public string Version { get { return "0.1"; } }
48 public void Initialise() {}
49 public void Initialise(string connect) {}
50 public void Dispose() {}
51
52 public UserProfileData GetUserByUUID(UUID user)
53 {
54 //m_log.DebugFormat("[TEMP USER PROFILE]: Received request for {0}", user);
55
56 lock (m_profiles)
57 {
58 if (m_profiles.ContainsKey(user))
59 return m_profiles[user];
60 else
61 return null;
62 }
63 }
64
65 public UserProfileData GetUserByName(string fname, string lname)
66 {
67 // We deliberately don't look up a temporary profile by name so that we don't obscure non-temporary
68 // profiles.
69
70 return null;
71 }
72
73 public virtual void AddTemporaryUserProfile(UserProfileData userProfile)
74 {
75 //m_log.DebugFormat("[TEMP USER PROFILE]: Adding {0} {1}", userProfile.Name, userProfile.ID);
76
77 lock (m_profiles)
78 {
79 m_profiles[userProfile.ID] = userProfile;
80 }
81 }
82
83 public UserProfileData GetUserByUri(Uri uri) { return null; }
84 public List<AvatarPickerAvatar> GeneratePickerResults(UUID queryID, string query) { return null; }
85 public UserAgentData GetAgentByUUID(UUID user) { return null; }
86 public UserAgentData GetAgentByName(string name) { return null; }
87 public UserAgentData GetAgentByName(string fname, string lname) { return null; }
88 public void StoreWebLoginKey(UUID agentID, UUID webLoginKey) {}
89 public void AddNewUserProfile(UserProfileData user) {}
90 public bool UpdateUserProfile(UserProfileData user) { return false; }
91 public void AddNewUserAgent(UserAgentData agent) {}
92 public void AddNewUserFriend(UUID friendlistowner, UUID friend, uint perms) {}
93 public void RemoveUserFriend(UUID friendlistowner, UUID friend) {}
94 public void UpdateUserFriendPerms(UUID friendlistowner, UUID friend, uint perms) {}
95 public List<FriendListItem> GetUserFriendList(UUID friendlistowner) { return null; }
96 public Dictionary<UUID, FriendRegionInfo> GetFriendRegionInfos(List<UUID> uuids) { return null; }
97 public bool MoneyTransferRequest(UUID from, UUID to, uint amount) { return false; }
98 public bool InventoryTransferRequest(UUID from, UUID to, UUID inventory) { return false; }
99 public AvatarAppearance GetUserAppearance(UUID user) { return null; }
100 public void UpdateUserAppearance(UUID user, AvatarAppearance appearance) {}
101 public void ResetAttachments(UUID userID) {}
102 public void LogoutUsers(UUID regionID) {}
103 }
104}
diff --git a/OpenSim/Framework/Communications/Tests/Cache/UserProfileCacheServiceTests.cs b/OpenSim/Framework/Communications/Tests/Cache/UserProfileCacheServiceTests.cs
deleted file mode 100644
index 830c877..0000000
--- a/OpenSim/Framework/Communications/Tests/Cache/UserProfileCacheServiceTests.cs
+++ /dev/null
@@ -1,345 +0,0 @@
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
28using NUnit.Framework;
29using NUnit.Framework.SyntaxHelpers;
30using System.Threading;
31using OpenMetaverse;
32using OpenSim.Data;
33using OpenSim.Framework;
34using OpenSim.Framework.Communications.Cache;
35using OpenSim.Region.Framework.Scenes;
36using OpenSim.Region.Communications.Local;
37using OpenSim.Tests.Common.Mock;
38using OpenSim.Tests.Common.Setup;
39using OpenSim.Tests.Common;
40
41namespace OpenSim.Framework.Communications.Tests
42{
43 [TestFixture]
44 public class UserProfileCacheServiceTests
45 {
46 /// <value>Used by tests to indicate whether an async operation timed out</value>
47 private bool timedOut;
48
49 private void InventoryReceived(UUID userId)
50 {
51 lock (this)
52 {
53 timedOut = false;
54 Monitor.PulseAll(this);
55 }
56 }
57
58 [Test]
59 public void TestGetUserDetails()
60 {
61 TestHelper.InMethod();
62
63 UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000002");
64 string firstName = "Bill";
65 string lastName = "Bailey";
66 CachedUserInfo nonExistingUserInfo;
67
68 TestCommunicationsManager commsManager = new TestCommunicationsManager();
69 // Scene myScene = SceneSetupHelpers.SetupScene(commsManager, "");
70
71 // Check we can't retrieve info before it exists by uuid
72 nonExistingUserInfo = commsManager.UserProfileCacheService.GetUserDetails(userId);
73 Assert.That(nonExistingUserInfo, Is.Null, "User info found by uuid before user creation");
74
75 // Check we can't retrieve info before it exists by name
76 nonExistingUserInfo = commsManager.UserProfileCacheService.GetUserDetails(firstName, lastName);
77 Assert.That(nonExistingUserInfo, Is.Null, "User info found by name before user creation");
78
79 LocalUserServices lus = (LocalUserServices)commsManager.UserService;
80 lus.AddUser(firstName, lastName, "troll", "bill@bailey.com", 1000, 1000, userId);
81
82 CachedUserInfo existingUserInfo;
83
84 // Check we can retrieve info by uuid
85 existingUserInfo = commsManager.UserProfileCacheService.GetUserDetails(userId);
86 Assert.That(existingUserInfo, Is.Not.Null, "User info not found by uuid");
87
88 // Check we can retrieve info by name
89 existingUserInfo = commsManager.UserProfileCacheService.GetUserDetails(firstName, lastName);
90 Assert.That(existingUserInfo, Is.Not.Null, "User info not found by name");
91 }
92
93 /**
94 * Disabled as not fully implemented
95 [Test]
96 public void TestUpdateProfile()
97 {
98 UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000292");
99 string firstName = "Inspector";
100 string originalLastName = "Morse";
101 string newLastName = "Gadget";
102
103 UserProfileData newProfile = new UserProfileData();
104 newProfile.ID = userId;
105 newProfile.FirstName = firstName;
106 newProfile.SurName = newLastName;
107
108 TestCommunicationsManager commsManager = new TestCommunicationsManager();
109 UserProfileCacheService userCacheService = commsManager.UserProfileCacheService;
110 IUserDataPlugin userDataPlugin = commsManager.UserDataPlugin;
111
112 // Check that we can't update info before it exists
113 Assert.That(userCacheService.StoreProfile(newProfile), Is.False);
114 Assert.That(userDataPlugin.GetUserByUUID(userId), Is.Null);
115
116 // Check that we can update a profile once it exists
117 LocalUserServices lus = (LocalUserServices)commsManager.UserService;
118 lus.AddUser(firstName, originalLastName, "pingu", "ted@excellentadventure.com", 1000, 1000, userId);
119
120 Assert.That(userCacheService.StoreProfile(newProfile), Is.True);
121 UserProfileData retrievedProfile = userCacheService.GetUserDetails(userId).UserProfile;
122 Assert.That(retrievedProfile.SurName, Is.EqualTo(newLastName));
123 Assert.That(userDataPlugin.GetUserByUUID(userId).SurName, Is.EqualTo(newLastName));
124 }
125 */
126
127 [Test]
128 public void TestFetchInventory()
129 {
130 TestHelper.InMethod();
131
132 Scene myScene = SceneSetupHelpers.SetupScene("inventory");
133
134 timedOut = true;
135 lock (this)
136 {
137 UserProfileTestUtils.CreateUserWithInventory(myScene.CommsManager, InventoryReceived);
138 Monitor.Wait(this, 60000);
139 }
140
141 Assert.That(timedOut, Is.False, "Timed out");
142 }
143
144 [Test]
145 public void TestGetChildFolder()
146 {
147 TestHelper.InMethod();
148
149 Scene myScene = SceneSetupHelpers.SetupScene("inventory");
150 CachedUserInfo userInfo;
151
152 lock (this)
153 {
154 userInfo = UserProfileTestUtils.CreateUserWithInventory(myScene.CommsManager, InventoryReceived);
155 Monitor.Wait(this, 60000);
156 }
157
158 UUID folderId = UUID.Parse("00000000-0000-0000-0000-000000000011");
159 Assert.That(userInfo.RootFolder.GetChildFolder(folderId), Is.Null);
160 userInfo.CreateFolder("testFolder", folderId, (ushort)AssetType.Animation, userInfo.RootFolder.ID);
161
162 Assert.That(userInfo.RootFolder.GetChildFolder(folderId), Is.Not.Null);
163 }
164
165 [Test]
166 public void TestCreateFolder()
167 {
168 TestHelper.InMethod();
169
170 Scene myScene = SceneSetupHelpers.SetupScene("inventory");
171 CachedUserInfo userInfo;
172
173 lock (this)
174 {
175 userInfo = UserProfileTestUtils.CreateUserWithInventory(myScene.CommsManager, InventoryReceived);
176 Monitor.Wait(this, 60000);
177 }
178
179 UUID folderId = UUID.Parse("00000000-0000-0000-0000-000000000010");
180 Assert.That(userInfo.RootFolder.ContainsChildFolder(folderId), Is.False);
181
182 // 1: Try a folder create that should fail because the parent id given does not exist
183 UUID missingFolderId = UUID.Random();
184 InventoryFolderBase myFolder = new InventoryFolderBase();
185 myFolder.ID = folderId;
186
187 Assert.That(
188 userInfo.CreateFolder("testFolder1", folderId, (ushort)AssetType.Animation, missingFolderId), Is.False);
189 Assert.That(myScene.InventoryService.GetFolder(myFolder), Is.Null);
190 Assert.That(userInfo.RootFolder.ContainsChildFolder(missingFolderId), Is.False);
191 Assert.That(userInfo.RootFolder.FindFolder(folderId), Is.Null);
192
193 // 2: Try a folder create that should work
194 Assert.That(
195 userInfo.CreateFolder("testFolder2", folderId, (ushort)AssetType.Animation, userInfo.RootFolder.ID), Is.True);
196 Assert.That(myScene.InventoryService.GetFolder(myFolder), Is.Not.Null);
197 Assert.That(userInfo.RootFolder.ContainsChildFolder(folderId), Is.True);
198 }
199
200 //[Test]
201 public void TestUpdateFolder()
202 {
203 TestHelper.InMethod();
204
205 Scene myScene = SceneSetupHelpers.SetupScene("inventory");
206 CachedUserInfo userInfo;
207
208 lock (this)
209 {
210 userInfo = UserProfileTestUtils.CreateUserWithInventory(myScene.CommsManager, InventoryReceived);
211 Monitor.Wait(this, 60000);
212 }
213
214 UUID folder1Id = UUID.Parse("00000000-0000-0000-0000-000000000060");
215 InventoryFolderImpl rootFolder = userInfo.RootFolder;
216 InventoryFolderBase myFolder = new InventoryFolderBase();
217 myFolder.ID = folder1Id;
218
219 userInfo.CreateFolder("folder1", folder1Id, (ushort)AssetType.Animation, rootFolder.ID);
220
221 // 1: Test updates that don't involve moving the folder
222 {
223 string newFolderName1 = "newFolderName1";
224 ushort folderType1 = (ushort)AssetType.Texture;
225 userInfo.UpdateFolder(newFolderName1, folder1Id, folderType1, rootFolder.ID);
226
227 InventoryFolderImpl folder1 = rootFolder.GetChildFolder(folder1Id);
228 Assert.That(newFolderName1, Is.EqualTo(folder1.Name));
229 Assert.That(folderType1, Is.EqualTo((ushort)folder1.Type));
230
231 InventoryFolderBase dataFolder1 = myScene.InventoryService.GetFolder(myFolder);
232 Assert.That(newFolderName1, Is.EqualTo(dataFolder1.Name));
233 Assert.That(folderType1, Is.EqualTo((ushort)dataFolder1.Type));
234 }
235
236 // 2: Test an update that also involves moving the folder
237 {
238 UUID folder2Id = UUID.Parse("00000000-0000-0000-0000-000000000061");
239 userInfo.CreateFolder("folder2", folder2Id, (ushort)AssetType.Animation, rootFolder.ID);
240 InventoryFolderImpl folder2 = rootFolder.GetChildFolder(folder2Id);
241
242 InventoryFolderBase myFolder2 = new InventoryFolderBase();
243 myFolder2.ID = folder2Id;
244
245 string newFolderName2 = "newFolderName2";
246 ushort folderType2 = (ushort)AssetType.Bodypart;
247 userInfo.UpdateFolder(newFolderName2, folder1Id, folderType2, folder2Id);
248
249 InventoryFolderImpl folder1 = folder2.GetChildFolder(folder1Id);
250 Assert.That(newFolderName2, Is.EqualTo(folder1.Name));
251 Assert.That(folderType2, Is.EqualTo((ushort)folder1.Type));
252 Assert.That(folder2Id, Is.EqualTo(folder1.ParentID));
253
254 Assert.That(folder2.ContainsChildFolder(folder1Id), Is.True);
255 Assert.That(rootFolder.ContainsChildFolder(folder1Id), Is.False);
256
257 InventoryFolderBase dataFolder1 = myScene.InventoryService.GetFolder(myFolder2);
258 Assert.That(newFolderName2, Is.EqualTo(dataFolder1.Name));
259 Assert.That(folderType2, Is.EqualTo((ushort)dataFolder1.Type));
260 Assert.That(folder2Id, Is.EqualTo(dataFolder1.ParentID));
261 }
262
263 }
264
265 [Test]
266 public void TestMoveFolder()
267 {
268 TestHelper.InMethod();
269
270 Scene myScene = SceneSetupHelpers.SetupScene("inventory");
271 CachedUserInfo userInfo;
272
273 lock (this)
274 {
275 userInfo = UserProfileTestUtils.CreateUserWithInventory(myScene.CommsManager, InventoryReceived);
276 Monitor.Wait(this, 60000);
277 }
278
279 UUID folder1Id = UUID.Parse("00000000-0000-0000-0000-000000000020");
280 UUID folder2Id = UUID.Parse("00000000-0000-0000-0000-000000000021");
281 UUID folderToMoveId = UUID.Parse("00000000-0000-0000-0000-000000000030");
282 InventoryFolderImpl rootFolder = userInfo.RootFolder;
283
284 userInfo.CreateFolder("folder1", folder1Id, (ushort)AssetType.Animation, rootFolder.ID);
285 InventoryFolderImpl folder1 = rootFolder.GetChildFolder(folder1Id);
286 userInfo.CreateFolder("folder2", folder2Id, (ushort)AssetType.Animation, rootFolder.ID);
287 InventoryFolderImpl folder2 = rootFolder.GetChildFolder(folder2Id);
288
289 // Check folder is currently in folder1
290 userInfo.CreateFolder("folderToMove", folderToMoveId, (ushort)AssetType.Animation, folder1Id);
291 Assert.That(folder1.ContainsChildFolder(folderToMoveId), Is.True);
292
293 userInfo.MoveFolder(folderToMoveId, folder2Id);
294
295 // Check folder is now in folder2 and no trace remains in folder1
296 InventoryFolderBase myFolder = new InventoryFolderBase();
297 myFolder.ID = folderToMoveId;
298 Assert.That(folder2.ContainsChildFolder(folderToMoveId), Is.True);
299 Assert.That(myScene.InventoryService.GetFolder(myFolder).ParentID, Is.EqualTo(folder2Id));
300
301 Assert.That(folder1.ContainsChildFolder(folderToMoveId), Is.False);
302 }
303
304 [Test]
305 public void TestPurgeFolder()
306 {
307 TestHelper.InMethod();
308 //log4net.Config.XmlConfigurator.Configure();
309
310 Scene myScene = SceneSetupHelpers.SetupScene("inventory");
311 CachedUserInfo userInfo;
312
313 lock (this)
314 {
315 userInfo = UserProfileTestUtils.CreateUserWithInventory(myScene.CommsManager, InventoryReceived);
316 Monitor.Wait(this, 60000);
317 }
318
319 UUID folder1Id = UUID.Parse("00000000-0000-0000-0000-000000000070");
320 InventoryFolderImpl rootFolder = userInfo.RootFolder;
321 InventoryFolderBase myFolder = new InventoryFolderBase();
322 myFolder.ID = folder1Id;
323
324 userInfo.CreateFolder("folder1", folder1Id, (ushort)AssetType.Animation, rootFolder.ID);
325 Assert.That(myScene.InventoryService.GetFolder(myFolder), Is.Not.Null);
326
327 // Test purge
328 userInfo.PurgeFolder(rootFolder.ID);
329
330 Assert.That(rootFolder.RequestListOfFolders(), Is.Empty);
331 Assert.That(myScene.InventoryService.GetFolder(myFolder), Is.Null);
332 }
333
334 [TearDown]
335 public void TearDown()
336 {
337 try
338 {
339 if (MainServer.Instance != null) MainServer.Instance.Stop();
340 }
341 catch (System.NullReferenceException)
342 { }
343 }
344 }
345} \ No newline at end of file
diff --git a/OpenSim/Framework/Communications/Tests/LoginServiceTests.cs b/OpenSim/Framework/Communications/Tests/LoginServiceTests.cs
deleted file mode 100644
index a274ae7..0000000
--- a/OpenSim/Framework/Communications/Tests/LoginServiceTests.cs
+++ /dev/null
@@ -1,453 +0,0 @@
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
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Net;
32using System.Text.RegularExpressions;
33using NUnit.Framework;
34using NUnit.Framework.SyntaxHelpers;
35using Nwc.XmlRpc;
36using OpenSim.Framework.Communications.Cache;
37using OpenSim.Framework.Communications.Services;
38using OpenSim.Region.Communications.Local;
39using OpenSim.Tests.Common.Setup;
40using OpenSim.Tests.Common.Mock;
41using OpenSim.Client.Linden;
42using OpenSim.Tests.Common;
43using OpenSim.Services.Interfaces;
44using OpenMetaverse;
45
46namespace OpenSim.Framework.Communications.Tests
47{
48 /// <summary>
49 /// Test the login service. For now, most of this will be done through the LocalLoginService as LoginService
50 /// is abstract
51 /// </summary>
52
53 [TestFixture]
54 public class LoginServiceTests
55 {
56 private string m_firstName = "Adam";
57 private string m_lastName = "West";
58 private string m_regionExternalName = "localhost";
59
60 private IPEndPoint m_capsEndPoint;
61 private TestCommunicationsManager m_commsManager;
62 private TestLoginToRegionConnector m_regionConnector;
63 private LocalUserServices m_localUserServices;
64 private LoginService m_loginService;
65 private UserProfileData m_userProfileData;
66 private TestScene m_testScene;
67
68 [SetUp]
69 public void SetUpLoginEnviroment()
70 {
71 m_capsEndPoint = new IPEndPoint(IPAddress.Loopback, 9123);
72 m_commsManager = new TestCommunicationsManager(new NetworkServersInfo(42, 43));
73 m_regionConnector = new TestLoginToRegionConnector();
74 m_testScene = SceneSetupHelpers.SetupScene(m_commsManager, "");
75
76 m_regionConnector.AddRegion(new RegionInfo(42, 43, m_capsEndPoint, m_regionExternalName));
77
78 //IInventoryService m_inventoryService = new MockInventoryService();
79
80 m_localUserServices = (LocalUserServices) m_commsManager.UserService;
81 m_localUserServices.AddUser(m_firstName,m_lastName,"boingboing","abc@ftw.com",42,43);
82
83 m_loginService = new LLStandaloneLoginService((UserManagerBase) m_localUserServices, "Hello folks", m_testScene.InventoryService,
84 m_commsManager.NetworkServersInfo, true, new LibraryRootFolder(String.Empty), m_regionConnector);
85
86 m_userProfileData = m_localUserServices.GetUserProfile(m_firstName, m_lastName);
87 }
88
89 /// <summary>
90 /// Test the normal response to a login. Does not test authentication.
91 /// </summary>
92 [Test]
93 public void T010_TestUnauthenticatedLogin()
94 {
95 TestHelper.InMethod();
96 // We want to use our own LoginService for this test, one that
97 // doesn't require authentication.
98 new LLStandaloneLoginService(
99 (UserManagerBase)m_commsManager.UserService, "Hello folks", new MockInventoryService(),
100 m_commsManager.NetworkServersInfo, false, new LibraryRootFolder(String.Empty), m_regionConnector);
101
102 Hashtable loginParams = new Hashtable();
103 loginParams["first"] = m_firstName;
104 loginParams["last"] = m_lastName;
105 loginParams["passwd"] = "boingboing";
106
107 ArrayList sendParams = new ArrayList();
108 sendParams.Add(loginParams);
109 sendParams.Add(m_capsEndPoint); // is this parameter correct?
110 sendParams.Add(new Uri("http://localhost:8002/")); // is this parameter correct?
111
112 XmlRpcRequest request = new XmlRpcRequest("login_to_simulator", sendParams);
113
114 IPAddress tmpLocal = Util.GetLocalHost();
115 IPEndPoint tmpEnd = new IPEndPoint(tmpLocal, 80);
116 XmlRpcResponse response = m_loginService.XmlRpcLoginMethod(request, tmpEnd);
117
118 Hashtable responseData = (Hashtable)response.Value;
119
120 Assert.That(responseData["first_name"], Is.EqualTo(m_firstName));
121 Assert.That(responseData["last_name"], Is.EqualTo(m_lastName));
122 Assert.That(
123 responseData["circuit_code"], Is.GreaterThanOrEqualTo(0) & Is.LessThanOrEqualTo(Int32.MaxValue));
124
125 Regex capsSeedPattern
126 = new Regex("^http://"
127 + NetworkUtil.GetHostFor(tmpLocal, m_regionExternalName)
128 + ":9000/CAPS/[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}0000/$");
129
130 Assert.That(capsSeedPattern.IsMatch((string)responseData["seed_capability"]), Is.True);
131 }
132
133 [Test]
134 public void T011_TestAuthenticatedLoginSuccess()
135 {
136 TestHelper.InMethod();
137 // TODO: Not check inventory part of response yet.
138 // TODO: Not checking all of login response thoroughly yet.
139
140 // 1) Test for positive authentication
141
142 Hashtable loginParams = new Hashtable();
143 loginParams["first"] = m_firstName;
144 loginParams["last"] = m_lastName;
145 loginParams["passwd"] = "boingboing";
146
147 ArrayList sendParams = new ArrayList();
148 sendParams.Add(loginParams);
149 sendParams.Add(m_capsEndPoint); // is this parameter correct?
150 sendParams.Add(new Uri("http://localhost:8002/")); // is this parameter correct?
151
152 XmlRpcRequest request = new XmlRpcRequest("login_to_simulator", sendParams);
153
154 IPAddress tmpLocal = Util.GetLocalHost();
155 IPEndPoint tmpEnd = new IPEndPoint(tmpLocal, 80);
156 XmlRpcResponse response = m_loginService.XmlRpcLoginMethod(request, tmpEnd);
157
158 Hashtable responseData = (Hashtable)response.Value;
159
160 UserAgentData uagent = m_userProfileData.CurrentAgent;
161 Assert.That(uagent,Is.Not.Null);
162
163 Assert.That(responseData["first_name"], Is.Not.Null);
164 Assert.That(responseData["first_name"], Is.EqualTo(m_firstName));
165 Assert.That(responseData["last_name"], Is.EqualTo(m_lastName));
166 Assert.That(responseData["agent_id"], Is.EqualTo(uagent.ProfileID.ToString()));
167 Assert.That(responseData["session_id"], Is.EqualTo(uagent.SessionID.ToString()));
168 Assert.That(responseData["secure_session_id"], Is.EqualTo(uagent.SecureSessionID.ToString()));
169 ArrayList invlibroot = (ArrayList) responseData["inventory-lib-root"];
170 Hashtable invlibroothash = (Hashtable) invlibroot[0];
171 Assert.That(invlibroothash["folder_id"],Is.EqualTo("00000112-000f-0000-0000-000100bba000"));
172 Assert.That(
173 responseData["circuit_code"], Is.GreaterThanOrEqualTo(0) & Is.LessThanOrEqualTo(Int32.MaxValue));
174 Assert.That(responseData["message"], Is.EqualTo("Hello folks"));
175 Assert.That(responseData["buddy-list"], Is.Empty);
176 Assert.That(responseData["start_location"], Is.EqualTo("last"));
177
178 Regex capsSeedPattern
179 = new Regex("^http://"
180 + NetworkUtil.GetHostFor(tmpLocal, m_regionExternalName)
181 + ":9000/CAPS/[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}0000/$");
182
183 Assert.That(capsSeedPattern.IsMatch((string)responseData["seed_capability"]), Is.True);
184 }
185
186 [Test]
187 public void T012_TestAuthenticatedLoginForBuddies()
188 {
189 TestHelper.InMethod();
190 // 1.1) Test for budddies!
191 m_localUserServices.AddUser("Friend","Number1","boingboing","abc@ftw.com",42,43);
192 m_localUserServices.AddUser("Friend","Number2","boingboing","abc@ftw.com",42,43);
193
194 UserProfileData friend1 = m_localUserServices.GetUserProfile("Friend","Number1");
195 UserProfileData friend2 = m_localUserServices.GetUserProfile("Friend","Number2");
196 m_localUserServices.AddNewUserFriend(friend1.ID,m_userProfileData.ID,1);
197 m_localUserServices.AddNewUserFriend(friend1.ID,friend2.ID,2);
198
199 Hashtable loginParams = new Hashtable();
200 loginParams["first"] = "Friend";
201 loginParams["last"] = "Number1";
202 loginParams["passwd"] = "boingboing";
203
204 ArrayList sendParams = new ArrayList();
205 sendParams.Add(loginParams);
206 sendParams.Add(m_capsEndPoint); // is this parameter correct?
207 sendParams.Add(new Uri("http://localhost:8002/")); // is this parameter correct?
208
209 XmlRpcRequest request = new XmlRpcRequest("login_to_simulator", sendParams);
210
211 IPAddress tmpLocal = Util.GetLocalHost();
212 IPEndPoint tmpEnd = new IPEndPoint(tmpLocal, 80);
213 XmlRpcResponse response = m_loginService.XmlRpcLoginMethod(request, tmpEnd);
214
215 Hashtable responseData = (Hashtable)response.Value;
216
217 ArrayList friendslist = (ArrayList) responseData["buddy-list"];
218
219 Assert.That(friendslist,Is.Not.Null);
220
221 Hashtable buddy1 = (Hashtable) friendslist[0];
222 Hashtable buddy2 = (Hashtable) friendslist[1];
223 Assert.That(friendslist.Count, Is.EqualTo(2));
224 Assert.That(m_userProfileData.ID.ToString(), Is.EqualTo(buddy1["buddy_id"]) | Is.EqualTo(buddy2["buddy_id"]));
225 Assert.That(friend2.ID.ToString(), Is.EqualTo(buddy1["buddy_id"]) | Is.EqualTo(buddy2["buddy_id"]));
226 }
227
228 [Test]
229 public void T020_TestAuthenticatedLoginBadUsername()
230 {
231 TestHelper.InMethod();
232
233 // 2) Test for negative authentication
234 //
235 string error_auth_message = "Could not authenticate your avatar. Please check your username and password, and check the grid if problems persist.";
236 //string error_region_unavailable = "The region you are attempting to log into is not responding. Please select another region and try again.";
237 // 2.1) Test for wrong user name
238 Hashtable loginParams = new Hashtable();
239 loginParams["first"] = m_lastName;
240 loginParams["last"] = m_firstName;
241 loginParams["passwd"] = "boingboing";
242
243 ArrayList sendParams = new ArrayList();
244 sendParams.Add(loginParams);
245 sendParams.Add(m_capsEndPoint); // is this parameter correct?
246 sendParams.Add(new Uri("http://localhost:8002/")); // is this parameter correct?
247
248 XmlRpcRequest request = new XmlRpcRequest("login_to_simulator", sendParams);
249
250 IPAddress tmpLocal = Util.GetLocalHost();
251 IPEndPoint tmpEnd = new IPEndPoint(tmpLocal, 80);
252 XmlRpcResponse response = m_loginService.XmlRpcLoginMethod(request, tmpEnd);
253
254 Hashtable responseData = (Hashtable)response.Value;
255 Assert.That(responseData["message"], Is.EqualTo(error_auth_message));
256
257 }
258
259 [Test]
260 public void T021_TestAuthenticatedLoginBadPassword()
261 {
262 TestHelper.InMethod();
263
264 string error_auth_message = "Could not authenticate your avatar. Please check your username and password, and check the grid if problems persist.";
265 // 2.2) Test for wrong password
266 Hashtable loginParams = new Hashtable();
267 loginParams["first"] = "Friend";
268 loginParams["last"] = "Number2";
269 loginParams["passwd"] = "boing";
270
271 ArrayList sendParams = new ArrayList();
272 sendParams.Add(loginParams);
273 sendParams.Add(m_capsEndPoint); // is this parameter correct?
274 sendParams.Add(new Uri("http://localhost:8002/")); // is this parameter correct?
275
276 XmlRpcRequest request = new XmlRpcRequest("login_to_simulator", sendParams);
277
278 IPAddress tmpLocal = Util.GetLocalHost();
279 IPEndPoint tmpEnd = new IPEndPoint(tmpLocal, 80);
280 XmlRpcResponse response = m_loginService.XmlRpcLoginMethod(request, tmpEnd);
281
282 Hashtable responseData = (Hashtable)response.Value;
283 Assert.That(responseData["message"], Is.EqualTo(error_auth_message));
284
285 }
286
287 [Test]
288 public void T022_TestAuthenticatedLoginBadXml()
289 {
290 TestHelper.InMethod();
291
292 string error_xml_message = "Error connecting to grid. Could not percieve credentials from login XML.";
293 // 2.3) Bad XML
294 Hashtable loginParams = new Hashtable();
295 loginParams["first"] = "Friend";
296 loginParams["banana"] = "Banana";
297 loginParams["passwd"] = "boingboing";
298
299 ArrayList sendParams = new ArrayList();
300 sendParams.Add(loginParams);
301 sendParams.Add(m_capsEndPoint); // is this parameter correct?
302 sendParams.Add(new Uri("http://localhost:8002/")); // is this parameter correct?
303
304 XmlRpcRequest request = new XmlRpcRequest("login_to_simulator", sendParams);
305
306 IPAddress tmpLocal = Util.GetLocalHost();
307 IPEndPoint tmpEnd = new IPEndPoint(tmpLocal, 80);
308 XmlRpcResponse response = m_loginService.XmlRpcLoginMethod(request, tmpEnd);
309
310 Hashtable responseData = (Hashtable)response.Value;
311 Assert.That(responseData["message"], Is.EqualTo(error_xml_message));
312
313 }
314
315 // [Test]
316 // Commenting out test now that LLStandAloneLoginService no longer replies with message in this case.
317 // Kept the code for future test with grid mode, which will keep this behavior.
318 public void T023_TestAuthenticatedLoginAlreadyLoggedIn()
319 {
320 TestHelper.InMethod();
321
322 //Console.WriteLine("Starting T023_TestAuthenticatedLoginAlreadyLoggedIn()");
323 //log4net.Config.XmlConfigurator.Configure();
324
325 string error_already_logged = "You appear to be already logged in. " +
326 "If this is not the case please wait for your session to timeout. " +
327 "If this takes longer than a few minutes please contact the grid owner. " +
328 "Please wait 5 minutes if you are going to connect to a region nearby to the region you were at previously.";
329 // 2.4) Already logged in and sucessfull post login
330 Hashtable loginParams = new Hashtable();
331 loginParams["first"] = "Adam";
332 loginParams["last"] = "West";
333 loginParams["passwd"] = "boingboing";
334
335 ArrayList sendParams = new ArrayList();
336 sendParams.Add(loginParams);
337 sendParams.Add(m_capsEndPoint); // is this parameter correct?
338 sendParams.Add(new Uri("http://localhost:8002/")); // is this parameter correct?
339
340 // First we log in.
341 XmlRpcRequest request = new XmlRpcRequest("login_to_simulator", sendParams);
342
343 IPAddress tmpLocal = Util.GetLocalHost();
344 IPEndPoint tmpEnd = new IPEndPoint(tmpLocal, 80);
345 XmlRpcResponse response = m_loginService.XmlRpcLoginMethod(request, tmpEnd);
346
347 Hashtable responseData = (Hashtable)response.Value;
348 Assert.That(responseData["message"], Is.EqualTo("Hello folks"));
349
350 // Then we try again, this time expecting failure.
351 request = new XmlRpcRequest("login_to_simulator", sendParams);
352 response = m_loginService.XmlRpcLoginMethod(request, tmpEnd);
353 responseData = (Hashtable)response.Value;
354 Assert.That(responseData["message"], Is.EqualTo(error_already_logged));
355
356 // Finally the third time we should be able to get right back in.
357 request = new XmlRpcRequest("login_to_simulator", sendParams);
358
359 response = m_loginService.XmlRpcLoginMethod(request, tmpEnd);
360 responseData = (Hashtable)response.Value;
361 Assert.That(responseData["message"], Is.EqualTo("Hello folks"));
362
363 //Console.WriteLine("Finished T023_TestAuthenticatedLoginAlreadyLoggedIn()");
364 }
365
366 [TearDown]
367 public void TearDown()
368 {
369 try
370 {
371 if (MainServer.Instance != null) MainServer.Instance.Stop();
372 } catch (NullReferenceException)
373 {}
374 }
375
376 public class TestLoginToRegionConnector : ILoginServiceToRegionsConnector
377 {
378 private List<RegionInfo> m_regionsList = new List<RegionInfo>();
379
380 public void AddRegion(RegionInfo regionInfo)
381 {
382 lock (m_regionsList)
383 {
384 if (!m_regionsList.Contains(regionInfo))
385 {
386 m_regionsList.Add(regionInfo);
387 }
388 }
389 }
390
391 public void LogOffUserFromGrid(ulong regionHandle, OpenMetaverse.UUID AvatarID, OpenMetaverse.UUID RegionSecret, string message)
392 {
393 }
394
395 public bool NewUserConnection(ulong regionHandle, AgentCircuitData agent, out string reason)
396 {
397 reason = String.Empty;
398 lock (m_regionsList)
399 {
400 foreach (RegionInfo regInfo in m_regionsList)
401 {
402 if (regInfo.RegionHandle == regionHandle)
403 return true;
404 }
405 }
406 reason = "Region not found";
407 return false;
408 }
409
410 public RegionInfo RequestClosestRegion(string region)
411 {
412 lock (m_regionsList)
413 {
414 foreach (RegionInfo regInfo in m_regionsList)
415 {
416 if (regInfo.RegionName == region)
417 return regInfo;
418 }
419 }
420
421 return null;
422 }
423
424 public RegionInfo RequestNeighbourInfo(OpenMetaverse.UUID regionID)
425 {
426 lock (m_regionsList)
427 {
428 foreach (RegionInfo regInfo in m_regionsList)
429 {
430 if (regInfo.RegionID == regionID)
431 return regInfo;
432 }
433 }
434
435 return null;
436 }
437
438 public RegionInfo RequestNeighbourInfo(ulong regionHandle)
439 {
440 lock (m_regionsList)
441 {
442 foreach (RegionInfo regInfo in m_regionsList)
443 {
444 if (regInfo.RegionHandle == regionHandle)
445 return regInfo;
446 }
447 }
448
449 return null;
450 }
451 }
452 }
453}
diff --git a/OpenSim/Framework/Communications/UserManagerBase.cs b/OpenSim/Framework/Communications/UserManagerBase.cs
deleted file mode 100644
index 02be141..0000000
--- a/OpenSim/Framework/Communications/UserManagerBase.cs
+++ /dev/null
@@ -1,930 +0,0 @@
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
28using System;
29using System.Collections.Generic;
30using System.Net;
31using System.Reflection;
32using System.Security.Cryptography;
33using log4net;
34using Nwc.XmlRpc;
35using OpenMetaverse;
36using OpenMetaverse.StructuredData;
37using OpenSim.Data;
38using OpenSim.Framework.Communications;
39using OpenSim.Framework.Statistics;
40using OpenSim.Services.Interfaces;
41
42namespace OpenSim.Framework.Communications
43{
44 /// <summary>
45 /// Base class for user management (create, read, etc)
46 /// </summary>
47 public abstract class UserManagerBase
48 : IUserService, IUserAdminService, IAvatarService, IMessagingService, IAuthentication
49 {
50 private static readonly ILog m_log
51 = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
52
53 /// <value>
54 /// List of plugins to search for user data
55 /// </value>
56 private List<IUserDataPlugin> m_plugins = new List<IUserDataPlugin>();
57
58 protected CommunicationsManager m_commsManager;
59 protected IInventoryService m_InventoryService;
60
61 /// <summary>
62 /// Constructor
63 /// </summary>
64 /// <param name="commsManager"></param>
65 public UserManagerBase(CommunicationsManager commsManager)
66 {
67 m_commsManager = commsManager;
68 }
69
70 public virtual void SetInventoryService(IInventoryService invService)
71 {
72 m_InventoryService = invService;
73 }
74
75 /// <summary>
76 /// Add a new user data plugin - plugins will be requested in the order they were added.
77 /// </summary>
78 /// <param name="plugin">The plugin that will provide user data</param>
79 public void AddPlugin(IUserDataPlugin plugin)
80 {
81 m_plugins.Add(plugin);
82 }
83
84 /// <summary>
85 /// Adds a list of user data plugins, as described by `provider' and
86 /// `connect', to `_plugins'.
87 /// </summary>
88 /// <param name="provider">
89 /// The filename of the inventory server plugin DLL.
90 /// </param>
91 /// <param name="connect">
92 /// The connection string for the storage backend.
93 /// </param>
94 public void AddPlugin(string provider, string connect)
95 {
96 m_plugins.AddRange(DataPluginFactory.LoadDataPlugins<IUserDataPlugin>(provider, connect));
97 }
98
99 #region UserProfile
100
101 public virtual void AddTemporaryUserProfile(UserProfileData userProfile)
102 {
103 foreach (IUserDataPlugin plugin in m_plugins)
104 {
105 plugin.AddTemporaryUserProfile(userProfile);
106 }
107 }
108
109 public virtual UserProfileData GetUserProfile(string fname, string lname)
110 {
111 foreach (IUserDataPlugin plugin in m_plugins)
112 {
113 UserProfileData profile = plugin.GetUserByName(fname, lname);
114
115 if (profile != null)
116 {
117 profile.CurrentAgent = GetUserAgent(profile.ID);
118 return profile;
119 }
120 }
121
122 return null;
123 }
124
125 public void LogoutUsers(UUID regionID)
126 {
127 foreach (IUserDataPlugin plugin in m_plugins)
128 {
129 plugin.LogoutUsers(regionID);
130 }
131 }
132
133 public void ResetAttachments(UUID userID)
134 {
135 foreach (IUserDataPlugin plugin in m_plugins)
136 {
137 plugin.ResetAttachments(userID);
138 }
139 }
140
141 public UserProfileData GetUserProfile(Uri uri)
142 {
143 foreach (IUserDataPlugin plugin in m_plugins)
144 {
145 UserProfileData profile = plugin.GetUserByUri(uri);
146
147 if (null != profile)
148 return profile;
149 }
150
151 return null;
152 }
153
154 public virtual UserAgentData GetAgentByUUID(UUID userId)
155 {
156 foreach (IUserDataPlugin plugin in m_plugins)
157 {
158 UserAgentData agent = plugin.GetAgentByUUID(userId);
159
160 if (agent != null)
161 {
162 return agent;
163 }
164 }
165
166 return null;
167 }
168
169 public Uri GetUserUri(UserProfileData userProfile)
170 {
171 throw new NotImplementedException();
172 }
173
174 // see IUserService
175 public virtual UserProfileData GetUserProfile(UUID uuid)
176 {
177 foreach (IUserDataPlugin plugin in m_plugins)
178 {
179 UserProfileData profile = plugin.GetUserByUUID(uuid);
180
181 if (null != profile)
182 {
183 profile.CurrentAgent = GetUserAgent(profile.ID);
184 return profile;
185 }
186 }
187
188 return null;
189 }
190
191 public virtual List<AvatarPickerAvatar> GenerateAgentPickerRequestResponse(UUID queryID, string query)
192 {
193 List<AvatarPickerAvatar> allPickerList = new List<AvatarPickerAvatar>();
194
195 foreach (IUserDataPlugin plugin in m_plugins)
196 {
197 try
198 {
199 List<AvatarPickerAvatar> pickerList = plugin.GeneratePickerResults(queryID, query);
200 if (pickerList != null)
201 allPickerList.AddRange(pickerList);
202 }
203 catch (Exception)
204 {
205 m_log.Error(
206 "[USERSTORAGE]: Unable to generate AgentPickerData via " + plugin.Name + "(" + query + ")");
207 }
208 }
209
210 return allPickerList;
211 }
212
213 public virtual bool UpdateUserProfile(UserProfileData data)
214 {
215 bool result = false;
216
217 foreach (IUserDataPlugin plugin in m_plugins)
218 {
219 try
220 {
221 plugin.UpdateUserProfile(data);
222 result = true;
223 }
224 catch (Exception e)
225 {
226 m_log.ErrorFormat(
227 "[USERSTORAGE]: Unable to set user {0} {1} via {2}: {3}",
228 data.FirstName, data.SurName, plugin.Name, e.ToString());
229 }
230 }
231
232 return result;
233 }
234
235 #endregion
236
237 #region Get UserAgent
238
239 /// <summary>
240 /// Loads a user agent by uuid (not called directly)
241 /// </summary>
242 /// <param name="uuid">The agent's UUID</param>
243 /// <returns>Agent profiles</returns>
244 public UserAgentData GetUserAgent(UUID uuid)
245 {
246 foreach (IUserDataPlugin plugin in m_plugins)
247 {
248 try
249 {
250 UserAgentData result = plugin.GetAgentByUUID(uuid);
251
252 if (result != null)
253 return result;
254 }
255 catch (Exception e)
256 {
257 m_log.Error("[USERSTORAGE]: Unable to find user via " + plugin.Name + "(" + e.ToString() + ")");
258 }
259 }
260
261 return null;
262 }
263
264 /// <summary>
265 /// Loads a user agent by name (not called directly)
266 /// </summary>
267 /// <param name="name">The agent's name</param>
268 /// <returns>A user agent</returns>
269 public UserAgentData GetUserAgent(string name)
270 {
271 foreach (IUserDataPlugin plugin in m_plugins)
272 {
273 try
274 {
275 UserAgentData result = plugin.GetAgentByName(name);
276
277 if (result != null)
278 return result;
279 }
280 catch (Exception e)
281 {
282 m_log.Error("[USERSTORAGE]: Unable to find user via " + plugin.Name + "(" + e.ToString() + ")");
283 }
284 }
285
286 return null;
287 }
288
289 /// <summary>
290 /// Loads a user agent by name (not called directly)
291 /// </summary>
292 /// <param name="fname">The agent's firstname</param>
293 /// <param name="lname">The agent's lastname</param>
294 /// <returns>A user agent</returns>
295 public UserAgentData GetUserAgent(string fname, string lname)
296 {
297 foreach (IUserDataPlugin plugin in m_plugins)
298 {
299 try
300 {
301 UserAgentData result = plugin.GetAgentByName(fname, lname);
302
303 if (result != null)
304 return result;
305 }
306 catch (Exception e)
307 {
308 m_log.Error("[USERSTORAGE]: Unable to find user via " + plugin.Name + "(" + e.ToString() + ")");
309 }
310 }
311
312 return null;
313 }
314
315 public virtual List<FriendListItem> GetUserFriendList(UUID ownerID)
316 {
317 List<FriendListItem> allFriends = new List<FriendListItem>();
318
319 foreach (IUserDataPlugin plugin in m_plugins)
320 {
321 try
322 {
323 List<FriendListItem> friends = plugin.GetUserFriendList(ownerID);
324
325 if (friends != null)
326 allFriends.AddRange(friends);
327 }
328 catch (Exception e)
329 {
330 m_log.Error("[USERSTORAGE]: Unable to GetUserFriendList via " + plugin.Name + "(" + e.ToString() + ")");
331 }
332 }
333
334 return allFriends;
335 }
336
337 public virtual Dictionary<UUID, FriendRegionInfo> GetFriendRegionInfos (List<UUID> uuids)
338 {
339 //Dictionary<UUID, FriendRegionInfo> allFriendRegions = new Dictionary<UUID, FriendRegionInfo>();
340
341 foreach (IUserDataPlugin plugin in m_plugins)
342 {
343 try
344 {
345 Dictionary<UUID, FriendRegionInfo> friendRegions = plugin.GetFriendRegionInfos(uuids);
346
347 if (friendRegions != null)
348 return friendRegions;
349 }
350 catch (Exception e)
351 {
352 m_log.Error("[USERSTORAGE]: Unable to GetFriendRegionInfos via " + plugin.Name + "(" + e.ToString() + ")");
353 }
354 }
355
356 return new Dictionary<UUID, FriendRegionInfo>();
357 }
358
359 public void StoreWebLoginKey(UUID agentID, UUID webLoginKey)
360 {
361 foreach (IUserDataPlugin plugin in m_plugins)
362 {
363 try
364 {
365 plugin.StoreWebLoginKey(agentID, webLoginKey);
366 }
367 catch (Exception e)
368 {
369 m_log.Error("[USERSTORAGE]: Unable to Store WebLoginKey via " + plugin.Name + "(" + e.ToString() + ")");
370 }
371 }
372 }
373
374 public virtual void AddNewUserFriend(UUID friendlistowner, UUID friend, uint perms)
375 {
376 foreach (IUserDataPlugin plugin in m_plugins)
377 {
378 try
379 {
380 plugin.AddNewUserFriend(friendlistowner, friend, perms);
381 }
382 catch (Exception e)
383 {
384 m_log.Error("[USERSTORAGE]: Unable to AddNewUserFriend via " + plugin.Name + "(" + e.ToString() + ")");
385 }
386 }
387 }
388
389 public virtual void RemoveUserFriend(UUID friendlistowner, UUID friend)
390 {
391 foreach (IUserDataPlugin plugin in m_plugins)
392 {
393 try
394 {
395 plugin.RemoveUserFriend(friendlistowner, friend);
396 }
397 catch (Exception e)
398 {
399 m_log.Error("[USERSTORAGE]: Unable to RemoveUserFriend via " + plugin.Name + "(" + e.ToString() + ")");
400 }
401 }
402 }
403
404 public virtual void UpdateUserFriendPerms(UUID friendlistowner, UUID friend, uint perms)
405 {
406 foreach (IUserDataPlugin plugin in m_plugins)
407 {
408 try
409 {
410 plugin.UpdateUserFriendPerms(friendlistowner, friend, perms);
411 }
412 catch (Exception e)
413 {
414 m_log.Error("[USERSTORAGE]: Unable to UpdateUserFriendPerms via " + plugin.Name + "(" + e.ToString() + ")");
415 }
416 }
417 }
418
419 /// <summary>
420 /// Resets the currentAgent in the user profile
421 /// </summary>
422 /// <param name="agentID">The agent's ID</param>
423 public virtual void ClearUserAgent(UUID agentID)
424 {
425 UserProfileData profile = GetUserProfile(agentID);
426
427 if (profile == null)
428 {
429 return;
430 }
431
432 profile.CurrentAgent = null;
433
434 UpdateUserProfile(profile);
435 }
436
437 #endregion
438
439 #region CreateAgent
440
441 /// <summary>
442 /// Creates and initialises a new user agent - make sure to use CommitAgent when done to submit to the DB
443 /// </summary>
444 /// <param name="profile">The users profile</param>
445 /// <param name="request">The users loginrequest</param>
446 public void CreateAgent(UserProfileData profile, XmlRpcRequest request)
447 {
448 //m_log.DebugFormat("[USER MANAGER]: Creating agent {0} {1}", profile.Name, profile.ID);
449
450 UserAgentData agent = new UserAgentData();
451
452 // User connection
453 agent.AgentOnline = true;
454
455 if (request.Params.Count > 1)
456 {
457 if (request.Params[1] != null)
458 {
459 IPEndPoint RemoteIPEndPoint = (IPEndPoint)request.Params[1];
460 agent.AgentIP = RemoteIPEndPoint.Address.ToString();
461 agent.AgentPort = (uint)RemoteIPEndPoint.Port;
462 }
463 }
464
465 // Generate sessions
466 RNGCryptoServiceProvider rand = new RNGCryptoServiceProvider();
467 byte[] randDataS = new byte[16];
468 byte[] randDataSS = new byte[16];
469 rand.GetBytes(randDataS);
470 rand.GetBytes(randDataSS);
471
472 agent.SecureSessionID = new UUID(randDataSS, 0);
473 agent.SessionID = new UUID(randDataS, 0);
474
475 // Profile UUID
476 agent.ProfileID = profile.ID;
477
478 // Current location/position/alignment
479 if (profile.CurrentAgent != null)
480 {
481 agent.Region = profile.CurrentAgent.Region;
482 agent.Handle = profile.CurrentAgent.Handle;
483 agent.Position = profile.CurrentAgent.Position;
484 agent.LookAt = profile.CurrentAgent.LookAt;
485 }
486 else
487 {
488 agent.Region = profile.HomeRegionID;
489 agent.Handle = profile.HomeRegion;
490 agent.Position = profile.HomeLocation;
491 agent.LookAt = profile.HomeLookAt;
492 }
493
494 // What time did the user login?
495 agent.LoginTime = Util.UnixTimeSinceEpoch();
496 agent.LogoutTime = 0;
497
498 profile.CurrentAgent = agent;
499 }
500
501 public void CreateAgent(UserProfileData profile, OSD request)
502 {
503 //m_log.DebugFormat("[USER MANAGER]: Creating agent {0} {1}", profile.Name, profile.ID);
504
505 UserAgentData agent = new UserAgentData();
506
507 // User connection
508 agent.AgentOnline = true;
509
510 //if (request.Params.Count > 1)
511 //{
512 // IPEndPoint RemoteIPEndPoint = (IPEndPoint)request.Params[1];
513 // agent.AgentIP = RemoteIPEndPoint.Address.ToString();
514 // agent.AgentPort = (uint)RemoteIPEndPoint.Port;
515 //}
516
517 // Generate sessions
518 RNGCryptoServiceProvider rand = new RNGCryptoServiceProvider();
519 byte[] randDataS = new byte[16];
520 byte[] randDataSS = new byte[16];
521 rand.GetBytes(randDataS);
522 rand.GetBytes(randDataSS);
523
524 agent.SecureSessionID = new UUID(randDataSS, 0);
525 agent.SessionID = new UUID(randDataS, 0);
526
527 // Profile UUID
528 agent.ProfileID = profile.ID;
529
530 // Current location/position/alignment
531 if (profile.CurrentAgent != null)
532 {
533 agent.Region = profile.CurrentAgent.Region;
534 agent.Handle = profile.CurrentAgent.Handle;
535 agent.Position = profile.CurrentAgent.Position;
536 agent.LookAt = profile.CurrentAgent.LookAt;
537 }
538 else
539 {
540 agent.Region = profile.HomeRegionID;
541 agent.Handle = profile.HomeRegion;
542 agent.Position = profile.HomeLocation;
543 agent.LookAt = profile.HomeLookAt;
544 }
545
546 // What time did the user login?
547 agent.LoginTime = Util.UnixTimeSinceEpoch();
548 agent.LogoutTime = 0;
549
550 profile.CurrentAgent = agent;
551 }
552
553 /// <summary>
554 /// Saves a target agent to the database
555 /// </summary>
556 /// <param name="profile">The users profile</param>
557 /// <returns>Successful?</returns>
558 public bool CommitAgent(ref UserProfileData profile)
559 {
560 //m_log.DebugFormat("[USER MANAGER]: Committing agent {0} {1}", profile.Name, profile.ID);
561
562 // TODO: how is this function different from setUserProfile? -> Add AddUserAgent() here and commit both tables "users" and "agents"
563 // TODO: what is the logic should be?
564 bool ret = false;
565 ret = AddUserAgent(profile.CurrentAgent);
566 ret = ret & UpdateUserProfile(profile);
567 return ret;
568 }
569
570 /// <summary>
571 /// Process a user logoff from OpenSim.
572 /// </summary>
573 /// <param name="userid"></param>
574 /// <param name="regionid"></param>
575 /// <param name="regionhandle"></param>
576 /// <param name="position"></param>
577 /// <param name="lookat"></param>
578 public virtual void LogOffUser(UUID userid, UUID regionid, ulong regionhandle, Vector3 position, Vector3 lookat)
579 {
580 if (StatsManager.UserStats != null)
581 StatsManager.UserStats.AddLogout();
582
583 UserProfileData userProfile = GetUserProfile(userid);
584
585 if (userProfile != null)
586 {
587 UserAgentData userAgent = userProfile.CurrentAgent;
588 if (userAgent != null)
589 {
590 userAgent.AgentOnline = false;
591 userAgent.LogoutTime = Util.UnixTimeSinceEpoch();
592 //userAgent.sessionID = UUID.Zero;
593 if (regionid != UUID.Zero)
594 {
595 userAgent.Region = regionid;
596 }
597 userAgent.Handle = regionhandle;
598 userAgent.Position = position;
599 userAgent.LookAt = lookat;
600 //userProfile.CurrentAgent = userAgent;
601 userProfile.LastLogin = userAgent.LogoutTime;
602
603 CommitAgent(ref userProfile);
604 }
605 else
606 {
607 // If currentagent is null, we can't reference it here or the UserServer crashes!
608 m_log.Info("[LOGOUT]: didn't save logout position: " + userid.ToString());
609 }
610 }
611 else
612 {
613 m_log.Warn("[LOGOUT]: Unknown User logged out");
614 }
615 }
616
617 public void LogOffUser(UUID userid, UUID regionid, ulong regionhandle, float posx, float posy, float posz)
618 {
619 LogOffUser(userid, regionid, regionhandle, new Vector3(posx, posy, posz), new Vector3());
620 }
621
622 #endregion
623
624 /// <summary>
625 /// Add a new user
626 /// </summary>
627 /// <param name="firstName">first name</param>
628 /// <param name="lastName">last name</param>
629 /// <param name="password">password</param>
630 /// <param name="email">email</param>
631 /// <param name="regX">location X</param>
632 /// <param name="regY">location Y</param>
633 /// <returns>The UUID of the created user profile. On failure, returns UUID.Zero</returns>
634 public virtual UUID AddUser(string firstName, string lastName, string password, string email, uint regX, uint regY)
635 {
636 return AddUser(firstName, lastName, password, email, regX, regY, UUID.Random());
637 }
638
639 /// <summary>
640 /// Add a new user
641 /// </summary>
642 /// <param name="firstName">first name</param>
643 /// <param name="lastName">last name</param>
644 /// <param name="password">password</param>
645 /// <param name="email">email</param>
646 /// <param name="regX">location X</param>
647 /// <param name="regY">location Y</param>
648 /// <param name="SetUUID">UUID of avatar.</param>
649 /// <returns>The UUID of the created user profile. On failure, returns UUID.Zero</returns>
650 public virtual UUID AddUser(
651 string firstName, string lastName, string password, string email, uint regX, uint regY, UUID SetUUID)
652 {
653
654 UserProfileData user = new UserProfileData();
655
656 user.PasswordSalt = Util.Md5Hash(UUID.Random().ToString());
657 string md5PasswdHash = Util.Md5Hash(Util.Md5Hash(password) + ":" + user.PasswordSalt);
658
659 user.HomeLocation = new Vector3(128, 128, 100);
660 user.ID = SetUUID;
661 user.FirstName = firstName;
662 user.SurName = lastName;
663 user.PasswordHash = md5PasswdHash;
664 user.Created = Util.UnixTimeSinceEpoch();
665 user.HomeLookAt = new Vector3(100, 100, 100);
666 user.HomeRegionX = regX;
667 user.HomeRegionY = regY;
668 user.Email = email;
669
670 foreach (IUserDataPlugin plugin in m_plugins)
671 {
672 try
673 {
674 plugin.AddNewUserProfile(user);
675 }
676 catch (Exception e)
677 {
678 m_log.Error("[USERSTORAGE]: Unable to add user via " + plugin.Name + "(" + e.ToString() + ")");
679 }
680 }
681
682 UserProfileData userProf = GetUserProfile(firstName, lastName);
683 if (userProf == null)
684 {
685 return UUID.Zero;
686 }
687 else
688 {
689 //
690 // WARNING: This is a horrible hack
691 // The purpose here is to avoid touching the user server at this point.
692 // There are dragons there that I can't deal with right now.
693 // diva 06/09/09
694 //
695 if (m_InventoryService != null)
696 {
697 // local service (standalone)
698 m_log.Debug("[USERSTORAGE]: using IInventoryService to create user's inventory");
699 m_InventoryService.CreateUserInventory(userProf.ID);
700 }
701 else if (m_commsManager.InterServiceInventoryService != null)
702 {
703 // used by the user server
704 m_log.Debug("[USERSTORAGE]: using m_commsManager.InterServiceInventoryService to create user's inventory");
705 m_commsManager.InterServiceInventoryService.CreateNewUserInventory(userProf.ID);
706 }
707
708 return userProf.ID;
709 }
710 }
711
712 /// <summary>
713 /// Reset a user password.
714 /// </summary>
715 /// <param name="firstName"></param>
716 /// <param name="lastName"></param>
717 /// <param name="newPassword"></param>
718 /// <returns>true if the update was successful, false otherwise</returns>
719 public virtual bool ResetUserPassword(string firstName, string lastName, string newPassword)
720 {
721 string md5PasswdHash = Util.Md5Hash(Util.Md5Hash(newPassword) + ":" + String.Empty);
722
723 UserProfileData profile = GetUserProfile(firstName, lastName);
724
725 if (null == profile)
726 {
727 m_log.ErrorFormat("[USERSTORAGE]: Could not find user {0} {1}", firstName, lastName);
728 return false;
729 }
730
731 profile.PasswordHash = md5PasswdHash;
732 profile.PasswordSalt = String.Empty;
733
734 UpdateUserProfile(profile);
735
736 return true;
737 }
738
739 public abstract UserProfileData SetupMasterUser(string firstName, string lastName);
740 public abstract UserProfileData SetupMasterUser(string firstName, string lastName, string password);
741 public abstract UserProfileData SetupMasterUser(UUID uuid);
742
743 /// <summary>
744 /// Add an agent using data plugins.
745 /// </summary>
746 /// <param name="agentdata">The agent data to be added</param>
747 /// <returns>
748 /// true if at least one plugin added the user agent. false if no plugin successfully added the agent
749 /// </returns>
750 public virtual bool AddUserAgent(UserAgentData agentdata)
751 {
752 bool result = false;
753
754 foreach (IUserDataPlugin plugin in m_plugins)
755 {
756 try
757 {
758 plugin.AddNewUserAgent(agentdata);
759 result = true;
760 }
761 catch (Exception e)
762 {
763 m_log.Error("[USERSTORAGE]: Unable to add agent via " + plugin.Name + "(" + e.ToString() + ")");
764 }
765 }
766
767 return result;
768 }
769
770 /// <summary>
771 /// Get avatar appearance information
772 /// </summary>
773 /// <param name="user"></param>
774 /// <returns></returns>
775 public virtual AvatarAppearance GetUserAppearance(UUID user)
776 {
777 foreach (IUserDataPlugin plugin in m_plugins)
778 {
779 try
780 {
781 AvatarAppearance appearance = plugin.GetUserAppearance(user);
782
783 if (appearance != null)
784 return appearance;
785 }
786 catch (Exception e)
787 {
788 m_log.ErrorFormat(
789 "[USERSTORAGE]: Unable to find user appearance {0} via {1} ({2})", user, plugin.Name, e);
790 }
791 }
792
793 return null;
794 }
795
796 public virtual void UpdateUserAppearance(UUID user, AvatarAppearance appearance)
797 {
798 foreach (IUserDataPlugin plugin in m_plugins)
799 {
800 try
801 {
802 plugin.UpdateUserAppearance(user, appearance);
803 }
804 catch (Exception e)
805 {
806 m_log.ErrorFormat("[USERSTORAGE]: Unable to update user appearance {0} via {1} ({2})", user.ToString(), plugin.Name, e.ToString());
807 }
808 }
809 }
810
811 #region IAuthentication
812
813 protected Dictionary<UUID, List<string>> m_userKeys = new Dictionary<UUID, List<string>>();
814
815 /// <summary>
816 /// This generates authorization keys in the form
817 /// http://userserver/uuid
818 /// after verifying that the caller is, indeed, authorized to request a key
819 /// </summary>
820 /// <param name="url">URL of the user server</param>
821 /// <param name="userID">The user ID requesting the new key</param>
822 /// <param name="authToken">The original authorization token for that user, obtained during login</param>
823 /// <returns></returns>
824 public string GetNewKey(string url, UUID userID, UUID authToken)
825 {
826 UserProfileData profile = GetUserProfile(userID);
827 string newKey = string.Empty;
828 if (!url.EndsWith("/"))
829 url = url + "/";
830
831 if (profile != null)
832 {
833 // I'm overloading webloginkey for this, so that no changes are needed in the DB
834 // The uses of webloginkey are fairly mutually exclusive
835 if (profile.WebLoginKey.Equals(authToken))
836 {
837 newKey = UUID.Random().ToString();
838 List<string> keys;
839 lock (m_userKeys)
840 {
841 if (m_userKeys.ContainsKey(userID))
842 {
843 keys = m_userKeys[userID];
844 }
845 else
846 {
847 keys = new List<string>();
848 m_userKeys.Add(userID, keys);
849 }
850 keys.Add(newKey);
851 }
852 m_log.InfoFormat("[USERAUTH]: Successfully generated new auth key for user {0}", userID);
853 }
854 else
855 m_log.Warn("[USERAUTH]: Unauthorized key generation request. Denying new key.");
856 }
857 else
858 m_log.Warn("[USERAUTH]: User not found.");
859
860 return url + newKey;
861 }
862
863 /// <summary>
864 /// This verifies the uuid portion of the key given out by GenerateKey
865 /// </summary>
866 /// <param name="userID"></param>
867 /// <param name="key"></param>
868 /// <returns></returns>
869 public bool VerifyKey(UUID userID, string key)
870 {
871 lock (m_userKeys)
872 {
873 if (m_userKeys.ContainsKey(userID))
874 {
875 List<string> keys = m_userKeys[userID];
876 if (keys.Contains(key))
877 {
878 // Keys are one-time only, so remove it
879 keys.Remove(key);
880 return true;
881 }
882 return false;
883 }
884 else
885 return false;
886 }
887 }
888
889 public virtual bool VerifySession(UUID userID, UUID sessionID)
890 {
891 UserProfileData userProfile = GetUserProfile(userID);
892
893 if (userProfile != null && userProfile.CurrentAgent != null)
894 {
895 m_log.DebugFormat(
896 "[USER AUTH]: Verifying session {0} for {1}; current session {2}",
897 sessionID, userID, userProfile.CurrentAgent.SessionID);
898
899 if (userProfile.CurrentAgent.SessionID == sessionID)
900 {
901 return true;
902 }
903 }
904
905 return false;
906 }
907
908 public virtual bool AuthenticateUserByPassword(UUID userID, string password)
909 {
910// m_log.DebugFormat("[USER AUTH]: Authenticating user {0} given password {1}", userID, password);
911
912 UserProfileData userProfile = GetUserProfile(userID);
913
914 if (null == userProfile)
915 return false;
916
917 string md5PasswordHash = Util.Md5Hash(Util.Md5Hash(password) + ":" + userProfile.PasswordSalt);
918
919// m_log.DebugFormat(
920// "[USER AUTH]: Submitted hash {0}, stored hash {1}", md5PasswordHash, userProfile.PasswordHash);
921
922 if (md5PasswordHash == userProfile.PasswordHash)
923 return true;
924 else
925 return false;
926 }
927
928 #endregion
929 }
930}