clockwerk-opensim-stable – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 vero 1 /*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27  
28 using System;
29 using System.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  
317 OSDMap parameters= new OSDMap();
318 UUID.TryParse(args[0], out creatorId);
319 parameters.Add("creatorId", OSD.FromUUID(creatorId));
320 OSD Params = (OSD)parameters;
321 if(!JsonRpcRequest(ref Params, "avatarclassifiedsrequest", serverURI, UUID.Random().ToString()))
322 {
323 // Error Handling here!
324 // if(parameters.ContainsKey("message")
325 }
326  
327 parameters = (OSDMap)Params;
328  
329 OSDArray list = (OSDArray)parameters["result"];
330  
331 Dictionary<UUID, string> classifieds = new Dictionary<UUID, string>();
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 // Vector3 avaPos = p.AbsolutePosition;
449  
450 string serverURI = string.Empty;
451 GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
452  
453 if (land == null)
454 {
455 ad.ParcelName = string.Empty;
456 }
457 else
458 {
459 ad.ParcelName = land.LandData.Name;
460 }
461  
462 ad.CreatorId = remoteClient.AgentId;
463 ad.ClassifiedId = queryclassifiedID;
464 ad.Category = Convert.ToInt32(queryCategory);
465 ad.Name = queryName;
466 ad.Description = queryDescription;
467 ad.ParentEstate = Convert.ToInt32(queryParentEstate);
468 ad.SnapshotId = querySnapshotID;
469 ad.SimName = remoteClient.Scene.RegionInfo.RegionName;
470 ad.GlobalPos = queryGlobalPos.ToString ();
471 ad.Flags = queryclassifiedFlags;
472 ad.Price = queryclassifiedPrice;
473 ad.ParcelId = p.currentParcelUUID;
474  
475 object Ad = ad;
476  
477 OSD.SerializeMembers(Ad);
478  
479 if(!JsonRpcRequest(ref Ad, "classified_update", serverURI, UUID.Random().ToString()))
480 {
481 remoteClient.SendAgentAlertMessage(
482 "Error updating classified", false);
483 }
484 }
485  
486 /// <summary>
487 /// Classifieds delete.
488 /// </summary>
489 /// <param name='queryClassifiedID'>
490 /// Query classified I.
491 /// </param>
492 /// <param name='remoteClient'>
493 /// Remote client.
494 /// </param>
495 public void ClassifiedDelete(UUID queryClassifiedID, IClientAPI remoteClient)
496 {
497 string serverURI = string.Empty;
498 GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
499  
500 UUID classifiedId;
501 OSDMap parameters= new OSDMap();
502 UUID.TryParse(queryClassifiedID.ToString(), out classifiedId);
503 parameters.Add("classifiedId", OSD.FromUUID(classifiedId));
504 OSD Params = (OSD)parameters;
505 if(!JsonRpcRequest(ref Params, "classified_delete", serverURI, UUID.Random().ToString()))
506 {
507 remoteClient.SendAgentAlertMessage(
508 "Error classified delete", false);
509 }
510  
511 parameters = (OSDMap)Params;
512 }
513 #endregion Classified
514  
515 #region Picks
516 /// <summary>
517 /// Handles the avatar picks request.
518 /// </summary>
519 /// <param name='sender'>
520 /// Sender.
521 /// </param>
522 /// <param name='method'>
523 /// Method.
524 /// </param>
525 /// <param name='args'>
526 /// Arguments.
527 /// </param>
528 public void PicksRequest(Object sender, string method, List<String> args)
529 {
530 if (!(sender is IClientAPI))
531 return;
532  
533 IClientAPI remoteClient = (IClientAPI)sender;
534  
535 UUID targetId;
536 UUID.TryParse(args[0], out targetId);
537  
538 // Can't handle NPC yet...
539 ScenePresence p = FindPresence(targetId);
540  
541 if (null != p)
542 {
543 if (p.PresenceType == PresenceType.Npc)
544 return;
545 }
546  
547 string serverURI = string.Empty;
548 GetUserProfileServerURI(targetId, out serverURI);
549  
550 OSDMap parameters= new OSDMap();
551 parameters.Add("creatorId", OSD.FromUUID(targetId));
552 OSD Params = (OSD)parameters;
553 if(!JsonRpcRequest(ref Params, "avatarpicksrequest", serverURI, UUID.Random().ToString()))
554 {
555 remoteClient.SendAgentAlertMessage(
556 "Error requesting picks", false);
557 return;
558 }
559  
560 parameters = (OSDMap)Params;
561  
562 OSDArray list = (OSDArray)parameters["result"];
563  
564 Dictionary<UUID, string> picks = new Dictionary<UUID, string>();
565  
566 foreach(OSD map in list)
567 {
568 OSDMap m = (OSDMap)map;
569 UUID cid = m["pickuuid"].AsUUID();
570 string name = m["name"].AsString();
571  
572 m_log.DebugFormat("[PROFILES]: PicksRequest {0}", name);
573  
574 picks[cid] = name;
575 }
576 remoteClient.SendAvatarPicksReply(new UUID(args[0]), picks);
577 }
578  
579 /// <summary>
580 /// Handles the pick info request.
581 /// </summary>
582 /// <param name='sender'>
583 /// Sender.
584 /// </param>
585 /// <param name='method'>
586 /// Method.
587 /// </param>
588 /// <param name='args'>
589 /// Arguments.
590 /// </param>
591 public void PickInfoRequest(Object sender, string method, List<String> args)
592 {
593 if (!(sender is IClientAPI))
594 return;
595  
596 UUID targetID;
597 UUID.TryParse(args[0], out targetID);
598 string serverURI = string.Empty;
599 GetUserProfileServerURI(targetID, out serverURI);
600 IClientAPI remoteClient = (IClientAPI)sender;
601  
602 UserProfilePick pick = new UserProfilePick();
603 UUID.TryParse(args[0], out pick.CreatorId);
604 UUID.TryParse(args[1], out pick.PickId);
605  
606  
607 object Pick = (object)pick;
608 if(!JsonRpcRequest(ref Pick, "pickinforequest", serverURI, UUID.Random().ToString()))
609 {
610 remoteClient.SendAgentAlertMessage(
611 "Error selecting pick", false);
612 }
613 pick = (UserProfilePick) Pick;
614 if(pick.SnapshotId == UUID.Zero)
615 {
616 // In case of a new UserPick, the data may not be ready and we would send wrong data, skip it...
617 m_log.DebugFormat("[PROFILES]: PickInfoRequest: SnapshotID is {0}", UUID.Zero.ToString());
618 return;
619 }
620  
621 Vector3 globalPos;
622 Vector3.TryParse(pick.GlobalPos,out globalPos);
623  
624 m_log.DebugFormat("[PROFILES]: PickInfoRequest: {0} : {1}", pick.Name.ToString(), pick.SnapshotId.ToString());
625  
626 remoteClient.SendPickInfoReply(pick.PickId,pick.CreatorId,pick.TopPick,pick.ParcelId,pick.Name,
627 pick.Desc,pick.SnapshotId,pick.User,pick.OriginalName,pick.SimName,
628 globalPos,pick.SortOrder,pick.Enabled);
629 }
630  
631 /// <summary>
632 /// Updates the userpicks
633 /// </summary>
634 /// <param name='remoteClient'>
635 /// Remote client.
636 /// </param>
637 /// <param name='pickID'>
638 /// Pick I.
639 /// </param>
640 /// <param name='creatorID'>
641 /// the creator of the pick
642 /// </param>
643 /// <param name='topPick'>
644 /// Top pick.
645 /// </param>
646 /// <param name='name'>
647 /// Name.
648 /// </param>
649 /// <param name='desc'>
650 /// Desc.
651 /// </param>
652 /// <param name='snapshotID'>
653 /// Snapshot I.
654 /// </param>
655 /// <param name='sortOrder'>
656 /// Sort order.
657 /// </param>
658 /// <param name='enabled'>
659 /// Enabled.
660 /// </param>
661 public void PickInfoUpdate(IClientAPI remoteClient, UUID pickID, UUID creatorID, bool topPick, string name, string desc, UUID snapshotID, int sortOrder, bool enabled)
662 {
663  
664 m_log.DebugFormat("[PROFILES]: Start PickInfoUpdate Name: {0} PickId: {1} SnapshotId: {2}", name, pickID.ToString(), snapshotID.ToString());
665 UserProfilePick pick = new UserProfilePick();
666 string serverURI = string.Empty;
667 GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
668 ScenePresence p = FindPresence(remoteClient.AgentId);
669  
670 Vector3 avaPos = p.AbsolutePosition;
671 // Getting the global position for the Avatar
672 Vector3 posGlobal = new Vector3(remoteClient.Scene.RegionInfo.RegionLocX*Constants.RegionSize + avaPos.X,
673 remoteClient.Scene.RegionInfo.RegionLocY*Constants.RegionSize + avaPos.Y,
674 avaPos.Z);
675  
676 string landOwnerName = string.Empty;
677 ILandObject land = p.Scene.LandChannel.GetLandObject(avaPos.X, avaPos.Y);
678 if(land.LandData.IsGroupOwned)
679 {
680 IGroupsModule groupMod = p.Scene.RequestModuleInterface<IGroupsModule>();
681 UUID groupId = land.LandData.GroupID;
682 GroupRecord groupRecord = groupMod.GetGroupRecord(groupId);
683 landOwnerName = groupRecord.GroupName;
684 }
685 else
686 {
687 IUserAccountService accounts = p.Scene.RequestModuleInterface<IUserAccountService>();
688 UserAccount user = accounts.GetUserAccount(p.Scene.RegionInfo.ScopeID, land.LandData.OwnerID);
689 landOwnerName = user.Name;
690 }
691  
692 pick.PickId = pickID;
693 pick.CreatorId = creatorID;
694 pick.TopPick = topPick;
695 pick.Name = name;
696 pick.Desc = desc;
697 pick.ParcelId = p.currentParcelUUID;
698 pick.SnapshotId = snapshotID;
699 pick.User = landOwnerName;
700 pick.SimName = remoteClient.Scene.RegionInfo.RegionName;
701 pick.GlobalPos = posGlobal.ToString();
702 pick.SortOrder = sortOrder;
703 pick.Enabled = enabled;
704  
705 object Pick = (object)pick;
706 if(!JsonRpcRequest(ref Pick, "picks_update", serverURI, UUID.Random().ToString()))
707 {
708 remoteClient.SendAgentAlertMessage(
709 "Error updating pick", false);
710 }
711  
712 m_log.DebugFormat("[PROFILES]: Finish PickInfoUpdate {0} {1}", pick.Name, pick.PickId.ToString());
713 }
714  
715 /// <summary>
716 /// Delete a Pick
717 /// </summary>
718 /// <param name='remoteClient'>
719 /// Remote client.
720 /// </param>
721 /// <param name='queryPickID'>
722 /// Query pick I.
723 /// </param>
724 public void PickDelete(IClientAPI remoteClient, UUID queryPickID)
725 {
726 string serverURI = string.Empty;
727 GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
728  
729 OSDMap parameters= new OSDMap();
730 parameters.Add("pickId", OSD.FromUUID(queryPickID));
731 OSD Params = (OSD)parameters;
732 if(!JsonRpcRequest(ref Params, "picks_delete", serverURI, UUID.Random().ToString()))
733 {
734 remoteClient.SendAgentAlertMessage(
735 "Error picks delete", false);
736 }
737 }
738 #endregion Picks
739  
740 #region Notes
741 /// <summary>
742 /// Handles the avatar notes request.
743 /// </summary>
744 /// <param name='sender'>
745 /// Sender.
746 /// </param>
747 /// <param name='method'>
748 /// Method.
749 /// </param>
750 /// <param name='args'>
751 /// Arguments.
752 /// </param>
753 public void NotesRequest(Object sender, string method, List<String> args)
754 {
755 UserProfileNotes note = new UserProfileNotes();
756  
757 if (!(sender is IClientAPI))
758 return;
759  
760 IClientAPI remoteClient = (IClientAPI)sender;
761 string serverURI = string.Empty;
762 GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
763 note.UserId = remoteClient.AgentId;
764 UUID.TryParse(args[0], out note.TargetId);
765  
766 object Note = (object)note;
767 if(!JsonRpcRequest(ref Note, "avatarnotesrequest", serverURI, UUID.Random().ToString()))
768 {
769 remoteClient.SendAgentAlertMessage(
770 "Error requesting note", false);
771 }
772 note = (UserProfileNotes) Note;
773  
774 remoteClient.SendAvatarNotesReply(note.TargetId, note.Notes);
775 }
776  
777 /// <summary>
778 /// Avatars the notes update.
779 /// </summary>
780 /// <param name='remoteClient'>
781 /// Remote client.
782 /// </param>
783 /// <param name='queryTargetID'>
784 /// Query target I.
785 /// </param>
786 /// <param name='queryNotes'>
787 /// Query notes.
788 /// </param>
789 public void NotesUpdate(IClientAPI remoteClient, UUID queryTargetID, string queryNotes)
790 {
791 UserProfileNotes note = new UserProfileNotes();
792  
793 note.UserId = remoteClient.AgentId;
794 note.TargetId = queryTargetID;
795 note.Notes = queryNotes;
796  
797 string serverURI = string.Empty;
798 GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
799  
800 object Note = note;
801 if(!JsonRpcRequest(ref Note, "avatar_notes_update", serverURI, UUID.Random().ToString()))
802 {
803 remoteClient.SendAgentAlertMessage(
804 "Error updating note", false);
805 }
806 }
807 #endregion Notes
808  
809 #region User Preferences
810 /// <summary>
811 /// Updates the user preferences.
812 /// </summary>
813 /// <param name='imViaEmail'>
814 /// Im via email.
815 /// </param>
816 /// <param name='visible'>
817 /// Visible.
818 /// </param>
819 /// <param name='remoteClient'>
820 /// Remote client.
821 /// </param>
822 public void UpdateUserPreferences(bool imViaEmail, bool visible, IClientAPI remoteClient)
823 {
824 UserPreferences pref = new UserPreferences();
825  
826 pref.UserId = remoteClient.AgentId;
827 pref.IMViaEmail = imViaEmail;
828 pref.Visible = visible;
829  
830 string serverURI = string.Empty;
831 bool foreign = GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
832  
833 object Pref = pref;
834 if(!JsonRpcRequest(ref Pref, "user_preferences_update", serverURI, UUID.Random().ToString()))
835 {
836 m_log.InfoFormat("[PROFILES]: UserPreferences update error");
837 remoteClient.SendAgentAlertMessage("Error updating preferences", false);
838 return;
839 }
840 }
841  
842 /// <summary>
843 /// Users the preferences request.
844 /// </summary>
845 /// <param name='remoteClient'>
846 /// Remote client.
847 /// </param>
848 public void UserPreferencesRequest(IClientAPI remoteClient)
849 {
850 UserPreferences pref = new UserPreferences();
851  
852 pref.UserId = remoteClient.AgentId;
853  
854 string serverURI = string.Empty;
855 bool foreign = GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
856  
857  
858 object Pref = (object)pref;
859 if(!JsonRpcRequest(ref Pref, "user_preferences_request", serverURI, UUID.Random().ToString()))
860 {
861 m_log.InfoFormat("[PROFILES]: UserPreferences request error");
862 remoteClient.SendAgentAlertMessage("Error requesting preferences", false);
863 return;
864 }
865 pref = (UserPreferences) Pref;
866  
867 remoteClient.SendUserInfoReply(pref.IMViaEmail, pref.Visible, pref.EMail);
868  
869 }
870 #endregion User Preferences
871  
872 #region Avatar Properties
873 /// <summary>
874 /// Update the avatars interests .
875 /// </summary>
876 /// <param name='remoteClient'>
877 /// Remote client.
878 /// </param>
879 /// <param name='wantmask'>
880 /// Wantmask.
881 /// </param>
882 /// <param name='wanttext'>
883 /// Wanttext.
884 /// </param>
885 /// <param name='skillsmask'>
886 /// Skillsmask.
887 /// </param>
888 /// <param name='skillstext'>
889 /// Skillstext.
890 /// </param>
891 /// <param name='languages'>
892 /// Languages.
893 /// </param>
894 public void AvatarInterestsUpdate(IClientAPI remoteClient, uint wantmask, string wanttext, uint skillsmask, string skillstext, string languages)
895 {
896 UserProfileProperties prop = new UserProfileProperties();
897  
898 prop.UserId = remoteClient.AgentId;
899 prop.WantToMask = (int)wantmask;
900 prop.WantToText = wanttext;
901 prop.SkillsMask = (int)skillsmask;
902 prop.SkillsText = skillstext;
903 prop.Language = languages;
904  
905 string serverURI = string.Empty;
906 GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
907  
908 object Param = prop;
909 if(!JsonRpcRequest(ref Param, "avatar_interests_update", serverURI, UUID.Random().ToString()))
910 {
911 remoteClient.SendAgentAlertMessage(
912 "Error updating interests", false);
913 }
914 }
915  
916 public void RequestAvatarProperties(IClientAPI remoteClient, UUID avatarID)
917 {
918 if ( String.IsNullOrEmpty(avatarID.ToString()) || String.IsNullOrEmpty(remoteClient.AgentId.ToString()))
919 {
920 // Looking for a reason that some viewers are sending null Id's
921 m_log.DebugFormat("[PROFILES]: This should not happen remoteClient.AgentId {0} - avatarID {1}", remoteClient.AgentId, avatarID);
922 return;
923 }
924  
925 // Can't handle NPC yet...
926 ScenePresence p = FindPresence(avatarID);
927  
928 if (null != p)
929 {
930 if (p.PresenceType == PresenceType.Npc)
931 return;
932 }
933  
934 string serverURI = string.Empty;
935 bool foreign = GetUserProfileServerURI(avatarID, out serverURI);
936  
937 UserAccount account = null;
938 Dictionary<string,object> userInfo;
939  
940 if (!foreign)
941 {
942 account = Scene.UserAccountService.GetUserAccount(Scene.RegionInfo.ScopeID, avatarID);
943 }
944 else
945 {
946 userInfo = new Dictionary<string, object>();
947 }
948  
949 Byte[] charterMember = new Byte[1];
950 string born = String.Empty;
951 uint flags = 0x00;
952  
953 if (null != account)
954 {
955 if (account.UserTitle == "")
956 {
957 charterMember[0] = (Byte)((account.UserFlags & 0xf00) >> 8);
958 }
959 else
960 {
961 charterMember = Utils.StringToBytes(account.UserTitle);
962 }
963  
964 born = Util.ToDateTime(account.Created).ToString(
965 "M/d/yyyy", CultureInfo.InvariantCulture);
966 flags = (uint)(account.UserFlags & 0xff);
967 }
968 else
969 {
970 if (GetUserAccountData(avatarID, out userInfo) == true)
971 {
972 if ((string)userInfo["user_title"] == "")
973 {
974 charterMember[0] = (Byte)(((Byte)userInfo["user_flags"] & 0xf00) >> 8);
975 }
976 else
977 {
978 charterMember = Utils.StringToBytes((string)userInfo["user_title"]);
979 }
980  
981 int val_born = (int)userInfo["user_created"];
982 born = Util.ToDateTime(val_born).ToString(
983 "M/d/yyyy", CultureInfo.InvariantCulture);
984  
985 // picky, picky
986 int val_flags = (int)userInfo["user_flags"];
987 flags = (uint)(val_flags & 0xff);
988 }
989 }
990  
991 UserProfileProperties props = new UserProfileProperties();
992 string result = string.Empty;
993  
994 props.UserId = avatarID;
995 GetProfileData(ref props, out result);
996  
997 remoteClient.SendAvatarProperties(props.UserId, props.AboutText, born, charterMember , props.FirstLifeText, flags,
998 props.FirstLifeImageId, props.ImageId, props.WebUrl, props.PartnerId);
999  
1000  
1001 remoteClient.SendAvatarInterestsReply(props.UserId, (uint)props.WantToMask, props.WantToText, (uint)props.SkillsMask,
1002 props.SkillsText, props.Language);
1003 }
1004  
1005 /// <summary>
1006 /// Updates the avatar properties.
1007 /// </summary>
1008 /// <param name='remoteClient'>
1009 /// Remote client.
1010 /// </param>
1011 /// <param name='newProfile'>
1012 /// New profile.
1013 /// </param>
1014 public void AvatarPropertiesUpdate(IClientAPI remoteClient, UserProfileData newProfile)
1015 {
1016 if (remoteClient.AgentId == newProfile.ID)
1017 {
1018 UserProfileProperties prop = new UserProfileProperties();
1019  
1020 prop.UserId = remoteClient.AgentId;
1021 prop.WebUrl = newProfile.ProfileUrl;
1022 prop.ImageId = newProfile.Image;
1023 prop.AboutText = newProfile.AboutText;
1024 prop.FirstLifeImageId = newProfile.FirstLifeImage;
1025 prop.FirstLifeText = newProfile.FirstLifeAboutText;
1026  
1027 string serverURI = string.Empty;
1028 GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
1029  
1030 object Prop = prop;
1031  
1032 if(!JsonRpcRequest(ref Prop, "avatar_properties_update", serverURI, UUID.Random().ToString()))
1033 {
1034 remoteClient.SendAgentAlertMessage(
1035 "Error updating properties", false);
1036 }
1037  
1038 RequestAvatarProperties(remoteClient, newProfile.ID);
1039 }
1040 }
1041  
1042 /// <summary>
1043 /// Gets the profile data.
1044 /// </summary>
1045 /// <returns>
1046 /// The profile data.
1047 /// </returns>
1048 /// <param name='userID'>
1049 /// User I.
1050 /// </param>
1051 bool GetProfileData(ref UserProfileProperties properties, out string message)
1052 {
1053 // Can't handle NPC yet...
1054 ScenePresence p = FindPresence(properties.UserId);
1055  
1056 if (null != p)
1057 {
1058 if (p.PresenceType == PresenceType.Npc)
1059 {
1060 message = "Id points to NPC";
1061 return false;
1062 }
1063 }
1064  
1065 string serverURI = string.Empty;
1066 GetUserProfileServerURI(properties.UserId, out serverURI);
1067  
1068 // This is checking a friend on the home grid
1069 // Not HG friend
1070 if ( String.IsNullOrEmpty(serverURI))
1071 {
1072 message = "No Presence - foreign friend";
1073 return false;
1074 }
1075  
1076 object Prop = (object)properties;
1077 JsonRpcRequest(ref Prop, "avatar_properties_request", serverURI, UUID.Random().ToString());
1078 properties = (UserProfileProperties)Prop;
1079  
1080 message = "Success";
1081 return true;
1082 }
1083 #endregion Avatar Properties
1084  
1085 #region Utils
1086 bool GetImageAssets(UUID avatarId)
1087 {
1088 string profileServerURI = string.Empty;
1089 string assetServerURI = string.Empty;
1090  
1091 bool foreign = GetUserProfileServerURI(avatarId, out profileServerURI);
1092  
1093 if(!foreign)
1094 return true;
1095  
1096 assetServerURI = UserManagementModule.GetUserServerURL(avatarId, "AssetServerURI");
1097  
1098 OSDMap parameters= new OSDMap();
1099 parameters.Add("avatarId", OSD.FromUUID(avatarId));
1100 OSD Params = (OSD)parameters;
1101 if(!JsonRpcRequest(ref Params, "image_assets_request", profileServerURI, UUID.Random().ToString()))
1102 {
1103 // Error Handling here!
1104 // if(parameters.ContainsKey("message")
1105 return false;
1106 }
1107  
1108 parameters = (OSDMap)Params;
1109  
1110 OSDArray list = (OSDArray)parameters["result"];
1111  
1112 foreach(OSD asset in list)
1113 {
1114 OSDString assetId = (OSDString)asset;
1115  
1116 Scene.AssetService.Get(string.Format("{0}/{1}",assetServerURI, assetId.AsString()));
1117 }
1118 return true;
1119 }
1120  
1121 /// <summary>
1122 /// Gets the user account data.
1123 /// </summary>
1124 /// <returns>
1125 /// The user profile data.
1126 /// </returns>
1127 /// <param name='userID'>
1128 /// If set to <c>true</c> user I.
1129 /// </param>
1130 /// <param name='userInfo'>
1131 /// If set to <c>true</c> user info.
1132 /// </param>
1133 bool GetUserAccountData(UUID userID, out Dictionary<string, object> userInfo)
1134 {
1135 Dictionary<string,object> info = new Dictionary<string, object>();
1136  
1137 if (UserManagementModule.IsLocalGridUser(userID))
1138 {
1139 // Is local
1140 IUserAccountService uas = Scene.UserAccountService;
1141 UserAccount account = uas.GetUserAccount(Scene.RegionInfo.ScopeID, userID);
1142  
1143 info["user_flags"] = account.UserFlags;
1144 info["user_created"] = account.Created;
1145  
1146 if (!String.IsNullOrEmpty(account.UserTitle))
1147 info["user_title"] = account.UserTitle;
1148 else
1149 info["user_title"] = "";
1150  
1151 userInfo = info;
1152  
1153 return false;
1154 }
1155 else
1156 {
1157 // Is Foreign
1158 string home_url = UserManagementModule.GetUserServerURL(userID, "HomeURI");
1159  
1160 if (String.IsNullOrEmpty(home_url))
1161 {
1162 info["user_flags"] = 0;
1163 info["user_created"] = 0;
1164 info["user_title"] = "Unavailable";
1165  
1166 userInfo = info;
1167 return true;
1168 }
1169  
1170 UserAgentServiceConnector uConn = new UserAgentServiceConnector(home_url);
1171  
1172 Dictionary<string, object> account = uConn.GetUserInfo(userID);
1173  
1174 if (account.Count > 0)
1175 {
1176 if (account.ContainsKey("user_flags"))
1177 info["user_flags"] = account["user_flags"];
1178 else
1179 info["user_flags"] = "";
1180  
1181 if (account.ContainsKey("user_created"))
1182 info["user_created"] = account["user_created"];
1183 else
1184 info["user_created"] = "";
1185  
1186 info["user_title"] = "HG Visitor";
1187 }
1188 else
1189 {
1190 info["user_flags"] = 0;
1191 info["user_created"] = 0;
1192 info["user_title"] = "HG Visitor";
1193 }
1194 userInfo = info;
1195 return true;
1196 }
1197 }
1198  
1199 /// <summary>
1200 /// Gets the user profile server UR.
1201 /// </summary>
1202 /// <returns>
1203 /// The user profile server UR.
1204 /// </returns>
1205 /// <param name='userID'>
1206 /// If set to <c>true</c> user I.
1207 /// </param>
1208 /// <param name='serverURI'>
1209 /// If set to <c>true</c> server UR.
1210 /// </param>
1211 bool GetUserProfileServerURI(UUID userID, out string serverURI)
1212 {
1213 bool local;
1214 local = UserManagementModule.IsLocalGridUser(userID);
1215  
1216 if (!local)
1217 {
1218 serverURI = UserManagementModule.GetUserServerURL(userID, "ProfileServerURI");
1219 // Is Foreign
1220 return true;
1221 }
1222 else
1223 {
1224 serverURI = ProfileServerUri;
1225 // Is local
1226 return false;
1227 }
1228 }
1229  
1230 /// <summary>
1231 /// Finds the presence.
1232 /// </summary>
1233 /// <returns>
1234 /// The presence.
1235 /// </returns>
1236 /// <param name='clientID'>
1237 /// Client I.
1238 /// </param>
1239 ScenePresence FindPresence(UUID clientID)
1240 {
1241 ScenePresence p;
1242  
1243 p = Scene.GetScenePresence(clientID);
1244 if (p != null && !p.IsChildAgent)
1245 return p;
1246  
1247 return null;
1248 }
1249 #endregion Util
1250  
1251 #region Web Util
1252 /// <summary>
1253 /// Sends json-rpc request with a serializable type.
1254 /// </summary>
1255 /// <returns>
1256 /// OSD Map.
1257 /// </returns>
1258 /// <param name='parameters'>
1259 /// Serializable type .
1260 /// </param>
1261 /// <param name='method'>
1262 /// Json-rpc method to call.
1263 /// </param>
1264 /// <param name='uri'>
1265 /// URI of json-rpc service.
1266 /// </param>
1267 /// <param name='jsonId'>
1268 /// Id for our call.
1269 /// </param>
1270 bool JsonRpcRequest(ref object parameters, string method, string uri, string jsonId)
1271 {
1272 if (jsonId == null)
1273 throw new ArgumentNullException ("jsonId");
1274 if (uri == null)
1275 throw new ArgumentNullException ("uri");
1276 if (method == null)
1277 throw new ArgumentNullException ("method");
1278 if (parameters == null)
1279 throw new ArgumentNullException ("parameters");
1280  
1281 // Prep our payload
1282 OSDMap json = new OSDMap();
1283  
1284 json.Add("jsonrpc", OSD.FromString("2.0"));
1285 json.Add("id", OSD.FromString(jsonId));
1286 json.Add("method", OSD.FromString(method));
1287 // Experiment
1288 json.Add("params", OSD.SerializeMembers(parameters));
1289  
1290 string jsonRequestData = OSDParser.SerializeJsonString(json);
1291 byte[] content = Encoding.UTF8.GetBytes(jsonRequestData);
1292  
1293 HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri);
1294 // webRequest.Credentials = new NetworkCredential(rpcUser, rpcPass);
1295 webRequest.ContentType = "application/json-rpc";
1296 webRequest.Method = "POST";
1297  
1298 Stream dataStream = webRequest.GetRequestStream();
1299 dataStream.Write(content, 0, content.Length);
1300 dataStream.Close();
1301  
1302 WebResponse webResponse = null;
1303 try
1304 {
1305 webResponse = webRequest.GetResponse();
1306 }
1307 catch (WebException e)
1308 {
1309 Console.WriteLine("Web Error" + e.Message);
1310 Console.WriteLine ("Please check input");
1311 return false;
1312 }
1313  
1314 Stream rstream = webResponse.GetResponseStream();
1315 OSDMap mret = (OSDMap)OSDParser.DeserializeJson(rstream);
1316  
1317 if (mret.ContainsKey("error"))
1318 return false;
1319  
1320 // get params...
1321 OSD.DeserializeMembers(ref parameters, (OSDMap) mret["result"]);
1322 return true;
1323 }
1324  
1325 /// <summary>
1326 /// Sends json-rpc request with OSD parameter.
1327 /// </summary>
1328 /// <returns>
1329 /// The rpc request.
1330 /// </returns>
1331 /// <param name='data'>
1332 /// data - incoming as parameters, outgong as result/error
1333 /// </param>
1334 /// <param name='method'>
1335 /// Json-rpc method to call.
1336 /// </param>
1337 /// <param name='uri'>
1338 /// URI of json-rpc service.
1339 /// </param>
1340 /// <param name='jsonId'>
1341 /// If set to <c>true</c> json identifier.
1342 /// </param>
1343 bool JsonRpcRequest(ref OSD data, string method, string uri, string jsonId)
1344 {
1345 OSDMap map = new OSDMap();
1346  
1347 map["jsonrpc"] = "2.0";
1348 if(string.IsNullOrEmpty(jsonId))
1349 map["id"] = UUID.Random().ToString();
1350 else
1351 map["id"] = jsonId;
1352  
1353 map["method"] = method;
1354 map["params"] = data;
1355  
1356 string jsonRequestData = OSDParser.SerializeJsonString(map);
1357 byte[] content = Encoding.UTF8.GetBytes(jsonRequestData);
1358  
1359 HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri);
1360 webRequest.ContentType = "application/json-rpc";
1361 webRequest.Method = "POST";
1362  
1363 Stream dataStream = webRequest.GetRequestStream();
1364 dataStream.Write(content, 0, content.Length);
1365 dataStream.Close();
1366  
1367 WebResponse webResponse = null;
1368 try
1369 {
1370 webResponse = webRequest.GetResponse();
1371 }
1372 catch (WebException e)
1373 {
1374 Console.WriteLine("Web Error" + e.Message);
1375 Console.WriteLine ("Please check input");
1376 return false;
1377 }
1378  
1379 Stream rstream = webResponse.GetResponseStream();
1380  
1381 OSDMap response = new OSDMap();
1382 try
1383 {
1384 response = (OSDMap)OSDParser.DeserializeJson(rstream);
1385 }
1386 catch (Exception e)
1387 {
1388 m_log.DebugFormat("[PROFILES]: JsonRpcRequest Error {0} - remote user with legacy profiles?", e.Message);
1389 return false;
1390 }
1391  
1392 if(response.ContainsKey("error"))
1393 {
1394 data = response["error"];
1395 return false;
1396 }
1397  
1398 data = response;
1399  
1400 return true;
1401 }
1402 #endregion Web Util
1403 }
1404 }