diff --git a/OpenSim/Region/CoreModules/Avatar/UserProfiles/OpenProfileClient.cs b/OpenSim/Region/CoreModules/Avatar/UserProfiles/OpenProfileClient.cs new file mode 100644 index 0000000000..23de3f599d --- /dev/null +++ b/OpenSim/Region/CoreModules/Avatar/UserProfiles/OpenProfileClient.cs @@ -0,0 +1,193 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Net.Sockets; +using System.Reflection; +using System.Text; +using System.Xml; +using log4net; +using Nwc.XmlRpc; +using OpenMetaverse; +using OpenSim.Framework; + +namespace OpenSim.Region.CoreModules.Avatar.UserProfiles +{ + /// + /// A client for accessing a profile server using the OpenProfile protocol. + /// + /// + /// This class was adapted from the full OpenProfile class. Since it's only a client, and not a server, + /// it's much simpler. + /// + public class OpenProfileClient + { + static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private string m_serverURI; + + /// + /// Creates a client for accessing a foreign grid's profile server using the OpenProfile protocol. + /// + /// The grid's profile server URL + public OpenProfileClient(string serverURI) + { + m_serverURI = serverURI; + } + + + /// + /// Gets an avatar's profile using the OpenProfile protocol. + /// + /// On success, this will contain the avatar's profile + /// Success/failure + /// + /// There are two profile modules currently in use in OpenSim: the older one is OpenProfile, and the newer + /// one is UserProfileModule (this file). This method attempts to read an avatar's profile from a foreign + /// grid using the OpenProfile protocol. + /// + public bool RequestAvatarPropertiesUsingOpenProfile(ref UserProfileProperties props) + { + Hashtable ReqHash = new Hashtable(); + ReqHash["avatar_id"] = props.UserId.ToString(); + + Hashtable profileData = GenericXMLRPCRequest(ReqHash, "avatar_properties_request", m_serverURI); + + ArrayList dataArray = (ArrayList)profileData["data"]; + + if (dataArray == null || dataArray[0] == null) + return false; + profileData = (Hashtable)dataArray[0]; + + props.WebUrl = string.Empty; + props.AboutText = String.Empty; + props.FirstLifeText = String.Empty; + props.ImageId = UUID.Zero; + props.FirstLifeImageId = UUID.Zero; + props.PartnerId = UUID.Zero; + + if (profileData["ProfileUrl"] != null) + props.WebUrl = profileData["ProfileUrl"].ToString(); + if (profileData["AboutText"] != null) + props.AboutText = profileData["AboutText"].ToString(); + if (profileData["FirstLifeAboutText"] != null) + props.FirstLifeText = profileData["FirstLifeAboutText"].ToString(); + if (profileData["Image"] != null) + props.ImageId = new UUID(profileData["Image"].ToString()); + if (profileData["FirstLifeImage"] != null) + props.FirstLifeImageId = new UUID(profileData["FirstLifeImage"].ToString()); + if (profileData["Partner"] != null) + props.PartnerId = new UUID(profileData["Partner"].ToString()); + + props.WantToMask = 0; + props.WantToText = String.Empty; + props.SkillsMask = 0; + props.SkillsText = String.Empty; + props.Language = String.Empty; + + if (profileData["wantmask"] != null) + props.WantToMask = Convert.ToInt32(profileData["wantmask"].ToString()); + if (profileData["wanttext"] != null) + props.WantToText = profileData["wanttext"].ToString(); + + if (profileData["skillsmask"] != null) + props.SkillsMask = Convert.ToInt32(profileData["skillsmask"].ToString()); + if (profileData["skillstext"] != null) + props.SkillsText = profileData["skillstext"].ToString(); + + if (profileData["languages"] != null) + props.Language = profileData["languages"].ToString(); + + return true; + } + + private Hashtable GenericXMLRPCRequest(Hashtable ReqParams, string method, string server) + { + ArrayList SendParams = new ArrayList(); + SendParams.Add(ReqParams); + + XmlRpcResponse Resp; + try + { + XmlRpcRequest Req = new XmlRpcRequest(method, SendParams); + Resp = Req.Send(server, 30000); + } + catch (WebException ex) + { + m_log.ErrorFormat("[PROFILE]: Unable to connect to Profile " + + "Server {0}. Exception {1}", server, ex); + + Hashtable ErrorHash = new Hashtable(); + ErrorHash["success"] = false; + ErrorHash["errorMessage"] = "Unable to fetch profile data at this time. "; + ErrorHash["errorURI"] = ""; + + return ErrorHash; + } + catch (SocketException ex) + { + m_log.ErrorFormat( + "[PROFILE]: Unable to connect to Profile Server {0}. Method {1}, params {2}. " + + "Exception {3}", server, method, ReqParams, ex); + + Hashtable ErrorHash = new Hashtable(); + ErrorHash["success"] = false; + ErrorHash["errorMessage"] = "Unable to fetch profile data at this time. "; + ErrorHash["errorURI"] = ""; + + return ErrorHash; + } + catch (XmlException ex) + { + m_log.ErrorFormat( + "[PROFILE]: Unable to connect to Profile Server {0}. Method {1}, params {2}. " + + "Exception {3}", server, method, ReqParams.ToString(), ex); + Hashtable ErrorHash = new Hashtable(); + ErrorHash["success"] = false; + ErrorHash["errorMessage"] = "Unable to fetch profile data at this time. "; + ErrorHash["errorURI"] = ""; + + return ErrorHash; + } + if (Resp.IsFault) + { + Hashtable ErrorHash = new Hashtable(); + ErrorHash["success"] = false; + ErrorHash["errorMessage"] = "Unable to fetch profile data at this time. "; + ErrorHash["errorURI"] = ""; + return ErrorHash; + } + Hashtable RespData = (Hashtable)Resp.Value; + + return RespData; + } + } +} diff --git a/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs b/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs index bb2a25813d..d949d70d9e 100644 --- a/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs @@ -47,7 +47,7 @@ using OpenSim.Services.Interfaces; using Mono.Addins; using OpenSim.Services.Connectors.Hypergrid; -namespace OpenSim.Region.OptionalModules.Avatar.UserProfiles +namespace OpenSim.Region.CoreModules.Avatar.UserProfiles { [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "UserProfilesModule")] public class UserProfileModule : IProfileModule, INonSharedRegionModule @@ -999,7 +999,31 @@ namespace OpenSim.Region.OptionalModules.Avatar.UserProfiles string result = string.Empty; props.UserId = avatarID; - GetProfileData(ref props, out result); + + try + { + GetProfileData(ref props, out result); + } + catch (Exception e) + { + if (foreign) + { + // Check if the foreign grid is using OpenProfile. + // If any error occurs then discard it, and report the original error. + try + { + OpenProfileClient client = new OpenProfileClient(serverURI); + if (!client.RequestAvatarPropertiesUsingOpenProfile(ref props)) + throw e; + } + catch (Exception) + { + throw e; + } + } + else + throw; + } remoteClient.SendAvatarProperties(props.UserId, props.AboutText, born, charterMember , props.FirstLifeText, flags, props.FirstLifeImageId, props.ImageId, props.WebUrl, props.PartnerId);