aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/Avatar/UserProfiles
diff options
context:
space:
mode:
authorBlueWall2013-05-13 22:11:28 -0400
committerBlueWall2013-05-30 17:59:18 -0400
commit328883700a15e4216bf7b251ac099d38f413375e (patch)
treefc90ce9fe8f7b1c5caca393144eac5b2824a9f3a /OpenSim/Region/CoreModules/Avatar/UserProfiles
parentminor: fix warnings in GodsModule that were due to duplicate using statements (diff)
downloadopensim-SC_OLD-328883700a15e4216bf7b251ac099d38f413375e.zip
opensim-SC_OLD-328883700a15e4216bf7b251ac099d38f413375e.tar.gz
opensim-SC_OLD-328883700a15e4216bf7b251ac099d38f413375e.tar.bz2
opensim-SC_OLD-328883700a15e4216bf7b251ac099d38f413375e.tar.xz
UserProfiles
UserProfiles for Robust and Standalone. Includes service and connectors for Robust and standalone opensim plus matching region module.
Diffstat (limited to 'OpenSim/Region/CoreModules/Avatar/UserProfiles')
-rw-r--r--OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs1386
1 files changed, 1386 insertions, 0 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs b/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs
new file mode 100644
index 0000000..563617d
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs
@@ -0,0 +1,1386 @@
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.IO;
30using System.Text;
31using System.Collections;
32using System.Collections.Generic;
33using System.Globalization;
34using System.Net;
35using System.Net.Sockets;
36using System.Reflection;
37using System.Xml;
38using OpenMetaverse;
39using OpenMetaverse.StructuredData;
40using log4net;
41using Nini.Config;
42using Nwc.XmlRpc;
43using OpenSim.Framework;
44using OpenSim.Region.Framework.Interfaces;
45using OpenSim.Region.Framework.Scenes;
46using OpenSim.Services.Interfaces;
47using Mono.Addins;
48using OpenSim.Services.Connectors.Hypergrid;
49
50namespace OpenSim.Region.OptionalModules.Avatar.UserProfiles
51{
52 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "UserProfilesModule")]
53 public class UserProfileModule : IProfileModule, INonSharedRegionModule
54 {
55 /// <summary>
56 /// Logging
57 /// </summary>
58 static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
59
60 // The pair of Dictionaries are used to handle the switching of classified ads
61 // by maintaining a cache of classified id to creator id mappings and an interest
62 // count. The entries are removed when the interest count reaches 0.
63 Dictionary<UUID,UUID> classifiedCache = new Dictionary<UUID, UUID>();
64 Dictionary<UUID,int> classifiedInterest = new Dictionary<UUID, int>();
65
66 public Scene Scene
67 {
68 get; private set;
69 }
70
71 /// <summary>
72 /// Gets or sets the ConfigSource.
73 /// </summary>
74 /// <value>
75 /// The configuration
76 /// </value>
77 public IConfigSource Config {
78 get;
79 set;
80 }
81
82 /// <summary>
83 /// Gets or sets the URI to the profile server.
84 /// </summary>
85 /// <value>
86 /// The profile server URI.
87 /// </value>
88 public string ProfileServerUri {
89 get;
90 set;
91 }
92
93 IProfileModule ProfileModule
94 {
95 get; set;
96 }
97
98 IUserManagement UserManagementModule
99 {
100 get; set;
101 }
102
103 /// <summary>
104 /// Gets or sets a value indicating whether this
105 /// <see cref="BlueWall.SlipStream.ProfileModule.UserProfileModule"/> is enabled.
106 /// </summary>
107 /// <value>
108 /// <c>true</c> if enabled; otherwise, <c>false</c>.
109 /// </value>
110 public bool Enabled {
111 get;
112 set;
113 }
114
115 #region IRegionModuleBase implementation
116 /// <summary>
117 /// This is called to initialize the region module. For shared modules, this is called exactly once, after
118 /// creating the single (shared) instance. For non-shared modules, this is called once on each instance, after
119 /// the instace for the region has been created.
120 /// </summary>
121 /// <param name='source'>
122 /// Source.
123 /// </param>
124 public void Initialise(IConfigSource source)
125 {
126 Config = source;
127
128 IConfig profileConfig = Config.Configs["Profile"];
129
130 if (profileConfig == null)
131 {
132 Enabled = false;
133 return;
134 }
135
136 // If we find ProfileURL then we configure for FULL support
137 // else we setup for BASIC support
138 ProfileServerUri = profileConfig.GetString("ProfileURL", "");
139 if (ProfileServerUri == "")
140 {
141 m_log.Info("[PROFILES] UserProfiles module is activated in BASIC mode");
142 Enabled = false;
143 return;
144 }
145 else
146 {
147 m_log.Info("[PROFILES] UserProfiles module is activated in FULL mode");
148 Enabled = true;
149 }
150 }
151
152 /// <summary>
153 /// Adds the region.
154 /// </summary>
155 /// <param name='scene'>
156 /// Scene.
157 /// </param>
158 public void AddRegion(Scene scene)
159 {
160 Scene = scene;
161 Scene.RegisterModuleInterface<IProfileModule>(this);
162 Scene.EventManager.OnNewClient += OnNewClient;
163 Scene.EventManager.OnMakeRootAgent += HandleOnMakeRootAgent;
164
165 UserManagementModule = Scene.RequestModuleInterface<IUserManagement>();
166 }
167
168 void HandleOnMakeRootAgent (ScenePresence obj)
169 {
170 GetImageAssets(((IScenePresence)obj).UUID);
171 }
172
173 /// <summary>
174 /// Removes the region.
175 /// </summary>
176 /// <param name='scene'>
177 /// Scene.
178 /// </param>
179 public void RemoveRegion(Scene scene)
180 {
181 }
182
183 /// <summary>
184 /// This will be called once for every scene loaded. In a shared module this will be multiple times in one
185 /// instance, while a nonshared module instance will only be called once. This method is called after AddRegion
186 /// has been called in all modules for that scene, providing an opportunity to request another module's
187 /// interface, or hook an event from another module.
188 /// </summary>
189 /// <param name='scene'>
190 /// Scene.
191 /// </param>
192 public void RegionLoaded(Scene scene)
193 {
194 }
195
196 /// <summary>
197 /// If this returns non-null, it is the type of an interface that this module intends to register. This will
198 /// cause the loader to defer loading of this module until all other modules have been loaded. If no other
199 /// module has registered the interface by then, this module will be activated, else it will remain inactive,
200 /// letting the other module take over. This should return non-null ONLY in modules that are intended to be
201 /// easily replaceable, e.g. stub implementations that the developer expects to be replaced by third party
202 /// provided modules.
203 /// </summary>
204 /// <value>
205 /// The replaceable interface.
206 /// </value>
207 public Type ReplaceableInterface
208 {
209 get { return typeof(IProfileModule); }
210 }
211
212 /// <summary>
213 /// Called as the instance is closed.
214 /// </summary>
215 public void Close()
216 {
217 }
218
219 /// <value>
220 /// The name of the module
221 /// </value>
222 /// <summary>
223 /// Gets the module name.
224 /// </summary>
225 public string Name
226 {
227 get { return "UserProfileModule"; }
228 }
229 #endregion IRegionModuleBase implementation
230
231 #region Region Event Handlers
232 /// <summary>
233 /// Raises the new client event.
234 /// </summary>
235 /// <param name='client'>
236 /// Client.
237 /// </param>
238 void OnNewClient(IClientAPI client)
239 {
240 // Basic or Full module?
241 if(!Enabled)
242 {
243 client.OnRequestAvatarProperties += BasicRequestProperties;
244 return;
245 }
246
247 //Profile
248 client.OnRequestAvatarProperties += RequestAvatarProperties;
249 client.OnUpdateAvatarProperties += AvatarPropertiesUpdate;
250 client.OnAvatarInterestUpdate += AvatarInterestsUpdate;
251
252 // Classifieds
253 client.AddGenericPacketHandler("avatarclassifiedsrequest", ClassifiedsRequest);
254 client.OnClassifiedInfoUpdate += ClassifiedInfoUpdate;
255 client.OnClassifiedInfoRequest += ClassifiedInfoRequest;
256 client.OnClassifiedDelete += ClassifiedDelete;
257
258 // Picks
259 client.AddGenericPacketHandler("avatarpicksrequest", PicksRequest);
260 client.AddGenericPacketHandler("pickinforequest", PickInfoRequest);
261 client.OnPickInfoUpdate += PickInfoUpdate;
262 client.OnPickDelete += PickDelete;
263
264 // Notes
265 client.AddGenericPacketHandler("avatarnotesrequest", NotesRequest);
266 client.OnAvatarNotesUpdate += NotesUpdate;
267 }
268 #endregion Region Event Handlers
269
270 #region Classified
271 ///
272 /// <summary>
273 /// Handles the avatar classifieds request.
274 /// </summary>
275 /// <param name='sender'>
276 /// Sender.
277 /// </param>
278 /// <param name='method'>
279 /// Method.
280 /// </param>
281 /// <param name='args'>
282 /// Arguments.
283 /// </param>
284 public void ClassifiedsRequest(Object sender, string method, List<String> args)
285 {
286 if (!(sender is IClientAPI))
287 return;
288
289 IClientAPI remoteClient = (IClientAPI)sender;
290
291 UUID targetID;
292 UUID.TryParse(args[0], out targetID);
293
294 // Can't handle NPC yet...
295 ScenePresence p = FindPresence(targetID);
296
297 if (null != p)
298 {
299 if (p.PresenceType == PresenceType.Npc)
300 return;
301 }
302
303 string serverURI = string.Empty;
304 bool foreign = GetUserProfileServerURI(targetID, out serverURI);
305 UUID creatorId = UUID.Zero;
306
307 OSDMap parameters= new OSDMap();
308 UUID.TryParse(args[0], out creatorId);
309 parameters.Add("creatorId", OSD.FromUUID(creatorId));
310 OSD Params = (OSD)parameters;
311 if(!JsonRpcRequest(ref Params, "avatarclassifiedsrequest", serverURI, UUID.Random().ToString()))
312 {
313 // Error Handling here!
314 // if(parameters.ContainsKey("message")
315 }
316
317 parameters = (OSDMap)Params;
318
319 OSDArray list = (OSDArray)parameters["result"];
320
321 Dictionary<UUID, string> classifieds = new Dictionary<UUID, string>();
322
323 foreach(OSD map in list)
324 {
325 OSDMap m = (OSDMap)map;
326 UUID cid = m["classifieduuid"].AsUUID();
327 string name = m["name"].AsString();
328
329 classifieds[cid] = name;
330
331 if(!classifiedCache.ContainsKey(cid))
332 {
333 classifiedCache.Add(cid,creatorId);
334 classifiedInterest.Add(cid, 0);
335 }
336
337 classifiedInterest[cid] ++;
338 }
339
340 remoteClient.SendAvatarClassifiedReply(new UUID(args[0]), classifieds);
341 }
342
343 public void ClassifiedInfoRequest(UUID queryClassifiedID, IClientAPI remoteClient)
344 {
345 UUID target = remoteClient.AgentId;
346 UserClassifiedAdd ad = new UserClassifiedAdd();
347 ad.ClassifiedId = queryClassifiedID;
348
349 if(classifiedCache.ContainsKey(queryClassifiedID))
350 {
351 target = classifiedCache[queryClassifiedID];
352
353 if(classifiedInterest[queryClassifiedID] -- == 0)
354 {
355 lock(classifiedCache)
356 {
357 lock(classifiedInterest)
358 {
359 classifiedInterest.Remove(queryClassifiedID);
360 }
361 classifiedCache.Remove(queryClassifiedID);
362 }
363 }
364 }
365
366
367 string serverURI = string.Empty;
368 bool foreign = GetUserProfileServerURI(target, out serverURI);
369
370 object Ad = (object)ad;
371 if(!JsonRpcRequest(ref Ad, "classifieds_info_query", serverURI, UUID.Random().ToString()))
372 {
373 remoteClient.SendAgentAlertMessage(
374 "Error getting classified info", false);
375 return;
376 }
377 ad = (UserClassifiedAdd) Ad;
378
379 if(ad.CreatorId == UUID.Zero)
380 return;
381
382 Vector3 globalPos = new Vector3();
383 Vector3.TryParse(ad.GlobalPos, out globalPos);
384
385 remoteClient.SendClassifiedInfoReply(ad.ClassifiedId, ad.CreatorId, (uint)ad.CreationDate, (uint)ad.ExpirationDate,
386 (uint)ad.Category, ad.Name, ad.Description, ad.ParcelId, (uint)ad.ParentEstate,
387 ad.SnapshotId, ad.SimName, globalPos, ad.ParcelName, ad.Flags, ad.Price);
388
389 }
390
391 /// <summary>
392 /// Classifieds info update.
393 /// </summary>
394 /// <param name='queryclassifiedID'>
395 /// Queryclassified I.
396 /// </param>
397 /// <param name='queryCategory'>
398 /// Query category.
399 /// </param>
400 /// <param name='queryName'>
401 /// Query name.
402 /// </param>
403 /// <param name='queryDescription'>
404 /// Query description.
405 /// </param>
406 /// <param name='queryParcelID'>
407 /// Query parcel I.
408 /// </param>
409 /// <param name='queryParentEstate'>
410 /// Query parent estate.
411 /// </param>
412 /// <param name='querySnapshotID'>
413 /// Query snapshot I.
414 /// </param>
415 /// <param name='queryGlobalPos'>
416 /// Query global position.
417 /// </param>
418 /// <param name='queryclassifiedFlags'>
419 /// Queryclassified flags.
420 /// </param>
421 /// <param name='queryclassifiedPrice'>
422 /// Queryclassified price.
423 /// </param>
424 /// <param name='remoteClient'>
425 /// Remote client.
426 /// </param>
427 public void ClassifiedInfoUpdate(UUID queryclassifiedID, uint queryCategory, string queryName, string queryDescription, UUID queryParcelID,
428 uint queryParentEstate, UUID querySnapshotID, Vector3 queryGlobalPos, byte queryclassifiedFlags,
429 int queryclassifiedPrice, IClientAPI remoteClient)
430 {
431 UserClassifiedAdd ad = new UserClassifiedAdd();
432
433 Scene s = (Scene) remoteClient.Scene;
434 Vector3 pos = remoteClient.SceneAgent.AbsolutePosition;
435 ILandObject land = s.LandChannel.GetLandObject(pos.X, pos.Y);
436 ScenePresence p = FindPresence(remoteClient.AgentId);
437 Vector3 avaPos = p.AbsolutePosition;
438
439 string serverURI = string.Empty;
440 bool foreign = GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
441
442 if (land == null)
443 {
444 ad.ParcelName = string.Empty;
445 }
446 else
447 {
448 ad.ParcelName = land.LandData.Name;
449 }
450
451 ad.CreatorId = remoteClient.AgentId;
452 ad.ClassifiedId = queryclassifiedID;
453 ad.Category = Convert.ToInt32(queryCategory);
454 ad.Name = queryName;
455 ad.Description = queryDescription;
456 ad.ParentEstate = Convert.ToInt32(queryParentEstate);
457 ad.SnapshotId = querySnapshotID;
458 ad.SimName = remoteClient.Scene.RegionInfo.RegionName;
459 ad.GlobalPos = queryGlobalPos.ToString ();
460 ad.Flags = queryclassifiedFlags;
461 ad.Price = queryclassifiedPrice;
462 ad.ParcelId = p.currentParcelUUID;
463
464 object Ad = ad;
465
466 OSD X = OSD.SerializeMembers(Ad);
467
468 if(!JsonRpcRequest(ref Ad, "classified_update", serverURI, UUID.Random().ToString()))
469 {
470 remoteClient.SendAgentAlertMessage(
471 "Error updating classified", false);
472 }
473 }
474
475 /// <summary>
476 /// Classifieds delete.
477 /// </summary>
478 /// <param name='queryClassifiedID'>
479 /// Query classified I.
480 /// </param>
481 /// <param name='remoteClient'>
482 /// Remote client.
483 /// </param>
484 public void ClassifiedDelete(UUID queryClassifiedID, IClientAPI remoteClient)
485 {
486 string serverURI = string.Empty;
487 bool foreign = GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
488
489 UUID classifiedId;
490 OSDMap parameters= new OSDMap();
491 UUID.TryParse(queryClassifiedID.ToString(), out classifiedId);
492 parameters.Add("classifiedId", OSD.FromUUID(classifiedId));
493 OSD Params = (OSD)parameters;
494 if(!JsonRpcRequest(ref Params, "classified_delete", serverURI, UUID.Random().ToString()))
495 {
496 remoteClient.SendAgentAlertMessage(
497 "Error classified delete", false);
498 }
499
500 parameters = (OSDMap)Params;
501 }
502 #endregion Classified
503
504 #region Picks
505 /// <summary>
506 /// Handles the avatar picks request.
507 /// </summary>
508 /// <param name='sender'>
509 /// Sender.
510 /// </param>
511 /// <param name='method'>
512 /// Method.
513 /// </param>
514 /// <param name='args'>
515 /// Arguments.
516 /// </param>
517 public void PicksRequest(Object sender, string method, List<String> args)
518 {
519 if (!(sender is IClientAPI))
520 return;
521
522 IClientAPI remoteClient = (IClientAPI)sender;
523
524 UUID targetId;
525 UUID.TryParse(args[0], out targetId);
526
527 // Can't handle NPC yet...
528 ScenePresence p = FindPresence(targetId);
529
530 if (null != p)
531 {
532 if (p.PresenceType == PresenceType.Npc)
533 return;
534 }
535
536 string serverURI = string.Empty;
537 bool foreign = GetUserProfileServerURI(targetId, out serverURI);
538
539 OSDMap parameters= new OSDMap();
540 parameters.Add("creatorId", OSD.FromUUID(targetId));
541 OSD Params = (OSD)parameters;
542 if(!JsonRpcRequest(ref Params, "avatarpicksrequest", serverURI, UUID.Random().ToString()))
543 {
544 remoteClient.SendAgentAlertMessage(
545 "Error requesting picks", false);
546 return;
547 }
548
549 parameters = (OSDMap)Params;
550
551 OSDArray list = (OSDArray)parameters["result"];
552
553 Dictionary<UUID, string> picks = new Dictionary<UUID, string>();
554
555 foreach(OSD map in list)
556 {
557 OSDMap m = (OSDMap)map;
558 UUID cid = m["pickuuid"].AsUUID();
559 string name = m["name"].AsString();
560
561 m_log.DebugFormat("[PROFILES]: PicksRequest {0}", name);
562
563 picks[cid] = name;
564 }
565 remoteClient.SendAvatarPicksReply(new UUID(args[0]), picks);
566 }
567
568 /// <summary>
569 /// Handles the pick info request.
570 /// </summary>
571 /// <param name='sender'>
572 /// Sender.
573 /// </param>
574 /// <param name='method'>
575 /// Method.
576 /// </param>
577 /// <param name='args'>
578 /// Arguments.
579 /// </param>
580 public void PickInfoRequest(Object sender, string method, List<String> args)
581 {
582 if (!(sender is IClientAPI))
583 return;
584
585 UUID targetID;
586 UUID.TryParse(args[0], out targetID);
587 string serverURI = string.Empty;
588 bool foreign = GetUserProfileServerURI(targetID, out serverURI);
589 IClientAPI remoteClient = (IClientAPI)sender;
590
591 UserProfilePick pick = new UserProfilePick();
592 UUID.TryParse(args[0], out pick.CreatorId);
593 UUID.TryParse(args[1], out pick.PickId);
594
595
596 object Pick = (object)pick;
597 if(!JsonRpcRequest(ref Pick, "pickinforequest", serverURI, UUID.Random().ToString()))
598 {
599 remoteClient.SendAgentAlertMessage(
600 "Error selecting pick", false);
601 }
602 pick = (UserProfilePick) Pick;
603 if(pick.SnapshotId == UUID.Zero)
604 {
605 // In case of a new UserPick, the data may not be ready and we would send wrong data, skip it...
606 m_log.DebugFormat("[PROFILES]: PickInfoRequest: SnapshotID is {0}", UUID.Zero.ToString());
607 return;
608 }
609
610 Vector3 globalPos;
611 Vector3.TryParse(pick.GlobalPos,out globalPos);
612
613 m_log.DebugFormat("[PROFILES]: PickInfoRequest: {0} : {1}", pick.Name.ToString(), pick.SnapshotId.ToString());
614
615 remoteClient.SendPickInfoReply(pick.PickId,pick.CreatorId,pick.TopPick,pick.ParcelId,pick.Name,
616 pick.Desc,pick.SnapshotId,pick.User,pick.OriginalName,pick.SimName,
617 globalPos,pick.SortOrder,pick.Enabled);
618 }
619
620 /// <summary>
621 /// Updates the userpicks
622 /// </summary>
623 /// <param name='remoteClient'>
624 /// Remote client.
625 /// </param>
626 /// <param name='pickID'>
627 /// Pick I.
628 /// </param>
629 /// <param name='creatorID'>
630 /// the creator of the pick
631 /// </param>
632 /// <param name='topPick'>
633 /// Top pick.
634 /// </param>
635 /// <param name='name'>
636 /// Name.
637 /// </param>
638 /// <param name='desc'>
639 /// Desc.
640 /// </param>
641 /// <param name='snapshotID'>
642 /// Snapshot I.
643 /// </param>
644 /// <param name='sortOrder'>
645 /// Sort order.
646 /// </param>
647 /// <param name='enabled'>
648 /// Enabled.
649 /// </param>
650 public void PickInfoUpdate(IClientAPI remoteClient, UUID pickID, UUID creatorID, bool topPick, string name, string desc, UUID snapshotID, int sortOrder, bool enabled)
651 {
652
653 m_log.DebugFormat("[PROFILES]: Start PickInfoUpdate Name: {0} PickId: {1} SnapshotId: {2}", name, pickID.ToString(), snapshotID.ToString());
654 UserProfilePick pick = new UserProfilePick();
655 string serverURI = string.Empty;
656 bool foreign = GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
657 ScenePresence p = FindPresence(remoteClient.AgentId);
658
659 Vector3 avaPos = p.AbsolutePosition;
660 // Getting the global position for the Avatar
661 Vector3 posGlobal = new Vector3(remoteClient.Scene.RegionInfo.RegionLocX*Constants.RegionSize + avaPos.X,
662 remoteClient.Scene.RegionInfo.RegionLocY*Constants.RegionSize + avaPos.Y,
663 avaPos.Z);
664
665 string landOwnerName = string.Empty;
666 ILandObject land = p.Scene.LandChannel.GetLandObject(avaPos.X, avaPos.Y);
667 if(land.LandData.IsGroupOwned)
668 {
669 IGroupsModule groupMod = p.Scene.RequestModuleInterface<IGroupsModule>();
670 UUID groupId = land.LandData.GroupID;
671 GroupRecord groupRecord = groupMod.GetGroupRecord(groupId);
672 landOwnerName = groupRecord.GroupName;
673 }
674 else
675 {
676 IUserAccountService accounts = p.Scene.RequestModuleInterface<IUserAccountService>();
677 UserAccount user = accounts.GetUserAccount(p.Scene.RegionInfo.ScopeID, land.LandData.OwnerID);
678 landOwnerName = user.Name;
679 }
680
681 pick.PickId = pickID;
682 pick.CreatorId = creatorID;
683 pick.TopPick = topPick;
684 pick.Name = name;
685 pick.Desc = desc;
686 pick.ParcelId = p.currentParcelUUID;
687 pick.SnapshotId = snapshotID;
688 pick.User = landOwnerName;
689 pick.SimName = remoteClient.Scene.RegionInfo.RegionName;
690 pick.GlobalPos = posGlobal.ToString();
691 pick.SortOrder = sortOrder;
692 pick.Enabled = enabled;
693
694 object Pick = (object)pick;
695 if(!JsonRpcRequest(ref Pick, "picks_update", serverURI, UUID.Random().ToString()))
696 {
697 remoteClient.SendAgentAlertMessage(
698 "Error updating pick", false);
699 }
700
701 m_log.DebugFormat("[PROFILES]: Finish PickInfoUpdate {0} {1}", pick.Name, pick.PickId.ToString());
702 }
703
704 /// <summary>
705 /// Delete a Pick
706 /// </summary>
707 /// <param name='remoteClient'>
708 /// Remote client.
709 /// </param>
710 /// <param name='queryPickID'>
711 /// Query pick I.
712 /// </param>
713 public void PickDelete(IClientAPI remoteClient, UUID queryPickID)
714 {
715 string serverURI = string.Empty;
716 bool foreign = GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
717
718 OSDMap parameters= new OSDMap();
719 parameters.Add("pickId", OSD.FromUUID(queryPickID));
720 OSD Params = (OSD)parameters;
721 if(!JsonRpcRequest(ref Params, "picks_delete", serverURI, UUID.Random().ToString()))
722 {
723 remoteClient.SendAgentAlertMessage(
724 "Error picks delete", false);
725 }
726 }
727 #endregion Picks
728
729 #region Notes
730 /// <summary>
731 /// Handles the avatar notes request.
732 /// </summary>
733 /// <param name='sender'>
734 /// Sender.
735 /// </param>
736 /// <param name='method'>
737 /// Method.
738 /// </param>
739 /// <param name='args'>
740 /// Arguments.
741 /// </param>
742 public void NotesRequest(Object sender, string method, List<String> args)
743 {
744 UserProfileNotes note = new UserProfileNotes();
745
746 if (!(sender is IClientAPI))
747 return;
748
749 IClientAPI remoteClient = (IClientAPI)sender;
750 string serverURI = string.Empty;
751 bool foreign = GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
752 note.TargetId = remoteClient.AgentId;
753 UUID.TryParse(args[0], out note.UserId);
754
755 object Note = (object)note;
756 if(!JsonRpcRequest(ref Note, "avatarnotesrequest", serverURI, UUID.Random().ToString()))
757 {
758 remoteClient.SendAgentAlertMessage(
759 "Error requesting note", false);
760 }
761 note = (UserProfileNotes) Note;
762
763 remoteClient.SendAvatarNotesReply(note.TargetId, note.Notes);
764 }
765
766 /// <summary>
767 /// Avatars the notes update.
768 /// </summary>
769 /// <param name='remoteClient'>
770 /// Remote client.
771 /// </param>
772 /// <param name='queryTargetID'>
773 /// Query target I.
774 /// </param>
775 /// <param name='queryNotes'>
776 /// Query notes.
777 /// </param>
778 public void NotesUpdate(IClientAPI remoteClient, UUID queryTargetID, string queryNotes)
779 {
780 UserProfileNotes note = new UserProfileNotes();
781
782 note.UserId = remoteClient.AgentId;
783 note.TargetId = queryTargetID;
784 note.Notes = queryNotes;
785
786 string serverURI = string.Empty;
787 bool foreign = GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
788
789 object Note = note;
790 if(!JsonRpcRequest(ref Note, "avatar_notes_update", serverURI, UUID.Random().ToString()))
791 {
792 remoteClient.SendAgentAlertMessage(
793 "Error updating note", false);
794 }
795 }
796 #endregion Notes
797
798 #region Avatar Properties
799 /// <summary>
800 /// Update the avatars interests .
801 /// </summary>
802 /// <param name='remoteClient'>
803 /// Remote client.
804 /// </param>
805 /// <param name='wantmask'>
806 /// Wantmask.
807 /// </param>
808 /// <param name='wanttext'>
809 /// Wanttext.
810 /// </param>
811 /// <param name='skillsmask'>
812 /// Skillsmask.
813 /// </param>
814 /// <param name='skillstext'>
815 /// Skillstext.
816 /// </param>
817 /// <param name='languages'>
818 /// Languages.
819 /// </param>
820 public void AvatarInterestsUpdate(IClientAPI remoteClient, uint wantmask, string wanttext, uint skillsmask, string skillstext, string languages)
821 {
822 UserProfileProperties prop = new UserProfileProperties();
823
824 prop.UserId = remoteClient.AgentId;
825 prop.WantToMask = (int)wantmask;
826 prop.WantToText = wanttext;
827 prop.SkillsMask = (int)skillsmask;
828 prop.SkillsText = skillstext;
829 prop.Language = languages;
830
831 string serverURI = string.Empty;
832 bool foreign = GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
833
834 object Param = prop;
835 if(!JsonRpcRequest(ref Param, "avatar_interests_update", serverURI, UUID.Random().ToString()))
836 {
837 remoteClient.SendAgentAlertMessage(
838 "Error updating interests", false);
839 }
840 }
841
842 public void BasicRequestProperties(IClientAPI remoteClient, UUID avatarID)
843 {
844 IScene s = remoteClient.Scene;
845 if (!(s is Scene))
846 return;
847
848 string profileUrl = String.Empty;
849 string aboutText = String.Empty;
850 string firstLifeAboutText = String.Empty;
851 UUID image = UUID.Zero;
852 UUID firstLifeImage = UUID.Zero;
853 UUID partner = UUID.Zero;
854 uint wantMask = 0;
855 string wantText = String.Empty;
856 uint skillsMask = 0;
857 string skillsText = String.Empty;
858 string languages = String.Empty;
859
860 UserAccount account = Scene.UserAccountService.GetUserAccount(Scene.RegionInfo.ScopeID, avatarID);
861
862 string name = "Avatar";
863 int created = 0;
864 if (account != null)
865 {
866 name = account.FirstName + " " + account.LastName;
867 created = account.Created;
868 }
869 Byte[] charterMember = Utils.StringToBytes(name);
870
871 profileUrl = "No profile data";
872 aboutText = string.Empty;
873 firstLifeAboutText = string.Empty;
874 image = UUID.Zero;
875 firstLifeImage = UUID.Zero;
876 partner = UUID.Zero;
877
878 remoteClient.SendAvatarProperties(avatarID, aboutText,
879 Util.ToDateTime(created).ToString(
880 "M/d/yyyy", CultureInfo.InvariantCulture),
881 charterMember, firstLifeAboutText,
882 (uint)(0 & 0xff),
883 firstLifeImage, image, profileUrl, partner);
884
885 //Viewer expects interest data when it asks for properties.
886 remoteClient.SendAvatarInterestsReply(avatarID, wantMask, wantText,
887 skillsMask, skillsText, languages);
888 }
889
890 /// <summary>
891 /// Requests the avatar properties.
892 /// </summary>
893 /// <param name='remoteClient'>
894 /// Remote client.
895 /// </param>
896 /// <param name='avatarID'>
897 /// Avatar I.
898 /// </param>
899 public void RequestAvatarProperties(IClientAPI remoteClient, UUID avatarID)
900 {
901 if ( String.IsNullOrEmpty(avatarID.ToString()) || String.IsNullOrEmpty(remoteClient.AgentId.ToString()))
902 {
903 // Looking for a reason that some viewers are sending null Id's
904 m_log.DebugFormat("[PROFILES]: This should not happen remoteClient.AgentId {0} - avatarID {1}", remoteClient.AgentId, avatarID);
905 return;
906 }
907
908 // Can't handle NPC yet...
909 ScenePresence p = FindPresence(avatarID);
910
911 if (null != p)
912 {
913 if (p.PresenceType == PresenceType.Npc)
914 return;
915 }
916
917 string serverURI = string.Empty;
918 bool foreign = GetUserProfileServerURI(avatarID, out serverURI);
919
920 UserAccount account = null;
921 Dictionary<string,object> userInfo;
922
923 if (!foreign)
924 {
925 account = Scene.UserAccountService.GetUserAccount(Scene.RegionInfo.ScopeID, avatarID);
926 }
927 else
928 {
929 userInfo = new Dictionary<string, object>();
930 }
931
932 Byte[] charterMember = new Byte[1];
933 string born = String.Empty;
934 uint flags = 0x00;
935
936 if (null != account)
937 {
938 if (account.UserTitle == "")
939 {
940 charterMember[0] = (Byte)((account.UserFlags & 0xf00) >> 8);
941 }
942 else
943 {
944 charterMember = Utils.StringToBytes(account.UserTitle);
945 }
946
947 born = Util.ToDateTime(account.Created).ToString(
948 "M/d/yyyy", CultureInfo.InvariantCulture);
949 flags = (uint)(account.UserFlags & 0xff);
950 }
951 else
952 {
953 if (GetUserAccountData(avatarID, out userInfo) == true)
954 {
955 if ((string)userInfo["user_title"] == "")
956 {
957 charterMember[0] = (Byte)(((Byte)userInfo["user_flags"] & 0xf00) >> 8);
958 }
959 else
960 {
961 charterMember = Utils.StringToBytes((string)userInfo["user_title"]);
962 }
963
964 int val_born = (int)userInfo["user_created"];
965 born = Util.ToDateTime(val_born).ToString(
966 "M/d/yyyy", CultureInfo.InvariantCulture);
967
968 // picky, picky
969 int val_flags = (int)userInfo["user_flags"];
970 flags = (uint)(val_flags & 0xff);
971 }
972 }
973
974 UserProfileProperties props = new UserProfileProperties();
975 string result = string.Empty;
976
977 props.UserId = avatarID;
978 GetProfileData(ref props, out result);
979
980 remoteClient.SendAvatarProperties(props.UserId, props.AboutText, born, charterMember , props.FirstLifeText, flags,
981 props.FirstLifeImageId, props.ImageId, props.WebUrl, props.PartnerId);
982
983
984 remoteClient.SendAvatarInterestsReply(props.UserId, (uint)props.WantToMask, props.WantToText, (uint)props.SkillsMask,
985 props.SkillsText, props.Language);
986 }
987
988 /// <summary>
989 /// Updates the avatar properties.
990 /// </summary>
991 /// <param name='remoteClient'>
992 /// Remote client.
993 /// </param>
994 /// <param name='newProfile'>
995 /// New profile.
996 /// </param>
997 public void AvatarPropertiesUpdate(IClientAPI remoteClient, UserProfileData newProfile)
998 {
999 if (remoteClient.AgentId == newProfile.ID)
1000 {
1001 UserProfileProperties prop = new UserProfileProperties();
1002
1003 prop.UserId = remoteClient.AgentId;
1004 prop.WebUrl = newProfile.ProfileUrl;
1005 prop.ImageId = newProfile.Image;
1006 prop.AboutText = newProfile.AboutText;
1007 prop.FirstLifeImageId = newProfile.FirstLifeImage;
1008 prop.FirstLifeText = newProfile.FirstLifeAboutText;
1009
1010 string serverURI = string.Empty;
1011 bool foreign = GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
1012
1013 object Prop = prop;
1014
1015 if(!JsonRpcRequest(ref Prop, "avatar_properties_update", serverURI, UUID.Random().ToString()))
1016 {
1017 remoteClient.SendAgentAlertMessage(
1018 "Error updating properties", false);
1019 }
1020
1021 RequestAvatarProperties(remoteClient, newProfile.ID);
1022 }
1023 }
1024
1025
1026 /// <summary>
1027 /// Gets the profile data.
1028 /// </summary>
1029 /// <returns>
1030 /// The profile data.
1031 /// </returns>
1032 /// <param name='userID'>
1033 /// User I.
1034 /// </param>
1035 bool GetProfileData(ref UserProfileProperties properties, out string message)
1036 {
1037 // Can't handle NPC yet...
1038 ScenePresence p = FindPresence(properties.UserId);
1039
1040 if (null != p)
1041 {
1042 if (p.PresenceType == PresenceType.Npc)
1043 {
1044 message = "Id points to NPC";
1045 return false;
1046 }
1047 }
1048
1049 string serverURI = string.Empty;
1050 bool foreign = GetUserProfileServerURI(properties.UserId, out serverURI);
1051
1052 // This is checking a friend on the home grid
1053 // Not HG friend
1054 if ( String.IsNullOrEmpty(serverURI))
1055 {
1056 message = "No Presence - foreign friend";
1057 return false;
1058 }
1059
1060 object Prop = (object)properties;
1061 JsonRpcRequest(ref Prop, "avatar_properties_request", serverURI, UUID.Random().ToString());
1062 properties = (UserProfileProperties)Prop;
1063
1064 message = "Success";
1065 return true;
1066 }
1067 #endregion Avatar Properties
1068
1069 #region Utils
1070 bool GetImageAssets(UUID avatarId)
1071 {
1072 string profileServerURI = string.Empty;
1073 string assetServerURI = string.Empty;
1074
1075 bool foreign = GetUserProfileServerURI(avatarId, out profileServerURI);
1076
1077 if(!foreign)
1078 return true;
1079
1080 assetServerURI = UserManagementModule.GetUserServerURL(avatarId, "AssetServerURI");
1081
1082 OSDMap parameters= new OSDMap();
1083 parameters.Add("avatarId", OSD.FromUUID(avatarId));
1084 OSD Params = (OSD)parameters;
1085 if(!JsonRpcRequest(ref Params, "image_assets_request", profileServerURI, UUID.Random().ToString()))
1086 {
1087 // Error Handling here!
1088 // if(parameters.ContainsKey("message")
1089 return false;
1090 }
1091
1092 parameters = (OSDMap)Params;
1093
1094 OSDArray list = (OSDArray)parameters["result"];
1095
1096 foreach(OSD asset in list)
1097 {
1098 OSDString assetId = (OSDString)asset;
1099
1100 Scene.AssetService.Get(string.Format("{0}/{1}",assetServerURI, assetId.AsString()), this,
1101 delegate (string assetID, Object s, AssetBase a)
1102 {
1103 // m_log.DebugFormat("[PROFILES]: Getting Image Assets {0}", assetID);
1104 return;
1105 });
1106 }
1107 return true;
1108 }
1109
1110 /// <summary>
1111 /// Gets the user account data.
1112 /// </summary>
1113 /// <returns>
1114 /// The user profile data.
1115 /// </returns>
1116 /// <param name='userID'>
1117 /// If set to <c>true</c> user I.
1118 /// </param>
1119 /// <param name='userInfo'>
1120 /// If set to <c>true</c> user info.
1121 /// </param>
1122 bool GetUserAccountData(UUID userID, out Dictionary<string, object> userInfo)
1123 {
1124 Dictionary<string,object> info = new Dictionary<string, object>();
1125
1126 if (UserManagementModule.IsLocalGridUser(userID))
1127 {
1128 // Is local
1129 IUserAccountService uas = Scene.UserAccountService;
1130 UserAccount account = uas.GetUserAccount(Scene.RegionInfo.ScopeID, userID);
1131
1132 info["user_flags"] = account.UserFlags;
1133 info["user_created"] = account.Created;
1134
1135 if (!String.IsNullOrEmpty(account.UserTitle))
1136 info["user_title"] = account.UserTitle;
1137 else
1138 info["user_title"] = "";
1139
1140 userInfo = info;
1141
1142 return false;
1143 }
1144 else
1145 {
1146 // Is Foreign
1147 string home_url = UserManagementModule.GetUserServerURL(userID, "HomeURI");
1148
1149 if (String.IsNullOrEmpty(home_url))
1150 {
1151 info["user_flags"] = 0;
1152 info["user_created"] = 0;
1153 info["user_title"] = "Unavailable";
1154
1155 userInfo = info;
1156 return true;
1157 }
1158
1159 UserAgentServiceConnector uConn = new UserAgentServiceConnector(home_url);
1160
1161 Dictionary<string, object> account = uConn.GetUserInfo(userID);
1162
1163 if (account.Count > 0)
1164 {
1165 if (account.ContainsKey("user_flags"))
1166 info["user_flags"] = account["user_flags"];
1167 else
1168 info["user_flags"] = "";
1169
1170 if (account.ContainsKey("user_created"))
1171 info["user_created"] = account["user_created"];
1172 else
1173 info["user_created"] = "";
1174
1175 info["user_title"] = "HG Visitor";
1176 }
1177 else
1178 {
1179 info["user_flags"] = 0;
1180 info["user_created"] = 0;
1181 info["user_title"] = "HG Visitor";
1182 }
1183 userInfo = info;
1184 return true;
1185 }
1186 }
1187
1188 /// <summary>
1189 /// Gets the user profile server UR.
1190 /// </summary>
1191 /// <returns>
1192 /// The user profile server UR.
1193 /// </returns>
1194 /// <param name='userID'>
1195 /// If set to <c>true</c> user I.
1196 /// </param>
1197 /// <param name='serverURI'>
1198 /// If set to <c>true</c> server UR.
1199 /// </param>
1200 bool GetUserProfileServerURI(UUID userID, out string serverURI)
1201 {
1202 bool local;
1203 local = UserManagementModule.IsLocalGridUser(userID);
1204
1205 if (!local)
1206 {
1207 serverURI = UserManagementModule.GetUserServerURL(userID, "ProfileServerURI");
1208 // Is Foreign
1209 return true;
1210 }
1211 else
1212 {
1213 serverURI = ProfileServerUri;
1214 // Is local
1215 return false;
1216 }
1217 }
1218
1219 /// <summary>
1220 /// Finds the presence.
1221 /// </summary>
1222 /// <returns>
1223 /// The presence.
1224 /// </returns>
1225 /// <param name='clientID'>
1226 /// Client I.
1227 /// </param>
1228 ScenePresence FindPresence(UUID clientID)
1229 {
1230 ScenePresence p;
1231
1232 p = Scene.GetScenePresence(clientID);
1233 if (p != null && !p.IsChildAgent)
1234 return p;
1235
1236 return null;
1237 }
1238 #endregion Util
1239
1240 #region Web Util
1241 /// <summary>
1242 /// Sends json-rpc request with a serializable type.
1243 /// </summary>
1244 /// <returns>
1245 /// OSD Map.
1246 /// </returns>
1247 /// <param name='parameters'>
1248 /// Serializable type .
1249 /// </param>
1250 /// <param name='method'>
1251 /// Json-rpc method to call.
1252 /// </param>
1253 /// <param name='uri'>
1254 /// URI of json-rpc service.
1255 /// </param>
1256 /// <param name='jsonId'>
1257 /// Id for our call.
1258 /// </param>
1259 bool JsonRpcRequest(ref object parameters, string method, string uri, string jsonId)
1260 {
1261 if (jsonId == null)
1262 throw new ArgumentNullException ("jsonId");
1263 if (uri == null)
1264 throw new ArgumentNullException ("uri");
1265 if (method == null)
1266 throw new ArgumentNullException ("method");
1267 if (parameters == null)
1268 throw new ArgumentNullException ("parameters");
1269
1270 // Prep our payload
1271 OSDMap json = new OSDMap();
1272
1273 json.Add("jsonrpc", OSD.FromString("2.0"));
1274 json.Add("id", OSD.FromString(jsonId));
1275 json.Add("method", OSD.FromString(method));
1276 // Experiment
1277 json.Add("params", OSD.SerializeMembers(parameters));
1278
1279 string jsonRequestData = OSDParser.SerializeJsonString(json);
1280 byte[] content = Encoding.UTF8.GetBytes(jsonRequestData);
1281
1282 HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri);
1283 // webRequest.Credentials = new NetworkCredential(rpcUser, rpcPass);
1284 webRequest.ContentType = "application/json-rpc";
1285 webRequest.Method = "POST";
1286
1287 Stream dataStream = webRequest.GetRequestStream();
1288 dataStream.Write(content, 0, content.Length);
1289 dataStream.Close();
1290
1291 WebResponse webResponse = null;
1292 try
1293 {
1294 webResponse = webRequest.GetResponse();
1295 }
1296 catch (WebException e)
1297 {
1298 Console.WriteLine("Web Error" + e.Message);
1299 Console.WriteLine ("Please check input");
1300 return false;
1301 }
1302
1303 byte[] buf = new byte[8192];
1304 Stream rstream = webResponse.GetResponseStream();
1305 OSDMap mret = (OSDMap)OSDParser.DeserializeJson(rstream);
1306
1307 if(mret.ContainsKey("error"))
1308 return false;
1309
1310 // get params...
1311 OSD.DeserializeMembers(ref parameters, (OSDMap) mret["result"]);
1312 return true;
1313 }
1314
1315 /// <summary>
1316 /// Sends json-rpc request with OSD parameter.
1317 /// </summary>
1318 /// <returns>
1319 /// The rpc request.
1320 /// </returns>
1321 /// <param name='data'>
1322 /// data - incoming as parameters, outgong as result/error
1323 /// </param>
1324 /// <param name='method'>
1325 /// Json-rpc method to call.
1326 /// </param>
1327 /// <param name='uri'>
1328 /// URI of json-rpc service.
1329 /// </param>
1330 /// <param name='jsonId'>
1331 /// If set to <c>true</c> json identifier.
1332 /// </param>
1333 bool JsonRpcRequest(ref OSD data, string method, string uri, string jsonId)
1334 {
1335 OSDMap map = new OSDMap();
1336
1337 map["jsonrpc"] = "2.0";
1338 if(string.IsNullOrEmpty(jsonId))
1339 map["id"] = UUID.Random().ToString();
1340 else
1341 map["id"] = jsonId;
1342
1343 map["method"] = method;
1344 map["params"] = data;
1345
1346 string jsonRequestData = OSDParser.SerializeJsonString(map);
1347 byte[] content = Encoding.UTF8.GetBytes(jsonRequestData);
1348
1349 HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri);
1350 webRequest.ContentType = "application/json-rpc";
1351 webRequest.Method = "POST";
1352
1353 Stream dataStream = webRequest.GetRequestStream();
1354 dataStream.Write(content, 0, content.Length);
1355 dataStream.Close();
1356
1357 WebResponse webResponse = null;
1358 try
1359 {
1360 webResponse = webRequest.GetResponse();
1361 }
1362 catch (WebException e)
1363 {
1364 Console.WriteLine("Web Error" + e.Message);
1365 Console.WriteLine ("Please check input");
1366 return false;
1367 }
1368
1369 byte[] buf = new byte[8192];
1370 Stream rstream = webResponse.GetResponseStream();
1371
1372 OSDMap response = new OSDMap();
1373 response = (OSDMap)OSDParser.DeserializeJson(rstream);
1374 if(response.ContainsKey("error"))
1375 {
1376 data = response["error"];
1377 return false;
1378 }
1379
1380 data = response;
1381
1382 return true;
1383 }
1384 #endregion Web Util
1385 }
1386}