opensim – Blame information for rev 1

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