diff --git a/OpenSim/Data/IProfilesData.cs b/OpenSim/Data/IProfilesData.cs
new file mode 100644
index 0000000000..eeccbf6965
--- /dev/null
+++ b/OpenSim/Data/IProfilesData.cs
@@ -0,0 +1,29 @@
+using System;
+using OpenMetaverse;
+using OpenMetaverse.StructuredData;
+using OpenSim.Framework;
+
+namespace OpenSim.Data
+{
+
+ public interface IProfilesData
+ {
+ OSDArray GetClassifiedRecords(UUID creatorId);
+ bool UpdateClassifiedRecord(UserClassifiedAdd ad, ref string result);
+ bool DeleteClassifiedRecord(UUID recordId);
+ OSDArray GetAvatarPicks(UUID avatarId);
+ UserProfilePick GetPickInfo(UUID avatarId, UUID pickId);
+ bool UpdatePicksRecord(UserProfilePick pick);
+ bool DeletePicksRecord(UUID pickId);
+ bool GetAvatarNotes(ref UserProfileNotes note);
+ bool UpdateAvatarNotes(ref UserProfileNotes note, ref string result);
+ bool GetAvatarProperties(ref UserProfileProperties props, ref string result);
+ bool UpdateAvatarProperties(ref UserProfileProperties props, ref string result);
+ bool UpdateAvatarInterests(UserProfileProperties up, ref string result);
+ bool GetClassifiedInfo(ref UserClassifiedAdd ad, ref string result);
+ bool GetUserAppData(ref UserAppData props, ref string result);
+ bool SetUserAppData(UserAppData props, ref string result);
+ OSDArray GetUserImageAssets(UUID avatarId);
+ }
+}
+
diff --git a/OpenSim/Data/MySQL/MySQLUserProfilesData.cs b/OpenSim/Data/MySQL/MySQLUserProfilesData.cs
new file mode 100644
index 0000000000..09bd44814e
--- /dev/null
+++ b/OpenSim/Data/MySQL/MySQLUserProfilesData.cs
@@ -0,0 +1,1023 @@
+using System;
+using System.Data;
+using System.Reflection;
+using OpenSim.Data;
+using OpenSim.Framework;
+using MySql.Data.MySqlClient;
+using OpenMetaverse;
+using OpenMetaverse.StructuredData;
+using log4net;
+
+namespace OpenSim.Data.MySQL
+{
+ public class UserProfilesData: IProfilesData
+ {
+ static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+
+ #region Properites
+ string ConnectionString
+ {
+ get; set;
+ }
+
+ protected object Lock
+ {
+ get; set;
+ }
+
+ protected virtual Assembly Assembly
+ {
+ get { return GetType().Assembly; }
+ }
+
+ #endregion Properties
+
+ #region class Member Functions
+ public UserProfilesData(string connectionString)
+ {
+ ConnectionString = connectionString;
+ Init();
+ }
+
+ void Init()
+ {
+ using (MySqlConnection dbcon = new MySqlConnection(ConnectionString))
+ {
+ dbcon.Open();
+
+ Migration m = new Migration(dbcon, Assembly, "UserProfiles");
+ m.Update();
+ }
+ }
+ #endregion Member Functions
+
+ #region Classifieds Queries
+ ///
+ /// Gets the classified records.
+ ///
+ ///
+ /// Array of classified records
+ ///
+ ///
+ /// Creator identifier.
+ ///
+ public OSDArray GetClassifiedRecords(UUID creatorId)
+ {
+ OSDArray data = new OSDArray();
+
+ using (MySqlConnection dbcon = new MySqlConnection(ConnectionString))
+ {
+ string query = "SELECT classifieduuid, name FROM classifieds WHERE creatoruuid = ?Id";
+ dbcon.Open();
+ using (MySqlCommand cmd = new MySqlCommand(query, dbcon))
+ {
+ cmd.Parameters.AddWithValue("?Id", creatorId);
+ using( MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.Default))
+ {
+ if(reader.HasRows)
+ {
+ while (reader.Read())
+ {
+ OSDMap n = new OSDMap();
+ UUID Id = UUID.Zero;
+
+ string Name = null;
+ try
+ {
+ UUID.TryParse(Convert.ToString( reader["classifieduuid"]), out Id);
+ Name = Convert.ToString(reader["name"]);
+ }
+ catch (Exception e)
+ {
+ m_log.DebugFormat("[PROFILES_DATA]" +
+ ": UserAccount exception {0}", e.Message);
+ }
+ n.Add("classifieduuid", OSD.FromUUID(Id));
+ n.Add("name", OSD.FromString(Name));
+ data.Add(n);
+ }
+ }
+ }
+ }
+ }
+ return data;
+ }
+
+ public bool UpdateClassifiedRecord(UserClassifiedAdd ad, ref string result)
+ {
+ string query = string.Empty;
+
+
+ query += "INSERT INTO classifieds (";
+ query += "`classifieduuid`,";
+ query += "`creatoruuid`,";
+ query += "`creationdate`,";
+ query += "`expirationdate`,";
+ query += "`category`,";
+ query += "`name`,";
+ query += "`description`,";
+ query += "`parceluuid`,";
+ query += "`parentestate`,";
+ query += "`snapshotuuid`,";
+ query += "`simname`,";
+ query += "`posglobal`,";
+ query += "`parcelname`,";
+ query += "`classifiedflags`,";
+ query += "`priceforlisting`) ";
+ query += "VALUES (";
+ query += "?ClassifiedId,";
+ query += "?CreatorId,";
+ query += "?CreatedDate,";
+ query += "?ExpirationDate,";
+ query += "?Category,";
+ query += "?Name,";
+ query += "?Description,";
+ query += "?ParcelId,";
+ query += "?ParentEstate,";
+ query += "?SnapshotId,";
+ query += "?SimName,";
+ query += "?GlobalPos,";
+ query += "?ParcelName,";
+ query += "?Flags,";
+ query += "?ListingPrice ) ";
+ query += "ON DUPLICATE KEY UPDATE ";
+ query += "category=?Category, ";
+ query += "expirationdate=?ExpirationDate, ";
+ query += "name=?Name, ";
+ query += "description=?Description, ";
+ query += "parentestate=?ParentEstate, ";
+ query += "posglobal=?GlobalPos, ";
+ query += "parcelname=?ParcelName, ";
+ query += "classifiedflags=?Flags, ";
+ query += "priceforlisting=?ListingPrice, ";
+ query += "snapshotuuid=?SnapshotId";
+
+ if(string.IsNullOrEmpty(ad.ParcelName))
+ ad.ParcelName = "Unknown";
+ if(ad.ParcelId == null)
+ ad.ParcelId = UUID.Zero;
+ if(string.IsNullOrEmpty(ad.Description))
+ ad.Description = "No Description";
+
+ DateTime epoch = new DateTime(1970, 1, 1);
+ DateTime now = DateTime.Now;
+ TimeSpan epochnow = now - epoch;
+ TimeSpan duration;
+ DateTime expiration;
+ TimeSpan epochexp;
+
+ if(ad.Flags == 2)
+ {
+ duration = new TimeSpan(7,0,0,0);
+ expiration = now.Add(duration);
+ epochexp = expiration - epoch;
+ }
+ else
+ {
+ duration = new TimeSpan(365,0,0,0);
+ expiration = now.Add(duration);
+ epochexp = expiration - epoch;
+ }
+ ad.CreationDate = (int)epochnow.TotalSeconds;
+ ad.ExpirationDate = (int)epochexp.TotalSeconds;
+
+ try
+ {
+ using (MySqlConnection dbcon = new MySqlConnection(ConnectionString))
+ {
+ dbcon.Open();
+ using (MySqlCommand cmd = new MySqlCommand(query, dbcon))
+ {
+ cmd.Parameters.AddWithValue("?ClassifiedId", ad.ClassifiedId.ToString());
+ cmd.Parameters.AddWithValue("?CreatorId", ad.CreatorId.ToString());
+ cmd.Parameters.AddWithValue("?CreatedDate", ad.CreationDate.ToString());
+ cmd.Parameters.AddWithValue("?ExpirationDate", ad.ExpirationDate.ToString());
+ cmd.Parameters.AddWithValue("?Category", ad.Category.ToString());
+ cmd.Parameters.AddWithValue("?Name", ad.Name.ToString());
+ cmd.Parameters.AddWithValue("?Description", ad.Description.ToString());
+ cmd.Parameters.AddWithValue("?ParcelId", ad.ParcelId.ToString());
+ cmd.Parameters.AddWithValue("?ParentEstate", ad.ParentEstate.ToString());
+ cmd.Parameters.AddWithValue("?SnapshotId", ad.SnapshotId.ToString ());
+ cmd.Parameters.AddWithValue("?SimName", ad.SimName.ToString());
+ cmd.Parameters.AddWithValue("?GlobalPos", ad.GlobalPos.ToString());
+ cmd.Parameters.AddWithValue("?ParcelName", ad.ParcelName.ToString());
+ cmd.Parameters.AddWithValue("?Flags", ad.Flags.ToString());
+ cmd.Parameters.AddWithValue("?ListingPrice", ad.Price.ToString ());
+
+ cmd.ExecuteNonQuery();
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ m_log.DebugFormat("[PROFILES_DATA]" +
+ ": ClassifiedesUpdate exception {0}", e.Message);
+ result = e.Message;
+ return false;
+ }
+ return true;
+ }
+
+ public bool DeleteClassifiedRecord(UUID recordId)
+ {
+ string query = string.Empty;
+
+ query += "DELETE FROM classifieds WHERE ";
+ query += "classifieduuid = ?ClasifiedId";
+
+ try
+ {
+ using (MySqlConnection dbcon = new MySqlConnection(ConnectionString))
+ {
+ dbcon.Open();
+
+ using (MySqlCommand cmd = new MySqlCommand(query, dbcon))
+ {
+ cmd.Parameters.AddWithValue("?ClassifiedId", recordId.ToString());
+
+ lock(Lock)
+ {
+ cmd.ExecuteNonQuery();
+ }
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ m_log.DebugFormat("[PROFILES_DATA]" +
+ ": DeleteClassifiedRecord exception {0}", e.Message);
+ return false;
+ }
+ return true;
+ }
+
+ public bool GetClassifiedInfo(ref UserClassifiedAdd ad, ref string result)
+ {
+ string query = string.Empty;
+
+ query += "SELECT * FROM classifieds WHERE ";
+ query += "classifieduuid = ?AdId";
+
+ try
+ {
+ using (MySqlConnection dbcon = new MySqlConnection(ConnectionString))
+ {
+ dbcon.Open();
+ using (MySqlCommand cmd = new MySqlCommand(query, dbcon))
+ {
+ cmd.Parameters.AddWithValue("?AdId", ad.ClassifiedId.ToString());
+
+ using (MySqlDataReader reader = cmd.ExecuteReader())
+ {
+ if(reader.Read ())
+ {
+ ad.CreatorId = new UUID(reader.GetGuid("creatoruuid"));
+ ad.ParcelId = new UUID(reader.GetGuid("parceluuid"));
+ ad.SnapshotId = new UUID(reader.GetGuid("snapshotuuid"));
+ ad.CreationDate = Convert.ToInt32(reader["creationdate"]);
+ ad.ExpirationDate = Convert.ToInt32(reader["expirationdate"]);
+ ad.ParentEstate = Convert.ToInt32(reader["parentestate"]);
+ ad.Flags = (byte)reader.GetUInt32("classifiedflags");
+ ad.Category = reader.GetInt32("category");
+ ad.Price = reader.GetInt16("priceforlisting");
+ ad.Name = reader.GetString("name");
+ ad.Description = reader.GetString("description");
+ ad.SimName = reader.GetString("simname");
+ ad.GlobalPos = reader.GetString("posglobal");
+ ad.ParcelName = reader.GetString("parcelname");
+
+ }
+ }
+ }
+ dbcon.Close();
+ }
+ }
+ catch (Exception e)
+ {
+ m_log.DebugFormat("[PROFILES_DATA]" +
+ ": GetPickInfo exception {0}", e.Message);
+ }
+ return true;
+ }
+ #endregion Classifieds Queries
+
+ #region Picks Queries
+ public OSDArray GetAvatarPicks(UUID avatarId)
+ {
+ string query = string.Empty;
+
+ query += "SELECT `pickuuid`,`name` FROM userpicks WHERE ";
+ query += "creatoruuid = ?Id";
+ OSDArray data = new OSDArray();
+
+ try
+ {
+ using (MySqlConnection dbcon = new MySqlConnection(ConnectionString))
+ {
+ dbcon.Open();
+ using (MySqlCommand cmd = new MySqlCommand(query, dbcon))
+ {
+ cmd.Parameters.AddWithValue("?Id", avatarId.ToString());
+
+ using (MySqlDataReader reader = cmd.ExecuteReader())
+ {
+ if(reader.HasRows)
+ {
+ while (reader.Read())
+ {
+ OSDMap record = new OSDMap();
+
+ record.Add("pickuuid",OSD.FromString((string)reader["pickuuid"]));
+ record.Add("name",OSD.FromString((string)reader["name"]));
+ data.Add(record);
+ }
+ }
+ }
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ m_log.DebugFormat("[PROFILES_DATA]" +
+ ": GetAvatarPicks exception {0}", e.Message);
+ }
+ return data;
+ }
+
+ public UserProfilePick GetPickInfo(UUID avatarId, UUID pickId)
+ {
+ string query = string.Empty;
+ UserProfilePick pick = new UserProfilePick();
+
+ query += "SELECT * FROM userpicks WHERE ";
+ query += "creatoruuid = ?CreatorId AND ";
+ query += "pickuuid = ?PickId";
+
+ try
+ {
+ using (MySqlConnection dbcon = new MySqlConnection(ConnectionString))
+ {
+ dbcon.Open();
+ using (MySqlCommand cmd = new MySqlCommand(query, dbcon))
+ {
+ cmd.Parameters.AddWithValue("?CreatorId", avatarId.ToString());
+ cmd.Parameters.AddWithValue("?PickId", pickId.ToString());
+
+ using (MySqlDataReader reader = cmd.ExecuteReader())
+ {
+ if(reader.HasRows)
+ {
+ reader.Read();
+
+ string description = (string)reader["description"];
+
+ if (string.IsNullOrEmpty(description))
+ description = "No description given.";
+
+ UUID.TryParse((string)reader["pickuuid"], out pick.PickId);
+ UUID.TryParse((string)reader["creatoruuid"], out pick.CreatorId);
+ UUID.TryParse((string)reader["parceluuid"], out pick.ParcelId);
+ UUID.TryParse((string)reader["snapshotuuid"], out pick.SnapshotId);
+ pick.GlobalPos = (string)reader["posglobal"];
+ bool.TryParse((string)reader["toppick"], out pick.TopPick);
+ bool.TryParse((string)reader["enabled"], out pick.Enabled);
+ pick.Name = (string)reader["name"];
+ pick.Desc = description;
+ pick.User = (string)reader["user"];
+ pick.OriginalName = (string)reader["originalname"];
+ pick.SimName = (string)reader["simname"];
+ pick.SortOrder = (int)reader["sortorder"];
+ }
+ }
+ }
+ dbcon.Close();
+ }
+ }
+ catch (Exception e)
+ {
+ m_log.DebugFormat("[PROFILES_DATA]" +
+ ": GetPickInfo exception {0}", e.Message);
+ }
+ return pick;
+ }
+
+ public bool UpdatePicksRecord(UserProfilePick pick)
+ {
+ string query = string.Empty;
+
+ query += "INSERT INTO userpicks VALUES (";
+ query += "?PickId,";
+ query += "?CreatorId,";
+ query += "?TopPick,";
+ query += "?ParcelId,";
+ query += "?Name,";
+ query += "?Desc,";
+ query += "?SnapshotId,";
+ query += "?User,";
+ query += "?Original,";
+ query += "?SimName,";
+ query += "?GlobalPos,";
+ query += "?SortOrder,";
+ query += "?Enabled) ";
+ query += "ON DUPLICATE KEY UPDATE ";
+ query += "parceluuid=?ParcelId,";
+ query += "name=?Name,";
+ query += "description=?Desc,";
+ query += "snapshotuuid=?SnapshotId,";
+ query += "pickuuid=?PickId,";
+ query += "posglobal=?GlobalPos";
+
+ try
+ {
+ using (MySqlConnection dbcon = new MySqlConnection(ConnectionString))
+ {
+ dbcon.Open();
+ using (MySqlCommand cmd = new MySqlCommand(query, dbcon))
+ {
+ cmd.Parameters.AddWithValue("?PickId", pick.PickId.ToString());
+ cmd.Parameters.AddWithValue("?CreatorId", pick.CreatorId.ToString());
+ cmd.Parameters.AddWithValue("?TopPick", pick.TopPick.ToString());
+ cmd.Parameters.AddWithValue("?ParcelId", pick.ParcelId.ToString());
+ cmd.Parameters.AddWithValue("?Name", pick.Name.ToString());
+ cmd.Parameters.AddWithValue("?Desc", pick.Desc.ToString());
+ cmd.Parameters.AddWithValue("?SnapshotId", pick.SnapshotId.ToString());
+ cmd.Parameters.AddWithValue("?User", pick.User.ToString());
+ cmd.Parameters.AddWithValue("?Original", pick.OriginalName.ToString());
+ cmd.Parameters.AddWithValue("?SimName",pick.SimName.ToString());
+ cmd.Parameters.AddWithValue("?GlobalPos", pick.GlobalPos);
+ cmd.Parameters.AddWithValue("?SortOrder", pick.SortOrder.ToString ());
+ cmd.Parameters.AddWithValue("?Enabled", pick.Enabled.ToString());
+
+ cmd.ExecuteNonQuery();
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ m_log.DebugFormat("[PROFILES_DATA]" +
+ ": UpdateAvatarNotes exception {0}", e.Message);
+ return false;
+ }
+ return true;
+ }
+
+ public bool DeletePicksRecord(UUID pickId)
+ {
+ string query = string.Empty;
+
+ query += "DELETE FROM userpicks WHERE ";
+ query += "pickuuid = ?PickId";
+
+ try
+ {
+ using (MySqlConnection dbcon = new MySqlConnection(ConnectionString))
+ {
+ dbcon.Open();
+
+ using (MySqlCommand cmd = new MySqlCommand(query, dbcon))
+ {
+ cmd.Parameters.AddWithValue("?PickId", pickId.ToString());
+
+ cmd.ExecuteNonQuery();
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ m_log.DebugFormat("[PROFILES_DATA]" +
+ ": DeleteUserPickRecord exception {0}", e.Message);
+ return false;
+ }
+ return true;
+ }
+ #endregion Picks Queries
+
+ #region Avatar Notes Queries
+ public bool GetAvatarNotes(ref UserProfileNotes notes)
+ { // WIP
+ string query = string.Empty;
+
+ query += "SELECT `notes` FROM usernotes WHERE ";
+ query += "useruuid = ?Id AND ";
+ query += "targetuuid = ?TargetId";
+ OSDArray data = new OSDArray();
+
+ try
+ {
+ using (MySqlConnection dbcon = new MySqlConnection(ConnectionString))
+ {
+ dbcon.Open();
+ using (MySqlCommand cmd = new MySqlCommand(query, dbcon))
+ {
+ cmd.Parameters.AddWithValue("?Id", notes.UserId.ToString());
+ cmd.Parameters.AddWithValue("?TargetId", notes.TargetId.ToString());
+
+ using (MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleRow))
+ {
+ if(reader.HasRows)
+ {
+ reader.Read();
+ notes.Notes = OSD.FromString((string)reader["notes"]);
+ }
+ }
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ m_log.DebugFormat("[PROFILES_DATA]" +
+ ": GetAvatarNotes exception {0}", e.Message);
+ }
+ return true;
+ }
+
+ public bool UpdateAvatarNotes(ref UserProfileNotes note, ref string result)
+ {
+ string query = string.Empty;
+ bool remove;
+
+ if(string.IsNullOrEmpty(note.Notes))
+ {
+ remove = true;
+ query += "DELETE FROM usernotes WHERE ";
+ query += "useruuid=?UserId AND ";
+ query += "targetuuid=?TargetId";
+ }
+ else
+ {
+ remove = false;
+ query += "INSERT INTO usernotes VALUES ( ";
+ query += "?UserId,";
+ query += "?TargetId,";
+ query += "?Notes )";
+ query += "ON DUPLICATE KEY ";
+ query += "UPDATE ";
+ query += "notes=?Notes";
+ }
+
+ try
+ {
+ using (MySqlConnection dbcon = new MySqlConnection(ConnectionString))
+ {
+ dbcon.Open();
+ using (MySqlCommand cmd = new MySqlCommand(query, dbcon))
+ {
+ if(!remove)
+ cmd.Parameters.AddWithValue("?Notes", note.Notes);
+ cmd.Parameters.AddWithValue("?TargetId", note.TargetId.ToString ());
+ cmd.Parameters.AddWithValue("?UserId", note.UserId.ToString());
+
+ cmd.ExecuteNonQuery();
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ m_log.DebugFormat("[PROFILES_DATA]" +
+ ": UpdateAvatarNotes exception {0}", e.Message);
+ return false;
+ }
+ return true;
+
+ }
+ #endregion Avatar Notes Queries
+
+ #region Avatar Properties
+ public bool GetAvatarProperties(ref UserProfileProperties props, ref string result)
+ {
+ string query = string.Empty;
+
+ query += "SELECT * FROM userprofile WHERE ";
+ query += "useruuid = ?Id";
+
+ try
+ {
+ using (MySqlConnection dbcon = new MySqlConnection(ConnectionString))
+ {
+ dbcon.Open();
+ using (MySqlCommand cmd = new MySqlCommand(query, dbcon))
+ {
+ cmd.Parameters.AddWithValue("?Id", props.UserId.ToString());
+
+ using (MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleRow))
+ {
+ if(reader.HasRows)
+ {
+ m_log.DebugFormat("[PROFILES_DATA]" +
+ ": Getting data for {0}.", props.UserId);
+ reader.Read();
+ props.WebUrl = (string)reader["profileURL"];
+ UUID.TryParse((string)reader["profileImage"], out props.ImageId);
+ props.AboutText = (string)reader["profileAboutText"];
+ UUID.TryParse((string)reader["profileFirstImage"], out props.FirstLifeImageId);
+ props.FirstLifeText = (string)reader["profileFirstText"];
+ UUID.TryParse((string)reader["profilePartner"], out props.PartnerId);
+ props.WantToMask = (int)reader["profileWantToMask"];
+ props.WantToText = (string)reader["profileWantToText"];
+ props.SkillsMask = (int)reader["profileSkillsMask"];
+ props.SkillsText = (string)reader["profileSkillsText"];
+ props.Language = (string)reader["profileLanguages"];
+ }
+ else
+ {
+ m_log.DebugFormat("[PROFILES_DATA]" +
+ ": No data for {0}", props.UserId);
+
+ props.WebUrl = string.Empty;
+ props.ImageId = UUID.Zero;
+ props.AboutText = string.Empty;
+ props.FirstLifeImageId = UUID.Zero;
+ props.FirstLifeText = string.Empty;
+ props.PartnerId = UUID.Zero;
+ props.WantToMask = 0;
+ props.WantToText = string.Empty;
+ props.SkillsMask = 0;
+ props.SkillsText = string.Empty;
+ props.Language = string.Empty;
+
+ query = "INSERT INTO userprofile (`useruuid`) VALUES (?userId)";
+
+ dbcon.Close();
+ dbcon.Open();
+
+ using (MySqlCommand put = new MySqlCommand(query, dbcon))
+ {
+ put.Parameters.AddWithValue("?userId", props.UserId.ToString());
+ put.ExecuteNonQuery();
+ }
+ }
+ }
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ m_log.DebugFormat("[PROFILES_DATA]" +
+ ": Requst properties exception {0}", e.Message);
+ result = e.Message;
+ return false;
+ }
+ return true;
+ }
+
+ public bool UpdateAvatarProperties(ref UserProfileProperties props, ref string result)
+ {
+ string query = string.Empty;
+
+ query += "UPDATE userprofile SET ";
+ query += "profileURL=?profileURL, ";
+ query += "profileImage=?image, ";
+ query += "profileAboutText=?abouttext,";
+ query += "profileFirstImage=?firstlifeimage,";
+ query += "profileFirstText=?firstlifetext ";
+ query += "WHERE useruuid=?uuid";
+
+ try
+ {
+ using (MySqlConnection dbcon = new MySqlConnection(ConnectionString))
+ {
+ dbcon.Open();
+ using (MySqlCommand cmd = new MySqlCommand(query, dbcon))
+ {
+ cmd.Parameters.AddWithValue("?profileURL", props.WebUrl);
+ cmd.Parameters.AddWithValue("?image", props.ImageId.ToString());
+ cmd.Parameters.AddWithValue("?abouttext", props.AboutText);
+ cmd.Parameters.AddWithValue("?firstlifeimage", props.FirstLifeImageId.ToString());
+ cmd.Parameters.AddWithValue("?firstlifetext", props.FirstLifeText);
+ cmd.Parameters.AddWithValue("?uuid", props.UserId.ToString());
+
+ cmd.ExecuteNonQuery();
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ m_log.DebugFormat("[PROFILES_DATA]" +
+ ": AgentPropertiesUpdate exception {0}", e.Message);
+
+ return false;
+ }
+ return true;
+ }
+ #endregion Avatar Properties
+
+ #region Avatar Interests
+ public bool UpdateAvatarInterests(UserProfileProperties up, ref string result)
+ {
+ string query = string.Empty;
+
+ query += "UPDATE userprofile SET ";
+ query += "profileWantToMask=?WantMask, ";
+ query += "profileWantToText=?WantText,";
+ query += "profileSkillsMask=?SkillsMask,";
+ query += "profileSkillsText=?SkillsText, ";
+ query += "profileLanguages=?Languages ";
+ query += "WHERE useruuid=?uuid";
+
+ try
+ {
+ using (MySqlConnection dbcon = new MySqlConnection(ConnectionString))
+ {
+ dbcon.Open();
+ using (MySqlCommand cmd = new MySqlCommand(query, dbcon))
+ {
+ cmd.Parameters.AddWithValue("?WantMask", up.WantToMask);
+ cmd.Parameters.AddWithValue("?WantText", up.WantToText);
+ cmd.Parameters.AddWithValue("?SkillsMask", up.SkillsMask);
+ cmd.Parameters.AddWithValue("?SkillsText", up.SkillsText);
+ cmd.Parameters.AddWithValue("?Languages", up.Language);
+ cmd.Parameters.AddWithValue("?uuid", up.UserId.ToString());
+
+ cmd.ExecuteNonQuery();
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ m_log.DebugFormat("[PROFILES_DATA]" +
+ ": AgentInterestsUpdate exception {0}", e.Message);
+ result = e.Message;
+ return false;
+ }
+ return true;
+ }
+ #endregion Avatar Interests
+
+ public OSDArray GetUserImageAssets(UUID avatarId)
+ {
+ OSDArray data = new OSDArray();
+ string query = "SELECT `snapshotuuid` FROM {0} WHERE `creatoruuid` = ?Id";
+
+ // Get classified image assets
+
+
+ try
+ {
+ using (MySqlConnection dbcon = new MySqlConnection(ConnectionString))
+ {
+ dbcon.Open();
+
+ using (MySqlCommand cmd = new MySqlCommand(string.Format (query,"`classifieds`"), dbcon))
+ {
+ cmd.Parameters.AddWithValue("?Id", avatarId.ToString());
+
+ using (MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleRow))
+ {
+ if(reader.HasRows)
+ {
+ while (reader.Read())
+ {
+ data.Add(new OSDString((string)reader["snapshotuuid"].ToString ()));
+ }
+ }
+ }
+ }
+
+ dbcon.Close();
+ dbcon.Open();
+
+ using (MySqlCommand cmd = new MySqlCommand(string.Format (query,"`userpicks`"), dbcon))
+ {
+ cmd.Parameters.AddWithValue("?Id", avatarId.ToString());
+
+ using (MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleRow))
+ {
+ if(reader.HasRows)
+ {
+ while (reader.Read())
+ {
+ data.Add(new OSDString((string)reader["snapshotuuid"].ToString ()));
+ }
+ }
+ }
+ }
+
+ dbcon.Close();
+ dbcon.Open();
+
+ query = "SELECT `profileImage`, `profileFirstImage` FROM `userprofile` WHERE `useruuid` = ?Id";
+
+ using (MySqlCommand cmd = new MySqlCommand(string.Format (query,"`userpicks`"), dbcon))
+ {
+ cmd.Parameters.AddWithValue("?Id", avatarId.ToString());
+
+ using (MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleRow))
+ {
+ if(reader.HasRows)
+ {
+ while (reader.Read())
+ {
+ data.Add(new OSDString((string)reader["profileImage"].ToString ()));
+ data.Add(new OSDString((string)reader["profileFirstImage"].ToString ()));
+ }
+ }
+ }
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ m_log.DebugFormat("[PROFILES_DATA]" +
+ ": GetAvatarNotes exception {0}", e.Message);
+ }
+ return data;
+ }
+
+ #region User Preferences
+ public OSDArray GetUserPreferences(UUID avatarId)
+ {
+ string query = string.Empty;
+
+ query += "SELECT imviaemail,visible,email FROM ";
+ query += "usersettings WHERE ";
+ query += "useruuid = ?Id";
+
+ OSDArray data = new OSDArray();
+
+ try
+ {
+ using (MySqlConnection dbcon = new MySqlConnection(ConnectionString))
+ {
+ dbcon.Open();
+ using (MySqlCommand cmd = new MySqlCommand(query, dbcon))
+ {
+ cmd.Parameters.AddWithValue("?Id", avatarId.ToString());
+
+ using (MySqlDataReader reader = cmd.ExecuteReader())
+ {
+ if(reader.HasRows)
+ {
+ reader.Read();
+ OSDMap record = new OSDMap();
+
+ record.Add("imviaemail",OSD.FromString((string)reader["imviaemail"]));
+ record.Add("visible",OSD.FromString((string)reader["visible"]));
+ record.Add("email",OSD.FromString((string)reader["email"]));
+ data.Add(record);
+ }
+ else
+ {
+ using (MySqlCommand put = new MySqlCommand(query, dbcon))
+ {
+ query = "INSERT INTO usersettings VALUES ";
+ query += "(?Id,'false','false', '')";
+
+ lock(Lock)
+ {
+ put.ExecuteNonQuery();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ m_log.DebugFormat("[PROFILES_DATA]" +
+ ": Get preferences exception {0}", e.Message);
+ }
+ return data;
+ }
+
+ public bool UpdateUserPreferences(bool emailIm, bool visible, UUID avatarId )
+ {
+ string query = string.Empty;
+
+ query += "UPDATE userpsettings SET ";
+ query += "imviaemail=?ImViaEmail, ";
+ query += "visible=?Visible,";
+ query += "WHERE useruuid=?uuid";
+
+ try
+ {
+ using (MySqlConnection dbcon = new MySqlConnection(ConnectionString))
+ {
+ dbcon.Open();
+ using (MySqlCommand cmd = new MySqlCommand(query, dbcon))
+ {
+ cmd.Parameters.AddWithValue("?ImViaEmail", emailIm.ToString().ToLower ());
+ cmd.Parameters.AddWithValue("?WantText", visible.ToString().ToLower ());
+ cmd.Parameters.AddWithValue("?uuid", avatarId.ToString());
+
+ lock(Lock)
+ {
+ cmd.ExecuteNonQuery();
+ }
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ m_log.DebugFormat("[PROFILES_DATA]" +
+ ": AgentInterestsUpdate exception {0}", e.Message);
+ return false;
+ }
+ return true;
+ }
+ #endregion User Preferences
+
+ #region Integration
+ public bool GetUserAppData(ref UserAppData props, ref string result)
+ {
+ string query = string.Empty;
+
+ query += "SELECT * FROM `userdata` WHERE ";
+ query += "UserId = ?Id AND ";
+ query += "TagId = ?TagId";
+
+ try
+ {
+ using (MySqlConnection dbcon = new MySqlConnection(ConnectionString))
+ {
+ dbcon.Open();
+ using (MySqlCommand cmd = new MySqlCommand(query, dbcon))
+ {
+ cmd.Parameters.AddWithValue("?Id", props.UserId.ToString());
+ cmd.Parameters.AddWithValue ("?TagId", props.TagId.ToString());
+
+ using (MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleRow))
+ {
+ if(reader.HasRows)
+ {
+ reader.Read();
+ props.DataKey = (string)reader["DataKey"];
+ props.DataVal = (string)reader["DataVal"];
+ }
+ else
+ {
+ query += "INSERT INTO userdata VALUES ( ";
+ query += "?UserId,";
+ query += "?TagId,";
+ query += "?DataKey,";
+ query += "?DataVal) ";
+
+ using (MySqlCommand put = new MySqlCommand(query, dbcon))
+ {
+ put.Parameters.AddWithValue("?Id", props.UserId.ToString());
+ put.Parameters.AddWithValue("?TagId", props.TagId.ToString());
+ put.Parameters.AddWithValue("?DataKey", props.DataKey.ToString());
+ put.Parameters.AddWithValue("?DataVal", props.DataVal.ToString());
+
+ lock(Lock)
+ {
+ put.ExecuteNonQuery();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ m_log.DebugFormat("[PROFILES_DATA]" +
+ ": Requst application data exception {0}", e.Message);
+ result = e.Message;
+ return false;
+ }
+ return true;
+ }
+
+ public bool SetUserAppData(UserAppData props, ref string result)
+ {
+ string query = string.Empty;
+
+ query += "UPDATE userdata SET ";
+ query += "TagId = ?TagId, ";
+ query += "DataKey = ?DataKey, ";
+ query += "DataVal = ?DataVal WHERE ";
+ query += "UserId = ?UserId AND ";
+ query += "TagId = ?TagId";
+
+ try
+ {
+ using (MySqlConnection dbcon = new MySqlConnection(ConnectionString))
+ {
+ dbcon.Open();
+ using (MySqlCommand cmd = new MySqlCommand(query, dbcon))
+ {
+ cmd.Parameters.AddWithValue("?UserId", props.UserId.ToString());
+ cmd.Parameters.AddWithValue("?TagId", props.TagId.ToString ());
+ cmd.Parameters.AddWithValue("?DataKey", props.DataKey.ToString ());
+ cmd.Parameters.AddWithValue("?DataVal", props.DataKey.ToString ());
+
+ lock(Lock)
+ {
+ cmd.ExecuteNonQuery();
+ }
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ m_log.DebugFormat("[PROFILES_DATA]" +
+ ": SetUserData exception {0}", e.Message);
+ return false;
+ }
+ return true;
+ }
+ #endregion Integration
+ }
+}
+
diff --git a/OpenSim/Data/MySQL/Resources/UserProfiles.migrations b/OpenSim/Data/MySQL/Resources/UserProfiles.migrations
new file mode 100644
index 0000000000..c29f1abf3e
--- /dev/null
+++ b/OpenSim/Data/MySQL/Resources/UserProfiles.migrations
@@ -0,0 +1,83 @@
+:VERSION 1 # -------------------------------
+
+begin;
+
+CREATE TABLE IF NOT EXISTS `classifieds` (
+ `classifieduuid` char(36) NOT NULL,
+ `creatoruuid` char(36) NOT NULL,
+ `creationdate` int(20) NOT NULL,
+ `expirationdate` int(20) NOT NULL,
+ `category` varchar(20) NOT NULL,
+ `name` varchar(255) NOT NULL,
+ `description` text NOT NULL,
+ `parceluuid` char(36) NOT NULL,
+ `parentestate` int(11) NOT NULL,
+ `snapshotuuid` char(36) NOT NULL,
+ `simname` varchar(255) NOT NULL,
+ `posglobal` varchar(255) NOT NULL,
+ `parcelname` varchar(255) NOT NULL,
+ `classifiedflags` int(8) NOT NULL,
+ `priceforlisting` int(5) NOT NULL,
+ PRIMARY KEY (`classifieduuid`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+
+
+CREATE TABLE IF NOT EXISTS `usernotes` (
+ `useruuid` varchar(36) NOT NULL,
+ `targetuuid` varchar(36) NOT NULL,
+ `notes` text NOT NULL,
+ UNIQUE KEY `useruuid` (`useruuid`,`targetuuid`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+
+CREATE TABLE IF NOT EXISTS `userpicks` (
+ `pickuuid` varchar(36) NOT NULL,
+ `creatoruuid` varchar(36) NOT NULL,
+ `toppick` enum('true','false') NOT NULL,
+ `parceluuid` varchar(36) NOT NULL,
+ `name` varchar(255) NOT NULL,
+ `description` text NOT NULL,
+ `snapshotuuid` varchar(36) NOT NULL,
+ `user` varchar(255) NOT NULL,
+ `originalname` varchar(255) NOT NULL,
+ `simname` varchar(255) NOT NULL,
+ `posglobal` varchar(255) NOT NULL,
+ `sortorder` int(2) NOT NULL,
+ `enabled` enum('true','false') NOT NULL,
+ PRIMARY KEY (`pickuuid`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+
+CREATE TABLE IF NOT EXISTS `userprofile` (
+ `useruuid` varchar(36) NOT NULL,
+ `profilePartner` varchar(36) NOT NULL,
+ `profileAllowPublish` binary(1) NOT NULL,
+ `profileMaturePublish` binary(1) NOT NULL,
+ `profileURL` varchar(255) NOT NULL,
+ `profileWantToMask` int(3) NOT NULL,
+ `profileWantToText` text NOT NULL,
+ `profileSkillsMask` int(3) NOT NULL,
+ `profileSkillsText` text NOT NULL,
+ `profileLanguages` text NOT NULL,
+ `profileImage` varchar(36) NOT NULL,
+ `profileAboutText` text NOT NULL,
+ `profileFirstImage` varchar(36) NOT NULL,
+ `profileFirstText` text NOT NULL,
+ PRIMARY KEY (`useruuid`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+commit;
+
+:VERSION 2 # -------------------------------
+
+begin;
+CREATE TABLE IF NOT EXISTS `userdata` (
+ `UserId` char(36) NOT NULL,
+ `TagId` varchar(64) NOT NULL,
+ `DataKey` varchar(255),
+ `DataVal` varchar(255),
+ PRIMARY KEY (`UserId`,`TagId`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+commit;
+
diff --git a/OpenSim/Framework/UserProfiles.cs b/OpenSim/Framework/UserProfiles.cs
new file mode 100644
index 0000000000..aabbb84538
--- /dev/null
+++ b/OpenSim/Framework/UserProfiles.cs
@@ -0,0 +1,90 @@
+using System;
+using OpenMetaverse;
+
+namespace OpenSim.Framework
+{
+ public class UserClassifiedAdd
+ {
+ public UUID ClassifiedId = UUID.Zero;
+ public UUID CreatorId = UUID.Zero;
+ public int CreationDate = 0;
+ public int ExpirationDate = 0;
+ public int Category = 0;
+ public string Name = string.Empty;
+ public string Description = string.Empty;
+ public UUID ParcelId = UUID.Zero;
+ public int ParentEstate = 0;
+ public UUID SnapshotId = UUID.Zero;
+ public string SimName = string.Empty;
+ public string GlobalPos = "<0,0,0>";
+ public string ParcelName = string.Empty;
+ public byte Flags = 0;
+ public int Price = 0;
+ }
+
+ public class UserProfileProperties
+ {
+ public UUID UserId = UUID.Zero;
+ public UUID PartnerId = UUID.Zero;
+ public bool PublishProfile = false;
+ public bool PublishMature = false;
+ public string WebUrl = string.Empty;
+ public int WantToMask = 0;
+ public string WantToText = string.Empty;
+ public int SkillsMask = 0;
+ public string SkillsText = string.Empty;
+ public string Language = string.Empty;
+ public UUID ImageId = UUID.Zero;
+ public string AboutText = string.Empty;
+ public UUID FirstLifeImageId = UUID.Zero;
+ public string FirstLifeText = string.Empty;
+ }
+
+ public class UserProfilePick
+ {
+ public UUID PickId = UUID.Zero;
+ public UUID CreatorId = UUID.Zero;
+ public bool TopPick = false;
+ public string Name = string.Empty;
+ public string OriginalName = string.Empty;
+ public string Desc = string.Empty;
+ public UUID ParcelId = UUID.Zero;
+ public UUID SnapshotId = UUID.Zero;
+ public string User = string.Empty;
+ public string SimName = string.Empty;
+ public string GlobalPos = "<0,0,0>";
+ public int SortOrder = 0;
+ public bool Enabled = false;
+ }
+
+ public class UserProfileNotes
+ {
+ public UUID UserId;
+ public UUID TargetId;
+ public string Notes;
+ }
+
+ public class UserAccountProperties
+ {
+ public string EmailAddress = string.Empty;
+ public string Firstname = string.Empty;
+ public string LastName = string.Empty;
+ public string Password = string.Empty;
+ public string UserId = string.Empty;
+ }
+
+ public class UserAccountAuth
+ {
+ public string UserId = UUID.Zero.ToString();
+ public string Password = string.Empty;
+ }
+
+ public class UserAppData
+ {
+ public string TagId = string.Empty;
+ public string DataKey = string.Empty;
+ public string UserId = UUID.Zero.ToString();
+ public string DataVal = string.Empty;
+ }
+}
+
diff --git a/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs b/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs
deleted file mode 100644
index bf24030771..0000000000
--- a/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * 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.Globalization;
-using System.Reflection;
-
-using OpenMetaverse;
-using log4net;
-using Nini.Config;
-using Mono.Addins;
-
-using OpenSim.Framework;
-using OpenSim.Region.Framework.Interfaces;
-using OpenSim.Region.Framework.Scenes;
-using OpenSim.Services.Interfaces;
-
-namespace OpenSim.Region.CoreModules.Avatar.Profile
-{
- [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "BasicProfileModule")]
- public class BasicProfileModule : IProfileModule, ISharedRegionModule
- {
- private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
-
- //
- // Module vars
- //
- private List m_Scenes = new List();
- private bool m_Enabled = false;
-
- #region ISharedRegionModule
-
- public void Initialise(IConfigSource config)
- {
- m_log.DebugFormat("[PROFILE MODULE]: Basic Profile Module enabled");
- m_Enabled = true;
- }
-
- public void AddRegion(Scene scene)
- {
- if (!m_Enabled)
- return;
-
- lock (m_Scenes)
- {
- if (!m_Scenes.Contains(scene))
- {
- m_Scenes.Add(scene);
- // Hook up events
- scene.EventManager.OnNewClient += OnNewClient;
- scene.RegisterModuleInterface(this);
- }
- }
- }
-
- public void RegionLoaded(Scene scene)
- {
- if (!m_Enabled)
- return;
- }
-
- public void RemoveRegion(Scene scene)
- {
- if (!m_Enabled)
- return;
-
- lock (m_Scenes)
- {
- m_Scenes.Remove(scene);
- }
- }
-
- public void PostInitialise()
- {
- }
-
- public void Close()
- {
- }
-
- public string Name
- {
- get { return "BasicProfileModule"; }
- }
-
- public Type ReplaceableInterface
- {
- get { return typeof(IProfileModule); }
- }
-
- #endregion
-
- /// New Client Event Handler
- private void OnNewClient(IClientAPI client)
- {
- //Profile
- client.OnRequestAvatarProperties += RequestAvatarProperties;
- }
-
- public void RequestAvatarProperties(IClientAPI remoteClient, UUID avatarID)
- {
- IScene s = remoteClient.Scene;
- if (!(s is Scene))
- return;
-
-// Scene scene = (Scene)s;
-
- string profileUrl = String.Empty;
- string aboutText = String.Empty;
- string firstLifeAboutText = String.Empty;
- UUID image = UUID.Zero;
- UUID firstLifeImage = UUID.Zero;
- UUID partner = UUID.Zero;
- uint wantMask = 0;
- string wantText = String.Empty;
- uint skillsMask = 0;
- string skillsText = String.Empty;
- string languages = String.Empty;
-
- UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, avatarID);
-
- string name = "Avatar";
- int created = 0;
- if (account != null)
- {
- name = account.FirstName + " " + account.LastName;
- created = account.Created;
- }
- Byte[] charterMember = Utils.StringToBytes(name);
-
- profileUrl = "No profile data";
- aboutText = string.Empty;
- firstLifeAboutText = string.Empty;
- image = UUID.Zero;
- firstLifeImage = UUID.Zero;
- partner = UUID.Zero;
-
- remoteClient.SendAvatarProperties(avatarID, aboutText,
- Util.ToDateTime(created).ToString(
- "M/d/yyyy", CultureInfo.InvariantCulture),
- charterMember, firstLifeAboutText,
- (uint)(0 & 0xff),
- firstLifeImage, image, profileUrl, partner);
-
- //Viewer expects interest data when it asks for properties.
- remoteClient.SendAvatarInterestsReply(avatarID, wantMask, wantText,
- skillsMask, skillsText, languages);
- }
-
- }
-}
diff --git a/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs b/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs
new file mode 100644
index 0000000000..563617d6b8
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs
@@ -0,0 +1,1386 @@
+/*
+ * 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.IO;
+using System.Text;
+using System.Collections;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Net;
+using System.Net.Sockets;
+using System.Reflection;
+using System.Xml;
+using OpenMetaverse;
+using OpenMetaverse.StructuredData;
+using log4net;
+using Nini.Config;
+using Nwc.XmlRpc;
+using OpenSim.Framework;
+using OpenSim.Region.Framework.Interfaces;
+using OpenSim.Region.Framework.Scenes;
+using OpenSim.Services.Interfaces;
+using Mono.Addins;
+using OpenSim.Services.Connectors.Hypergrid;
+
+namespace OpenSim.Region.OptionalModules.Avatar.UserProfiles
+{
+ [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "UserProfilesModule")]
+ public class UserProfileModule : IProfileModule, INonSharedRegionModule
+ {
+ ///
+ /// Logging
+ ///
+ static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+
+ // The pair of Dictionaries are used to handle the switching of classified ads
+ // by maintaining a cache of classified id to creator id mappings and an interest
+ // count. The entries are removed when the interest count reaches 0.
+ Dictionary classifiedCache = new Dictionary();
+ Dictionary classifiedInterest = new Dictionary();
+
+ public Scene Scene
+ {
+ get; private set;
+ }
+
+ ///
+ /// Gets or sets the ConfigSource.
+ ///
+ ///
+ /// The configuration
+ ///
+ public IConfigSource Config {
+ get;
+ set;
+ }
+
+ ///
+ /// Gets or sets the URI to the profile server.
+ ///
+ ///
+ /// The profile server URI.
+ ///
+ public string ProfileServerUri {
+ get;
+ set;
+ }
+
+ IProfileModule ProfileModule
+ {
+ get; set;
+ }
+
+ IUserManagement UserManagementModule
+ {
+ get; set;
+ }
+
+ ///
+ /// Gets or sets a value indicating whether this
+ /// is enabled.
+ ///
+ ///
+ /// true if enabled; otherwise, false.
+ ///
+ public bool Enabled {
+ get;
+ set;
+ }
+
+ #region IRegionModuleBase implementation
+ ///
+ /// This is called to initialize the region module. For shared modules, this is called exactly once, after
+ /// creating the single (shared) instance. For non-shared modules, this is called once on each instance, after
+ /// the instace for the region has been created.
+ ///
+ ///
+ /// Source.
+ ///
+ public void Initialise(IConfigSource source)
+ {
+ Config = source;
+
+ IConfig profileConfig = Config.Configs["Profile"];
+
+ if (profileConfig == null)
+ {
+ Enabled = false;
+ return;
+ }
+
+ // If we find ProfileURL then we configure for FULL support
+ // else we setup for BASIC support
+ ProfileServerUri = profileConfig.GetString("ProfileURL", "");
+ if (ProfileServerUri == "")
+ {
+ m_log.Info("[PROFILES] UserProfiles module is activated in BASIC mode");
+ Enabled = false;
+ return;
+ }
+ else
+ {
+ m_log.Info("[PROFILES] UserProfiles module is activated in FULL mode");
+ Enabled = true;
+ }
+ }
+
+ ///
+ /// Adds the region.
+ ///
+ ///
+ /// Scene.
+ ///
+ public void AddRegion(Scene scene)
+ {
+ Scene = scene;
+ Scene.RegisterModuleInterface(this);
+ Scene.EventManager.OnNewClient += OnNewClient;
+ Scene.EventManager.OnMakeRootAgent += HandleOnMakeRootAgent;
+
+ UserManagementModule = Scene.RequestModuleInterface();
+ }
+
+ void HandleOnMakeRootAgent (ScenePresence obj)
+ {
+ GetImageAssets(((IScenePresence)obj).UUID);
+ }
+
+ ///
+ /// Removes the region.
+ ///
+ ///
+ /// Scene.
+ ///
+ public void RemoveRegion(Scene scene)
+ {
+ }
+
+ ///
+ /// This will be called once for every scene loaded. In a shared module this will be multiple times in one
+ /// instance, while a nonshared module instance will only be called once. This method is called after AddRegion
+ /// has been called in all modules for that scene, providing an opportunity to request another module's
+ /// interface, or hook an event from another module.
+ ///
+ ///
+ /// Scene.
+ ///
+ public void RegionLoaded(Scene scene)
+ {
+ }
+
+ ///
+ /// If this returns non-null, it is the type of an interface that this module intends to register. This will
+ /// cause the loader to defer loading of this module until all other modules have been loaded. If no other
+ /// module has registered the interface by then, this module will be activated, else it will remain inactive,
+ /// letting the other module take over. This should return non-null ONLY in modules that are intended to be
+ /// easily replaceable, e.g. stub implementations that the developer expects to be replaced by third party
+ /// provided modules.
+ ///
+ ///
+ /// The replaceable interface.
+ ///
+ public Type ReplaceableInterface
+ {
+ get { return typeof(IProfileModule); }
+ }
+
+ ///
+ /// Called as the instance is closed.
+ ///
+ public void Close()
+ {
+ }
+
+ ///
+ /// The name of the module
+ ///
+ ///
+ /// Gets the module name.
+ ///
+ public string Name
+ {
+ get { return "UserProfileModule"; }
+ }
+ #endregion IRegionModuleBase implementation
+
+ #region Region Event Handlers
+ ///
+ /// Raises the new client event.
+ ///
+ ///
+ /// Client.
+ ///
+ void OnNewClient(IClientAPI client)
+ {
+ // Basic or Full module?
+ if(!Enabled)
+ {
+ client.OnRequestAvatarProperties += BasicRequestProperties;
+ return;
+ }
+
+ //Profile
+ client.OnRequestAvatarProperties += RequestAvatarProperties;
+ client.OnUpdateAvatarProperties += AvatarPropertiesUpdate;
+ client.OnAvatarInterestUpdate += AvatarInterestsUpdate;
+
+ // Classifieds
+ client.AddGenericPacketHandler("avatarclassifiedsrequest", ClassifiedsRequest);
+ client.OnClassifiedInfoUpdate += ClassifiedInfoUpdate;
+ client.OnClassifiedInfoRequest += ClassifiedInfoRequest;
+ client.OnClassifiedDelete += ClassifiedDelete;
+
+ // Picks
+ client.AddGenericPacketHandler("avatarpicksrequest", PicksRequest);
+ client.AddGenericPacketHandler("pickinforequest", PickInfoRequest);
+ client.OnPickInfoUpdate += PickInfoUpdate;
+ client.OnPickDelete += PickDelete;
+
+ // Notes
+ client.AddGenericPacketHandler("avatarnotesrequest", NotesRequest);
+ client.OnAvatarNotesUpdate += NotesUpdate;
+ }
+ #endregion Region Event Handlers
+
+ #region Classified
+ ///
+ ///
+ /// Handles the avatar classifieds request.
+ ///
+ ///
+ /// Sender.
+ ///
+ ///
+ /// Method.
+ ///
+ ///
+ /// Arguments.
+ ///
+ public void ClassifiedsRequest(Object sender, string method, List args)
+ {
+ if (!(sender is IClientAPI))
+ return;
+
+ IClientAPI remoteClient = (IClientAPI)sender;
+
+ UUID targetID;
+ UUID.TryParse(args[0], out targetID);
+
+ // Can't handle NPC yet...
+ ScenePresence p = FindPresence(targetID);
+
+ if (null != p)
+ {
+ if (p.PresenceType == PresenceType.Npc)
+ return;
+ }
+
+ string serverURI = string.Empty;
+ bool foreign = GetUserProfileServerURI(targetID, out serverURI);
+ UUID creatorId = UUID.Zero;
+
+ OSDMap parameters= new OSDMap();
+ UUID.TryParse(args[0], out creatorId);
+ parameters.Add("creatorId", OSD.FromUUID(creatorId));
+ OSD Params = (OSD)parameters;
+ if(!JsonRpcRequest(ref Params, "avatarclassifiedsrequest", serverURI, UUID.Random().ToString()))
+ {
+ // Error Handling here!
+ // if(parameters.ContainsKey("message")
+ }
+
+ parameters = (OSDMap)Params;
+
+ OSDArray list = (OSDArray)parameters["result"];
+
+ Dictionary classifieds = new Dictionary();
+
+ foreach(OSD map in list)
+ {
+ OSDMap m = (OSDMap)map;
+ UUID cid = m["classifieduuid"].AsUUID();
+ string name = m["name"].AsString();
+
+ classifieds[cid] = name;
+
+ if(!classifiedCache.ContainsKey(cid))
+ {
+ classifiedCache.Add(cid,creatorId);
+ classifiedInterest.Add(cid, 0);
+ }
+
+ classifiedInterest[cid] ++;
+ }
+
+ remoteClient.SendAvatarClassifiedReply(new UUID(args[0]), classifieds);
+ }
+
+ public void ClassifiedInfoRequest(UUID queryClassifiedID, IClientAPI remoteClient)
+ {
+ UUID target = remoteClient.AgentId;
+ UserClassifiedAdd ad = new UserClassifiedAdd();
+ ad.ClassifiedId = queryClassifiedID;
+
+ if(classifiedCache.ContainsKey(queryClassifiedID))
+ {
+ target = classifiedCache[queryClassifiedID];
+
+ if(classifiedInterest[queryClassifiedID] -- == 0)
+ {
+ lock(classifiedCache)
+ {
+ lock(classifiedInterest)
+ {
+ classifiedInterest.Remove(queryClassifiedID);
+ }
+ classifiedCache.Remove(queryClassifiedID);
+ }
+ }
+ }
+
+
+ string serverURI = string.Empty;
+ bool foreign = GetUserProfileServerURI(target, out serverURI);
+
+ object Ad = (object)ad;
+ if(!JsonRpcRequest(ref Ad, "classifieds_info_query", serverURI, UUID.Random().ToString()))
+ {
+ remoteClient.SendAgentAlertMessage(
+ "Error getting classified info", false);
+ return;
+ }
+ ad = (UserClassifiedAdd) Ad;
+
+ if(ad.CreatorId == UUID.Zero)
+ return;
+
+ Vector3 globalPos = new Vector3();
+ Vector3.TryParse(ad.GlobalPos, out globalPos);
+
+ remoteClient.SendClassifiedInfoReply(ad.ClassifiedId, ad.CreatorId, (uint)ad.CreationDate, (uint)ad.ExpirationDate,
+ (uint)ad.Category, ad.Name, ad.Description, ad.ParcelId, (uint)ad.ParentEstate,
+ ad.SnapshotId, ad.SimName, globalPos, ad.ParcelName, ad.Flags, ad.Price);
+
+ }
+
+ ///
+ /// Classifieds info update.
+ ///
+ ///
+ /// Queryclassified I.
+ ///
+ ///
+ /// Query category.
+ ///
+ ///
+ /// Query name.
+ ///
+ ///
+ /// Query description.
+ ///
+ ///
+ /// Query parcel I.
+ ///
+ ///
+ /// Query parent estate.
+ ///
+ ///
+ /// Query snapshot I.
+ ///
+ ///
+ /// Query global position.
+ ///
+ ///
+ /// Queryclassified flags.
+ ///
+ ///
+ /// Queryclassified price.
+ ///
+ ///
+ /// Remote client.
+ ///
+ public void ClassifiedInfoUpdate(UUID queryclassifiedID, uint queryCategory, string queryName, string queryDescription, UUID queryParcelID,
+ uint queryParentEstate, UUID querySnapshotID, Vector3 queryGlobalPos, byte queryclassifiedFlags,
+ int queryclassifiedPrice, IClientAPI remoteClient)
+ {
+ UserClassifiedAdd ad = new UserClassifiedAdd();
+
+ Scene s = (Scene) remoteClient.Scene;
+ Vector3 pos = remoteClient.SceneAgent.AbsolutePosition;
+ ILandObject land = s.LandChannel.GetLandObject(pos.X, pos.Y);
+ ScenePresence p = FindPresence(remoteClient.AgentId);
+ Vector3 avaPos = p.AbsolutePosition;
+
+ string serverURI = string.Empty;
+ bool foreign = GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
+
+ if (land == null)
+ {
+ ad.ParcelName = string.Empty;
+ }
+ else
+ {
+ ad.ParcelName = land.LandData.Name;
+ }
+
+ ad.CreatorId = remoteClient.AgentId;
+ ad.ClassifiedId = queryclassifiedID;
+ ad.Category = Convert.ToInt32(queryCategory);
+ ad.Name = queryName;
+ ad.Description = queryDescription;
+ ad.ParentEstate = Convert.ToInt32(queryParentEstate);
+ ad.SnapshotId = querySnapshotID;
+ ad.SimName = remoteClient.Scene.RegionInfo.RegionName;
+ ad.GlobalPos = queryGlobalPos.ToString ();
+ ad.Flags = queryclassifiedFlags;
+ ad.Price = queryclassifiedPrice;
+ ad.ParcelId = p.currentParcelUUID;
+
+ object Ad = ad;
+
+ OSD X = OSD.SerializeMembers(Ad);
+
+ if(!JsonRpcRequest(ref Ad, "classified_update", serverURI, UUID.Random().ToString()))
+ {
+ remoteClient.SendAgentAlertMessage(
+ "Error updating classified", false);
+ }
+ }
+
+ ///
+ /// Classifieds delete.
+ ///
+ ///
+ /// Query classified I.
+ ///
+ ///
+ /// Remote client.
+ ///
+ public void ClassifiedDelete(UUID queryClassifiedID, IClientAPI remoteClient)
+ {
+ string serverURI = string.Empty;
+ bool foreign = GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
+
+ UUID classifiedId;
+ OSDMap parameters= new OSDMap();
+ UUID.TryParse(queryClassifiedID.ToString(), out classifiedId);
+ parameters.Add("classifiedId", OSD.FromUUID(classifiedId));
+ OSD Params = (OSD)parameters;
+ if(!JsonRpcRequest(ref Params, "classified_delete", serverURI, UUID.Random().ToString()))
+ {
+ remoteClient.SendAgentAlertMessage(
+ "Error classified delete", false);
+ }
+
+ parameters = (OSDMap)Params;
+ }
+ #endregion Classified
+
+ #region Picks
+ ///
+ /// Handles the avatar picks request.
+ ///
+ ///
+ /// Sender.
+ ///
+ ///
+ /// Method.
+ ///
+ ///
+ /// Arguments.
+ ///
+ public void PicksRequest(Object sender, string method, List args)
+ {
+ if (!(sender is IClientAPI))
+ return;
+
+ IClientAPI remoteClient = (IClientAPI)sender;
+
+ UUID targetId;
+ UUID.TryParse(args[0], out targetId);
+
+ // Can't handle NPC yet...
+ ScenePresence p = FindPresence(targetId);
+
+ if (null != p)
+ {
+ if (p.PresenceType == PresenceType.Npc)
+ return;
+ }
+
+ string serverURI = string.Empty;
+ bool foreign = GetUserProfileServerURI(targetId, out serverURI);
+
+ OSDMap parameters= new OSDMap();
+ parameters.Add("creatorId", OSD.FromUUID(targetId));
+ OSD Params = (OSD)parameters;
+ if(!JsonRpcRequest(ref Params, "avatarpicksrequest", serverURI, UUID.Random().ToString()))
+ {
+ remoteClient.SendAgentAlertMessage(
+ "Error requesting picks", false);
+ return;
+ }
+
+ parameters = (OSDMap)Params;
+
+ OSDArray list = (OSDArray)parameters["result"];
+
+ Dictionary picks = new Dictionary();
+
+ foreach(OSD map in list)
+ {
+ OSDMap m = (OSDMap)map;
+ UUID cid = m["pickuuid"].AsUUID();
+ string name = m["name"].AsString();
+
+ m_log.DebugFormat("[PROFILES]: PicksRequest {0}", name);
+
+ picks[cid] = name;
+ }
+ remoteClient.SendAvatarPicksReply(new UUID(args[0]), picks);
+ }
+
+ ///
+ /// Handles the pick info request.
+ ///
+ ///
+ /// Sender.
+ ///
+ ///
+ /// Method.
+ ///
+ ///
+ /// Arguments.
+ ///
+ public void PickInfoRequest(Object sender, string method, List args)
+ {
+ if (!(sender is IClientAPI))
+ return;
+
+ UUID targetID;
+ UUID.TryParse(args[0], out targetID);
+ string serverURI = string.Empty;
+ bool foreign = GetUserProfileServerURI(targetID, out serverURI);
+ IClientAPI remoteClient = (IClientAPI)sender;
+
+ UserProfilePick pick = new UserProfilePick();
+ UUID.TryParse(args[0], out pick.CreatorId);
+ UUID.TryParse(args[1], out pick.PickId);
+
+
+ object Pick = (object)pick;
+ if(!JsonRpcRequest(ref Pick, "pickinforequest", serverURI, UUID.Random().ToString()))
+ {
+ remoteClient.SendAgentAlertMessage(
+ "Error selecting pick", false);
+ }
+ pick = (UserProfilePick) Pick;
+ if(pick.SnapshotId == UUID.Zero)
+ {
+ // In case of a new UserPick, the data may not be ready and we would send wrong data, skip it...
+ m_log.DebugFormat("[PROFILES]: PickInfoRequest: SnapshotID is {0}", UUID.Zero.ToString());
+ return;
+ }
+
+ Vector3 globalPos;
+ Vector3.TryParse(pick.GlobalPos,out globalPos);
+
+ m_log.DebugFormat("[PROFILES]: PickInfoRequest: {0} : {1}", pick.Name.ToString(), pick.SnapshotId.ToString());
+
+ remoteClient.SendPickInfoReply(pick.PickId,pick.CreatorId,pick.TopPick,pick.ParcelId,pick.Name,
+ pick.Desc,pick.SnapshotId,pick.User,pick.OriginalName,pick.SimName,
+ globalPos,pick.SortOrder,pick.Enabled);
+ }
+
+ ///
+ /// Updates the userpicks
+ ///
+ ///
+ /// Remote client.
+ ///
+ ///
+ /// Pick I.
+ ///
+ ///
+ /// the creator of the pick
+ ///
+ ///
+ /// Top pick.
+ ///
+ ///
+ /// Name.
+ ///
+ ///
+ /// Desc.
+ ///
+ ///
+ /// Snapshot I.
+ ///
+ ///
+ /// Sort order.
+ ///
+ ///
+ /// Enabled.
+ ///
+ public void PickInfoUpdate(IClientAPI remoteClient, UUID pickID, UUID creatorID, bool topPick, string name, string desc, UUID snapshotID, int sortOrder, bool enabled)
+ {
+
+ m_log.DebugFormat("[PROFILES]: Start PickInfoUpdate Name: {0} PickId: {1} SnapshotId: {2}", name, pickID.ToString(), snapshotID.ToString());
+ UserProfilePick pick = new UserProfilePick();
+ string serverURI = string.Empty;
+ bool foreign = GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
+ ScenePresence p = FindPresence(remoteClient.AgentId);
+
+ Vector3 avaPos = p.AbsolutePosition;
+ // Getting the global position for the Avatar
+ Vector3 posGlobal = new Vector3(remoteClient.Scene.RegionInfo.RegionLocX*Constants.RegionSize + avaPos.X,
+ remoteClient.Scene.RegionInfo.RegionLocY*Constants.RegionSize + avaPos.Y,
+ avaPos.Z);
+
+ string landOwnerName = string.Empty;
+ ILandObject land = p.Scene.LandChannel.GetLandObject(avaPos.X, avaPos.Y);
+ if(land.LandData.IsGroupOwned)
+ {
+ IGroupsModule groupMod = p.Scene.RequestModuleInterface();
+ UUID groupId = land.LandData.GroupID;
+ GroupRecord groupRecord = groupMod.GetGroupRecord(groupId);
+ landOwnerName = groupRecord.GroupName;
+ }
+ else
+ {
+ IUserAccountService accounts = p.Scene.RequestModuleInterface();
+ UserAccount user = accounts.GetUserAccount(p.Scene.RegionInfo.ScopeID, land.LandData.OwnerID);
+ landOwnerName = user.Name;
+ }
+
+ pick.PickId = pickID;
+ pick.CreatorId = creatorID;
+ pick.TopPick = topPick;
+ pick.Name = name;
+ pick.Desc = desc;
+ pick.ParcelId = p.currentParcelUUID;
+ pick.SnapshotId = snapshotID;
+ pick.User = landOwnerName;
+ pick.SimName = remoteClient.Scene.RegionInfo.RegionName;
+ pick.GlobalPos = posGlobal.ToString();
+ pick.SortOrder = sortOrder;
+ pick.Enabled = enabled;
+
+ object Pick = (object)pick;
+ if(!JsonRpcRequest(ref Pick, "picks_update", serverURI, UUID.Random().ToString()))
+ {
+ remoteClient.SendAgentAlertMessage(
+ "Error updating pick", false);
+ }
+
+ m_log.DebugFormat("[PROFILES]: Finish PickInfoUpdate {0} {1}", pick.Name, pick.PickId.ToString());
+ }
+
+ ///
+ /// Delete a Pick
+ ///
+ ///
+ /// Remote client.
+ ///
+ ///
+ /// Query pick I.
+ ///
+ public void PickDelete(IClientAPI remoteClient, UUID queryPickID)
+ {
+ string serverURI = string.Empty;
+ bool foreign = GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
+
+ OSDMap parameters= new OSDMap();
+ parameters.Add("pickId", OSD.FromUUID(queryPickID));
+ OSD Params = (OSD)parameters;
+ if(!JsonRpcRequest(ref Params, "picks_delete", serverURI, UUID.Random().ToString()))
+ {
+ remoteClient.SendAgentAlertMessage(
+ "Error picks delete", false);
+ }
+ }
+ #endregion Picks
+
+ #region Notes
+ ///
+ /// Handles the avatar notes request.
+ ///
+ ///
+ /// Sender.
+ ///
+ ///
+ /// Method.
+ ///
+ ///
+ /// Arguments.
+ ///
+ public void NotesRequest(Object sender, string method, List args)
+ {
+ UserProfileNotes note = new UserProfileNotes();
+
+ if (!(sender is IClientAPI))
+ return;
+
+ IClientAPI remoteClient = (IClientAPI)sender;
+ string serverURI = string.Empty;
+ bool foreign = GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
+ note.TargetId = remoteClient.AgentId;
+ UUID.TryParse(args[0], out note.UserId);
+
+ object Note = (object)note;
+ if(!JsonRpcRequest(ref Note, "avatarnotesrequest", serverURI, UUID.Random().ToString()))
+ {
+ remoteClient.SendAgentAlertMessage(
+ "Error requesting note", false);
+ }
+ note = (UserProfileNotes) Note;
+
+ remoteClient.SendAvatarNotesReply(note.TargetId, note.Notes);
+ }
+
+ ///
+ /// Avatars the notes update.
+ ///
+ ///
+ /// Remote client.
+ ///
+ ///
+ /// Query target I.
+ ///
+ ///
+ /// Query notes.
+ ///
+ public void NotesUpdate(IClientAPI remoteClient, UUID queryTargetID, string queryNotes)
+ {
+ UserProfileNotes note = new UserProfileNotes();
+
+ note.UserId = remoteClient.AgentId;
+ note.TargetId = queryTargetID;
+ note.Notes = queryNotes;
+
+ string serverURI = string.Empty;
+ bool foreign = GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
+
+ object Note = note;
+ if(!JsonRpcRequest(ref Note, "avatar_notes_update", serverURI, UUID.Random().ToString()))
+ {
+ remoteClient.SendAgentAlertMessage(
+ "Error updating note", false);
+ }
+ }
+ #endregion Notes
+
+ #region Avatar Properties
+ ///
+ /// Update the avatars interests .
+ ///
+ ///
+ /// Remote client.
+ ///
+ ///
+ /// Wantmask.
+ ///
+ ///
+ /// Wanttext.
+ ///
+ ///
+ /// Skillsmask.
+ ///
+ ///
+ /// Skillstext.
+ ///
+ ///
+ /// Languages.
+ ///
+ public void AvatarInterestsUpdate(IClientAPI remoteClient, uint wantmask, string wanttext, uint skillsmask, string skillstext, string languages)
+ {
+ UserProfileProperties prop = new UserProfileProperties();
+
+ prop.UserId = remoteClient.AgentId;
+ prop.WantToMask = (int)wantmask;
+ prop.WantToText = wanttext;
+ prop.SkillsMask = (int)skillsmask;
+ prop.SkillsText = skillstext;
+ prop.Language = languages;
+
+ string serverURI = string.Empty;
+ bool foreign = GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
+
+ object Param = prop;
+ if(!JsonRpcRequest(ref Param, "avatar_interests_update", serverURI, UUID.Random().ToString()))
+ {
+ remoteClient.SendAgentAlertMessage(
+ "Error updating interests", false);
+ }
+ }
+
+ public void BasicRequestProperties(IClientAPI remoteClient, UUID avatarID)
+ {
+ IScene s = remoteClient.Scene;
+ if (!(s is Scene))
+ return;
+
+ string profileUrl = String.Empty;
+ string aboutText = String.Empty;
+ string firstLifeAboutText = String.Empty;
+ UUID image = UUID.Zero;
+ UUID firstLifeImage = UUID.Zero;
+ UUID partner = UUID.Zero;
+ uint wantMask = 0;
+ string wantText = String.Empty;
+ uint skillsMask = 0;
+ string skillsText = String.Empty;
+ string languages = String.Empty;
+
+ UserAccount account = Scene.UserAccountService.GetUserAccount(Scene.RegionInfo.ScopeID, avatarID);
+
+ string name = "Avatar";
+ int created = 0;
+ if (account != null)
+ {
+ name = account.FirstName + " " + account.LastName;
+ created = account.Created;
+ }
+ Byte[] charterMember = Utils.StringToBytes(name);
+
+ profileUrl = "No profile data";
+ aboutText = string.Empty;
+ firstLifeAboutText = string.Empty;
+ image = UUID.Zero;
+ firstLifeImage = UUID.Zero;
+ partner = UUID.Zero;
+
+ remoteClient.SendAvatarProperties(avatarID, aboutText,
+ Util.ToDateTime(created).ToString(
+ "M/d/yyyy", CultureInfo.InvariantCulture),
+ charterMember, firstLifeAboutText,
+ (uint)(0 & 0xff),
+ firstLifeImage, image, profileUrl, partner);
+
+ //Viewer expects interest data when it asks for properties.
+ remoteClient.SendAvatarInterestsReply(avatarID, wantMask, wantText,
+ skillsMask, skillsText, languages);
+ }
+
+ ///
+ /// Requests the avatar properties.
+ ///
+ ///
+ /// Remote client.
+ ///
+ ///
+ /// Avatar I.
+ ///
+ public void RequestAvatarProperties(IClientAPI remoteClient, UUID avatarID)
+ {
+ if ( String.IsNullOrEmpty(avatarID.ToString()) || String.IsNullOrEmpty(remoteClient.AgentId.ToString()))
+ {
+ // Looking for a reason that some viewers are sending null Id's
+ m_log.DebugFormat("[PROFILES]: This should not happen remoteClient.AgentId {0} - avatarID {1}", remoteClient.AgentId, avatarID);
+ return;
+ }
+
+ // Can't handle NPC yet...
+ ScenePresence p = FindPresence(avatarID);
+
+ if (null != p)
+ {
+ if (p.PresenceType == PresenceType.Npc)
+ return;
+ }
+
+ string serverURI = string.Empty;
+ bool foreign = GetUserProfileServerURI(avatarID, out serverURI);
+
+ UserAccount account = null;
+ Dictionary userInfo;
+
+ if (!foreign)
+ {
+ account = Scene.UserAccountService.GetUserAccount(Scene.RegionInfo.ScopeID, avatarID);
+ }
+ else
+ {
+ userInfo = new Dictionary();
+ }
+
+ Byte[] charterMember = new Byte[1];
+ string born = String.Empty;
+ uint flags = 0x00;
+
+ if (null != account)
+ {
+ if (account.UserTitle == "")
+ {
+ charterMember[0] = (Byte)((account.UserFlags & 0xf00) >> 8);
+ }
+ else
+ {
+ charterMember = Utils.StringToBytes(account.UserTitle);
+ }
+
+ born = Util.ToDateTime(account.Created).ToString(
+ "M/d/yyyy", CultureInfo.InvariantCulture);
+ flags = (uint)(account.UserFlags & 0xff);
+ }
+ else
+ {
+ if (GetUserAccountData(avatarID, out userInfo) == true)
+ {
+ if ((string)userInfo["user_title"] == "")
+ {
+ charterMember[0] = (Byte)(((Byte)userInfo["user_flags"] & 0xf00) >> 8);
+ }
+ else
+ {
+ charterMember = Utils.StringToBytes((string)userInfo["user_title"]);
+ }
+
+ int val_born = (int)userInfo["user_created"];
+ born = Util.ToDateTime(val_born).ToString(
+ "M/d/yyyy", CultureInfo.InvariantCulture);
+
+ // picky, picky
+ int val_flags = (int)userInfo["user_flags"];
+ flags = (uint)(val_flags & 0xff);
+ }
+ }
+
+ UserProfileProperties props = new UserProfileProperties();
+ string result = string.Empty;
+
+ props.UserId = avatarID;
+ GetProfileData(ref props, out result);
+
+ remoteClient.SendAvatarProperties(props.UserId, props.AboutText, born, charterMember , props.FirstLifeText, flags,
+ props.FirstLifeImageId, props.ImageId, props.WebUrl, props.PartnerId);
+
+
+ remoteClient.SendAvatarInterestsReply(props.UserId, (uint)props.WantToMask, props.WantToText, (uint)props.SkillsMask,
+ props.SkillsText, props.Language);
+ }
+
+ ///
+ /// Updates the avatar properties.
+ ///
+ ///
+ /// Remote client.
+ ///
+ ///
+ /// New profile.
+ ///
+ public void AvatarPropertiesUpdate(IClientAPI remoteClient, UserProfileData newProfile)
+ {
+ if (remoteClient.AgentId == newProfile.ID)
+ {
+ UserProfileProperties prop = new UserProfileProperties();
+
+ prop.UserId = remoteClient.AgentId;
+ prop.WebUrl = newProfile.ProfileUrl;
+ prop.ImageId = newProfile.Image;
+ prop.AboutText = newProfile.AboutText;
+ prop.FirstLifeImageId = newProfile.FirstLifeImage;
+ prop.FirstLifeText = newProfile.FirstLifeAboutText;
+
+ string serverURI = string.Empty;
+ bool foreign = GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
+
+ object Prop = prop;
+
+ if(!JsonRpcRequest(ref Prop, "avatar_properties_update", serverURI, UUID.Random().ToString()))
+ {
+ remoteClient.SendAgentAlertMessage(
+ "Error updating properties", false);
+ }
+
+ RequestAvatarProperties(remoteClient, newProfile.ID);
+ }
+ }
+
+
+ ///
+ /// Gets the profile data.
+ ///
+ ///
+ /// The profile data.
+ ///
+ ///
+ /// User I.
+ ///
+ bool GetProfileData(ref UserProfileProperties properties, out string message)
+ {
+ // Can't handle NPC yet...
+ ScenePresence p = FindPresence(properties.UserId);
+
+ if (null != p)
+ {
+ if (p.PresenceType == PresenceType.Npc)
+ {
+ message = "Id points to NPC";
+ return false;
+ }
+ }
+
+ string serverURI = string.Empty;
+ bool foreign = GetUserProfileServerURI(properties.UserId, out serverURI);
+
+ // This is checking a friend on the home grid
+ // Not HG friend
+ if ( String.IsNullOrEmpty(serverURI))
+ {
+ message = "No Presence - foreign friend";
+ return false;
+ }
+
+ object Prop = (object)properties;
+ JsonRpcRequest(ref Prop, "avatar_properties_request", serverURI, UUID.Random().ToString());
+ properties = (UserProfileProperties)Prop;
+
+ message = "Success";
+ return true;
+ }
+ #endregion Avatar Properties
+
+ #region Utils
+ bool GetImageAssets(UUID avatarId)
+ {
+ string profileServerURI = string.Empty;
+ string assetServerURI = string.Empty;
+
+ bool foreign = GetUserProfileServerURI(avatarId, out profileServerURI);
+
+ if(!foreign)
+ return true;
+
+ assetServerURI = UserManagementModule.GetUserServerURL(avatarId, "AssetServerURI");
+
+ OSDMap parameters= new OSDMap();
+ parameters.Add("avatarId", OSD.FromUUID(avatarId));
+ OSD Params = (OSD)parameters;
+ if(!JsonRpcRequest(ref Params, "image_assets_request", profileServerURI, UUID.Random().ToString()))
+ {
+ // Error Handling here!
+ // if(parameters.ContainsKey("message")
+ return false;
+ }
+
+ parameters = (OSDMap)Params;
+
+ OSDArray list = (OSDArray)parameters["result"];
+
+ foreach(OSD asset in list)
+ {
+ OSDString assetId = (OSDString)asset;
+
+ Scene.AssetService.Get(string.Format("{0}/{1}",assetServerURI, assetId.AsString()), this,
+ delegate (string assetID, Object s, AssetBase a)
+ {
+ // m_log.DebugFormat("[PROFILES]: Getting Image Assets {0}", assetID);
+ return;
+ });
+ }
+ return true;
+ }
+
+ ///
+ /// Gets the user account data.
+ ///
+ ///
+ /// The user profile data.
+ ///
+ ///
+ /// If set to true user I.
+ ///
+ ///
+ /// If set to true user info.
+ ///
+ bool GetUserAccountData(UUID userID, out Dictionary userInfo)
+ {
+ Dictionary info = new Dictionary();
+
+ if (UserManagementModule.IsLocalGridUser(userID))
+ {
+ // Is local
+ IUserAccountService uas = Scene.UserAccountService;
+ UserAccount account = uas.GetUserAccount(Scene.RegionInfo.ScopeID, userID);
+
+ info["user_flags"] = account.UserFlags;
+ info["user_created"] = account.Created;
+
+ if (!String.IsNullOrEmpty(account.UserTitle))
+ info["user_title"] = account.UserTitle;
+ else
+ info["user_title"] = "";
+
+ userInfo = info;
+
+ return false;
+ }
+ else
+ {
+ // Is Foreign
+ string home_url = UserManagementModule.GetUserServerURL(userID, "HomeURI");
+
+ if (String.IsNullOrEmpty(home_url))
+ {
+ info["user_flags"] = 0;
+ info["user_created"] = 0;
+ info["user_title"] = "Unavailable";
+
+ userInfo = info;
+ return true;
+ }
+
+ UserAgentServiceConnector uConn = new UserAgentServiceConnector(home_url);
+
+ Dictionary account = uConn.GetUserInfo(userID);
+
+ if (account.Count > 0)
+ {
+ if (account.ContainsKey("user_flags"))
+ info["user_flags"] = account["user_flags"];
+ else
+ info["user_flags"] = "";
+
+ if (account.ContainsKey("user_created"))
+ info["user_created"] = account["user_created"];
+ else
+ info["user_created"] = "";
+
+ info["user_title"] = "HG Visitor";
+ }
+ else
+ {
+ info["user_flags"] = 0;
+ info["user_created"] = 0;
+ info["user_title"] = "HG Visitor";
+ }
+ userInfo = info;
+ return true;
+ }
+ }
+
+ ///
+ /// Gets the user profile server UR.
+ ///
+ ///
+ /// The user profile server UR.
+ ///
+ ///
+ /// If set to true user I.
+ ///
+ ///
+ /// If set to true server UR.
+ ///
+ bool GetUserProfileServerURI(UUID userID, out string serverURI)
+ {
+ bool local;
+ local = UserManagementModule.IsLocalGridUser(userID);
+
+ if (!local)
+ {
+ serverURI = UserManagementModule.GetUserServerURL(userID, "ProfileServerURI");
+ // Is Foreign
+ return true;
+ }
+ else
+ {
+ serverURI = ProfileServerUri;
+ // Is local
+ return false;
+ }
+ }
+
+ ///
+ /// Finds the presence.
+ ///
+ ///
+ /// The presence.
+ ///
+ ///
+ /// Client I.
+ ///
+ ScenePresence FindPresence(UUID clientID)
+ {
+ ScenePresence p;
+
+ p = Scene.GetScenePresence(clientID);
+ if (p != null && !p.IsChildAgent)
+ return p;
+
+ return null;
+ }
+ #endregion Util
+
+ #region Web Util
+ ///
+ /// Sends json-rpc request with a serializable type.
+ ///
+ ///
+ /// OSD Map.
+ ///
+ ///
+ /// Serializable type .
+ ///
+ ///
+ /// Json-rpc method to call.
+ ///
+ ///
+ /// URI of json-rpc service.
+ ///
+ ///
+ /// Id for our call.
+ ///
+ bool JsonRpcRequest(ref object parameters, string method, string uri, string jsonId)
+ {
+ if (jsonId == null)
+ throw new ArgumentNullException ("jsonId");
+ if (uri == null)
+ throw new ArgumentNullException ("uri");
+ if (method == null)
+ throw new ArgumentNullException ("method");
+ if (parameters == null)
+ throw new ArgumentNullException ("parameters");
+
+ // Prep our payload
+ OSDMap json = new OSDMap();
+
+ json.Add("jsonrpc", OSD.FromString("2.0"));
+ json.Add("id", OSD.FromString(jsonId));
+ json.Add("method", OSD.FromString(method));
+ // Experiment
+ json.Add("params", OSD.SerializeMembers(parameters));
+
+ string jsonRequestData = OSDParser.SerializeJsonString(json);
+ byte[] content = Encoding.UTF8.GetBytes(jsonRequestData);
+
+ HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri);
+ // webRequest.Credentials = new NetworkCredential(rpcUser, rpcPass);
+ webRequest.ContentType = "application/json-rpc";
+ webRequest.Method = "POST";
+
+ Stream dataStream = webRequest.GetRequestStream();
+ dataStream.Write(content, 0, content.Length);
+ dataStream.Close();
+
+ WebResponse webResponse = null;
+ try
+ {
+ webResponse = webRequest.GetResponse();
+ }
+ catch (WebException e)
+ {
+ Console.WriteLine("Web Error" + e.Message);
+ Console.WriteLine ("Please check input");
+ return false;
+ }
+
+ byte[] buf = new byte[8192];
+ Stream rstream = webResponse.GetResponseStream();
+ OSDMap mret = (OSDMap)OSDParser.DeserializeJson(rstream);
+
+ if(mret.ContainsKey("error"))
+ return false;
+
+ // get params...
+ OSD.DeserializeMembers(ref parameters, (OSDMap) mret["result"]);
+ return true;
+ }
+
+ ///
+ /// Sends json-rpc request with OSD parameter.
+ ///
+ ///
+ /// The rpc request.
+ ///
+ ///
+ /// data - incoming as parameters, outgong as result/error
+ ///
+ ///
+ /// Json-rpc method to call.
+ ///
+ ///
+ /// URI of json-rpc service.
+ ///
+ ///
+ /// If set to true json identifier.
+ ///
+ bool JsonRpcRequest(ref OSD data, string method, string uri, string jsonId)
+ {
+ OSDMap map = new OSDMap();
+
+ map["jsonrpc"] = "2.0";
+ if(string.IsNullOrEmpty(jsonId))
+ map["id"] = UUID.Random().ToString();
+ else
+ map["id"] = jsonId;
+
+ map["method"] = method;
+ map["params"] = data;
+
+ string jsonRequestData = OSDParser.SerializeJsonString(map);
+ byte[] content = Encoding.UTF8.GetBytes(jsonRequestData);
+
+ HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri);
+ webRequest.ContentType = "application/json-rpc";
+ webRequest.Method = "POST";
+
+ Stream dataStream = webRequest.GetRequestStream();
+ dataStream.Write(content, 0, content.Length);
+ dataStream.Close();
+
+ WebResponse webResponse = null;
+ try
+ {
+ webResponse = webRequest.GetResponse();
+ }
+ catch (WebException e)
+ {
+ Console.WriteLine("Web Error" + e.Message);
+ Console.WriteLine ("Please check input");
+ return false;
+ }
+
+ byte[] buf = new byte[8192];
+ Stream rstream = webResponse.GetResponseStream();
+
+ OSDMap response = new OSDMap();
+ response = (OSDMap)OSDParser.DeserializeJson(rstream);
+ if(response.ContainsKey("error"))
+ {
+ data = response["error"];
+ return false;
+ }
+
+ data = response;
+
+ return true;
+ }
+ #endregion Web Util
+ }
+}
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/UserProfiles/LocalUserProfilesServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/UserProfiles/LocalUserProfilesServiceConnector.cs
new file mode 100644
index 0000000000..323535ab07
--- /dev/null
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/UserProfiles/LocalUserProfilesServiceConnector.cs
@@ -0,0 +1,226 @@
+
+/*
+ * 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 log4net;
+using Mono.Addins;
+using Nini.Config;
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using OpenSim.Framework;
+using OpenSim.Framework.Console;
+using OpenSim.Server.Base;
+using OpenSim.Server.Handlers;
+using OpenSim.Region.Framework.Interfaces;
+using OpenSim.Framework.Servers.HttpServer;
+using OpenSim.Framework.Servers;
+using OpenSim.Region.Framework.Scenes;
+using OpenSim.Services.Interfaces;
+using GridRegion = OpenSim.Services.Interfaces.GridRegion;
+using OpenMetaverse;
+
+namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Profile
+{
+ [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "LocalUserProfilesServicesConnector")]
+ public class LocalUserProfilesServicesConnector : ISharedRegionModule
+ {
+ private static readonly ILog m_log =
+ LogManager.GetLogger(
+ MethodBase.GetCurrentMethod().DeclaringType);
+
+ private Dictionary regions = new Dictionary();
+
+ public IUserProfilesService ServiceModule
+ {
+ get; private set;
+ }
+
+ public bool Enabled
+ {
+ get; private set;
+ }
+
+ public string Name
+ {
+ get
+ {
+ return "LocalUserProfilesServicesConnector";
+ }
+ }
+
+ public string ConfigName
+ {
+ get; private set;
+ }
+
+ public Type ReplaceableInterface
+ {
+ get { return null; }
+ }
+
+ public LocalUserProfilesServicesConnector()
+ {
+ m_log.Debug("[LOCAL USERPROFILES SERVICE CONNECTOR]: LocalUserProfileServicesConnector no params");
+ }
+
+ public LocalUserProfilesServicesConnector(IConfigSource source)
+ {
+ m_log.Debug("[LOCAL USERPROFILES SERVICE CONNECTOR]: LocalUserProfileServicesConnector instantiated directly.");
+ InitialiseService(source);
+ }
+
+ public void InitialiseService(IConfigSource source)
+ {
+ ConfigName = "UserProfilesService";
+
+ // Instantiate the request handler
+ IHttpServer Server = MainServer.Instance;
+
+ IConfig config = source.Configs[ConfigName];
+ if (config == null)
+ {
+ m_log.Error("[LOCAL USERPROFILES SERVICE CONNECTOR]: UserProfilesService missing from OpenSim.ini");
+ return;
+ }
+
+ if(!config.GetBoolean("Enabled",false))
+ {
+ Enabled = false;
+ return;
+ }
+
+ Enabled = true;
+
+ string serviceDll = config.GetString("LocalServiceModule",
+ String.Empty);
+
+ if (serviceDll == String.Empty)
+ {
+ m_log.Error("[LOCAL USERPROFILES SERVICE CONNECTOR]: No LocalServiceModule named in section UserProfilesService");
+ return;
+ }
+
+ Object[] args = new Object[] { source, ConfigName };
+ ServiceModule =
+ ServerUtils.LoadPlugin(serviceDll,
+ args);
+
+ if (ServiceModule == null)
+ {
+ m_log.Error("[LOCAL USERPROFILES SERVICE CONNECTOR]: Can't load user profiles service");
+ return;
+ }
+
+ Enabled = true;
+
+ JsonRpcProfileHandlers handler = new JsonRpcProfileHandlers(ServiceModule);
+
+ Server.AddJsonRPCHandler("avatarclassifiedsrequest", handler.AvatarClassifiedsRequest);
+ Server.AddJsonRPCHandler("classified_update", handler.ClassifiedUpdate);
+ Server.AddJsonRPCHandler("classifieds_info_query", handler.ClassifiedInfoRequest);
+ Server.AddJsonRPCHandler("classified_delete", handler.ClassifiedDelete);
+ Server.AddJsonRPCHandler("avatarpicksrequest", handler.AvatarPicksRequest);
+ Server.AddJsonRPCHandler("pickinforequest", handler.PickInfoRequest);
+ Server.AddJsonRPCHandler("picks_update", handler.PicksUpdate);
+ Server.AddJsonRPCHandler("picks_delete", handler.PicksDelete);
+ Server.AddJsonRPCHandler("avatarnotesrequest", handler.AvatarNotesRequest);
+ Server.AddJsonRPCHandler("avatar_notes_update", handler.NotesUpdate);
+ Server.AddJsonRPCHandler("avatar_properties_request", handler.AvatarPropertiesRequest);
+ Server.AddJsonRPCHandler("avatar_properties_update", handler.AvatarPropertiesUpdate);
+ Server.AddJsonRPCHandler("avatar_interests_update", handler.AvatarInterestsUpdate);
+ Server.AddJsonRPCHandler("image_assets_request", handler.AvatarImageAssetsRequest);
+ Server.AddJsonRPCHandler("user_data_request", handler.RequestUserAppData);
+ Server.AddJsonRPCHandler("user_data_update", handler.UpdateUserAppData);
+
+ }
+
+ #region ISharedRegionModule implementation
+
+ void ISharedRegionModule.PostInitialise()
+ {
+ if(!Enabled)
+ return;
+ }
+
+ #endregion
+
+ #region IRegionModuleBase implementation
+
+ void IRegionModuleBase.Initialise(IConfigSource source)
+ {
+ IConfig moduleConfig = source.Configs["Modules"];
+ if (moduleConfig != null)
+ {
+ string name = moduleConfig.GetString("UserProfilesServices", "");
+ if (name == Name)
+ {
+ InitialiseService(source);
+ m_log.Info("[LOCAL USERPROFILES SERVICE CONNECTOR]: Local user profiles connector enabled");
+ }
+ }
+ }
+
+ void IRegionModuleBase.Close()
+ {
+ return;
+ }
+
+ void IRegionModuleBase.AddRegion(Scene scene)
+ {
+ if (!Enabled)
+ return;
+
+ lock (regions)
+ {
+ if (regions.ContainsKey(scene.RegionInfo.RegionID))
+ m_log.ErrorFormat("[LOCAL USERPROFILES SERVICE CONNECTOR]: simulator seems to have more than one region with the same UUID. Please correct this!");
+ else
+ regions.Add(scene.RegionInfo.RegionID, scene);
+ }
+ }
+
+ void IRegionModuleBase.RemoveRegion(Scene scene)
+ {
+ if (!Enabled)
+ return;
+
+ lock (regions)
+ {
+ if (regions.ContainsKey(scene.RegionInfo.RegionID))
+ regions.Remove(scene.RegionInfo.RegionID);
+ }
+ }
+
+ void IRegionModuleBase.RegionLoaded(Scene scene)
+ {
+ if (!Enabled)
+ return;
+ }
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs
index c32820e94d..3849a3fb91 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs
@@ -56,6 +56,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
public LocalGridServicesConnector()
{
+ m_log.Debug("[LOCAL GRID SERVICE CONNECTOR]: LocalGridServicesConnector no parms.");
}
public LocalGridServicesConnector(IConfigSource source)
diff --git a/OpenSim/Server/Handlers/Profiles/UserProfilesConnector.cs b/OpenSim/Server/Handlers/Profiles/UserProfilesConnector.cs
new file mode 100644
index 0000000000..4ad729748b
--- /dev/null
+++ b/OpenSim/Server/Handlers/Profiles/UserProfilesConnector.cs
@@ -0,0 +1,92 @@
+using System;
+using System.Reflection;
+using Nini.Config;
+using OpenSim.Server.Base;
+using OpenSim.Services.Interfaces;
+using OpenSim.Framework.Servers.HttpServer;
+using OpenSim.Framework;
+using OpenSim.Server.Handlers.Base;
+using log4net;
+
+namespace OpenSim.Server.Handlers.Profiles
+{
+ public class UserProfilesConnector: ServiceConnector
+ {
+ static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+
+
+ // Our Local Module
+ public IUserProfilesService ServiceModule
+ {
+ get; private set;
+ }
+
+ // The HTTP server.
+ public IHttpServer Server
+ {
+ get; private set;
+ }
+
+ public string ConfigName
+ {
+ get; private set;
+ }
+
+ public bool Enabled
+ {
+ get; private set;
+ }
+
+ public UserProfilesConnector(IConfigSource config, IHttpServer server, string configName) :
+ base(config, server, configName)
+ {
+ ConfigName = "UserProfilesService";
+ if(!string.IsNullOrEmpty(configName))
+ ConfigName = configName;
+
+ IConfig serverConfig = config.Configs[ConfigName];
+ if (serverConfig == null)
+ throw new Exception(String.Format("No section {0} in config file", ConfigName));
+
+ if(!serverConfig.GetBoolean("Enabled",false))
+ {
+ Enabled = false;
+ return;
+ }
+
+ Enabled = true;
+
+ Server = server;
+
+ string service = serverConfig.GetString("LocalServiceModule", String.Empty);
+
+ Object[] args = new Object[] { config, ConfigName };
+ ServiceModule = ServerUtils.LoadPlugin(service, args);
+
+ JsonRpcProfileHandlers handler = new JsonRpcProfileHandlers(ServiceModule);
+
+ Server.AddJsonRPCHandler("avatarclassifiedsrequest", handler.AvatarClassifiedsRequest);
+ Server.AddJsonRPCHandler("classified_update", handler.ClassifiedUpdate);
+ Server.AddJsonRPCHandler("classifieds_info_query", handler.ClassifiedInfoRequest);
+ Server.AddJsonRPCHandler("classified_delete", handler.ClassifiedDelete);
+ Server.AddJsonRPCHandler("avatarpicksrequest", handler.AvatarPicksRequest);
+ Server.AddJsonRPCHandler("pickinforequest", handler.PickInfoRequest);
+ Server.AddJsonRPCHandler("picks_update", handler.PicksUpdate);
+ Server.AddJsonRPCHandler("picks_delete", handler.PicksDelete);
+ Server.AddJsonRPCHandler("avatarnotesrequest", handler.AvatarNotesRequest);
+ Server.AddJsonRPCHandler("avatar_notes_update", handler.NotesUpdate);
+ Server.AddJsonRPCHandler("avatar_properties_request", handler.AvatarPropertiesRequest);
+ Server.AddJsonRPCHandler("avatar_properties_update", handler.AvatarPropertiesUpdate);
+ Server.AddJsonRPCHandler("avatar_interests_update", handler.AvatarInterestsUpdate);
+ Server.AddJsonRPCHandler("image_assets_request", handler.AvatarImageAssetsRequest);
+// Server.AddJsonRPCHandler("user_preferences_request", handler.UserPreferencesRequest);
+// Server.AddJsonRPCHandler("user_preferences_update", handler.UserPreferencesUpdate);
+// Server.AddJsonRPCHandler("user_account_create", handler.UserAccountCreate);
+// Server.AddJsonRPCHandler("user_account_auth", handler.UserAccountAuth);
+// Server.AddJsonRPCHandler("user_account_test", handler.UserAccountTest);
+ Server.AddJsonRPCHandler("user_data_request", handler.RequestUserAppData);
+ Server.AddJsonRPCHandler("user_data_update", handler.UpdateUserAppData);
+ }
+ }
+}
+
diff --git a/OpenSim/Server/Handlers/Profiles/UserProfilesHandlers.cs b/OpenSim/Server/Handlers/Profiles/UserProfilesHandlers.cs
new file mode 100644
index 0000000000..93da102b8e
--- /dev/null
+++ b/OpenSim/Server/Handlers/Profiles/UserProfilesHandlers.cs
@@ -0,0 +1,434 @@
+using System;
+using System.Reflection;
+using OpenMetaverse;
+using OpenMetaverse.StructuredData;
+using log4net;
+using OpenSim.Services.Interfaces;
+using OpenSim.Framework.Servers.HttpServer;
+using OpenSim.Framework;
+
+namespace OpenSim.Server.Handlers
+{
+ public class UserProfilesHandlers
+ {
+ public UserProfilesHandlers ()
+ {
+ }
+ }
+
+ public class JsonRpcProfileHandlers
+ {
+ static readonly ILog m_log =
+ LogManager.GetLogger(
+ MethodBase.GetCurrentMethod().DeclaringType);
+
+ public IUserProfilesService Service
+ {
+ get; private set;
+ }
+
+ public JsonRpcProfileHandlers(IUserProfilesService service)
+ {
+ Service = service;
+ }
+
+ #region Classifieds
+ ///
+ /// Request avatar's classified ads.
+ ///
+ ///
+ /// An array containing all the calassified uuid and it's name created by the creator id
+ ///
+ ///
+ /// Our parameters are in the OSDMap json["params"]
+ ///
+ ///
+ /// If set to true response.
+ ///
+ public bool AvatarClassifiedsRequest(OSDMap json, ref JsonRpcResponse response)
+ {
+ if(!json.ContainsKey("params"))
+ {
+ response.Error.Code = ErrorCode.ParseError;
+ m_log.DebugFormat ("Classified Request");
+ return false;
+ }
+
+ OSDMap request = (OSDMap)json["params"];
+ UUID creatorId = new UUID(request["creatorId"].AsString());
+
+
+ OSDArray data = (OSDArray) Service.AvatarClassifiedsRequest(creatorId);
+ response.Result = data;
+
+ return true;
+ }
+
+ public bool ClassifiedUpdate(OSDMap json, ref JsonRpcResponse response)
+ {
+ if(!json.ContainsKey("params"))
+ {
+ response.Error.Code = ErrorCode.ParseError;
+ response.Error.Message = "Error parsing classified update request";
+ m_log.DebugFormat ("Classified Update Request");
+ return false;
+ }
+
+ string result = string.Empty;
+ UserClassifiedAdd ad = new UserClassifiedAdd();
+ object Ad = (object)ad;
+ OSD.DeserializeMembers(ref Ad, (OSDMap)json["params"]);
+ if(Service.ClassifiedUpdate(ad, ref result))
+ {
+ response.Result = OSD.SerializeMembers(ad);
+ return true;
+ }
+
+ response.Error.Code = ErrorCode.InternalError;
+ response.Error.Message = string.Format("{0}", result);
+ return false;
+ }
+
+ public bool ClassifiedDelete(OSDMap json, ref JsonRpcResponse response)
+ {
+ if(!json.ContainsKey("params"))
+ {
+ response.Error.Code = ErrorCode.ParseError;
+ m_log.DebugFormat ("Classified Delete Request");
+ return false;
+ }
+
+ OSDMap request = (OSDMap)json["params"];
+ UUID classifiedId = new UUID(request["classifiedID"].AsString());
+
+ OSDMap res = new OSDMap();
+ res["result"] = OSD.FromString("success");
+ response.Result = res;
+
+ return true;
+
+ }
+
+ public bool ClassifiedInfoRequest(OSDMap json, ref JsonRpcResponse response)
+ {
+ if(!json.ContainsKey("params"))
+ {
+ response.Error.Code = ErrorCode.ParseError;
+ response.Error.Message = "no parameters supplied";
+ m_log.DebugFormat ("Classified Info Request");
+ return false;
+ }
+
+ string result = string.Empty;
+ UserClassifiedAdd ad = new UserClassifiedAdd();
+ object Ad = (object)ad;
+ OSD.DeserializeMembers(ref Ad, (OSDMap)json["params"]);
+ if(Service.ClassifiedInfoRequest(ref ad, ref result))
+ {
+ response.Result = OSD.SerializeMembers(ad);
+ return true;
+ }
+
+ response.Error.Code = ErrorCode.InternalError;
+ response.Error.Message = string.Format("{0}", result);
+ return false;
+ }
+ #endregion Classifieds
+
+ #region Picks
+ public bool AvatarPicksRequest(OSDMap json, ref JsonRpcResponse response)
+ {
+ if(!json.ContainsKey("params"))
+ {
+ response.Error.Code = ErrorCode.ParseError;
+ m_log.DebugFormat ("Avatar Picks Request");
+ return false;
+ }
+
+ OSDMap request = (OSDMap)json["params"];
+ UUID creatorId = new UUID(request["creatorId"].AsString());
+
+
+ OSDArray data = (OSDArray) Service.AvatarPicksRequest(creatorId);
+ response.Result = data;
+
+ return true;
+ }
+
+ public bool PickInfoRequest(OSDMap json, ref JsonRpcResponse response)
+ {
+ if(!json.ContainsKey("params"))
+ {
+ response.Error.Code = ErrorCode.ParseError;
+ response.Error.Message = "no parameters supplied";
+ m_log.DebugFormat ("Avatar Picks Info Request");
+ return false;
+ }
+
+ string result = string.Empty;
+ UserProfilePick pick = new UserProfilePick();
+ object Pick = (object)pick;
+ OSD.DeserializeMembers(ref Pick, (OSDMap)json["params"]);
+ if(Service.PickInfoRequest(ref pick, ref result))
+ {
+ response.Result = OSD.SerializeMembers(pick);
+ return true;
+ }
+
+ response.Error.Code = ErrorCode.InternalError;
+ response.Error.Message = string.Format("{0}", result);
+ return false;
+ }
+
+ public bool PicksUpdate(OSDMap json, ref JsonRpcResponse response)
+ {
+ if(!json.ContainsKey("params"))
+ {
+ response.Error.Code = ErrorCode.ParseError;
+ response.Error.Message = "no parameters supplied";
+ m_log.DebugFormat ("Avatar Picks Update Request");
+ return false;
+ }
+
+ string result = string.Empty;
+ UserProfilePick pick = new UserProfilePick();
+ object Pick = (object)pick;
+ OSD.DeserializeMembers(ref Pick, (OSDMap)json["params"]);
+ if(Service.PicksUpdate(ref pick, ref result))
+ {
+ response.Result = OSD.SerializeMembers(pick);
+ return true;
+ }
+
+ response.Error.Code = ErrorCode.InternalError;
+ response.Error.Message = "unable to update pick";
+
+ return false;
+ }
+
+ public bool PicksDelete(OSDMap json, ref JsonRpcResponse response)
+ {
+ if(!json.ContainsKey("params"))
+ {
+ response.Error.Code = ErrorCode.ParseError;
+ m_log.DebugFormat ("Avatar Picks Delete Request");
+ return false;
+ }
+
+ OSDMap request = (OSDMap)json["params"];
+ UUID pickId = new UUID(request["pickId"].AsString());
+ if(Service.PicksDelete(pickId))
+ return true;
+
+ response.Error.Code = ErrorCode.InternalError;
+ response.Error.Message = "data error removing record";
+ return false;
+ }
+ #endregion Picks
+
+ #region Notes
+ public bool AvatarNotesRequest(OSDMap json, ref JsonRpcResponse response)
+ {
+ if(!json.ContainsKey("params"))
+ {
+ response.Error.Code = ErrorCode.ParseError;
+ response.Error.Message = "Params missing";
+ m_log.DebugFormat ("Avatar Notes Request");
+ return false;
+ }
+
+ string result = string.Empty;
+ UserProfileNotes note = new UserProfileNotes();
+ object Note = (object)note;
+ OSD.DeserializeMembers(ref Note, (OSDMap)json["params"]);
+ if(Service.AvatarNotesRequest(ref note))
+ {
+ response.Result = OSD.SerializeMembers(note);
+ return true;
+ }
+
+ object Notes = (object) note;
+ OSD.DeserializeMembers(ref Notes, (OSDMap)json["params"]);
+ return true;
+ }
+
+ public bool NotesUpdate(OSDMap json, ref JsonRpcResponse response)
+ {
+ if(!json.ContainsKey("params"))
+ {
+ response.Error.Code = ErrorCode.ParseError;
+ response.Error.Message = "No parameters";
+ m_log.DebugFormat ("Avatar Notes Update Request");
+ return false;
+ }
+
+ string result = string.Empty;
+ UserProfileNotes note = new UserProfileNotes();
+ object Notes = (object) note;
+ OSD.DeserializeMembers(ref Notes, (OSDMap)json["params"]);
+ if(Service.NotesUpdate(ref note, ref result))
+ {
+ response.Result = OSD.SerializeMembers(note);
+ return true;
+ }
+ return true;
+ }
+ #endregion Notes
+
+ #region Profile Properties
+ public bool AvatarPropertiesRequest(OSDMap json, ref JsonRpcResponse response)
+ {
+ if(!json.ContainsKey("params"))
+ {
+ response.Error.Code = ErrorCode.ParseError;
+ response.Error.Message = "no parameters supplied";
+ m_log.DebugFormat ("Avatar Properties Request");
+ return false;
+ }
+
+ string result = string.Empty;
+ UserProfileProperties props = new UserProfileProperties();
+ object Props = (object)props;
+ OSD.DeserializeMembers(ref Props, (OSDMap)json["params"]);
+ if(Service.AvatarPropertiesRequest(ref props, ref result))
+ {
+ response.Result = OSD.SerializeMembers(props);
+ return true;
+ }
+
+ response.Error.Code = ErrorCode.InternalError;
+ response.Error.Message = string.Format("{0}", result);
+ return false;
+ }
+
+ public bool AvatarPropertiesUpdate(OSDMap json, ref JsonRpcResponse response)
+ {
+ if(!json.ContainsKey("params"))
+ {
+ response.Error.Code = ErrorCode.ParseError;
+ response.Error.Message = "no parameters supplied";
+ m_log.DebugFormat ("Avatar Properties Update Request");
+ return false;
+ }
+
+ string result = string.Empty;
+ UserProfileProperties props = new UserProfileProperties();
+ object Props = (object)props;
+ OSD.DeserializeMembers(ref Props, (OSDMap)json["params"]);
+ if(Service.AvatarPropertiesUpdate(ref props, ref result))
+ {
+ response.Result = OSD.SerializeMembers(props);
+ return true;
+ }
+
+ response.Error.Code = ErrorCode.InternalError;
+ response.Error.Message = string.Format("{0}", result);
+ return false;
+ }
+ #endregion Profile Properties
+
+ #region Interests
+ public bool AvatarInterestsUpdate(OSDMap json, ref JsonRpcResponse response)
+ {
+ if(!json.ContainsKey("params"))
+ {
+ response.Error.Code = ErrorCode.ParseError;
+ response.Error.Message = "no parameters supplied";
+ m_log.DebugFormat ("Avatar Interests Update Request");
+ return false;
+ }
+
+ string result = string.Empty;
+ UserProfileProperties props = new UserProfileProperties();
+ object Props = (object)props;
+ OSD.DeserializeMembers(ref Props, (OSDMap)json["params"]);
+ if(Service.AvatarInterestsUpdate(props, ref result))
+ {
+ response.Result = OSD.SerializeMembers(props);
+ return true;
+ }
+
+ response.Error.Code = ErrorCode.InternalError;
+ response.Error.Message = string.Format("{0}", result);
+ return false;
+ }
+ #endregion Interests
+
+ #region Utility
+ public bool AvatarImageAssetsRequest(OSDMap json, ref JsonRpcResponse response)
+ {
+ if(!json.ContainsKey("params"))
+ {
+ response.Error.Code = ErrorCode.ParseError;
+ m_log.DebugFormat ("Avatar Image Assets Request");
+ return false;
+ }
+
+ OSDMap request = (OSDMap)json["params"];
+ UUID avatarId = new UUID(request["avatarId"].AsString());
+
+ OSDArray data = (OSDArray) Service.AvatarImageAssetsRequest(avatarId);
+ response.Result = data;
+
+ return true;
+ }
+ #endregion Utiltiy
+
+ #region UserData
+ public bool RequestUserAppData(OSDMap json, ref JsonRpcResponse response)
+ {
+ if(!json.ContainsKey("params"))
+ {
+ response.Error.Code = ErrorCode.ParseError;
+ response.Error.Message = "no parameters supplied";
+ m_log.DebugFormat ("User Application Service URL Request: No Parameters!");
+ return false;
+ }
+
+ string result = string.Empty;
+ UserAppData props = new UserAppData();
+ object Props = (object)props;
+ OSD.DeserializeMembers(ref Props, (OSDMap)json["params"]);
+ if(Service.RequestUserAppData(ref props, ref result))
+ {
+ OSDMap res = new OSDMap();
+ res["result"] = OSD.FromString("success");
+ res["token"] = OSD.FromString (result);
+ response.Result = res;
+
+ return true;
+ }
+
+ response.Error.Code = ErrorCode.InternalError;
+ response.Error.Message = string.Format("{0}", result);
+ return false;
+ }
+
+ public bool UpdateUserAppData(OSDMap json, ref JsonRpcResponse response)
+ {
+ if(!json.ContainsKey("params"))
+ {
+ response.Error.Code = ErrorCode.ParseError;
+ response.Error.Message = "no parameters supplied";
+ m_log.DebugFormat ("User App Data Update Request");
+ return false;
+ }
+
+ string result = string.Empty;
+ UserAppData props = new UserAppData();
+ object Props = (object)props;
+ OSD.DeserializeMembers(ref Props, (OSDMap)json["params"]);
+ if(Service.SetUserAppData(props, ref result))
+ {
+ response.Result = OSD.SerializeMembers(props);
+ return true;
+ }
+
+ response.Error.Code = ErrorCode.InternalError;
+ response.Error.Message = string.Format("{0}", result);
+ return false;
+ }
+ #endregion UserData
+ }
+}
+
diff --git a/OpenSim/Services/Interfaces/IUserProfilesService.cs b/OpenSim/Services/Interfaces/IUserProfilesService.cs
new file mode 100644
index 0000000000..12fc986a76
--- /dev/null
+++ b/OpenSim/Services/Interfaces/IUserProfilesService.cs
@@ -0,0 +1,48 @@
+using System;
+using OpenSim.Framework;
+using OpenMetaverse;
+using OpenMetaverse.StructuredData;
+
+namespace OpenSim.Services.Interfaces
+{
+ public interface IUserProfilesService
+ {
+ #region Classifieds
+ OSD AvatarClassifiedsRequest(UUID creatorId);
+ bool ClassifiedUpdate(UserClassifiedAdd ad, ref string result);
+ bool ClassifiedInfoRequest(ref UserClassifiedAdd ad, ref string result);
+ bool ClassifiedDelete(UUID recordId);
+ #endregion Classifieds
+
+ #region Picks
+ OSD AvatarPicksRequest(UUID creatorId);
+ bool PickInfoRequest(ref UserProfilePick pick, ref string result);
+ bool PicksUpdate(ref UserProfilePick pick, ref string result);
+ bool PicksDelete(UUID pickId);
+ #endregion Picks
+
+ #region Notes
+ bool AvatarNotesRequest(ref UserProfileNotes note);
+ bool NotesUpdate(ref UserProfileNotes note, ref string result);
+ #endregion Notes
+
+ #region Profile Properties
+ bool AvatarPropertiesRequest(ref UserProfileProperties prop, ref string result);
+ bool AvatarPropertiesUpdate(ref UserProfileProperties prop, ref string result);
+ #endregion Profile Properties
+
+ #region Interests
+ bool AvatarInterestsUpdate(UserProfileProperties prop, ref string result);
+ #endregion Interests
+
+ #region Utility
+ OSD AvatarImageAssetsRequest(UUID avatarId);
+ #endregion Utility
+
+ #region UserData
+ bool RequestUserAppData(ref UserAppData prop, ref string result);
+ bool SetUserAppData(UserAppData prop, ref string result);
+ #endregion UserData
+ }
+}
+
diff --git a/OpenSim/Services/UserProfilesService/UserProfilesService.cs b/OpenSim/Services/UserProfilesService/UserProfilesService.cs
new file mode 100644
index 0000000000..959c661b5f
--- /dev/null
+++ b/OpenSim/Services/UserProfilesService/UserProfilesService.cs
@@ -0,0 +1,160 @@
+using System;
+using System.Reflection;
+using System.Text;
+using Nini.Config;
+using log4net;
+using OpenSim.Server.Base;
+using OpenSim.Services.Interfaces;
+using OpenSim.Services.UserAccountService;
+using OpenSim.Data;
+using OpenMetaverse;
+using OpenMetaverse.StructuredData;
+using OpenSim.Framework;
+
+namespace OpenSim.Services.ProfilesService
+{
+ public class UserProfilesService: UserProfilesServiceBase, IUserProfilesService
+ {
+ static readonly ILog m_log =
+ LogManager.GetLogger(
+ MethodBase.GetCurrentMethod().DeclaringType);
+
+ IUserAccountService userAccounts;
+ IAuthenticationService authService;
+
+ public UserProfilesService(IConfigSource config, string configName):
+ base(config, configName)
+ {
+ IConfig Config = config.Configs[configName];
+ if (Config == null)
+ {
+ m_log.Warn("[PROFILES]: No configuration found!");
+ return;
+ }
+ Object[] args = null;
+
+ args = new Object[] { config };
+ string accountService = Config.GetString("UserAccountService", String.Empty);
+ if (accountService != string.Empty)
+ userAccounts = ServerUtils.LoadPlugin(accountService, args);
+
+ args = new Object[] { config };
+ string authServiceConfig = Config.GetString("AuthenticationServiceModule", String.Empty);
+ if (accountService != string.Empty)
+ authService = ServerUtils.LoadPlugin(authServiceConfig, args);
+ }
+
+ #region Classifieds
+ public OSD AvatarClassifiedsRequest(UUID creatorId)
+ {
+ OSDArray records = ProfilesData.GetClassifiedRecords(creatorId);
+
+ return records;
+ }
+
+ public bool ClassifiedUpdate(UserClassifiedAdd ad, ref string result)
+ {
+ if(!ProfilesData.UpdateClassifiedRecord(ad, ref result))
+ {
+ return false;
+ }
+ result = "success";
+ return true;
+ }
+
+ public bool ClassifiedDelete(UUID recordId)
+ {
+ if(ProfilesData.DeleteClassifiedRecord(recordId))
+ return true;
+
+ return false;
+ }
+
+ public bool ClassifiedInfoRequest(ref UserClassifiedAdd ad, ref string result)
+ {
+ if(ProfilesData.GetClassifiedInfo(ref ad, ref result))
+ return true;
+
+ return false;
+ }
+ #endregion Classifieds
+
+ #region Picks
+ public OSD AvatarPicksRequest(UUID creatorId)
+ {
+ OSDArray records = ProfilesData.GetAvatarPicks(creatorId);
+
+ return records;
+ }
+
+ public bool PickInfoRequest(ref UserProfilePick pick, ref string result)
+ {
+ pick = ProfilesData.GetPickInfo(pick.CreatorId, pick.PickId);
+ result = "OK";
+ return true;
+ }
+
+ public bool PicksUpdate(ref UserProfilePick pick, ref string result)
+ {
+ return ProfilesData.UpdatePicksRecord(pick);
+ }
+
+ public bool PicksDelete(UUID pickId)
+ {
+ return ProfilesData.DeletePicksRecord(pickId);
+ }
+ #endregion Picks
+
+ #region Notes
+ public bool AvatarNotesRequest(ref UserProfileNotes note)
+ {
+ return ProfilesData.GetAvatarNotes(ref note);
+ }
+
+ public bool NotesUpdate(ref UserProfileNotes note, ref string result)
+ {
+ return ProfilesData.UpdateAvatarNotes(ref note, ref result);
+ }
+ #endregion Notes
+
+ #region Profile Properties
+ public bool AvatarPropertiesRequest(ref UserProfileProperties prop, ref string result)
+ {
+ return ProfilesData.GetAvatarProperties(ref prop, ref result);
+ }
+
+ public bool AvatarPropertiesUpdate(ref UserProfileProperties prop, ref string result)
+ {
+ return ProfilesData.UpdateAvatarProperties(ref prop, ref result);
+ }
+ #endregion Profile Properties
+
+ #region Interests
+ public bool AvatarInterestsUpdate(UserProfileProperties prop, ref string result)
+ {
+ return ProfilesData.UpdateAvatarInterests(prop, ref result);
+ }
+ #endregion Interests
+
+ #region Utility
+ public OSD AvatarImageAssetsRequest(UUID avatarId)
+ {
+ OSDArray records = ProfilesData.GetUserImageAssets(avatarId);
+ return records;
+ }
+ #endregion Utility
+
+ #region UserData
+ public bool RequestUserAppData(ref UserAppData prop, ref string result)
+ {
+ return ProfilesData.GetUserAppData(ref prop, ref result);
+ }
+
+ public bool SetUserAppData(UserAppData prop, ref string result)
+ {
+ return true;
+ }
+ #endregion UserData
+ }
+}
+
diff --git a/OpenSim/Services/UserProfilesService/UserProfilesServiceBase.cs b/OpenSim/Services/UserProfilesService/UserProfilesServiceBase.cs
new file mode 100644
index 0000000000..dc0be038c5
--- /dev/null
+++ b/OpenSim/Services/UserProfilesService/UserProfilesServiceBase.cs
@@ -0,0 +1,59 @@
+using System;
+using System.Reflection;
+using Nini.Config;
+using log4net;
+using OpenSim.Services.Base;
+using OpenSim.Data;
+
+namespace OpenSim.Services.ProfilesService
+{
+ public class UserProfilesServiceBase: ServiceBase
+ {
+ static readonly ILog m_log =
+ LogManager.GetLogger(
+ MethodBase.GetCurrentMethod().DeclaringType);
+
+ public IProfilesData ProfilesData;
+
+ public string ConfigName
+ {
+ get; private set;
+ }
+
+ public UserProfilesServiceBase(IConfigSource config, string configName):
+ base(config)
+ {
+ if(string.IsNullOrEmpty(configName))
+ {
+ m_log.WarnFormat("[PROFILES]: Configuration section not given!");
+ return;
+ }
+
+ string dllName = String.Empty;
+ string connString = null;
+ string realm = String.Empty;
+
+ IConfig dbConfig = config.Configs["DatabaseService"];
+ if (dbConfig != null)
+ {
+ if (dllName == String.Empty)
+ dllName = dbConfig.GetString("StorageProvider", String.Empty);
+ if (string.IsNullOrEmpty(connString))
+ connString = dbConfig.GetString("ConnectionString", String.Empty);
+ }
+
+ IConfig ProfilesConfig = config.Configs[configName];
+ if (ProfilesConfig != null)
+ {
+ connString = ProfilesConfig.GetString("ConnectionString", connString);
+ realm = ProfilesConfig.GetString("Realm", realm);
+ }
+
+ ProfilesData = LoadPlugin(dllName, new Object[] { connString });
+ if (ProfilesData == null)
+ throw new Exception("Could not find a storage interface in the given module");
+
+ }
+ }
+}
+
diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example
index 5e486d4d2e..38e2a075a9 100644
--- a/bin/OpenSim.ini.example
+++ b/bin/OpenSim.ini.example
@@ -1032,6 +1032,12 @@
;# {InitialTerrain} {} {Initial terrain type} {pinhead-island flat} pinhead-island
; InitialTerrain = "pinhead-island"
+[Profile]
+ ;# {ProfileURL} {} {Set url to UserProfilesService} {}
+ ;; Set the value of the url to your UserProfilesService
+ ;; If un-set / "" the module is disabled
+ ;; ProfileURL = http://127.0.0.1:8002
+
[Architecture]
;# {Include-Architecture} {} {Choose one of the following architectures} {config-include/Standalone.ini config-include/StandaloneHypergrid.ini config-include/Grid.ini config-include/GridHypergrid.ini config-include/SimianGrid.ini config-include/HyperSimianGrid.ini} config-include/Standalone.ini
;; Uncomment one of the following includes as required. For instance, to create a standalone OpenSim,
diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini
index 81843b1c34..237f684577 100644
--- a/bin/OpenSimDefaults.ini
+++ b/bin/OpenSimDefaults.ini
@@ -377,6 +377,19 @@
AllowRegionRestartFromClient = true
+[UserProfiles]
+ ;# {ProfileURL} {} {Set url to UserProfilesService} {}
+ ;; Set the value of the url to your UserProfilesService
+ ;; If un-set / "" the module is disabled
+ ;; If the ProfileURL is not set, then very BASIC
+ ;; profile support will be configured. If the ProfileURL is set to a
+ ;; valid URL, then full profile support will be configured. The URL
+ ;; points to your grid's Robust user profiles service
+ ;;
+ ; ProfileURL = http://127.0.0.1:9000
+
+
+
[SMTP]
enabled = false
diff --git a/bin/Robust.HG.ini.example b/bin/Robust.HG.ini.example
index bc2b4cfb29..d9f1ca1725 100644
--- a/bin/Robust.HG.ini.example
+++ b/bin/Robust.HG.ini.example
@@ -71,10 +71,12 @@ HGInventoryServiceConnector = "HGInventoryService@8002/OpenSim.Server.Handlers.d
HGAssetServiceConnector = "HGAssetService@8002/OpenSim.Server.Handlers.dll:AssetServiceConnector"
;; Uncomment this if you want Groups V2, HG to work
; HGGroupsServiceConnector = "8002/OpenSim.Addons.Groups.dll:HGGroupsServiceRobustConnector"
-
;; Additions for other add-on modules. For example:
;; WifiServerConnector = "8002/Diva.Wifi.dll:WifiServerConnector"
+;; Uncomment for UserProfiles see [UserProfilesService] to configure...
+; UserProfilesServiceConnector = "8002/OpenSim.Server.Handlers.dll:UserProfilesConnector"
+
; * This is common for all services, it's the network setup for the entire
; * server instance, if none is specified above
; *
@@ -595,4 +597,12 @@ HGAssetServiceConnector = "HGAssetService@8002/OpenSim.Server.Handlers.dll:Asset
;; Can overwrite the default in [Hypergrid], but probably shouldn't
; HomeURI = "http://127.0.0.1:8002"
+[UserProfilesService]
+ LocalServiceModule = "OpenSim.Services.UserProfilesService.dll:UserProfilesService"
+ Enabled = false
+ ;; Configure this for separate profiles database
+ ;; ConnectionString = "Data Source=localhost;Database=opensim;User ID=opensim;Password=*****;Old Guids=true;"
+ ;; Realm = UserProfiles
+ UserAccountService = OpenSim.Services.UserAccountService.dll:UserAccountService
+ AuthenticationServiceModule = "OpenSim.Services.AuthenticationService.dll:PasswordAuthenticationService"
diff --git a/bin/Robust.ini.example b/bin/Robust.ini.example
index 1d66b7fcfd..7d6492bf94 100644
--- a/bin/Robust.ini.example
+++ b/bin/Robust.ini.example
@@ -51,6 +51,8 @@ MapGetServiceConnector = "8002/OpenSim.Server.Handlers.dll:MapGetServiceConnecto
;; Uncomment this if you want Groups V2 to work
;GroupsServiceConnector = "8003/OpenSim.Addons.Groups.dll:GroupsServiceRobustConnector"
+;; Uncomment for UserProfiles see [UserProfilesService] to configure...
+; UserProfilesServiceConnector = "8002/OpenSim.Server.Handlers.dll:UserProfilesConnector"
; * This is common for all services, it's the network setup for the entire
; * server instance, if none is specified above
@@ -391,4 +393,13 @@ MapGetServiceConnector = "8002/OpenSim.Server.Handlers.dll:MapGetServiceConnecto
; password help: optional: page providing password assistance for users of your grid
;password = http://127.0.0.1/password
+[UserProfilesService]
+ LocalServiceModule = "OpenSim.Services.UserProfilesService.dll:UserProfilesService"
+ Enabled = false
+ ;; Configure this for separate profiles database
+ ;; ConnectionString = "Data Source=localhost;Database=opensim;User ID=opensim;Password=*****;Old Guids=true;"
+ ;; Realm = UserProfiles
+ UserAccountService = OpenSim.Services.UserAccountService.dll:UserAccountService
+ AuthenticationServiceModule = "OpenSim.Services.AuthenticationService.dll:PasswordAuthenticationService"
+
diff --git a/bin/config-include/StandaloneCommon.ini.example b/bin/config-include/StandaloneCommon.ini.example
index 254724417f..8c23c41418 100644
--- a/bin/config-include/StandaloneCommon.ini.example
+++ b/bin/config-include/StandaloneCommon.ini.example
@@ -352,3 +352,19 @@
;; If appearance is restricted, which accounts' appearances are allowed to be exported?
;; Comma-separated list of account names
AccountForAppearance = "Test User, Astronaut Smith"
+
+;; UserProfiles Service
+;;
+;; To use, set Enabled to true then configure for your site...
+[UserProfilesService]
+ LocalServiceModule = "OpenSim.Services.UserProfilesService.dll:UserProfilesService"
+ Enabled = false
+
+ ;; Configure this for separate databse
+ ; ConnectionString = "Data Source=localhost;Database=opensim;User ID=opensim;Password=***;Old Guids=true;"
+ ; Realm = UserProfiles
+
+ UserAccountService = OpenSim.Services.UserAccountService.dll:UserAccountService
+ AuthenticationServiceModule = "OpenSim.Services.AuthenticationService.dll:PasswordAuthenticationService"
+
+
diff --git a/bin/config-include/StandaloneHypergrid.ini b/bin/config-include/StandaloneHypergrid.ini
index ba92030132..39c33e8ca2 100644
--- a/bin/config-include/StandaloneHypergrid.ini
+++ b/bin/config-include/StandaloneHypergrid.ini
@@ -19,6 +19,7 @@
GridUserServices = "LocalGridUserServicesConnector"
SimulationServices = "RemoteSimulationConnectorModule"
AvatarServices = "LocalAvatarServicesConnector"
+ UserProfilesServices = "LocalUserProfilesServicesConnector"
MapImageService = "MapImageServiceModule"
EntityTransferModule = "HGEntityTransferModule"
InventoryAccessModule = "HGInventoryAccessModule"
@@ -184,7 +185,6 @@
UserAgentService = "OpenSim.Services.HypergridService.dll:UserAgentService"
InGatekeeper = True
-
;; This should always be the very last thing on this file
[Includes]
Include-Common = "config-include/StandaloneCommon.ini"
diff --git a/prebuild.xml b/prebuild.xml
index 5967ef6ebb..03cac764ce 100644
--- a/prebuild.xml
+++ b/prebuild.xml
@@ -281,6 +281,7 @@
+
@@ -1239,6 +1240,42 @@
+
+
+
+ ../../../bin/
+
+
+
+
+ ../../../bin/
+
+
+
+ ../../../bin/
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1977,6 +2014,7 @@
+