diff --git a/OpenSim/Data/IFriendsData.cs b/OpenSim/Data/IFriendsData.cs index 1f1a0316f6..3fdf87b51a 100644 --- a/OpenSim/Data/IFriendsData.cs +++ b/OpenSim/Data/IFriendsData.cs @@ -34,7 +34,7 @@ namespace OpenSim.Data { public class FriendsData { - public UUID PrincipalID; + public string PrincipalID; public string Friend; public Dictionary Data; } @@ -46,6 +46,8 @@ namespace OpenSim.Data { bool Store(FriendsData data); bool Delete(UUID ownerID, string friend); + bool Delete(string ownerID, string friend); FriendsData[] GetFriends(UUID principalID); + FriendsData[] GetFriends(string principalID); } } diff --git a/OpenSim/Data/MSSQL/MSSQLEstateData.cs b/OpenSim/Data/MSSQL/MSSQLEstateData.cs index d10ebe4f48..9c54e77a23 100644 --- a/OpenSim/Data/MSSQL/MSSQLEstateData.cs +++ b/OpenSim/Data/MSSQL/MSSQLEstateData.cs @@ -41,7 +41,7 @@ namespace OpenSim.Data.MSSQL { private const string _migrationStore = "EstateStore"; - private static readonly ILog _Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private MSSQLManager _Database; private string m_connectionString; @@ -72,7 +72,12 @@ namespace OpenSim.Data.MSSQL } //Migration settings - _Database.CheckMigration(_migrationStore); + using (SqlConnection conn = new SqlConnection(m_connectionString)) + { + conn.Open(); + Migration m = new Migration(conn, GetType().Assembly, "EstateStore"); + m.Update(); + } //Interesting way to get parameters! Maybe implement that also with other types Type t = typeof(EstateSettings); @@ -112,19 +117,19 @@ namespace OpenSim.Data.MSSQL { FieldInfo f = _FieldMap[name]; object v = reader[name]; - if (f.FieldType == typeof(bool) ) + if (f.FieldType == typeof(bool)) { f.SetValue(es, Convert.ToInt32(v) != 0); } - else if (f.FieldType == typeof(UUID) ) + else if (f.FieldType == typeof(UUID)) { f.SetValue(es, new UUID((Guid)v)); // uuid); } - else if (f.FieldType == typeof(string)) + else if (f.FieldType == typeof(string)) { f.SetValue(es, v.ToString()); } - else if (f.FieldType == typeof(UInt32)) + else if (f.FieldType == typeof(UInt32)) { f.SetValue(es, Convert.ToUInt32(v)); } @@ -186,7 +191,7 @@ namespace OpenSim.Data.MSSQL } catch (Exception e) { - _Log.DebugFormat("[ESTATE DB]: Error inserting regionID and EstateID in estate_map: {0}", e); + m_log.DebugFormat("[ESTATE DB]: Error inserting regionID and EstateID in estate_map: {0}", e); } } @@ -310,12 +315,12 @@ namespace OpenSim.Data.MSSQL conn.Open(); using (SqlCommand cmd = conn.CreateCommand()) { - cmd.CommandText = "delete from estateban where EstateID = @EstateID"; + cmd.CommandText = "delete from estateban where EstateID = @EstateID"; cmd.Parameters.AddWithValue("@EstateID", (int)es.EstateID); cmd.ExecuteNonQuery(); //Insert after - cmd.CommandText = "insert into estateban (EstateID, bannedUUID) values ( @EstateID, @bannedUUID )"; + cmd.CommandText = "insert into estateban (EstateID, bannedUUID,bannedIp, bannedIpHostMask, bannedNameMask) values ( @EstateID, @bannedUUID, '','','' )"; cmd.Parameters.AddWithValue("@bannedUUID", Guid.Empty); foreach (EstateBan b in es.EstateBans) { @@ -350,43 +355,195 @@ namespace OpenSim.Data.MSSQL public EstateSettings LoadEstateSettings(int estateID) { - // TODO: Implementation! - return new EstateSettings(); + EstateSettings es = new EstateSettings(); + string sql = "select estate_settings." + String.Join(",estate_settings.", FieldList) + " from estate_settings where EstateID = @EstateID"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + { + conn.Open(); + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.AddWithValue("@EstateID", (int)estateID); + using (SqlDataReader reader = cmd.ExecuteReader()) + { + if (reader.Read()) + { + foreach (string name in FieldList) + { + FieldInfo f = _FieldMap[name]; + object v = reader[name]; + if (f.FieldType == typeof(bool)) + { + f.SetValue(es, Convert.ToInt32(v) != 0); + } + else if (f.FieldType == typeof(UUID)) + { + f.SetValue(es, new UUID((Guid)v)); // uuid); + } + else if (f.FieldType == typeof(string)) + { + f.SetValue(es, v.ToString()); + } + else if (f.FieldType == typeof(UInt32)) + { + f.SetValue(es, Convert.ToUInt32(v)); + } + else if (f.FieldType == typeof(Single)) + { + f.SetValue(es, Convert.ToSingle(v)); + } + else + f.SetValue(es, v); + } + } + + } + } + } + LoadBanList(es); + + es.EstateManagers = LoadUUIDList(es.EstateID, "estate_managers"); + es.EstateAccess = LoadUUIDList(es.EstateID, "estate_users"); + es.EstateGroups = LoadUUIDList(es.EstateID, "estate_groups"); + + //Set event + es.OnSave += StoreEstateSettings; + return es; + } - + public List LoadEstateSettingsAll() { - // TODO: Implementation! - return new List(); + List allEstateSettings = new List(); + + List allEstateIds = GetEstatesAll(); + + foreach (int estateId in allEstateIds) + allEstateSettings.Add(LoadEstateSettings(estateId)); + + return allEstateSettings; } public List GetEstates(string search) { - // TODO: Implementation! - return new List(); + List result = new List(); + string sql = "select estateID from estate_settings where EstateName = @EstateName"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + { + conn.Open(); + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.AddWithValue("@EstateName", search); + + using (IDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + result.Add(Convert.ToInt32(reader["EstateID"])); + } + reader.Close(); + } + } + } + + return result; } - + public List GetEstatesAll() { - // TODO: Implementation! - return new List(); + List result = new List(); + string sql = "select estateID from estate_settings"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + { + conn.Open(); + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + using (IDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + result.Add(Convert.ToInt32(reader["EstateID"])); + } + reader.Close(); + } + } + } + + return result; } public List GetEstatesByOwner(UUID ownerID) { - return new List(); + List result = new List(); + string sql = "select estateID from estate_settings where EstateOwner = @EstateOwner"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + { + conn.Open(); + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.AddWithValue("@EstateOwner", ownerID); + + using (IDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + result.Add(Convert.ToInt32(reader["EstateID"])); + } + reader.Close(); + } + } + } + + return result; } public bool LinkRegion(UUID regionID, int estateID) { - // TODO: Implementation! + string sql = "insert into estate_map values (@RegionID, @EstateID)"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + { + conn.Open(); + try + { + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.AddWithValue("@RegionID", regionID); + cmd.Parameters.AddWithValue("@EstateID", estateID); + + int ret = cmd.ExecuteNonQuery(); + return (ret != 0); + } + } + catch (Exception ex) + { + m_log.Error("[REGION DB]: LinkRegion failed: " + ex.Message); + } + } return false; } public List GetRegions(int estateID) { - // TODO: Implementation! - return new List(); + List result = new List(); + string sql = "select RegionID from estate_map where EstateID = @EstateID"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + { + conn.Open(); + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.AddWithValue("@EstateID", estateID); + + using (IDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + result.Add(DBGuid.FromDB(reader["RegionID"])); + } + reader.Close(); + } + } + } + + return result; } public bool DeleteEstate(int estateID) diff --git a/OpenSim/Data/MSSQL/MSSQLFriendsData.cs b/OpenSim/Data/MSSQL/MSSQLFriendsData.cs index af4fd9ba55..09dde5e182 100644 --- a/OpenSim/Data/MSSQL/MSSQLFriendsData.cs +++ b/OpenSim/Data/MSSQL/MSSQLFriendsData.cs @@ -51,6 +51,11 @@ namespace OpenSim.Data.MSSQL } public bool Delete(UUID principalID, string friend) + { + return Delete(principalID.ToString(), friend); + } + + public bool Delete(string principalID, string friend) { using (SqlConnection conn = new SqlConnection(m_ConnectionString)) using (SqlCommand cmd = new SqlCommand()) @@ -67,6 +72,11 @@ namespace OpenSim.Data.MSSQL } public FriendsData[] GetFriends(UUID principalID) + { + return GetFriends(principalID.ToString()); + } + + public FriendsData[] GetFriends(string principalID) { using (SqlConnection conn = new SqlConnection(m_ConnectionString)) using (SqlCommand cmd = new SqlCommand()) diff --git a/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs b/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs index 6e695cecc3..8f471c40c8 100644 --- a/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs +++ b/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs @@ -168,14 +168,13 @@ namespace OpenSim.Data.MSSQL protected T[] DoQuery(SqlCommand cmd) { + List result = new List(); using (SqlDataReader reader = cmd.ExecuteReader()) { if (reader == null) return new T[0]; - CheckColumnNames(reader); - - List result = new List(); + CheckColumnNames(reader); while (reader.Read()) { @@ -262,6 +261,15 @@ namespace OpenSim.Data.MSSQL { names.Add(fi.Name); values.Add("@" + fi.Name); + // Temporarily return more information about what field is unexpectedly null for + // http://opensimulator.org/mantis/view.php?id=5403. This might be due to a bug in the + // InventoryTransferModule or we may be required to substitute a DBNull here. + if (fi.GetValue(row) == null) + throw new NullReferenceException( + string.Format( + "[MSSQL GENERIC TABLE HANDLER]: Trying to store field {0} for {1} which is unexpectedly null", + fi.Name, row)); + if (constraintFields.Count > 0 && constraintFields.Contains(fi.Name)) { constraints.Add(new KeyValuePair(fi.Name, fi.GetValue(row).ToString())); @@ -358,12 +366,18 @@ namespace OpenSim.Data.MSSQL string where = String.Join(" AND ", terms.ToArray()); - string query = String.Format("DELETE * FROM {0} WHERE {1}", m_Realm, where); + string query = String.Format("DELETE FROM {0} WHERE {1}", m_Realm, where); cmd.Connection = conn; cmd.CommandText = query; conn.Open(); - return cmd.ExecuteNonQuery() > 0; + + if (cmd.ExecuteNonQuery() > 0) + { + //m_log.Warn("[MSSQLGenericTable]: " + deleteCommand); + return true; + } + return false; } } } diff --git a/OpenSim/Data/MSSQL/MSSQLMigration.cs b/OpenSim/Data/MSSQL/MSSQLMigration.cs index cd395b84d1..1aa96c7ff0 100644 --- a/OpenSim/Data/MSSQL/MSSQLMigration.cs +++ b/OpenSim/Data/MSSQL/MSSQLMigration.cs @@ -29,16 +29,19 @@ using System; using System.Data; using System.Data.Common; using System.Reflection; +using System.Data.SqlClient; namespace OpenSim.Data.MSSQL { public class MSSQLMigration : Migration { - public MSSQLMigration(DbConnection conn, Assembly assem, string type) : base(conn, assem, type) + public MSSQLMigration(DbConnection conn, Assembly assem, string type) + : base(conn, assem, type) { } - public MSSQLMigration(DbConnection conn, Assembly assem, string subtype, string type) : base(conn, assem, subtype, type) + public MSSQLMigration(DbConnection conn, Assembly assem, string subtype, string type) + : base(conn, assem, subtype, type) { } @@ -67,5 +70,30 @@ namespace OpenSim.Data.MSSQL } return version; } + + protected override void ExecuteScript(DbConnection conn, string[] script) + { + if (!(conn is SqlConnection)) + { + base.ExecuteScript(conn, script); + return; + } + + foreach (string sql in script) + { + try + { + using (SqlCommand cmd = new SqlCommand(sql, (SqlConnection)conn)) + { + cmd.ExecuteNonQuery(); + } + } + catch (Exception ex) + { + throw new Exception(sql); + + } + } + } } } diff --git a/OpenSim/Data/MSSQL/MSSQLRegionData.cs b/OpenSim/Data/MSSQL/MSSQLRegionData.cs index cdf8ec09fb..3ae87c3804 100644 --- a/OpenSim/Data/MSSQL/MSSQLRegionData.cs +++ b/OpenSim/Data/MSSQL/MSSQLRegionData.cs @@ -70,6 +70,7 @@ namespace OpenSim.Data.MSSQL string sql = "select * from ["+m_Realm+"] where regionName like @regionName"; if (scopeID != UUID.Zero) sql += " and ScopeID = @scopeID"; + sql += " order by regionName"; using (SqlConnection conn = new SqlConnection(m_ConnectionString)) using (SqlCommand cmd = new SqlCommand(sql, conn)) { diff --git a/OpenSim/Data/MSSQL/MSSQLSimulationData.cs b/OpenSim/Data/MSSQL/MSSQLSimulationData.cs index 5155e567e6..78f80e154a 100644 --- a/OpenSim/Data/MSSQL/MSSQLSimulationData.cs +++ b/OpenSim/Data/MSSQL/MSSQLSimulationData.cs @@ -55,6 +55,10 @@ namespace OpenSim.Data.MSSQL /// private MSSQLManager _Database; private string m_connectionString; + protected virtual Assembly Assembly + { + get { return GetType().Assembly; } + } public MSSQLSimulationData() { @@ -74,9 +78,28 @@ namespace OpenSim.Data.MSSQL m_connectionString = connectionString; _Database = new MSSQLManager(connectionString); + using (SqlConnection conn = new SqlConnection(connectionString)) + { + conn.Open(); + //New Migration settings + Migration m = new Migration(conn, Assembly, "RegionStore"); + m.Update(); - //Migration settings - _Database.CheckMigration(_migrationStore); + // Clean dropped attachments + // + try + { + using (SqlCommand cmd = conn.CreateCommand()) + { + cmd.CommandText = "delete from prims where prims.UUID in (select UUID from primshapes where PCode = 9 and State <> 0); delete from primshapes where PCode = 9 and State <> 0"; + cmd.ExecuteNonQuery(); + } + } + catch (Exception ex) + { + _Log.Error("[REGION DB]: Error cleaning up dropped attachments: " + ex.Message); + } + } } /// @@ -214,7 +237,7 @@ namespace OpenSim.Data.MSSQL { command.Parameters.Clear(); command.Parameters.Add(_Database.CreateParameter("@PrimID", objectPart.UUID)); - + List inventory = new List(); using (SqlDataReader reader = command.ExecuteReader()) @@ -241,6 +264,14 @@ namespace OpenSim.Data.MSSQL /// public void StoreObject(SceneObjectGroup obj, UUID regionUUID) { + uint flags = obj.RootPart.GetEffectiveObjectFlags(); + // Eligibility check + // + if ((flags & (uint)PrimFlags.Temporary) != 0) + return; + if ((flags & (uint)PrimFlags.TemporaryOnRez) != 0) + return; + _Log.DebugFormat("[MSSQL]: Adding/Changing SceneObjectGroup: {0} to region: {1}, object has {2} prims.", obj.UUID, regionUUID, obj.Parts.Length); using (SqlConnection conn = new SqlConnection(m_connectionString)) @@ -700,16 +731,470 @@ VALUES } public RegionLightShareData LoadRegionWindlightSettings(UUID regionUUID) { - //This connector doesn't support the windlight module yet - //Return default LL windlight settings - return new RegionLightShareData(); + RegionLightShareData nWP = new RegionLightShareData(); + nWP.OnSave += StoreRegionWindlightSettings; + string sql = "select * from [regionwindlight] where region_id = @regionID"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.Add(_Database.CreateParameter("@regionID", regionUUID)); + conn.Open(); + using (SqlDataReader result = cmd.ExecuteReader()) + { + if (!result.Read()) + { + //No result, so store our default windlight profile and return it + nWP.regionID = regionUUID; + StoreRegionWindlightSettings(nWP); + return nWP; + } + else + { + nWP.regionID = DBGuid.FromDB(result["region_id"]); + nWP.waterColor.X = Convert.ToSingle(result["water_color_r"]); + nWP.waterColor.Y = Convert.ToSingle(result["water_color_g"]); + nWP.waterColor.Z = Convert.ToSingle(result["water_color_b"]); + nWP.waterFogDensityExponent = Convert.ToSingle(result["water_fog_density_exponent"]); + nWP.underwaterFogModifier = Convert.ToSingle(result["underwater_fog_modifier"]); + nWP.reflectionWaveletScale.X = Convert.ToSingle(result["reflection_wavelet_scale_1"]); + nWP.reflectionWaveletScale.Y = Convert.ToSingle(result["reflection_wavelet_scale_2"]); + nWP.reflectionWaveletScale.Z = Convert.ToSingle(result["reflection_wavelet_scale_3"]); + nWP.fresnelScale = Convert.ToSingle(result["fresnel_scale"]); + nWP.fresnelOffset = Convert.ToSingle(result["fresnel_offset"]); + nWP.refractScaleAbove = Convert.ToSingle(result["refract_scale_above"]); + nWP.refractScaleBelow = Convert.ToSingle(result["refract_scale_below"]); + nWP.blurMultiplier = Convert.ToSingle(result["blur_multiplier"]); + nWP.bigWaveDirection.X = Convert.ToSingle(result["big_wave_direction_x"]); + nWP.bigWaveDirection.Y = Convert.ToSingle(result["big_wave_direction_y"]); + nWP.littleWaveDirection.X = Convert.ToSingle(result["little_wave_direction_x"]); + nWP.littleWaveDirection.Y = Convert.ToSingle(result["little_wave_direction_y"]); + UUID.TryParse(result["normal_map_texture"].ToString(), out nWP.normalMapTexture); + nWP.horizon.X = Convert.ToSingle(result["horizon_r"]); + nWP.horizon.Y = Convert.ToSingle(result["horizon_g"]); + nWP.horizon.Z = Convert.ToSingle(result["horizon_b"]); + nWP.horizon.W = Convert.ToSingle(result["horizon_i"]); + nWP.hazeHorizon = Convert.ToSingle(result["haze_horizon"]); + nWP.blueDensity.X = Convert.ToSingle(result["blue_density_r"]); + nWP.blueDensity.Y = Convert.ToSingle(result["blue_density_g"]); + nWP.blueDensity.Z = Convert.ToSingle(result["blue_density_b"]); + nWP.blueDensity.W = Convert.ToSingle(result["blue_density_i"]); + nWP.hazeDensity = Convert.ToSingle(result["haze_density"]); + nWP.densityMultiplier = Convert.ToSingle(result["density_multiplier"]); + nWP.distanceMultiplier = Convert.ToSingle(result["distance_multiplier"]); + nWP.maxAltitude = Convert.ToUInt16(result["max_altitude"]); + nWP.sunMoonColor.X = Convert.ToSingle(result["sun_moon_color_r"]); + nWP.sunMoonColor.Y = Convert.ToSingle(result["sun_moon_color_g"]); + nWP.sunMoonColor.Z = Convert.ToSingle(result["sun_moon_color_b"]); + nWP.sunMoonColor.W = Convert.ToSingle(result["sun_moon_color_i"]); + nWP.sunMoonPosition = Convert.ToSingle(result["sun_moon_position"]); + nWP.ambient.X = Convert.ToSingle(result["ambient_r"]); + nWP.ambient.Y = Convert.ToSingle(result["ambient_g"]); + nWP.ambient.Z = Convert.ToSingle(result["ambient_b"]); + nWP.ambient.W = Convert.ToSingle(result["ambient_i"]); + nWP.eastAngle = Convert.ToSingle(result["east_angle"]); + nWP.sunGlowFocus = Convert.ToSingle(result["sun_glow_focus"]); + nWP.sunGlowSize = Convert.ToSingle(result["sun_glow_size"]); + nWP.sceneGamma = Convert.ToSingle(result["scene_gamma"]); + nWP.starBrightness = Convert.ToSingle(result["star_brightness"]); + nWP.cloudColor.X = Convert.ToSingle(result["cloud_color_r"]); + nWP.cloudColor.Y = Convert.ToSingle(result["cloud_color_g"]); + nWP.cloudColor.Z = Convert.ToSingle(result["cloud_color_b"]); + nWP.cloudColor.W = Convert.ToSingle(result["cloud_color_i"]); + nWP.cloudXYDensity.X = Convert.ToSingle(result["cloud_x"]); + nWP.cloudXYDensity.Y = Convert.ToSingle(result["cloud_y"]); + nWP.cloudXYDensity.Z = Convert.ToSingle(result["cloud_density"]); + nWP.cloudCoverage = Convert.ToSingle(result["cloud_coverage"]); + nWP.cloudScale = Convert.ToSingle(result["cloud_scale"]); + nWP.cloudDetailXYDensity.X = Convert.ToSingle(result["cloud_detail_x"]); + nWP.cloudDetailXYDensity.Y = Convert.ToSingle(result["cloud_detail_y"]); + nWP.cloudDetailXYDensity.Z = Convert.ToSingle(result["cloud_detail_density"]); + nWP.cloudScrollX = Convert.ToSingle(result["cloud_scroll_x"]); + nWP.cloudScrollXLock = Convert.ToBoolean(result["cloud_scroll_x_lock"]); + nWP.cloudScrollY = Convert.ToSingle(result["cloud_scroll_y"]); + nWP.cloudScrollYLock = Convert.ToBoolean(result["cloud_scroll_y_lock"]); + nWP.drawClassicClouds = Convert.ToBoolean(result["draw_classic_clouds"]); + nWP.valid = true; + } + } + } + return nWP; } + public void RemoveRegionWindlightSettings(UUID regionID) { + string sql = "delete from [regionwindlight] where region_id = @region_id"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + conn.Open(); + cmd.Parameters.Add(_Database.CreateParameter("@region_id", regionID)); + cmd.ExecuteNonQuery(); + } } + public void StoreRegionWindlightSettings(RegionLightShareData wl) { - //This connector doesn't support the windlight module yet + string sql = "select count (region_id) from regionwindlight where region_id = @region_id"; + bool exists = false; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + { + conn.Open(); + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.Add(_Database.CreateParameter("@region_id", wl.regionID)); + exists = (int)cmd.ExecuteScalar() > 0; + } + } + if (exists) + { + RemoveRegionWindlightSettings(wl.regionID); + } + + // sql insert + sql = @"INSERT INTO [regionwindlight] + ([region_id] + ,[water_color_r] + ,[water_color_g] + ,[water_color_b] + ,[water_fog_density_exponent] + ,[underwater_fog_modifier] + ,[reflection_wavelet_scale_1] + ,[reflection_wavelet_scale_2] + ,[reflection_wavelet_scale_3] + ,[fresnel_scale] + ,[fresnel_offset] + ,[refract_scale_above] + ,[refract_scale_below] + ,[blur_multiplier] + ,[big_wave_direction_x] + ,[big_wave_direction_y] + ,[little_wave_direction_x] + ,[little_wave_direction_y] + ,[normal_map_texture] + ,[horizon_r] + ,[horizon_g] + ,[horizon_b] + ,[horizon_i] + ,[haze_horizon] + ,[blue_density_r] + ,[blue_density_g] + ,[blue_density_b] + ,[blue_density_i] + ,[haze_density] + ,[density_multiplier] + ,[distance_multiplier] + ,[max_altitude] + ,[sun_moon_color_r] + ,[sun_moon_color_g] + ,[sun_moon_color_b] + ,[sun_moon_color_i] + ,[sun_moon_position] + ,[ambient_r] + ,[ambient_g] + ,[ambient_b] + ,[ambient_i] + ,[east_angle] + ,[sun_glow_focus] + ,[sun_glow_size] + ,[scene_gamma] + ,[star_brightness] + ,[cloud_color_r] + ,[cloud_color_g] + ,[cloud_color_b] + ,[cloud_color_i] + ,[cloud_x] + ,[cloud_y] + ,[cloud_density] + ,[cloud_coverage] + ,[cloud_scale] + ,[cloud_detail_x] + ,[cloud_detail_y] + ,[cloud_detail_density] + ,[cloud_scroll_x] + ,[cloud_scroll_x_lock] + ,[cloud_scroll_y] + ,[cloud_scroll_y_lock] + ,[draw_classic_clouds]) + VALUES + (@region_id + ,@water_color_r + ,@water_color_g + ,@water_color_b + ,@water_fog_density_exponent + ,@underwater_fog_modifier + ,@reflection_wavelet_scale_1 + ,@reflection_wavelet_scale_2 + ,@reflection_wavelet_scale_3 + ,@fresnel_scale + ,@fresnel_offset + ,@refract_scale_above + ,@refract_scale_below + ,@blur_multiplier + ,@big_wave_direction_x + ,@big_wave_direction_y + ,@little_wave_direction_x + ,@little_wave_direction_y + ,@normal_map_texture + ,@horizon_r + ,@horizon_g + ,@horizon_b + ,@horizon_i + ,@haze_horizon + ,@blue_density_r + ,@blue_density_g + ,@blue_density_b + ,@blue_density_i + ,@haze_density + ,@density_multiplier + ,@distance_multiplier + ,@max_altitude + ,@sun_moon_color_r + ,@sun_moon_color_g + ,@sun_moon_color_b + ,@sun_moon_color_i + ,@sun_moon_position + ,@ambient_r + ,@ambient_g + ,@ambient_b + ,@ambient_i + ,@east_angle + ,@sun_glow_focus + ,@sun_glow_size + ,@scene_gamma + ,@star_brightness + ,@cloud_color_r + ,@cloud_color_g + ,@cloud_color_b + ,@cloud_color_i + ,@cloud_x + ,@cloud_y + ,@cloud_density + ,@cloud_coverage + ,@cloud_scale + ,@cloud_detail_x + ,@cloud_detail_y + ,@cloud_detail_density + ,@cloud_scroll_x + ,@cloud_scroll_x_lock + ,@cloud_scroll_y + ,@cloud_scroll_y_lock + ,@draw_classic_clouds)"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + { + conn.Open(); + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.Add(_Database.CreateParameter("region_id", wl.regionID)); + cmd.Parameters.Add(_Database.CreateParameter("water_color_r", wl.waterColor.X)); + cmd.Parameters.Add(_Database.CreateParameter("water_color_g", wl.waterColor.Y)); + cmd.Parameters.Add(_Database.CreateParameter("water_color_b", wl.waterColor.Z)); + cmd.Parameters.Add(_Database.CreateParameter("water_fog_density_exponent", wl.waterFogDensityExponent)); + cmd.Parameters.Add(_Database.CreateParameter("underwater_fog_modifier", wl.underwaterFogModifier)); + cmd.Parameters.Add(_Database.CreateParameter("reflection_wavelet_scale_1", wl.reflectionWaveletScale.X)); + cmd.Parameters.Add(_Database.CreateParameter("reflection_wavelet_scale_2", wl.reflectionWaveletScale.Y)); + cmd.Parameters.Add(_Database.CreateParameter("reflection_wavelet_scale_3", wl.reflectionWaveletScale.Z)); + cmd.Parameters.Add(_Database.CreateParameter("fresnel_scale", wl.fresnelScale)); + cmd.Parameters.Add(_Database.CreateParameter("fresnel_offset", wl.fresnelOffset)); + cmd.Parameters.Add(_Database.CreateParameter("refract_scale_above", wl.refractScaleAbove)); + cmd.Parameters.Add(_Database.CreateParameter("refract_scale_below", wl.refractScaleBelow)); + cmd.Parameters.Add(_Database.CreateParameter("blur_multiplier", wl.blurMultiplier)); + cmd.Parameters.Add(_Database.CreateParameter("big_wave_direction_x", wl.bigWaveDirection.X)); + cmd.Parameters.Add(_Database.CreateParameter("big_wave_direction_y", wl.bigWaveDirection.Y)); + cmd.Parameters.Add(_Database.CreateParameter("little_wave_direction_x", wl.littleWaveDirection.X)); + cmd.Parameters.Add(_Database.CreateParameter("little_wave_direction_y", wl.littleWaveDirection.Y)); + cmd.Parameters.Add(_Database.CreateParameter("normal_map_texture", wl.normalMapTexture)); + cmd.Parameters.Add(_Database.CreateParameter("horizon_r", wl.horizon.X)); + cmd.Parameters.Add(_Database.CreateParameter("horizon_g", wl.horizon.Y)); + cmd.Parameters.Add(_Database.CreateParameter("horizon_b", wl.horizon.Z)); + cmd.Parameters.Add(_Database.CreateParameter("horizon_i", wl.horizon.W)); + cmd.Parameters.Add(_Database.CreateParameter("haze_horizon", wl.hazeHorizon)); + cmd.Parameters.Add(_Database.CreateParameter("blue_density_r", wl.blueDensity.X)); + cmd.Parameters.Add(_Database.CreateParameter("blue_density_g", wl.blueDensity.Y)); + cmd.Parameters.Add(_Database.CreateParameter("blue_density_b", wl.blueDensity.Z)); + cmd.Parameters.Add(_Database.CreateParameter("blue_density_i", wl.blueDensity.W)); + cmd.Parameters.Add(_Database.CreateParameter("haze_density", wl.hazeDensity)); + cmd.Parameters.Add(_Database.CreateParameter("density_multiplier", wl.densityMultiplier)); + cmd.Parameters.Add(_Database.CreateParameter("distance_multiplier", wl.distanceMultiplier)); + cmd.Parameters.Add(_Database.CreateParameter("max_altitude", wl.maxAltitude)); + cmd.Parameters.Add(_Database.CreateParameter("sun_moon_color_r", wl.sunMoonColor.X)); + cmd.Parameters.Add(_Database.CreateParameter("sun_moon_color_g", wl.sunMoonColor.Y)); + cmd.Parameters.Add(_Database.CreateParameter("sun_moon_color_b", wl.sunMoonColor.Z)); + cmd.Parameters.Add(_Database.CreateParameter("sun_moon_color_i", wl.sunMoonColor.W)); + cmd.Parameters.Add(_Database.CreateParameter("sun_moon_position", wl.sunMoonPosition)); + cmd.Parameters.Add(_Database.CreateParameter("ambient_r", wl.ambient.X)); + cmd.Parameters.Add(_Database.CreateParameter("ambient_g", wl.ambient.Y)); + cmd.Parameters.Add(_Database.CreateParameter("ambient_b", wl.ambient.Z)); + cmd.Parameters.Add(_Database.CreateParameter("ambient_i", wl.ambient.W)); + cmd.Parameters.Add(_Database.CreateParameter("east_angle", wl.eastAngle)); + cmd.Parameters.Add(_Database.CreateParameter("sun_glow_focus", wl.sunGlowFocus)); + cmd.Parameters.Add(_Database.CreateParameter("sun_glow_size", wl.sunGlowSize)); + cmd.Parameters.Add(_Database.CreateParameter("scene_gamma", wl.sceneGamma)); + cmd.Parameters.Add(_Database.CreateParameter("star_brightness", wl.starBrightness)); + cmd.Parameters.Add(_Database.CreateParameter("cloud_color_r", wl.cloudColor.X)); + cmd.Parameters.Add(_Database.CreateParameter("cloud_color_g", wl.cloudColor.Y)); + cmd.Parameters.Add(_Database.CreateParameter("cloud_color_b", wl.cloudColor.Z)); + cmd.Parameters.Add(_Database.CreateParameter("cloud_color_i", wl.cloudColor.W)); + cmd.Parameters.Add(_Database.CreateParameter("cloud_x", wl.cloudXYDensity.X)); + cmd.Parameters.Add(_Database.CreateParameter("cloud_y", wl.cloudXYDensity.Y)); + cmd.Parameters.Add(_Database.CreateParameter("cloud_density", wl.cloudXYDensity.Z)); + cmd.Parameters.Add(_Database.CreateParameter("cloud_coverage", wl.cloudCoverage)); + cmd.Parameters.Add(_Database.CreateParameter("cloud_scale", wl.cloudScale)); + cmd.Parameters.Add(_Database.CreateParameter("cloud_detail_x", wl.cloudDetailXYDensity.X)); + cmd.Parameters.Add(_Database.CreateParameter("cloud_detail_y", wl.cloudDetailXYDensity.Y)); + cmd.Parameters.Add(_Database.CreateParameter("cloud_detail_density", wl.cloudDetailXYDensity.Z)); + cmd.Parameters.Add(_Database.CreateParameter("cloud_scroll_x", wl.cloudScrollX)); + cmd.Parameters.Add(_Database.CreateParameter("cloud_scroll_x_lock", wl.cloudScrollXLock)); + cmd.Parameters.Add(_Database.CreateParameter("cloud_scroll_y", wl.cloudScrollY)); + cmd.Parameters.Add(_Database.CreateParameter("cloud_scroll_y_lock", wl.cloudScrollYLock)); + cmd.Parameters.Add(_Database.CreateParameter("draw_classic_clouds", wl.drawClassicClouds)); + + cmd.ExecuteNonQuery(); + } + } + #region update + // } + // else + // { + // // sql update + // sql = @"UPDATE [OpenSim].[dbo].[regionwindlight] + // SET [region_id] = @region_id + // ,[water_color_r] = @water_color_r + // ,[water_color_g] = @water_color_g + // ,[water_color_b] = @water_color_b + // ,[water_fog_density_exponent] = @water_fog_density_exponent + // ,[underwater_fog_modifier] = @underwater_fog_modifier + // ,[reflection_wavelet_scale_1] = @reflection_wavelet_scale_1 + // ,[reflection_wavelet_scale_2] = @reflection_wavelet_scale_2 + // ,[reflection_wavelet_scale_3] = @reflection_wavelet_scale_3 + // ,[fresnel_scale] = @fresnel_scale + // ,[fresnel_offset] = @fresnel_offset + // ,[refract_scale_above] = @refract_scale_above + // ,[refract_scale_below] = @refract_scale_below + // ,[blur_multiplier] = @blur_multiplier + // ,[big_wave_direction_x] = @big_wave_direction_x + // ,[big_wave_direction_y] = @big_wave_direction_y + // ,[little_wave_direction_x] = @little_wave_direction_x + // ,[little_wave_direction_y] = @little_wave_direction_y + // ,[normal_map_texture] = @normal_map_texture + // ,[horizon_r] = @horizon_r + // ,[horizon_g] = @horizon_g + // ,[horizon_b] = @horizon_b + // ,[horizon_i] = @horizon_i + // ,[haze_horizon] = @haze_horizon + // ,[blue_density_r] = @blue_density_r + // ,[blue_density_g] = @blue_density_g + // ,[blue_density_b] = @blue_density_b + // ,[blue_density_i] = @blue_density_i + // ,[haze_density] = @haze_density + // ,[density_multiplier] = @density_multiplier + // ,[distance_multiplier] = @distance_multiplier + // ,[max_altitude] = @max_altitude + // ,[sun_moon_color_r] = @sun_moon_color_r + // ,[sun_moon_color_g] = @sun_moon_color_g + // ,[sun_moon_color_b] = @sun_moon_color_b + // ,[sun_moon_color_i] = @sun_moon_color_i + // ,[sun_moon_position] = @sun_moon_position + // ,[ambient_r] = @ambient_r + // ,[ambient_g] = @ambient_g + // ,[ambient_b] = @ambient_b + // ,[ambient_i] = @ambient_i + // ,[east_angle] = @east_angle + // ,[sun_glow_focus] = @sun_glow_focus + // ,[sun_glow_size] = @sun_glow_size + // ,[scene_gamma] = @scene_gamma + // ,[star_brightness] = @star_brightness + // ,[cloud_color_r] = @cloud_color_r + // ,[cloud_color_g] = @cloud_color_g + // ,[cloud_color_b] = @cloud_color_b + // ,[cloud_color_i] = @cloud_color_i + // ,[cloud_x] = @cloud_x + // ,[cloud_y] = @cloud_y + // ,[cloud_density] = @cloud_density + // ,[cloud_coverage] = @cloud_coverage + // ,[cloud_scale] = @cloud_scale + // ,[cloud_detail_x] = @cloud_detail_x + // ,[cloud_detail_y] = @cloud_detail_y + // ,[cloud_detail_density] = @cloud_detail_density + // ,[cloud_scroll_x] = @cloud_scroll_x + // ,[cloud_scroll_x_lock] = @cloud_scroll_x_lock + // ,[cloud_scroll_y] = @cloud_scroll_y + // ,[cloud_scroll_y_lock] = @cloud_scroll_y_lock + // ,[draw_classic_clouds] = @draw_classic_clouds + // WHERE region_id = @region_id"; + // using (SqlConnection conn = new SqlConnection(m_connectionString)) + // { + // conn.Open(); + // using (SqlCommand cmd = new SqlCommand(sql, conn)) + // { + // cmd.Parameters.AddWithValue("region_id", wl.regionID); + // cmd.Parameters.AddWithValue("water_color_r", wl.waterColor.X); + // cmd.Parameters.AddWithValue("water_color_g", wl.waterColor.Y); + // cmd.Parameters.AddWithValue("water_color_b", wl.waterColor.Z); + // cmd.Parameters.AddWithValue("water_fog_density_exponent", wl.waterFogDensityExponent); + // cmd.Parameters.AddWithValue("underwater_fog_modifier", wl.underwaterFogModifier); + // cmd.Parameters.AddWithValue("reflection_wavelet_scale_1", wl.reflectionWaveletScale.X); + // cmd.Parameters.AddWithValue("reflection_wavelet_scale_2", wl.reflectionWaveletScale.Y); + // cmd.Parameters.AddWithValue("reflection_wavelet_scale_3", wl.reflectionWaveletScale.Z); + // cmd.Parameters.AddWithValue("fresnel_scale", wl.fresnelScale); + // cmd.Parameters.AddWithValue("fresnel_offset", wl.fresnelOffset); + // cmd.Parameters.AddWithValue("refract_scale_above", wl.refractScaleAbove); + // cmd.Parameters.AddWithValue("refract_scale_below", wl.refractScaleBelow); + // cmd.Parameters.AddWithValue("blur_multiplier", wl.blurMultiplier); + // cmd.Parameters.AddWithValue("big_wave_direction_x", wl.bigWaveDirection.X); + // cmd.Parameters.AddWithValue("big_wave_direction_y", wl.bigWaveDirection.Y); + // cmd.Parameters.AddWithValue("little_wave_direction_x", wl.littleWaveDirection.X); + // cmd.Parameters.AddWithValue("little_wave_direction_y", wl.littleWaveDirection.Y); + // cmd.Parameters.AddWithValue("normal_map_texture", wl.normalMapTexture); + // cmd.Parameters.AddWithValue("horizon_r", wl.horizon.X); + // cmd.Parameters.AddWithValue("horizon_g", wl.horizon.Y); + // cmd.Parameters.AddWithValue("horizon_b", wl.horizon.Z); + // cmd.Parameters.AddWithValue("horizon_i", wl.horizon.W); + // cmd.Parameters.AddWithValue("haze_horizon", wl.hazeHorizon); + // cmd.Parameters.AddWithValue("blue_density_r", wl.blueDensity.X); + // cmd.Parameters.AddWithValue("blue_density_g", wl.blueDensity.Y); + // cmd.Parameters.AddWithValue("blue_density_b", wl.blueDensity.Z); + // cmd.Parameters.AddWithValue("blue_density_i", wl.blueDensity.W); + // cmd.Parameters.AddWithValue("haze_density", wl.hazeDensity); + // cmd.Parameters.AddWithValue("density_multiplier", wl.densityMultiplier); + // cmd.Parameters.AddWithValue("distance_multiplier", wl.distanceMultiplier); + // cmd.Parameters.AddWithValue("max_altitude", wl.maxAltitude); + // cmd.Parameters.AddWithValue("sun_moon_color_r", wl.sunMoonColor.X); + // cmd.Parameters.AddWithValue("sun_moon_color_g", wl.sunMoonColor.Y); + // cmd.Parameters.AddWithValue("sun_moon_color_b", wl.sunMoonColor.Z); + // cmd.Parameters.AddWithValue("sun_moon_color_i", wl.sunMoonColor.W); + // cmd.Parameters.AddWithValue("sun_moon_position", wl.sunMoonPosition); + // cmd.Parameters.AddWithValue("ambient_r", wl.ambient.X); + // cmd.Parameters.AddWithValue("ambient_g", wl.ambient.Y); + // cmd.Parameters.AddWithValue("ambient_b", wl.ambient.Z); + // cmd.Parameters.AddWithValue("ambient_i", wl.ambient.W); + // cmd.Parameters.AddWithValue("east_angle", wl.eastAngle); + // cmd.Parameters.AddWithValue("sun_glow_focus", wl.sunGlowFocus); + // cmd.Parameters.AddWithValue("sun_glow_size", wl.sunGlowSize); + // cmd.Parameters.AddWithValue("scene_gamma", wl.sceneGamma); + // cmd.Parameters.AddWithValue("star_brightness", wl.starBrightness); + // cmd.Parameters.AddWithValue("cloud_color_r", wl.cloudColor.X); + // cmd.Parameters.AddWithValue("cloud_color_g", wl.cloudColor.Y); + // cmd.Parameters.AddWithValue("cloud_color_b", wl.cloudColor.Z); + // cmd.Parameters.AddWithValue("cloud_color_i", wl.cloudColor.W); + // cmd.Parameters.AddWithValue("cloud_x", wl.cloudXYDensity.X); + // cmd.Parameters.AddWithValue("cloud_y", wl.cloudXYDensity.Y); + // cmd.Parameters.AddWithValue("cloud_density", wl.cloudXYDensity.Z); + // cmd.Parameters.AddWithValue("cloud_coverage", wl.cloudCoverage); + // cmd.Parameters.AddWithValue("cloud_scale", wl.cloudScale); + // cmd.Parameters.AddWithValue("cloud_detail_x", wl.cloudDetailXYDensity.X); + // cmd.Parameters.AddWithValue("cloud_detail_y", wl.cloudDetailXYDensity.Y); + // cmd.Parameters.AddWithValue("cloud_detail_density", wl.cloudDetailXYDensity.Z); + // cmd.Parameters.AddWithValue("cloud_scroll_x", wl.cloudScrollX); + // cmd.Parameters.AddWithValue("cloud_scroll_x_lock", wl.cloudScrollXLock); + // cmd.Parameters.AddWithValue("cloud_scroll_y", wl.cloudScrollY); + // cmd.Parameters.AddWithValue("cloud_scroll_y_lock", wl.cloudScrollYLock); + // cmd.Parameters.AddWithValue("draw_classic_clouds", wl.drawClassicClouds); + + // cmd.ExecuteNonQuery(); + // } + // } + // } + #endregion } /// /// Loads the settings of a region. @@ -1136,7 +1621,7 @@ VALUES if (Convert.ToInt16(primRow["PassTouches"]) != 0) prim.PassTouches = true; prim.LinkNum = Convert.ToInt32(primRow["LinkNumber"]); - + if (!(primRow["MediaURL"] is System.DBNull)) prim.MediaUrl = (string)primRow["MediaURL"]; @@ -1192,11 +1677,11 @@ VALUES { } - if (!(shapeRow["Media"] is System.DBNull) ) + if (!(shapeRow["Media"] is System.DBNull)) { baseShape.Media = PrimitiveBaseShape.MediaList.FromXml((string)shapeRow["Media"]); } - + return baseShape; } @@ -1576,15 +2061,15 @@ VALUES parameters.Add(_Database.CreateParameter("ExtraParams", s.ExtraParams)); parameters.Add(_Database.CreateParameter("State", s.State)); - if(null == s.Media ) + if (null == s.Media) { - parameters.Add(_Database.CreateParameter("Media", DBNull.Value)); + parameters.Add(_Database.CreateParameter("Media", DBNull.Value)); } else { - parameters.Add(_Database.CreateParameter("Media", s.Media.ToXml())); + parameters.Add(_Database.CreateParameter("Media", s.Media.ToXml())); } - + return parameters.ToArray(); } diff --git a/OpenSim/Data/MSSQL/MSSQLXInventoryData.cs b/OpenSim/Data/MSSQL/MSSQLXInventoryData.cs index dc35a2e0c0..1f6994ddb5 100644 --- a/OpenSim/Data/MSSQL/MSSQLXInventoryData.cs +++ b/OpenSim/Data/MSSQL/MSSQLXInventoryData.cs @@ -66,11 +66,18 @@ namespace OpenSim.Data.MSSQL public bool StoreFolder(XInventoryFolder folder) { + if (folder.folderName.Length > 64) + folder.folderName = folder.folderName.Substring(0, 64); return m_Folders.Store(folder); } public bool StoreItem(XInventoryItem item) { + if (item.inventoryName.Length > 64) + item.inventoryName = item.inventoryName.Substring(0, 64); + if (item.inventoryDescription.Length > 128) + item.inventoryDescription = item.inventoryDescription.Substring(0, 128); + return m_Items.Store(item); } @@ -78,7 +85,6 @@ namespace OpenSim.Data.MSSQL { return m_Folders.Delete(field, val); } - public bool DeleteFolders(string[] fields, string[] vals) { return m_Folders.Delete(fields, vals); @@ -88,12 +94,10 @@ namespace OpenSim.Data.MSSQL { return m_Items.Delete(field, val); } - public bool DeleteItems(string[] fields, string[] vals) { return m_Items.Delete(fields, vals); } - public bool MoveItem(string id, string newParent) { return m_Items.MoveItem(id, newParent); @@ -172,5 +176,27 @@ namespace OpenSim.Data.MSSQL } } + public override bool Store(XInventoryItem item) + { + if (!base.Store(item)) + return false; + string sql = "update inventoryfolders set version=version+1 where folderID = @folderID"; + using (SqlConnection conn = new SqlConnection(m_ConnectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + conn.Open(); + + cmd.Parameters.AddWithValue("@folderID", item.parentFolderID.ToString()); + try + { + cmd.ExecuteNonQuery(); + } + catch (Exception e) + { + return false; + } + } + return true; + } } } diff --git a/OpenSim/Data/MSSQL/Resources/Avatar.migrations b/OpenSim/Data/MSSQL/Resources/Avatar.migrations index 5364153363..61f7b562d2 100644 --- a/OpenSim/Data/MSSQL/Resources/Avatar.migrations +++ b/OpenSim/Data/MSSQL/Resources/Avatar.migrations @@ -37,4 +37,28 @@ EXECUTE sp_rename N'dbo.Tmp_Avatars', N'Avatars', 'OBJECT' COMMIT +:VERSION 3 + +BEGIN TRANSACTION + +CREATE TABLE dbo.Tmp_Avatars + ( + PrincipalID uniqueidentifier NOT NULL, + [Name] varchar(32) NOT NULL, + Value text NOT NULL DEFAULT '', + PRIMARY KEY CLUSTERED +( + [PrincipalID] ASC, [Name] ASC +)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] +) ON [PRIMARY] + TEXTIMAGE_ON [PRIMARY] + +IF EXISTS(SELECT * FROM dbo.Avatars) + EXEC('INSERT INTO dbo.Tmp_Avatars (PrincipalID, Name, Value) + SELECT PrincipalID, CONVERT(text, Name), Value FROM dbo.Avatars WITH (HOLDLOCK TABLOCKX)') + +DROP TABLE dbo.Avatars + +EXECUTE sp_rename N'dbo.Tmp_Avatars', N'Avatars', 'OBJECT' +COMMIT diff --git a/OpenSim/Data/MSSQL/Resources/GridUserStore.migrations b/OpenSim/Data/MSSQL/Resources/GridUserStore.migrations index 7a7cecdb40..ecd3f4dbda 100644 --- a/OpenSim/Data/MSSQL/Resources/GridUserStore.migrations +++ b/OpenSim/Data/MSSQL/Resources/GridUserStore.migrations @@ -17,3 +17,49 @@ CREATE TABLE "GridUser" ( ) COMMIT + +:VERSION 2 # -------------------------- + +BEGIN TRANSACTION + +CREATE TABLE [GridUser_tmp] ( + [UserID] VARCHAR(255) NOT NULL, + [HomeRegionID] uniqueidentifier NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000', + [HomePosition] CHAR(64) NOT NULL DEFAULT '<0,0,0>', + [HomeLookAt] CHAR(64) NOT NULL DEFAULT '<0,0,0>', + [LastRegionID] uniqueidentifier NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000', + [LastPosition] CHAR(64) NOT NULL DEFAULT '<0,0,0>', + [LastLookAt] CHAR(64) NOT NULL DEFAULT '<0,0,0>', + [Online] CHAR(5) NOT NULL DEFAULT 'false', + [Login] CHAR(16) NOT NULL DEFAULT '0', + [Logout] CHAR(16) NOT NULL DEFAULT '0', + + PRIMARY KEY CLUSTERED + ( + [UserID] ASC + )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] + ) ON [PRIMARY] + +COMMIT + +IF EXISTS(SELECT * FROM dbo.GridUser) + EXEC('INSERT INTO dbo.GridUser_tmp ([UserID] + ,[HomeRegionID] + ,[HomePosition] + ,[HomeLookAt] + ,[LastRegionID] + ,[LastPosition] + ,[LastLookAt] + ,[Online] + ,[Login] + ,[Logout]) + SELECT CONVERT(varchar(36), [HomeRegionID]), [HomePosition] ,[HomeLookAt] , CONVERT(varchar(36),[LastRegionID]) + ,[LastPosition] + ,[LastLookAt] + ,[Online] + ,[Login] + ,[Logout] FROM dbo.GridUser WITH (HOLDLOCK TABLOCKX)') + +DROP TABLE dbo.GridUser + +EXECUTE sp_rename N'dbo.GridUser_tmp', N'GridUser', 'OBJECT' \ No newline at end of file diff --git a/OpenSim/Data/MSSQL/Resources/RegionStore.migrations b/OpenSim/Data/MSSQL/Resources/RegionStore.migrations index 340b63dec3..3995e6ce2c 100644 --- a/OpenSim/Data/MSSQL/Resources/RegionStore.migrations +++ b/OpenSim/Data/MSSQL/Resources/RegionStore.migrations @@ -1003,7 +1003,7 @@ CREATE TABLE "regionwindlight" ( PRIMARY KEY ("region_id") ) -COMMIT TRANSACTION +COMMIT :VERSION 26 diff --git a/OpenSim/Data/MySQL/MySQLFriendsData.cs b/OpenSim/Data/MySQL/MySQLFriendsData.cs index 663fad6603..130ba5e9c2 100644 --- a/OpenSim/Data/MySQL/MySQLFriendsData.cs +++ b/OpenSim/Data/MySQL/MySQLFriendsData.cs @@ -43,6 +43,11 @@ namespace OpenSim.Data.MySQL } public bool Delete(UUID principalID, string friend) + { + return Delete(principalID.ToString(), friend); + } + + public bool Delete(string principalID, string friend) { MySqlCommand cmd = new MySqlCommand(); @@ -64,5 +69,14 @@ namespace OpenSim.Data.MySQL return DoQuery(cmd); } + + public FriendsData[] GetFriends(string principalID) + { + MySqlCommand cmd = new MySqlCommand(); + + cmd.CommandText = String.Format("select a.*,case when b.Flags is null then -1 else b.Flags end as TheirFlags from {0} as a left join {0} as b on a.PrincipalID = b.Friend and a.Friend = b.PrincipalID where a.PrincipalID LIKE ?PrincipalID", m_Realm); + cmd.Parameters.AddWithValue("?PrincipalID", principalID.ToString() + '%'); + return DoQuery(cmd); + } } } diff --git a/OpenSim/Data/MySQL/Resources/FriendsStore.migrations b/OpenSim/Data/MySQL/Resources/FriendsStore.migrations index ce713bdb89..55d82eca73 100644 --- a/OpenSim/Data/MySQL/Resources/FriendsStore.migrations +++ b/OpenSim/Data/MySQL/Resources/FriendsStore.migrations @@ -21,5 +21,12 @@ INSERT INTO `Friends` SELECT `ownerID`, `friendID`, `friendPerms`, 0 FROM `userf COMMIT; +:VERSION 3 # ------------------------- +BEGIN; +ALTER TABLE `Friends` MODIFY COLUMN PrincipalID varchar(255) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000'; +ALTER TABLE `Friends` DROP PRIMARY KEY; +ALTER TABLE `Friends` ADD PRIMARY KEY(PrincipalID(36), Friend(36)); + +COMMIT; diff --git a/OpenSim/Data/MySQL/Resources/RegionStore.migrations b/OpenSim/Data/MySQL/Resources/RegionStore.migrations index 645f4e8f16..c2b130cb88 100644 --- a/OpenSim/Data/MySQL/Resources/RegionStore.migrations +++ b/OpenSim/Data/MySQL/Resources/RegionStore.migrations @@ -826,3 +826,19 @@ ALTER TABLE `prims` MODIFY COLUMN `CreatorID` VARCHAR(255) NOT NULL DEFAULT ''; ALTER TABLE `primitems` MODIFY COLUMN `CreatorID` VARCHAR(255) NOT NULL DEFAULT ''; COMMIT; + +:VERSION 38 #--------------------- + +BEGIN; + +alter table land ENGINE = MyISAM; +alter table landaccesslist ENGINE = MyISAM; +alter table migrations ENGINE = MyISAM; +alter table primitems ENGINE = MyISAM; +alter table prims ENGINE = MyISAM; +alter table primshapes ENGINE = MyISAM; +alter table regionban ENGINE = MyISAM; +alter table regionsettings ENGINE = MyISAM; +alter table terrain ENGINE = MyISAM; + +COMMIT; \ No newline at end of file diff --git a/OpenSim/Data/Null/NullFriendsData.cs b/OpenSim/Data/Null/NullFriendsData.cs index e7f7fd3738..d90788a111 100644 --- a/OpenSim/Data/Null/NullFriendsData.cs +++ b/OpenSim/Data/Null/NullFriendsData.cs @@ -42,6 +42,11 @@ namespace OpenSim.Data.Null { } + public FriendsData[] GetFriends(UUID principalID) + { + return GetFriends(principalID.ToString()); + } + /// /// Tries to implement the Get [] semantics, but it cuts corners. /// Specifically, it gets all friendships even if they weren't accepted yet. @@ -49,11 +54,11 @@ namespace OpenSim.Data.Null /// /// /// - public FriendsData[] GetFriends(UUID userID) + public FriendsData[] GetFriends(string userID) { List lst = m_Data.FindAll(delegate (FriendsData fdata) { - return fdata.PrincipalID == userID; + return fdata.PrincipalID == userID.ToString(); }); if (lst != null) @@ -72,9 +77,14 @@ namespace OpenSim.Data.Null return true; } - public bool Delete(UUID userID, string friendID) + public bool Delete(UUID principalID, string friend) { - List lst = m_Data.FindAll(delegate(FriendsData fdata) { return fdata.PrincipalID == userID; }); + return Delete(principalID.ToString(), friend); + } + + public bool Delete(string userID, string friendID) + { + List lst = m_Data.FindAll(delegate(FriendsData fdata) { return fdata.PrincipalID == userID.ToString(); }); if (lst != null) { FriendsData friend = lst.Find(delegate(FriendsData fdata) { return fdata.Friend == friendID; }); diff --git a/OpenSim/Data/SQLite/SQLiteFriendsData.cs b/OpenSim/Data/SQLite/SQLiteFriendsData.cs index 4bfd228364..b14c3482bb 100644 --- a/OpenSim/Data/SQLite/SQLiteFriendsData.cs +++ b/OpenSim/Data/SQLite/SQLiteFriendsData.cs @@ -46,7 +46,12 @@ namespace OpenSim.Data.SQLite { } - public FriendsData[] GetFriends(UUID userID) + public FriendsData[] GetFriends(UUID principalID) + { + return GetFriends(principalID.ToString()); + } + + public FriendsData[] GetFriends(string userID) { SqliteCommand cmd = new SqliteCommand(); @@ -58,6 +63,11 @@ namespace OpenSim.Data.SQLite } public bool Delete(UUID principalID, string friend) + { + return Delete(principalID.ToString(), friend); + } + + public bool Delete(string principalID, string friend) { SqliteCommand cmd = new SqliteCommand(); diff --git a/OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs b/OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs index 3fb2d3facb..0d7ae1fc93 100644 --- a/OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs +++ b/OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs @@ -280,7 +280,7 @@ namespace OpenSim.Data.SQLite string where = String.Join(" and ", terms.ToArray()); - string query = String.Format("delete * from {0} where {1}", m_Realm, where); + string query = String.Format("delete from {0} where {1}", m_Realm, where); cmd.CommandText = query; diff --git a/OpenSim/Framework/AgentCircuitData.cs b/OpenSim/Framework/AgentCircuitData.cs index dbd47d392a..125910e5bc 100644 --- a/OpenSim/Framework/AgentCircuitData.cs +++ b/OpenSim/Framework/AgentCircuitData.cs @@ -345,6 +345,7 @@ namespace OpenSim.Framework } } } + } diff --git a/OpenSim/Framework/AssetBase.cs b/OpenSim/Framework/AssetBase.cs index 98fa84683b..8e24f911c4 100644 --- a/OpenSim/Framework/AssetBase.cs +++ b/OpenSim/Framework/AssetBase.cs @@ -223,6 +223,12 @@ namespace OpenSim.Framework set { m_metadata.Temporary = value; } } + public string CreatorID + { + get { return m_metadata.CreatorID; } + set { m_metadata.CreatorID = value; } + } + public AssetFlags Flags { get { return m_metadata.Flags; } diff --git a/OpenSim/Framework/AssetLandmark.cs b/OpenSim/Framework/AssetLandmark.cs index f433235ec8..103f75676c 100644 --- a/OpenSim/Framework/AssetLandmark.cs +++ b/OpenSim/Framework/AssetLandmark.cs @@ -35,6 +35,7 @@ namespace OpenSim.Framework public Vector3 Position; public ulong RegionHandle; public UUID RegionID; + public string Gatekeeper = string.Empty; public int Version; public AssetLandmark(AssetBase a) @@ -51,6 +52,8 @@ namespace OpenSim.Framework string[] parts = temp.Split('\n'); int.TryParse(parts[0].Substring(17, 1), out Version); UUID.TryParse(parts[1].Substring(10, 36), out RegionID); + if (parts.Length >= 5) + Gatekeeper = parts[4].Replace("gatekeeper ", ""); // The position is a vector with spaces as separators ("10.3 32.5 43"). // Parse each scalar separately to take into account the system's culture setting. string[] scalars = parts[2].Substring(10, parts[2].Length - 10).Split(' '); diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index 3cf5f32a29..31a45e2372 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -83,7 +83,7 @@ namespace OpenSim.Framework IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags); public delegate void TeleportLandmarkRequest( - IClientAPI remoteClient, UUID regionID, Vector3 position); + IClientAPI remoteClient, AssetLandmark lm); public delegate void DisconnectUser(); @@ -1165,7 +1165,19 @@ namespace OpenSim.Framework void SendAgentAlertMessage(string message, bool modal); void SendLoadURL(string objectname, UUID objectID, UUID ownerID, bool groupOwned, string message, string url); - void SendDialog(string objectname, UUID objectID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch, + /// + /// Open a dialog box on the client. + /// + /// + /// + /// /param> + /// + /// + /// + /// + /// + /// + void SendDialog(string objectname, UUID objectID, UUID ownerID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch, string[] buttonlabels); bool AddMoney(int debit); diff --git a/OpenSim/Framework/Serialization/External/RegionSettingsSerializer.cs b/OpenSim/Framework/Serialization/External/RegionSettingsSerializer.cs index 6ba4c5a55e..931898ce10 100644 --- a/OpenSim/Framework/Serialization/External/RegionSettingsSerializer.cs +++ b/OpenSim/Framework/Serialization/External/RegionSettingsSerializer.cs @@ -182,6 +182,9 @@ namespace OpenSim.Framework.Serialization.External case "FixedSun": settings.FixedSun = bool.Parse(xtr.ReadElementContentAsString()); break; + case "SunPosition": + settings.SunPosition = double.Parse(xtr.ReadElementContentAsString()); + break; } } @@ -237,8 +240,9 @@ namespace OpenSim.Framework.Serialization.External xtw.WriteElementString("TerrainLowerLimit", settings.TerrainLowerLimit.ToString()); xtw.WriteElementString("UseEstateSun", settings.UseEstateSun.ToString()); xtw.WriteElementString("FixedSun", settings.FixedSun.ToString()); - // XXX: Need to expose interface to get sun phase information from sun module - // xtw.WriteStartElement("SunPhase", + xtw.WriteElementString("SunPosition", settings.SunPosition.ToString()); + // Note: 'SunVector' isn't saved because this value is owned by the Sun Module, which + // calculates it automatically according to the date and other factors. xtw.WriteEndElement(); xtw.WriteEndElement(); diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs index c12d666a00..460f7599a1 100644 --- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs +++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs @@ -412,7 +412,7 @@ namespace OpenSim.Framework.Servers.HttpServer // OpenSim.Framework.WebUtil.OSHeaderRequestID if (request.Headers["opensim-request-id"] != null) reqnum = String.Format("{0}:{1}",request.RemoteIPEndPoint,request.Headers["opensim-request-id"]); - // m_log.DebugFormat("[BASE HTTP SERVER]: <{0}> handle request for {1}",reqnum,request.RawUrl); + //m_log.DebugFormat("[BASE HTTP SERVER]: <{0}> handle request for {1}",reqnum,request.RawUrl); Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US", true); @@ -440,7 +440,7 @@ namespace OpenSim.Framework.Servers.HttpServer string path = request.RawUrl; string handlerKey = GetHandlerKey(request.HttpMethod, path); -// m_log.DebugFormat("[BASE HTTP SERVER]: Handling {0} request for {1}", request.HttpMethod, path); + //m_log.DebugFormat("[BASE HTTP SERVER]: Handling {0} request for {1}", request.HttpMethod, path); if (TryGetStreamHandler(handlerKey, out requestHandler)) { diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs index 366a38f1ec..5ace351e69 100644 --- a/OpenSim/Framework/Util.cs +++ b/OpenSim/Framework/Util.cs @@ -1706,5 +1706,68 @@ namespace OpenSim.Framework return (T)Enum.Parse(typeof(T), value); ; } #endregion + + #region Universal User Identifiers + /// + /// + /// uuid[;endpoint[;name]] + /// + /// + /// + /// + public static bool ParseUniversalUserIdentifier(string value, out UUID uuid, out string url, out string firstname, out string lastname, out string secret) + { + uuid = UUID.Zero; url = string.Empty; firstname = "Unknown"; lastname = "User"; secret = string.Empty; + + string[] parts = value.Split(';'); + if (parts.Length >= 1) + if (!UUID.TryParse(parts[0], out uuid)) + return false; + + if (parts.Length >= 2) + url = parts[1]; + + if (parts.Length >= 3) + { + string[] name = parts[2].Split(); + if (name.Length == 2) + { + firstname = name[0]; + lastname = name[1]; + } + } + if (parts.Length >= 4) + secret = parts[3]; + + return true; + } + + /// + /// + /// + /// + /// uuid[;endpoint[;name]] + public static string ProduceUserUniversalIdentifier(AgentCircuitData acircuit) + { + if (acircuit.ServiceURLs.ContainsKey("HomeURI")) + { + string agentsURI = acircuit.ServiceURLs["HomeURI"].ToString(); + if (!agentsURI.EndsWith("/")) + agentsURI += "/"; + + // This is ugly, but there's no other way, given that the name is changed + // in the agent circuit data for foreigners + if (acircuit.lastname.Contains("@")) + { + string[] parts = acircuit.firstname.Split(new char[] { '.' }); + if (parts.Length == 2) + return acircuit.AgentID.ToString() + ";" + agentsURI + ";" + parts[0] + " " + parts[1]; + } + return acircuit.AgentID.ToString() + ";" + agentsURI + ";" + acircuit.firstname + " " + acircuit.lastname; + } + else + return acircuit.AgentID.ToString(); + } + #endregion } } diff --git a/OpenSim/Region/Application/Application.cs b/OpenSim/Region/Application/Application.cs index 7e320e6798..3b261e77dd 100644 --- a/OpenSim/Region/Application/Application.cs +++ b/OpenSim/Region/Application/Application.cs @@ -231,6 +231,8 @@ namespace OpenSim configSource.Alias.AddAlias("Off", false); configSource.Alias.AddAlias("True", true); configSource.Alias.AddAlias("False", false); + configSource.Alias.AddAlias("Yes", true); + configSource.Alias.AddAlias("No", false); configSource.AddSwitch("Startup", "background"); configSource.AddSwitch("Startup", "inifile"); @@ -239,6 +241,8 @@ namespace OpenSim configSource.AddSwitch("Startup", "physics"); configSource.AddSwitch("Startup", "gui"); configSource.AddSwitch("Startup", "console"); + configSource.AddSwitch("Startup", "save_crashes"); + configSource.AddSwitch("Startup", "crash_dir"); configSource.AddConfig("StandAlone"); configSource.AddConfig("Network"); diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs index 503123ed91..04a68ae4a9 100644 --- a/OpenSim/Region/Application/OpenSimBase.cs +++ b/OpenSim/Region/Application/OpenSimBase.cs @@ -918,7 +918,7 @@ namespace OpenSim if (regInfo.EstateSettings.EstateID == 0) // No record at all { - MainConsole.Instance.OutputFormat("Region {0} is not part of an estate.", regInfo.RegionName); + m_log.WarnFormat("[ESTATE] Region {0} is not part of an estate.", regInfo.RegionName); List estates = EstateDataService.LoadEstateSettingsAll(); List estateNames = new List(); @@ -929,7 +929,7 @@ namespace OpenSim { if (estates.Count == 0) { - MainConsole.Instance.Output("No existing estates found. You must create a new one."); + m_log.Info("[ESTATE] No existing estates found. You must create a new one."); if (CreateEstate(regInfo, estateNames)) break; diff --git a/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs new file mode 100644 index 0000000000..9f78948df4 --- /dev/null +++ b/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs @@ -0,0 +1,152 @@ +/* + * 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.Reflection; +using log4net; +using Nini.Config; +using Mono.Addins; +using OpenMetaverse; +using OpenMetaverse.StructuredData; +using OpenSim.Framework; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; +using Caps = OpenSim.Framework.Capabilities.Caps; + +namespace OpenSim.Region.ClientStack.Linden +{ + /// + /// SimulatorFeatures capability. This is required for uploading Mesh. + /// Since is accepts an open-ended response, we also send more information + /// for viewers that care to interpret it. + /// + /// NOTE: Part of this code was adapted from the Aurora project, specifically + /// the normal part of the response in the capability handler. + /// + /// + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] + public class SimulatorFeaturesModule : ISharedRegionModule + { + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private Scene m_scene; + + private string m_MapImageServerURL = string.Empty; + private string m_SearchURL = string.Empty; + + #region ISharedRegionModule Members + + public void Initialise(IConfigSource source) + { + IConfig config = source.Configs["SimulatorFeatures"]; + if (config == null) + return; + + m_MapImageServerURL = config.GetString("MapImageServerURI", string.Empty); + if (m_MapImageServerURL != string.Empty) + { + m_MapImageServerURL = m_MapImageServerURL.Trim(); + if (!m_MapImageServerURL.EndsWith("/")) + m_MapImageServerURL = m_MapImageServerURL + "/"; + } + + m_SearchURL = config.GetString("SearchServerURI", string.Empty); + } + + public void AddRegion(Scene s) + { + m_scene = s; + m_scene.EventManager.OnRegisterCaps += RegisterCaps; + } + + public void RemoveRegion(Scene s) + { + m_scene.EventManager.OnRegisterCaps -= RegisterCaps; + } + + public void RegionLoaded(Scene s) + { + } + + public void PostInitialise() + { + } + + public void Close() { } + + public string Name { get { return "SimulatorFeaturesModule"; } } + + public Type ReplaceableInterface + { + get { return null; } + } + + #endregion + + public void RegisterCaps(UUID agentID, Caps caps) + { + IRequestHandler reqHandler = new RestHTTPHandler("GET", "/CAPS/" + UUID.Random(), SimulatorFeatures); + caps.RegisterHandler("SimulatorFeatures", reqHandler); + } + + private Hashtable SimulatorFeatures(Hashtable mDhttpMethod) + { + m_log.DebugFormat("[SIMULATOR FEATURES MODULE]: SimulatorFeatures request"); + OSDMap data = new OSDMap(); + data["MeshRezEnabled"] = true; + data["MeshUploadEnabled"] = true; + data["MeshXferEnabled"] = true; + data["PhysicsMaterialsEnabled"] = true; + + OSDMap typesMap = new OSDMap(); + typesMap["convex"] = true; + typesMap["none"] = true; + typesMap["prim"] = true; + data["PhysicsShapeTypes"] = typesMap; + + // Extra information for viewers that want to use it + OSDMap gridServicesMap = new OSDMap(); + if (m_MapImageServerURL != string.Empty) + gridServicesMap["map-server-url"] = m_MapImageServerURL; + if (m_SearchURL != string.Empty) + gridServicesMap["search"] = m_SearchURL; + data["GridServices"] = gridServicesMap; + + //Send back data + Hashtable responsedata = new Hashtable(); + responsedata["int_response_code"] = 200; + responsedata["content_type"] = "text/plain"; + responsedata["keepalive"] = false; + responsedata["str_response_string"] = OSDParser.SerializeLLSDXmlString(data); + return responsedata; + } + + } +} diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 05e6d27d10..60485186e0 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -438,6 +438,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP #endregion Properties +// ~LLClientView() +// { +// m_log.DebugFormat("[LLCLIENTVIEW]: Destructor called for {0}, circuit code {1}", Name, CircuitCode); +// } + /// /// Constructor /// @@ -1476,6 +1481,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP money.MoneyData.TransactionSuccess = success; money.MoneyData.Description = description; money.MoneyData.MoneyBalance = balance; + money.TransactionInfo.ItemDescription = Util.StringToBytes256("NONE"); OutPacket(money, ThrottleOutPacketType.Task); } @@ -2231,7 +2237,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutPacket(loadURL, ThrottleOutPacketType.Task); } - public void SendDialog(string objectname, UUID objectID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch, string[] buttonlabels) + public void SendDialog( + string objectname, UUID objectID, UUID ownerID, string ownerFirstName, string ownerLastName, string msg, + UUID textureID, int ch, string[] buttonlabels) { ScriptDialogPacket dialog = (ScriptDialogPacket)PacketPool.Instance.GetPacket(PacketType.ScriptDialog); dialog.Data.ObjectID = objectID; @@ -2249,6 +2257,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP buttons[i].ButtonLabel = Util.StringToBytes256(buttonlabels[i]); } dialog.Buttons = buttons; + + dialog.OwnerData = new ScriptDialogPacket.OwnerDataBlock[1]; + dialog.OwnerData[0] = new ScriptDialogPacket.OwnerDataBlock(); + dialog.OwnerData[0].OwnerID = ownerID; + OutPacket(dialog, ThrottleOutPacketType.Task); } @@ -2320,8 +2333,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP OrbitalPosition = (OrbitalPosition - m_sunPainDaHalfOrbitalCutoff) * 0.6666666667f + m_sunPainDaHalfOrbitalCutoff; } - - SimulatorViewerTimeMessagePacket viewertime = (SimulatorViewerTimeMessagePacket)PacketPool.Instance.GetPacket(PacketType.SimulatorViewerTimeMessage); viewertime.TimeInfo.SunDirection = Position; viewertime.TimeInfo.SunAngVelocity = Velocity; @@ -8358,16 +8369,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP AssetLandmark lm; if (lmid != UUID.Zero) { + //AssetBase lma = m_assetCache.GetAsset(lmid, false); AssetBase lma = m_assetService.Get(lmid.ToString()); if (lma == null) { // Failed to find landmark - TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel); - tpCancel.Info.SessionID = tpReq.Info.SessionID; - tpCancel.Info.AgentID = tpReq.Info.AgentID; - OutPacket(tpCancel, ThrottleOutPacketType.Task); + + // Let's try to search in the user's home asset server + lma = FindAssetInUserAssetServer(lmid.ToString()); + + if (lma == null) + { + // Really doesn't exist + TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel); + tpCancel.Info.SessionID = tpReq.Info.SessionID; + tpCancel.Info.AgentID = tpReq.Info.AgentID; + OutPacket(tpCancel, ThrottleOutPacketType.Task); + } } try @@ -8398,13 +8418,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP TeleportLandmarkRequest handlerTeleportLandmarkRequest = OnTeleportLandmarkRequest; if (handlerTeleportLandmarkRequest != null) { - handlerTeleportLandmarkRequest(this, lm.RegionID, lm.Position); + handlerTeleportLandmarkRequest(this, lm); } else { //no event handler so cancel request - - TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel); tpCancel.Info.AgentID = tpReq.Info.AgentID; tpCancel.Info.SessionID = tpReq.Info.SessionID; @@ -8414,6 +8432,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP return true; } + private AssetBase FindAssetInUserAssetServer(string id) + { + AgentCircuitData aCircuit = ((Scene)Scene).AuthenticateHandler.GetAgentCircuitData(CircuitCode); + if (aCircuit != null && aCircuit.ServiceURLs != null && aCircuit.ServiceURLs.ContainsKey("AssetServerURI")) + { + string assetServer = aCircuit.ServiceURLs["AssetServerURI"].ToString(); + return ((Scene)Scene).AssetService.Get(assetServer + "/" + id); + } + + return null; + } + private bool HandleTeleportLocationRequest(IClientAPI sender, Packet Pack) { TeleportLocationRequestPacket tpLocReq = (TeleportLocationRequestPacket)Pack; diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index 7cba702298..9ef5bc95c3 100644 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs @@ -64,13 +64,13 @@ namespace Flotsam.RegionModules.AssetCache private bool m_Enabled; private const string m_ModuleName = "FlotsamAssetCache"; - private const string m_DefaultCacheDirectory = m_ModuleName; + private const string m_DefaultCacheDirectory = "./assetcache"; private string m_CacheDirectory = m_DefaultCacheDirectory; private readonly List m_InvalidChars = new List(); private int m_LogLevel = 0; - private ulong m_HitRateDisplay = 1; // How often to display hit statistics, given in requests + private ulong m_HitRateDisplay = 100; // How often to display hit statistics, given in requests private static ulong m_Requests; private static ulong m_RequestsForInprogress; @@ -87,14 +87,14 @@ namespace Flotsam.RegionModules.AssetCache #endif private ExpiringCache m_MemoryCache; - private bool m_MemoryCacheEnabled = true; + private bool m_MemoryCacheEnabled = false; // Expiration is expressed in hours. - private const double m_DefaultMemoryExpiration = 1.0; + private const double m_DefaultMemoryExpiration = 2; private const double m_DefaultFileExpiration = 48; private TimeSpan m_MemoryExpiration = TimeSpan.FromHours(m_DefaultMemoryExpiration); private TimeSpan m_FileExpiration = TimeSpan.FromHours(m_DefaultFileExpiration); - private TimeSpan m_FileExpirationCleanupTimer = TimeSpan.FromHours(m_DefaultFileExpiration); + private TimeSpan m_FileExpirationCleanupTimer = TimeSpan.FromHours(0.166); private static int m_CacheDirectoryTiers = 1; private static int m_CacheDirectoryTierLen = 3; @@ -141,26 +141,38 @@ namespace Flotsam.RegionModules.AssetCache IConfig assetConfig = source.Configs["AssetCache"]; if (assetConfig == null) { - m_log.Warn("[FLOTSAM ASSET CACHE]: AssetCache missing from OpenSim.ini, using defaults."); - m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Directory", m_DefaultCacheDirectory); - return; + m_log.Warn( + "[FLOTSAM ASSET CACHE]: AssetCache section missing from config (not copied config-include/FlotsamCache.ini.example? Using defaults."); + } + else + { + m_CacheDirectory = assetConfig.GetString("CacheDirectory", m_DefaultCacheDirectory); + + m_MemoryCacheEnabled = assetConfig.GetBoolean("MemoryCacheEnabled", m_MemoryCacheEnabled); + m_MemoryExpiration = TimeSpan.FromHours(assetConfig.GetDouble("MemoryCacheTimeout", m_DefaultMemoryExpiration)); + + #if WAIT_ON_INPROGRESS_REQUESTS + m_WaitOnInprogressTimeout = assetConfig.GetInt("WaitOnInprogressTimeout", 3000); + #endif + + m_LogLevel = assetConfig.GetInt("LogLevel", m_LogLevel); + m_HitRateDisplay = (ulong)assetConfig.GetLong("HitRateDisplay", (long)m_HitRateDisplay); + + m_FileExpiration = TimeSpan.FromHours(assetConfig.GetDouble("FileCacheTimeout", m_DefaultFileExpiration)); + m_FileExpirationCleanupTimer + = TimeSpan.FromHours( + assetConfig.GetDouble("FileCleanupTimer", m_FileExpirationCleanupTimer.TotalHours)); + + m_CacheDirectoryTiers = assetConfig.GetInt("CacheDirectoryTiers", m_CacheDirectoryTiers); + m_CacheDirectoryTierLen = assetConfig.GetInt("CacheDirectoryTierLength", m_CacheDirectoryTierLen); + + m_CacheWarnAt = assetConfig.GetInt("CacheWarnAt", m_CacheWarnAt); + + m_DeepScanBeforePurge = assetConfig.GetBoolean("DeepScanBeforePurge", m_DeepScanBeforePurge); } - m_CacheDirectory = assetConfig.GetString("CacheDirectory", m_DefaultCacheDirectory); - m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Directory", m_CacheDirectory); + m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Directory {0}", m_CacheDirectory); - m_MemoryCacheEnabled = assetConfig.GetBoolean("MemoryCacheEnabled", false); - m_MemoryExpiration = TimeSpan.FromHours(assetConfig.GetDouble("MemoryCacheTimeout", m_DefaultMemoryExpiration)); - -#if WAIT_ON_INPROGRESS_REQUESTS - m_WaitOnInprogressTimeout = assetConfig.GetInt("WaitOnInprogressTimeout", 3000); -#endif - - m_LogLevel = assetConfig.GetInt("LogLevel", 0); - m_HitRateDisplay = (ulong)assetConfig.GetInt("HitRateDisplay", 1000); - - m_FileExpiration = TimeSpan.FromHours(assetConfig.GetDouble("FileCacheTimeout", m_DefaultFileExpiration)); - m_FileExpirationCleanupTimer = TimeSpan.FromHours(assetConfig.GetDouble("FileCleanupTimer", m_DefaultFileExpiration)); if ((m_FileExpiration > TimeSpan.Zero) && (m_FileExpirationCleanupTimer > TimeSpan.Zero)) { m_CacheCleanTimer = new System.Timers.Timer(m_FileExpirationCleanupTimer.TotalMilliseconds); @@ -170,7 +182,6 @@ namespace Flotsam.RegionModules.AssetCache m_CacheCleanTimer.Start(); } - m_CacheDirectoryTiers = assetConfig.GetInt("CacheDirectoryTiers", 1); if (m_CacheDirectoryTiers < 1) { m_CacheDirectoryTiers = 1; @@ -180,7 +191,6 @@ namespace Flotsam.RegionModules.AssetCache m_CacheDirectoryTiers = 3; } - m_CacheDirectoryTierLen = assetConfig.GetInt("CacheDirectoryTierLength", 3); if (m_CacheDirectoryTierLen < 1) { m_CacheDirectoryTierLen = 1; @@ -190,14 +200,10 @@ namespace Flotsam.RegionModules.AssetCache m_CacheDirectoryTierLen = 4; } - m_CacheWarnAt = assetConfig.GetInt("CacheWarnAt", 30000); - - m_DeepScanBeforePurge = assetConfig.GetBoolean("DeepScanBeforePurge", false); - - MainConsole.Instance.Commands.AddCommand(this.Name, true, "fcache status", "fcache status", "Display cache status", HandleConsoleCommand); - MainConsole.Instance.Commands.AddCommand(this.Name, true, "fcache clear", "fcache clear [file] [memory]", "Remove all assets in the file and/or memory cache", HandleConsoleCommand); - MainConsole.Instance.Commands.AddCommand(this.Name, true, "fcache assets", "fcache assets", "Attempt a deep scan and cache of all assets in all scenes", HandleConsoleCommand); - MainConsole.Instance.Commands.AddCommand(this.Name, true, "fcache expire", "fcache expire ", "Purge cached assets older then the specified date/time", HandleConsoleCommand); + MainConsole.Instance.Commands.AddCommand(Name, true, "fcache status", "fcache status", "Display cache status", HandleConsoleCommand); + MainConsole.Instance.Commands.AddCommand(Name, true, "fcache clear", "fcache clear [file] [memory]", "Remove all assets in the cache. If file or memory is specified then only this cache is cleared.", HandleConsoleCommand); + MainConsole.Instance.Commands.AddCommand(Name, true, "fcache assets", "fcache assets", "Attempt a deep scan and cache of all assets in all scenes", HandleConsoleCommand); + MainConsole.Instance.Commands.AddCommand(Name, true, "fcache expire", "fcache expire ", "Purge cached assets older then the specified date/time", HandleConsoleCommand); } } } @@ -732,24 +738,39 @@ namespace Flotsam.RegionModules.AssetCache break; case "clear": - if (cmdparams.Length < 3) + if (cmdparams.Length < 2) { - m_log.Warn("[FLOTSAM ASSET CACHE] Please specify memory and/or file cache."); + m_log.Warn("[FLOTSAM ASSET CACHE] Usage is fcache clear [file] [memory]"); break; } + + bool clearMemory = false, clearFile = false; + + if (cmdparams.Length == 2) + { + clearMemory = true; + clearFile = true; + } foreach (string s in cmdparams) { if (s.ToLower() == "memory") - { - m_MemoryCache.Clear(); - m_log.Info("[FLOTSAM ASSET CACHE] Memory cache cleared."); - } + clearMemory = true; else if (s.ToLower() == "file") - { - ClearFileCache(); - m_log.Info("[FLOTSAM ASSET CACHE] File cache cleared."); - } + clearFile = true; } + + if (clearMemory) + { + m_MemoryCache.Clear(); + m_log.Info("[FLOTSAM ASSET CACHE] Memory cache cleared."); + } + + if (clearFile) + { + ClearFileCache(); + m_log.Info("[FLOTSAM ASSET CACHE] File cache cleared."); + } + break; diff --git a/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs b/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs index ded8743a70..8a1658269e 100644 --- a/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs @@ -124,7 +124,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog ScenePresence sp = m_scene.GetScenePresence(avatarID); if (sp != null) - sp.ControllingClient.SendDialog(objectName, objectID, ownerFirstName, ownerLastName, message, textureID, ch, buttonlabels); + sp.ControllingClient.SendDialog( + objectName, objectID, ownerID, ownerFirstName, ownerLastName, message, textureID, ch, buttonlabels); } public void SendUrlToUser( diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs index 0cd05e3aa4..c8167c5e1f 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs @@ -49,6 +49,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends { public class FriendsModule : ISharedRegionModule, IFriendsModule { + protected bool m_Enabled = false; + protected class UserFriendData { public UUID PrincipalID; @@ -67,7 +69,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends } } - private static readonly FriendInfo[] EMPTY_FRIENDS = new FriendInfo[0]; + protected static readonly FriendInfo[] EMPTY_FRIENDS = new FriendInfo[0]; private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); protected List m_Scenes = new List(); @@ -130,7 +132,24 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends } } + #region ISharedRegionModule public void Initialise(IConfigSource config) + { + IConfig moduleConfig = config.Configs["Modules"]; + if (moduleConfig != null) + { + string name = moduleConfig.GetString("FriendsModule", "FriendsModule"); + if (name == Name) + { + InitModule(config); + + m_Enabled = true; + m_log.InfoFormat("[FRIENDS MODULE]: {0} enabled.", Name); + } + } + } + + protected void InitModule(IConfigSource config) { IConfig friendsConfig = config.Configs["Friends"]; if (friendsConfig != null) @@ -153,7 +172,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends m_log.Error("[FRIENDS]: No Connector defined in section Friends, or failed to load, cannot continue"); throw new Exception("Connector load error"); } - } public void PostInitialise() @@ -164,8 +182,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends { } - public void AddRegion(Scene scene) + public virtual void AddRegion(Scene scene) { + if (!m_Enabled) + return; + m_log.DebugFormat("[FRIENDS MODULE]: AddRegion on {0}", Name); + m_Scenes.Add(scene); scene.RegisterModuleInterface(this); @@ -181,10 +203,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends public void RemoveRegion(Scene scene) { + if (!m_Enabled) + return; + m_Scenes.Remove(scene); } - public string Name + public virtual string Name { get { return "FriendsModule"; } } @@ -194,13 +219,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends get { return null; } } - public uint GetFriendPerms(UUID principalID, UUID friendID) + #endregion + + public virtual uint GetFriendPerms(UUID principalID, UUID friendID) { FriendInfo[] friends = GetFriends(principalID); - foreach (FriendInfo fi in friends) + FriendInfo finfo = GetFriend(friends, friendID); + if (finfo != null) { - if (fi.Friend == friendID.ToString()) - return (uint)fi.TheirFlags; + return (uint)finfo.TheirFlags; } return 0; @@ -214,30 +241,34 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends client.OnTerminateFriendship += OnTerminateFriendship; client.OnGrantUserRights += OnGrantUserRights; - // Asynchronously fetch the friends list or increment the refcount for the existing - // friends list - Util.FireAndForget( - delegate(object o) - { - lock (m_Friends) - { - UserFriendData friendsData; - if (m_Friends.TryGetValue(client.AgentId, out friendsData)) - { - friendsData.Refcount++; - } - else - { - friendsData = new UserFriendData(); - friendsData.PrincipalID = client.AgentId; - friendsData.Friends = FriendsService.GetFriends(client.AgentId); - friendsData.Refcount = 1; + Util.FireAndForget(delegate { FetchFriendslist(client); }); + } - m_Friends[client.AgentId] = friendsData; - } - } + /// Fetch the friends list or increment the refcount for the existing + /// friends list + /// Returns true if the list was fetched, false if it wasn't + protected virtual bool FetchFriendslist(IClientAPI client) + { + UUID agentID = client.AgentId; + lock (m_Friends) + { + UserFriendData friendsData; + if (m_Friends.TryGetValue(agentID, out friendsData)) + { + friendsData.Refcount++; + return false; } - ); + else + { + friendsData = new UserFriendData(); + friendsData.PrincipalID = agentID; + friendsData.Friends = GetFriendsFromService(client); + friendsData.Refcount = 1; + + m_Friends[agentID] = friendsData; + return true; + } + } } private void OnClientClosed(UUID agentID, Scene scene) @@ -263,14 +294,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends private void OnMakeRootAgent(ScenePresence sp) { - UUID agentID = sp.ControllingClient.AgentId; - UpdateFriendsCache(agentID); + RefetchFriends(sp.ControllingClient); } private void OnClientLogin(IClientAPI client) { UUID agentID = client.AgentId; + //m_log.DebugFormat("[XXX]: OnClientLogin!"); // Inform the friends that this user is online StatusChange(agentID, true); @@ -279,7 +310,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends m_NeedsListOfFriends.Add(agentID); } - public void SendFriendsOnlineIfNeeded(IClientAPI client) + public virtual bool SendFriendsOnlineIfNeeded(IClientAPI client) { UUID agentID = client.AgentId; @@ -287,7 +318,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends lock (m_NeedsListOfFriends) { if (!m_NeedsListOfFriends.Remove(agentID)) - return; + return false; } // Send the friends online @@ -313,10 +344,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends foreach (string fid in outstanding) { UUID fromAgentID; - if (!UUID.TryParse(fid, out fromAgentID)) + string firstname = "Unknown", lastname = "User"; + if (!GetAgentInfo(client.Scene.RegionInfo.ScopeID, fid, out fromAgentID, out firstname, out lastname)) + { + m_log.DebugFormat("[FRIENDS MODULE]: skipping malformed friend {0}", fid); continue; - - UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(client.Scene.RegionInfo.ScopeID, fromAgentID); + } PresenceInfo presence = null; PresenceInfo[] presences = PresenceService.GetAgents(new string[] { fid }); @@ -326,13 +359,37 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends im.offline = 0; im.fromAgentID = fromAgentID.Guid; - im.fromAgentName = account.FirstName + " " + account.LastName; + im.fromAgentName = firstname + " " + lastname; im.offline = (byte)((presence == null) ? 1 : 0); im.imSessionID = im.fromAgentID; + im.message = FriendshipMessage(fid); // Finally LocalFriendshipOffered(agentID, im); } + + return true; + } + + protected virtual string FriendshipMessage(string friendID) + { + return "Will you be my friend?"; + } + + protected virtual bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last) + { + first = "Unknown"; last = "User"; + if (!UUID.TryParse(fid, out agentID)) + return false; + + UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(scopeID, agentID); + if (account != null) + { + first = account.FirstName; + last = account.LastName; + } + + return true; } List GetOnlineFriends(UUID userID) @@ -348,19 +405,22 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends } if (friendList.Count > 0) - { - PresenceInfo[] presence = PresenceService.GetAgents(friendList.ToArray()); - foreach (PresenceInfo pi in presence) - { - UUID presenceID; - if (UUID.TryParse(pi.UserID, out presenceID)) - online.Add(presenceID); - } - } + GetOnlineFriends(userID, friendList, online); return online; } + protected virtual void GetOnlineFriends(UUID userID, List friendList, /*collector*/ List online) + { + PresenceInfo[] presence = PresenceService.GetAgents(friendList.ToArray()); + foreach (PresenceInfo pi in presence) + { + UUID presenceID; + if (UUID.TryParse(pi.UserID, out presenceID)) + online.Add(presenceID); + } + } + /// /// Find the client for a ID /// @@ -415,51 +475,51 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends Util.FireAndForget( delegate { - foreach (FriendInfo fi in friendList) - { - //m_log.DebugFormat("[FRIENDS]: Notifying {0}", fi.PrincipalID); - // Notify about this user status - StatusNotify(fi, agentID, online); - } + m_log.DebugFormat("[FRIENDS MODULE]: Notifying {0} friends", friendList.Count); + // Notify about this user status + StatusNotify(friendList, agentID, online); } ); } } - private void StatusNotify(FriendInfo friend, UUID userID, bool online) + protected virtual void StatusNotify(List friendList, UUID userID, bool online) { - UUID friendID; - if (UUID.TryParse(friend.Friend, out friendID)) + foreach (FriendInfo friend in friendList) { - // Try local - if (LocalStatusNotification(userID, friendID, online)) - return; - - // The friend is not here [as root]. Let's forward. - PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() }); - if (friendSessions != null && friendSessions.Length > 0) + UUID friendID; + if (UUID.TryParse(friend.Friend, out friendID)) { - PresenceInfo friendSession = null; - foreach (PresenceInfo pinfo in friendSessions) - if (pinfo.RegionID != UUID.Zero) // let's guard against sessions-gone-bad - { - friendSession = pinfo; - break; - } + // Try local + if (LocalStatusNotification(userID, friendID, online)) + return; - if (friendSession != null) + // The friend is not here [as root]. Let's forward. + PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() }); + if (friendSessions != null && friendSessions.Length > 0) { - GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); - //m_log.DebugFormat("[FRIENDS]: Remote Notify to region {0}", region.RegionName); - m_FriendsSimConnector.StatusNotify(region, userID, friendID, online); - } - } + PresenceInfo friendSession = null; + foreach (PresenceInfo pinfo in friendSessions) + if (pinfo.RegionID != UUID.Zero) // let's guard against sessions-gone-bad + { + friendSession = pinfo; + break; + } - // Friend is not online. Ignore. - } - else - { - m_log.WarnFormat("[FRIENDS]: Error parsing friend ID {0}", friend.Friend); + if (friendSession != null) + { + GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); + //m_log.DebugFormat("[FRIENDS]: Remote Notify to region {0}", region.RegionName); + m_FriendsSimConnector.StatusNotify(region, userID, friendID, online); + } + } + + // Friend is not online. Ignore. + } + else + { + m_log.WarnFormat("[FRIENDS]: Error parsing friend ID {0}", friend.Friend); + } } } @@ -475,7 +535,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends // This user wants to be friends with the other user. // Let's add the relation backwards, in case the other is not online - FriendsService.StoreFriend(friendID, principalID.ToString(), 0); + StoreBackwards(friendID, principalID); // Now let's ask the other user to be friends with this user ForwardFriendshipOffer(principalID, friendID, im); @@ -487,11 +547,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends // !!!!!!!! This is a hack so that we don't have to keep state (transactionID/imSessionID) // We stick this agent's ID as imSession, so that it's directly available on the receiving end im.imSessionID = im.fromAgentID; + im.fromAgentName = GetFriendshipRequesterName(agentID); - // Try the local sim - UserAccount account = UserAccountService.GetUserAccount(UUID.Zero, agentID); - im.fromAgentName = (account == null) ? "Unknown" : account.FirstName + " " + account.LastName; - + // Try the local sim if (LocalFriendshipOffered(friendID, im)) return; @@ -509,12 +567,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends // If the prospective friend is not online, he'll get the message upon login. } + protected virtual string GetFriendshipRequesterName(UUID agentID) + { + UserAccount account = UserAccountService.GetUserAccount(UUID.Zero, agentID); + return (account == null) ? "Unknown" : account.FirstName + " " + account.LastName; + } + private void OnApproveFriendRequest(IClientAPI client, UUID agentID, UUID friendID, List callingCardFolders) { m_log.DebugFormat("[FRIENDS]: {0} accepted friendship from {1}", agentID, friendID); - - FriendsService.StoreFriend(agentID, friendID.ToString(), 1); - FriendsService.StoreFriend(friendID, agentID.ToString(), 1); + + StoreFriendships(agentID, friendID); ICallingCardModule ccm = client.Scene.RequestModuleInterface(); if (ccm != null) @@ -523,7 +586,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends } // Update the local cache - UpdateFriendsCache(agentID); + RefetchFriends(client); // // Notify the friend @@ -554,8 +617,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends { m_log.DebugFormat("[FRIENDS]: {0} denied friendship to {1}", agentID, friendID); - FriendsService.Delete(agentID, friendID.ToString()); - FriendsService.Delete(friendID, agentID.ToString()); + DeleteFriendship(agentID, friendID); // // Notify the friend @@ -582,11 +644,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends private void OnTerminateFriendship(IClientAPI client, UUID agentID, UUID exfriendID) { - FriendsService.Delete(agentID, exfriendID.ToString()); - FriendsService.Delete(exfriendID, agentID.ToString()); + if (!DeleteFriendship(agentID, exfriendID)) + client.SendAlertMessage("Unable to terminate friendship on this sim."); // Update local cache - UpdateFriendsCache(agentID); + RefetchFriends(client); client.SendTerminateFriend(exfriendID); @@ -612,23 +674,25 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends private void OnGrantUserRights(IClientAPI remoteClient, UUID requester, UUID target, int rights) { + m_log.DebugFormat("[FRIENDS MODULE]: User {0} changing rights to {1} for friend {2}", requester, rights, target); + FriendInfo[] friends = GetFriends(remoteClient.AgentId); if (friends.Length == 0) - return; - - m_log.DebugFormat("[FRIENDS MODULE]: User {0} changing rights to {1} for friend {2}", requester, rights, target); - // Let's find the friend in this user's friend list - FriendInfo friend = null; - foreach (FriendInfo fi in friends) { - if (fi.Friend == target.ToString()) - friend = fi; + return; } + // Let's find the friend in this user's friend list + FriendInfo friend = GetFriend(friends, target); + if (friend != null) // Found it { // Store it on the DB - FriendsService.StoreFriend(requester, target.ToString(), rights); + if (!StoreRights(requester, target, rights)) + { + remoteClient.SendAlertMessage("Unable to grant rights."); + return; + } // Store it in the local cache int myFlags = friend.MyFlags; @@ -658,6 +722,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends } } } + else + m_log.DebugFormat("[FRIENDS MODULE]: friend {0} not found for {1}", target, requester); + } + + protected virtual FriendInfo GetFriend(FriendInfo[] friends, UUID friendID) + { + foreach (FriendInfo fi in friends) + { + if (fi.Friend == friendID.ToString()) + return fi; + } + return null; } #region Local @@ -693,7 +769,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends // Update the local cache - UpdateFriendsCache(friendID); + RefetchFriends(friendClient); // we're done return true; @@ -726,7 +802,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends // the friend in this sim as root agent friendClient.SendTerminateFriend(exfriendID); // update local cache - UpdateFriendsCache(exfriendID); + RefetchFriends(friendClient); // we're done return true; } @@ -756,15 +832,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends } // Update local cache - lock (m_Friends) - { - FriendInfo[] friends = GetFriends(friendID); - foreach (FriendInfo finfo in friends) - { - if (finfo.Friend == userID.ToString()) - finfo.TheirFlags = rights; - } - } + UpdateLocalCache(userID, friendID, rights); return true; } @@ -775,10 +843,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends public bool LocalStatusNotification(UUID userID, UUID friendID, bool online) { + m_log.DebugFormat("[FRIENDS]: Local Status Notify {0} that user {1} is {2}", friendID, userID, online); IClientAPI friendClient = LocateClientObject(friendID); if (friendClient != null) { - //m_log.DebugFormat("[FRIENDS]: Local Status Notify {0} that user {1} is {2}", friendID, userID, online); // the friend in this sim as root agent if (online) friendClient.SendAgentOnline(new UUID[] { userID }); @@ -793,7 +861,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends #endregion - private FriendInfo[] GetFriends(UUID agentID) + #region Get / Set friends in several flavours + /// + /// Get friends from local cache only + /// + /// + /// + protected FriendInfo[] GetFriends(UUID agentID) { UserFriendData friendsData; @@ -806,14 +880,63 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends return EMPTY_FRIENDS; } - private void UpdateFriendsCache(UUID agentID) + /// + /// Update loca cache only + /// + /// + /// + /// + protected void UpdateLocalCache(UUID userID, UUID friendID, int rights) { + // Update local cache + lock (m_Friends) + { + FriendInfo[] friends = GetFriends(friendID); + FriendInfo finfo = GetFriend(friends, userID); + finfo.TheirFlags = rights; + } + } + + protected virtual FriendInfo[] GetFriendsFromService(IClientAPI client) + { + return FriendsService.GetFriends(client.AgentId); + } + + private void RefetchFriends(IClientAPI client) + { + UUID agentID = client.AgentId; lock (m_Friends) { UserFriendData friendsData; if (m_Friends.TryGetValue(agentID, out friendsData)) - friendsData.Friends = FriendsService.GetFriends(agentID); + friendsData.Friends = GetFriendsFromService(client); } } + + protected virtual bool StoreRights(UUID agentID, UUID friendID, int rights) + { + FriendsService.StoreFriend(agentID.ToString(), friendID.ToString(), rights); + return true; + } + + protected virtual void StoreBackwards(UUID friendID, UUID agentID) + { + FriendsService.StoreFriend(friendID.ToString(), agentID.ToString(), 0); + } + + protected virtual void StoreFriendships(UUID agentID, UUID friendID) + { + FriendsService.StoreFriend(agentID.ToString(), friendID.ToString(), 1); + FriendsService.StoreFriend(friendID.ToString(), agentID.ToString(), 1); + } + + protected virtual bool DeleteFriendship(UUID agentID, UUID exfriendID) + { + FriendsService.Delete(agentID, exfriendID.ToString()); + FriendsService.Delete(exfriendID, agentID.ToString()); + return true; + } + + #endregion } } diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs new file mode 100644 index 0000000000..dda67f9c2b --- /dev/null +++ b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs @@ -0,0 +1,623 @@ +/* + * 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.Reflection; +using System.Threading; + +using log4net; +using Nini.Config; +using Nwc.XmlRpc; +using Mono.Addins; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; +using OpenSim.Services.Connectors.Hypergrid; +using FriendInfo = OpenSim.Services.Interfaces.FriendInfo; +using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo; +using GridRegion = OpenSim.Services.Interfaces.GridRegion; + +namespace OpenSim.Region.CoreModules.Avatar.Friends +{ + public class HGFriendsModule : FriendsModule, ISharedRegionModule, IFriendsModule, IFriendsSimConnector + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + #region ISharedRegionModule + public override string Name + { + get { return "HGFriendsModule"; } + } + + public override void AddRegion(Scene scene) + { + if (!m_Enabled) + return; + + base.AddRegion(scene); + scene.RegisterModuleInterface(this); + } + + #endregion + + #region IFriendsSimConnector + + /// + /// Notify the user that the friend's status changed + /// + /// user to be notified + /// friend whose status changed + /// status + /// + public bool StatusNotify(UUID friendID, UUID userID, bool online) + { + return LocalStatusNotification(friendID, userID, online); + } + + #endregion + + protected override bool FetchFriendslist(IClientAPI client) + { + if (base.FetchFriendslist(client)) + { + UUID agentID = client.AgentId; + // we do this only for the root agent + if (m_Friends[agentID].Refcount == 1) + { + // We need to preload the user management cache with the names + // of foreign friends, just like we do with SOPs' creators + foreach (FriendInfo finfo in m_Friends[agentID].Friends) + { + if (finfo.TheirFlags != -1) + { + UUID id; + if (!UUID.TryParse(finfo.Friend, out id)) + { + string url = string.Empty, first = string.Empty, last = string.Empty, tmp = string.Empty; + if (Util.ParseUniversalUserIdentifier(finfo.Friend, out id, out url, out first, out last, out tmp)) + { + IUserManagement uMan = m_Scenes[0].RequestModuleInterface(); + uMan.AddUser(id, url + ";" + first + " " + last); + } + } + } + } + return true; + } + } + return false; + } + + public override bool SendFriendsOnlineIfNeeded(IClientAPI client) + { + if (base.SendFriendsOnlineIfNeeded(client)) + { + AgentCircuitData aCircuit = ((Scene)client.Scene).AuthenticateHandler.GetAgentCircuitData(client.AgentId); + if (aCircuit != null && (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0) + { + UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(client.Scene.RegionInfo.ScopeID, client.AgentId); + if (account == null) // foreign + { + FriendInfo[] friends = GetFriends(client.AgentId); + foreach (FriendInfo f in friends) + { + client.SendChangeUserRights(new UUID(f.Friend), client.AgentId, f.TheirFlags); + } + } + } + } + return false; + } + + protected override void GetOnlineFriends(UUID userID, List friendList, /*collector*/ List online) + { + List fList = new List(); + foreach (string s in friendList) + fList.Add(s.Substring(0, 36)); + + PresenceInfo[] presence = PresenceService.GetAgents(fList.ToArray()); + foreach (PresenceInfo pi in presence) + { + UUID presenceID; + if (UUID.TryParse(pi.UserID, out presenceID)) + online.Add(presenceID); + } + } + + //protected override void GetOnlineFriends(UUID userID, List friendList, /*collector*/ List online) + //{ + // // Let's single out the UUIs + // List localFriends = new List(); + // List foreignFriends = new List(); + // string tmp = string.Empty; + + // foreach (string s in friendList) + // { + // UUID id; + // if (UUID.TryParse(s, out id)) + // localFriends.Add(s); + // else if (Util.ParseUniversalUserIdentifier(s, out id, out tmp, out tmp, out tmp, out tmp)) + // { + // foreignFriends.Add(s); + // // add it here too, who knows maybe the foreign friends happens to be on this grid + // localFriends.Add(id.ToString()); + // } + // } + + // // OK, see who's present on this grid + // List toBeRemoved = new List(); + // PresenceInfo[] presence = PresenceService.GetAgents(localFriends.ToArray()); + // foreach (PresenceInfo pi in presence) + // { + // UUID presenceID; + // if (UUID.TryParse(pi.UserID, out presenceID)) + // { + // online.Add(presenceID); + // foreach (string s in foreignFriends) + // if (s.StartsWith(pi.UserID)) + // toBeRemoved.Add(s); + // } + // } + + // foreach (string s in toBeRemoved) + // foreignFriends.Remove(s); + + // // OK, let's send this up the stack, and leave a closure here + // // collecting online friends in other grids + // Util.FireAndForget(delegate { CollectOnlineFriendsElsewhere(userID, foreignFriends); }); + + //} + + //private void CollectOnlineFriendsElsewhere(UUID userID, List foreignFriends) + //{ + // // let's divide the friends on a per-domain basis + // Dictionary> friendsPerDomain = new Dictionary>(); + // foreach (string friend in foreignFriends) + // { + // UUID friendID; + // if (!UUID.TryParse(friend, out friendID)) + // { + // // it's a foreign friend + // string url = string.Empty, tmp = string.Empty; + // if (Util.ParseUniversalUserIdentifier(friend, out friendID, out url, out tmp, out tmp, out tmp)) + // { + // if (!friendsPerDomain.ContainsKey(url)) + // friendsPerDomain[url] = new List(); + // friendsPerDomain[url].Add(friend); + // } + // } + // } + + // // Now, call those worlds + + // foreach (KeyValuePair> kvp in friendsPerDomain) + // { + // List ids = new List(); + // foreach (string f in kvp.Value) + // ids.Add(f); + // UserAgentServiceConnector uConn = new UserAgentServiceConnector(kvp.Key); + // List online = uConn.GetOnlineFriends(userID, ids); + // // Finally send the notifications to the user + // // this whole process may take a while, so let's check at every + // // iteration that the user is still here + // IClientAPI client = LocateClientObject(userID); + // if (client != null) + // client.SendAgentOnline(online.ToArray()); + // else + // break; + // } + + //} + + protected override void StatusNotify(List friendList, UUID userID, bool online) + { + // First, let's divide the friends on a per-domain basis + Dictionary> friendsPerDomain = new Dictionary>(); + foreach (FriendInfo friend in friendList) + { + UUID friendID; + if (UUID.TryParse(friend.Friend, out friendID)) + { + if (!friendsPerDomain.ContainsKey("local")) + friendsPerDomain["local"] = new List(); + friendsPerDomain["local"].Add(friend); + } + else + { + // it's a foreign friend + string url = string.Empty, tmp = string.Empty; + if (Util.ParseUniversalUserIdentifier(friend.Friend, out friendID, out url, out tmp, out tmp, out tmp)) + { + // Let's try our luck in the local sim. Who knows, maybe it's here + if (LocalStatusNotification(userID, friendID, online)) + continue; + + if (!friendsPerDomain.ContainsKey(url)) + friendsPerDomain[url] = new List(); + friendsPerDomain[url].Add(friend); + } + } + } + + // For the local friends, just call the base method + // Let's do this first of all + if (friendsPerDomain.ContainsKey("local")) + base.StatusNotify(friendsPerDomain["local"], userID, online); + + foreach (KeyValuePair> kvp in friendsPerDomain) + { + if (kvp.Key != "local") + { + // For the others, call the user agent service + List ids = new List(); + foreach (FriendInfo f in kvp.Value) + ids.Add(f.Friend); + UserAgentServiceConnector uConn = new UserAgentServiceConnector(kvp.Key); + List friendsOnline = uConn.StatusNotification(ids, userID, online); + + if (online && friendsOnline.Count > 0) + { + IClientAPI client = LocateClientObject(userID); + if (client != null) + client.SendAgentOnline(friendsOnline.ToArray()); + } + } + } + } + + protected override bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last) + { + first = "Unknown"; last = "User"; + if (base.GetAgentInfo(scopeID, fid, out agentID, out first, out last)) + return true; + + // fid is not a UUID... + string url = string.Empty, tmp = string.Empty; + if (Util.ParseUniversalUserIdentifier(fid, out agentID, out url, out first, out last, out tmp)) + { + IUserManagement userMan = m_Scenes[0].RequestModuleInterface(); + userMan.AddUser(agentID, first, last, url); + + return true; + } + return false; + } + + protected override string GetFriendshipRequesterName(UUID agentID) + { + // For the time being we assume that HG friendship requests can only happen + // when avies are on the same region. + IClientAPI client = LocateClientObject(agentID); + if (client != null) + return client.FirstName + " " + client.LastName; + else + return base.GetFriendshipRequesterName(agentID); + } + + protected override string FriendshipMessage(string friendID) + { + UUID id; + if (UUID.TryParse(friendID, out id)) + return base.FriendshipMessage(friendID); + + return "Please confirm this friendship you made while you were away."; + } + + protected override FriendInfo GetFriend(FriendInfo[] friends, UUID friendID) + { + foreach (FriendInfo fi in friends) + { + if (fi.Friend.StartsWith(friendID.ToString())) + return fi; + } + return null; + } + + + protected override FriendInfo[] GetFriendsFromService(IClientAPI client) + { + UserAccount account1 = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, client.AgentId); + if (account1 != null) + return base.GetFriendsFromService(client); + + FriendInfo[] finfos = new FriendInfo[0]; + // Foreigner + AgentCircuitData agentClientCircuit = ((Scene)(client.Scene)).AuthenticateHandler.GetAgentCircuitData(client.CircuitCode); + if (agentClientCircuit != null) + { + string agentUUI = Util.ProduceUserUniversalIdentifier(agentClientCircuit); + + finfos = FriendsService.GetFriends(agentUUI); + m_log.DebugFormat("[HGFRIENDS MODULE]: Fetched {0} local friends for visitor {1}", finfos.Length, agentUUI); + } + return finfos; + } + + protected override bool StoreRights(UUID agentID, UUID friendID, int rights) + { + UserAccount account1 = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, agentID); + UserAccount account2 = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, friendID); + // Are they both local users? + if (account1 != null && account2 != null) + { + // local grid users + return base.StoreRights(agentID, friendID, rights); + } + + if (account1 != null) // agent is local, friend is foreigner + { + FriendInfo[] finfos = GetFriends(agentID); + FriendInfo finfo = GetFriend(finfos, friendID); + if (finfo != null) + { + FriendsService.StoreFriend(agentID.ToString(), finfo.Friend, rights); + return true; + } + } + + if (account2 != null) // agent is foreigner, friend is local + { + string agentUUI = GetUUI(friendID, agentID); + if (agentUUI != string.Empty) + { + FriendsService.StoreFriend(agentUUI, friendID.ToString(), rights); + return true; + } + } + + return false; + + } + + protected override void StoreBackwards(UUID friendID, UUID agentID) + { + UserAccount account1 = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, agentID); + UserAccount account2 = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, friendID); + // Are they both local users? + if (account1 != null && account2 != null) + { + // local grid users + m_log.DebugFormat("[HGFRIENDS MODULE]: Users are both local"); + base.StoreBackwards(friendID, agentID); + return; + } + + // no provision for this temporary friendship state + //FriendsService.StoreFriend(friendID.ToString(), agentID.ToString(), 0); + } + + protected override void StoreFriendships(UUID agentID, UUID friendID) + { + UserAccount agentAccount = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, agentID); + UserAccount friendAccount = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, friendID); + // Are they both local users? + if (agentAccount != null && friendAccount != null) + { + // local grid users + m_log.DebugFormat("[HGFRIENDS MODULE]: Users are both local"); + base.StoreFriendships(agentID, friendID); + return; + } + + // ok, at least one of them is foreigner, let's get their data + IClientAPI agentClient = LocateClientObject(agentID); + IClientAPI friendClient = LocateClientObject(friendID); + AgentCircuitData agentClientCircuit = null; + AgentCircuitData friendClientCircuit = null; + string agentUUI = string.Empty; + string friendUUI = string.Empty; + string agentFriendService = string.Empty; + string friendFriendService = string.Empty; + + if (agentClient != null) + { + agentClientCircuit = ((Scene)(agentClient.Scene)).AuthenticateHandler.GetAgentCircuitData(agentClient.CircuitCode); + agentUUI = Util.ProduceUserUniversalIdentifier(agentClientCircuit); + agentFriendService = agentClientCircuit.ServiceURLs["FriendsServerURI"].ToString(); + } + if (friendClient != null) + { + friendClientCircuit = ((Scene)(friendClient.Scene)).AuthenticateHandler.GetAgentCircuitData(friendClient.CircuitCode); + friendUUI = Util.ProduceUserUniversalIdentifier(friendClientCircuit); + friendFriendService = friendClientCircuit.ServiceURLs["FriendsServerURI"].ToString(); + } + + m_log.DebugFormat("[HGFRIENDS MODULE] HG Friendship! thisUUI={0}; friendUUI={1}; foreignThisFriendService={2}; foreignFriendFriendService={3}", + agentUUI, friendUUI, agentFriendService, friendFriendService); + + // Generate a random 8-character hex number that will sign this friendship + string secret = UUID.Random().ToString().Substring(0, 8); + + if (agentAccount != null) // agent is local, 'friend' is foreigner + { + // This may happen when the agent returned home, in which case the friend is not there + // We need to look for its information in the friends list itself + bool confirming = false; + if (friendUUI == string.Empty) + { + FriendInfo[] finfos = GetFriends(agentID); + foreach (FriendInfo finfo in finfos) + { + if (finfo.TheirFlags == -1) + { + if (finfo.Friend.StartsWith(friendID.ToString())) + { + friendUUI = finfo.Friend; + confirming = true; + } + } + } + } + + // If it's confirming the friendship, we already have the full friendUUI with the secret + string theFriendUUID = confirming ? friendUUI : friendUUI + ";" + secret; + + // store in the local friends service a reference to the foreign friend + FriendsService.StoreFriend(agentID.ToString(), theFriendUUID, 1); + // and also the converse + FriendsService.StoreFriend(theFriendUUID, agentID.ToString(), 1); + + if (!confirming && friendClientCircuit != null) + { + // store in the foreign friends service a reference to the local agent + HGFriendsServicesConnector friendsConn = new HGFriendsServicesConnector(friendFriendService, friendClientCircuit.SessionID, friendClientCircuit.ServiceSessionID); + friendsConn.NewFriendship(friendID, agentUUI + ";" + secret); + } + } + else if (friendAccount != null) // 'friend' is local, agent is foreigner + { + // store in the local friends service a reference to the foreign agent + FriendsService.StoreFriend(friendID.ToString(), agentUUI + ";" + secret, 1); + // and also the converse + FriendsService.StoreFriend(agentUUI + ";" + secret, friendID.ToString(), 1); + + if (agentClientCircuit != null) + { + // store in the foreign friends service a reference to the local agent + HGFriendsServicesConnector friendsConn = new HGFriendsServicesConnector(agentFriendService, agentClientCircuit.SessionID, agentClientCircuit.ServiceSessionID); + friendsConn.NewFriendship(agentID, friendUUI + ";" + secret); + } + } + else // They're both foreigners! + { + HGFriendsServicesConnector friendsConn; + if (agentClientCircuit != null) + { + friendsConn = new HGFriendsServicesConnector(agentFriendService, agentClientCircuit.SessionID, agentClientCircuit.ServiceSessionID); + friendsConn.NewFriendship(agentID, friendUUI + ";" + secret); + } + if (friendClientCircuit != null) + { + friendsConn = new HGFriendsServicesConnector(friendFriendService, friendClientCircuit.SessionID, friendClientCircuit.ServiceSessionID); + friendsConn.NewFriendship(friendID, agentUUI + ";" + secret); + } + } + // my brain hurts now + } + + protected override bool DeleteFriendship(UUID agentID, UUID exfriendID) + { + UserAccount agentAccount = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, agentID); + UserAccount friendAccount = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, exfriendID); + // Are they both local users? + if (agentAccount != null && friendAccount != null) + { + // local grid users + return base.DeleteFriendship(agentID, exfriendID); + } + + // ok, at least one of them is foreigner, let's get their data + string agentUUI = string.Empty; + string friendUUI = string.Empty; + + if (agentAccount != null) // agent is local, 'friend' is foreigner + { + // We need to look for its information in the friends list itself + FriendInfo[] finfos = GetFriends(agentID); + FriendInfo finfo = GetFriend(finfos, exfriendID); + if (finfo != null) + { + friendUUI = finfo.Friend; + + // delete in the local friends service the reference to the foreign friend + FriendsService.Delete(agentID, friendUUI); + // and also the converse + FriendsService.Delete(friendUUI, agentID.ToString()); + + // notify the exfriend's service + Util.FireAndForget(delegate { Delete(exfriendID, agentID, friendUUI); }); + + m_log.DebugFormat("[HGFRIENDS MODULE]: {0} terminated {1}", agentID, friendUUI); + return true; + } + } + else if (friendAccount != null) // agent is foreigner, 'friend' is local + { + agentUUI = GetUUI(exfriendID, agentID); + + if (agentUUI != string.Empty) + { + // delete in the local friends service the reference to the foreign agent + FriendsService.Delete(exfriendID, agentUUI); + // and also the converse + FriendsService.Delete(agentUUI, exfriendID.ToString()); + + // notify the agent's service? + Util.FireAndForget(delegate { Delete(agentID, exfriendID, agentUUI); }); + + m_log.DebugFormat("[HGFRIENDS MODULE]: {0} terminated {1}", agentUUI, exfriendID); + return true; + } + } + //else They're both foreigners! Can't handle this + + return false; + } + + private string GetUUI(UUID localUser, UUID foreignUser) + { + // Let's see if the user is here by any chance + FriendInfo[] finfos = GetFriends(localUser); + if (finfos != EMPTY_FRIENDS) // friend is here, cool + { + FriendInfo finfo = GetFriend(finfos, foreignUser); + if (finfo != null) + { + return finfo.Friend; + } + } + else // user is not currently on this sim, need to get from the service + { + finfos = FriendsService.GetFriends(localUser); + foreach (FriendInfo finfo in finfos) + { + if (finfo.Friend.StartsWith(foreignUser.ToString())) // found it! + { + return finfo.Friend; + } + } + } + return string.Empty; + } + + private void Delete(UUID foreignUser, UUID localUser, string uui) + { + UUID id; + string url = string.Empty, secret = string.Empty, tmp = string.Empty; + if (Util.ParseUniversalUserIdentifier(uui, out id, out url, out tmp, out tmp, out secret)) + { + m_log.DebugFormat("[HGFRIENDS MODULE]: Deleting friendship from {0}", url); + HGFriendsServicesConnector friendConn = new HGFriendsServicesConnector(url); + friendConn.DeleteFriendship(foreignUser, localUser, secret); + } + } + } +} diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs new file mode 100644 index 0000000000..7753c259b3 --- /dev/null +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs @@ -0,0 +1,350 @@ +/* + * 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.Net; +using System.Reflection; +using log4net; +using Nini.Config; +using Nwc.XmlRpc; +using Mono.Addins; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using GridRegion = OpenSim.Services.Interfaces.GridRegion; +using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo; +using OpenSim.Services.Interfaces; +using OpenSim.Services.Connectors.InstantMessage; +using OpenSim.Services.Connectors.Hypergrid; +using OpenSim.Server.Handlers.Hypergrid; + +namespace OpenSim.Region.CoreModules.Avatar.InstantMessage +{ + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] + public class HGMessageTransferModule : ISharedRegionModule, IMessageTransferModule, IInstantMessageSimConnector + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + protected bool m_Enabled = false; + protected List m_Scenes = new List(); + + protected IInstantMessage m_IMService; + protected Dictionary m_UserLocationMap = new Dictionary(); + + public event UndeliveredMessage OnUndeliveredMessage; + + IUserManagement m_uMan; + IUserManagement UserManagementModule + { + get + { + if (m_uMan == null) + m_uMan = m_Scenes[0].RequestModuleInterface(); + return m_uMan; + } + } + + public virtual void Initialise(IConfigSource config) + { + IConfig cnf = config.Configs["Messaging"]; + if (cnf != null && cnf.GetString( + "MessageTransferModule", "MessageTransferModule") != Name) + { + m_log.Debug("[HG MESSAGE TRANSFER]: Disabled by configuration"); + return; + } + + InstantMessageServerConnector imServer = new InstantMessageServerConnector(config, MainServer.Instance, this); + m_IMService = imServer.GetService(); + m_Enabled = true; + } + + public virtual void AddRegion(Scene scene) + { + if (!m_Enabled) + return; + + lock (m_Scenes) + { + m_log.DebugFormat("[HG MESSAGE TRANSFER]: Message transfer module {0} active", Name); + scene.RegisterModuleInterface(this); + m_Scenes.Add(scene); + } + } + + public virtual void PostInitialise() + { + if (!m_Enabled) + return; + + } + + public virtual void RegionLoaded(Scene scene) + { + } + + public virtual void RemoveRegion(Scene scene) + { + if (!m_Enabled) + return; + + lock (m_Scenes) + { + m_Scenes.Remove(scene); + } + } + + public virtual void Close() + { + } + + public virtual string Name + { + get { return "HGMessageTransferModule"; } + } + + public virtual Type ReplaceableInterface + { + get { return null; } + } + + public void SendInstantMessage(GridInstantMessage im, MessageResultNotification result) + { + UUID toAgentID = new UUID(im.toAgentID); + + // Try root avatar only first + foreach (Scene scene in m_Scenes) + { + if (scene.Entities.ContainsKey(toAgentID) && + scene.Entities[toAgentID] is ScenePresence) + { +// m_log.DebugFormat( +// "[INSTANT MESSAGE]: Looking for root agent {0} in {1}", +// toAgentID.ToString(), scene.RegionInfo.RegionName); + + ScenePresence user = (ScenePresence) scene.Entities[toAgentID]; + if (!user.IsChildAgent) + { + // Local message +// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", user.Name, toAgentID); + user.ControllingClient.SendInstantMessage(im); + + // Message sent + result(true); + return; + } + } + } + + // try child avatar second + foreach (Scene scene in m_Scenes) + { +// m_log.DebugFormat( +// "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName); + + if (scene.Entities.ContainsKey(toAgentID) && + scene.Entities[toAgentID] is ScenePresence) + { + // Local message + ScenePresence user = (ScenePresence) scene.Entities[toAgentID]; + +// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", user.Name, toAgentID); + user.ControllingClient.SendInstantMessage(im); + + // Message sent + result(true); + return; + } + } + +// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID); + // Is the user a local user? + UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, toAgentID); + string url = string.Empty; + bool foreigner = false; + if (account == null) // foreign user + { + url = UserManagementModule.GetUserServerURL(toAgentID, "IMServerURI"); + foreigner = true; + } + + Util.FireAndForget(delegate + { + bool success = false; + if (foreigner && url == string.Empty) // we don't know about this user + { + string recipientUUI = TryGetRecipientUUI(new UUID(im.fromAgentID), toAgentID); + m_log.DebugFormat("[HG MESSAGE TRANSFER]: Got UUI {0}", recipientUUI); + if (recipientUUI != string.Empty) + { + UUID id; string u = string.Empty, first = string.Empty, last = string.Empty, secret = string.Empty; + if (Util.ParseUniversalUserIdentifier(recipientUUI, out id, out u, out first, out last, out secret)) + { + success = m_IMService.OutgoingInstantMessage(im, u, true); + if (success) + UserManagementModule.AddUser(toAgentID, u + ";" + first + " " + last); + } + } + } + else + success = m_IMService.OutgoingInstantMessage(im, url, foreigner); + + if (!success && !foreigner) + HandleUndeliveredMessage(im, result); + else + result(success); + }); + + return; + } + + protected bool SendIMToScene(GridInstantMessage gim, UUID toAgentID) + { + bool successful = false; + foreach (Scene scene in m_Scenes) + { + if (scene.Entities.ContainsKey(toAgentID) && + scene.Entities[toAgentID] is ScenePresence) + { + ScenePresence user = + (ScenePresence)scene.Entities[toAgentID]; + + if (!user.IsChildAgent) + { + scene.EventManager.TriggerIncomingInstantMessage(gim); + successful = true; + } + } + } + if (!successful) + { + // If the message can't be delivered to an agent, it + // is likely to be a group IM. On a group IM, the + // imSessionID = toAgentID = group id. Raise the + // unhandled IM event to give the groups module + // a chance to pick it up. We raise that in a random + // scene, since the groups module is shared. + // + m_Scenes[0].EventManager.TriggerUnhandledInstantMessage(gim); + } + + return successful; + } + + protected void HandleUndeliveredMessage(GridInstantMessage im, MessageResultNotification result) + { + UndeliveredMessage handlerUndeliveredMessage = OnUndeliveredMessage; + + // If this event has handlers, then an IM from an agent will be + // considered delivered. This will suppress the error message. + // + if (handlerUndeliveredMessage != null) + { + handlerUndeliveredMessage(im); + if (im.dialog == (byte)InstantMessageDialog.MessageFromAgent) + result(true); + else + result(false); + return; + } + + //m_log.DebugFormat("[INSTANT MESSAGE]: Undeliverable"); + result(false); + } + + private string TryGetRecipientUUI(UUID fromAgent, UUID toAgent) + { + // Let's call back the fromAgent's user agent service + // Maybe that service knows about the toAgent + IClientAPI client = LocateClientObject(fromAgent); + if (client != null) + { + AgentCircuitData circuit = m_Scenes[0].AuthenticateHandler.GetAgentCircuitData(client.AgentId); + if (circuit != null) + { + if (circuit.ServiceURLs.ContainsKey("HomeURI")) + { + string uasURL = circuit.ServiceURLs["HomeURI"].ToString(); + m_log.DebugFormat("[HG MESSAGE TRANSFER]: getting UUI of user {0} from {1}", toAgent, uasURL); + UserAgentServiceConnector uasConn = new UserAgentServiceConnector(uasURL); + return uasConn.GetUUI(fromAgent, toAgent); + } + } + } + + return string.Empty; + } + + + /// + /// Find the scene for an agent + /// + private Scene GetClientScene(UUID agentId) + { + lock (m_Scenes) + { + foreach (Scene scene in m_Scenes) + { + ScenePresence presence = scene.GetScenePresence(agentId); + if (presence != null && !presence.IsChildAgent) + return scene; + } + } + + return null; + } + + /// + /// Find the client for a ID + /// + public IClientAPI LocateClientObject(UUID agentID) + { + Scene scene = GetClientScene(agentID); + if (scene != null) + { + ScenePresence presence = scene.GetScenePresence(agentID); + if (presence != null) + return presence.ControllingClient; + } + + return null; + } + + #region IInstantMessageSimConnector + public bool SendInstantMessage(GridInstantMessage im) + { + //m_log.DebugFormat("[XXX] Hook SendInstantMessage {0}", im.message); + UUID agentID = new UUID(im.toAgentID); + return SendIMToScene(im, agentID); + } + #endregion + + + } +} diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs index 47e34dcdd6..0d90a158c3 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs @@ -149,14 +149,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// /// Find an item given a PATH_DELIMITOR delimited path starting from the user's root folder. - /// + /// + /// /// This method does not handle paths that contain multiple delimitors /// /// FIXME: We do not yet handle situations where folders or items have the same name. We could handle this by some /// XPath like expression /// /// FIXME: Delimitors which occur in names themselves are not currently escapable. - /// + /// /// /// /// Inventory service to query @@ -178,32 +179,66 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver return FindItemByPath(inventoryService, rootFolder, path); } - + /// /// Find an item given a PATH_DELIMITOR delimited path starting from this folder. - /// - /// This method does not handle paths that contain multiple delimitors + /// + /// + /// This method does not handle paths that contain multiple delimiters /// /// FIXME: We do not yet handle situations where folders or items have the same name. We could handle this by some /// XPath like expression /// /// FIXME: Delimitors which occur in names themselves are not currently escapable. - /// - /// - /// - /// Inventory service to query - /// - /// - /// The folder from which the path starts - /// - /// - /// - /// The path to the required item. - /// + /// + /// + /// Inventory service to query + /// The folder from which the path starts + /// The path to the required item. /// null if the item is not found public static InventoryItemBase FindItemByPath( IInventoryService inventoryService, InventoryFolderBase startFolder, string path) { + List foundItems = FindItemsByPath(inventoryService, startFolder, path); + + if (foundItems.Count != 0) + return foundItems[0]; + else + return null; + } + + public static List FindItemsByPath( + IInventoryService inventoryService, UUID userId, string path) + { + InventoryFolderBase rootFolder = inventoryService.GetRootFolder(userId); + + if (null == rootFolder) + return new List(); + + return FindItemsByPath(inventoryService, rootFolder, path); + } + + /// + /// Find items that match a given PATH_DELIMITOR delimited path starting from this folder. + /// + /// + /// This method does not handle paths that contain multiple delimiters + /// + /// FIXME: We do not yet handle situations where folders or items have the same name. We could handle this by some + /// XPath like expression + /// + /// FIXME: Delimitors which occur in names themselves are not currently escapable. + /// + /// + /// Inventory service to query + /// The folder from which the path starts + /// The path to the required item. + /// The items that were found with this path. An empty list if no items were found. + public static List FindItemsByPath( + IInventoryService inventoryService, InventoryFolderBase startFolder, string path) + { + List foundItems = new List(); + // If the path isn't just / then trim any starting extraneous slashes path = path.TrimStart(new char[] { PATH_DELIMITER }); @@ -215,11 +250,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver if (components.Length == 1) { // m_log.DebugFormat( -// "FOUND SINGLE COMPONENT [{0}]. Looking for this in [{1}] {2}", +// "FOUND SINGLE COMPONENT [{0}]. Looking for this in [{1}] {2}", // components[0], startFolder.Name, startFolder.ID); List items = inventoryService.GetFolderItems(startFolder.Owner, startFolder.ID); - + // m_log.DebugFormat("[INVENTORY ARCHIVE UTILS]: Found {0} items in FindItemByPath()", items.Count); foreach (InventoryItemBase item in items) @@ -227,24 +262,23 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver // m_log.DebugFormat("[INVENTORY ARCHIVE UTILS]: Inspecting item {0} {1}", item.Name, item.ID); if (item.Name == components[0]) - return item; + foundItems.Add(item); } } else { // m_log.DebugFormat("FOUND COMPONENTS [{0}] and [{1}]", components[0], components[1]); - + InventoryCollection contents = inventoryService.GetFolderContent(startFolder.Owner, startFolder.ID); foreach (InventoryFolderBase folder in contents.Folders) { if (folder.Name == components[0]) - return FindItemByPath(inventoryService, folder, components[1]); + foundItems.AddRange(FindItemsByPath(inventoryService, folder, components[1])); } } - // We didn't find an item or intermediate folder with the given name - return null; + return foundItems; } /// diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs index e043caa19c..63fde078a9 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs @@ -146,6 +146,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver protected void SaveInvItem(InventoryItemBase inventoryItem, string path, Dictionary options, IUserAccountService userAccountService) { + if (options.ContainsKey("verbose")) + m_log.InfoFormat( + "[INVENTORY ARCHIVER]: Saving item {0} {1} with asset {2}", + inventoryItem.ID, inventoryItem.Name, inventoryItem.AssetID); + string filename = path + CreateArchiveItemName(inventoryItem); // Record the creator of this item for user record purposes (which might go away soon) @@ -154,7 +159,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver string serialization = UserInventoryItemSerializer.Serialize(inventoryItem, options, userAccountService); m_archiveWriter.WriteFile(filename, serialization); - if (SaveAssets) + AssetType itemAssetType = (AssetType)inventoryItem.AssetType; + + // Don't chase down link asset items as they actually point to their target item IDs rather than an asset + if (SaveAssets && itemAssetType != AssetType.Link && itemAssetType != AssetType.LinkFolder) m_assetGatherer.GatherAssetUuids(inventoryItem.AssetID, (AssetType)inventoryItem.AssetType, m_assetUuids); } @@ -246,10 +254,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver // The path may point to an item instead if (inventoryFolder == null) - { inventoryItem = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, rootFolder, m_invPath); - //inventoryItem = m_userInfo.RootFolder.FindItemByPath(m_invPath); - } if (null == inventoryFolder && null == inventoryItem) { @@ -441,4 +446,4 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver return s; } } -} \ No newline at end of file +} diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs new file mode 100644 index 0000000000..c82cfd2d75 --- /dev/null +++ b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs @@ -0,0 +1,244 @@ +/* + * 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.Generic; +using System.Reflection; +using log4net; +using Nini.Config; +using OpenMetaverse; +using Mono.Addins; + +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Connectors.Hypergrid; + +using GridRegion = OpenSim.Services.Interfaces.GridRegion; + +namespace OpenSim.Region.CoreModules.Avatar.Lure +{ + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] + public class HGLureModule : ISharedRegionModule + { + private static readonly ILog m_log = LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + + private readonly List m_scenes = new List(); + + private IMessageTransferModule m_TransferModule = null; + private bool m_Enabled = false; + + private string m_ThisGridURL; + + private ExpiringCache m_PendingLures = new ExpiringCache(); + + public void Initialise(IConfigSource config) + { + if (config.Configs["Messaging"] != null) + { + if (config.Configs["Messaging"].GetString("LureModule", string.Empty) == "HGLureModule") + { + m_Enabled = true; + + m_ThisGridURL = config.Configs["Messaging"].GetString("Gatekeeper", string.Empty); + m_log.DebugFormat("[LURE MODULE]: {0} enabled", Name); + } + } + } + + public void AddRegion(Scene scene) + { + if (!m_Enabled) + return; + + lock (m_scenes) + { + m_scenes.Add(scene); + scene.EventManager.OnIncomingInstantMessage += OnIncomingInstantMessage; + scene.EventManager.OnNewClient += OnNewClient; + } + } + + public void RegionLoaded(Scene scene) + { + if (!m_Enabled) + return; + + if (m_TransferModule == null) + { + m_TransferModule = + scene.RequestModuleInterface(); + + if (m_TransferModule == null) + { + m_log.Error("[LURE MODULE]: No message transfer module, lures will not work!"); + + m_Enabled = false; + m_scenes.Clear(); + scene.EventManager.OnNewClient -= OnNewClient; + scene.EventManager.OnIncomingInstantMessage -= OnIncomingInstantMessage; + } + } + + } + + public void RemoveRegion(Scene scene) + { + if (!m_Enabled) + return; + + lock (m_scenes) + { + m_scenes.Remove(scene); + scene.EventManager.OnNewClient -= OnNewClient; + scene.EventManager.OnIncomingInstantMessage -= OnIncomingInstantMessage; + } + } + + void OnNewClient(IClientAPI client) + { + client.OnInstantMessage += OnInstantMessage; + client.OnStartLure += OnStartLure; + client.OnTeleportLureRequest += OnTeleportLureRequest; + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "HGLureModule"; } + } + + public Type ReplaceableInterface + { + get { return null; } + } + + void OnInstantMessage(IClientAPI client, GridInstantMessage im) + { + } + + void OnIncomingInstantMessage(GridInstantMessage im) + { + if (im.dialog == (byte)InstantMessageDialog.RequestTeleport) + { + UUID sessionID = new UUID(im.imSessionID); + m_log.DebugFormat("[HG LURE MODULE]: RequestTeleport sessionID={0}, regionID={1}, message={2}", im.imSessionID, im.RegionID, im.message); + m_PendingLures.Add(sessionID, im, 7200); // 2 hours + + // Forward. We do this, because the IM module explicitly rejects + // IMs of this type + if (m_TransferModule != null) + m_TransferModule.SendInstantMessage(im, delegate(bool success) { }); + + } + } + + public void OnStartLure(byte lureType, string message, UUID targetid, IClientAPI client) + { + if (!(client.Scene is Scene)) + return; + + Scene scene = (Scene)(client.Scene); + ScenePresence presence = scene.GetScenePresence(client.AgentId); + + message += "@" + m_ThisGridURL; + + m_log.DebugFormat("[HG LURE MODULE]: TP invite with message {0}", message); + + GridInstantMessage m = new GridInstantMessage(scene, client.AgentId, + client.FirstName+" "+client.LastName, targetid, + (byte)InstantMessageDialog.RequestTeleport, false, + message, UUID.Random(), false, presence.AbsolutePosition, + new Byte[0]); + m.RegionID = client.Scene.RegionInfo.RegionID.Guid; + + if (m_TransferModule != null) + { + m_TransferModule.SendInstantMessage(m, + delegate(bool success) { }); + } + } + + public void OnTeleportLureRequest(UUID lureID, uint teleportFlags, IClientAPI client) + { + if (!(client.Scene is Scene)) + return; + + Scene scene = (Scene)(client.Scene); + + GridInstantMessage im = null; + if (m_PendingLures.TryGetValue(lureID, out im)) + { + m_PendingLures.Remove(lureID); + Lure(client, teleportFlags, im); + } + else + m_log.DebugFormat("[HG LURE MODULE]: pending lure {0} not found", lureID); + + } + + private void Lure(IClientAPI client, uint teleportflags, GridInstantMessage im) + { + Scene scene = (Scene)(client.Scene); + GridRegion region = scene.GridService.GetRegionByUUID(scene.RegionInfo.ScopeID, new UUID(im.RegionID)); + if (region != null) + scene.RequestTeleportLocation(client, region.RegionHandle, im.Position + new Vector3(0.5f, 0.5f, 0f), Vector3.UnitX, teleportflags); + else // we don't have that region here. Check if it's HG + { + string[] parts = im.message.Split(new char[] { '@' }); + if (parts.Length > 1) + { + string url = parts[parts.Length - 1]; // the last part + if (url.Trim(new char[] {'/'}) != m_ThisGridURL.Trim(new char[] {'/'})) + { + m_log.DebugFormat("[HG LURE MODULE]: Luring agent to grid {0} region {1} position {2}", url, im.RegionID, im.Position); + GatekeeperServiceConnector gConn = new GatekeeperServiceConnector(); + GridRegion gatekeeper = new GridRegion(); + gatekeeper.ServerURI = url; + GridRegion finalDestination = gConn.GetHyperlinkRegion(gatekeeper, new UUID(im.RegionID)); + if (finalDestination != null) + { + ScenePresence sp = scene.GetScenePresence(client.AgentId); + IEntityTransferModule transferMod = scene.RequestModuleInterface(); + IEventQueue eq = sp.Scene.RequestModuleInterface(); + if (transferMod != null && sp != null && eq != null) + transferMod.DoTeleport(sp, gatekeeper, finalDestination, im.Position + new Vector3(0.5f, 0.5f, 0f), Vector3.UnitX, teleportflags, eq); + } + } + } + } + } + } +} diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs index a12b57af7a..dcfdf8f02b 100644 --- a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs @@ -45,16 +45,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure private readonly List m_scenes = new List(); private IMessageTransferModule m_TransferModule = null; - private bool m_Enabled = true; + private bool m_Enabled = false; public void Initialise(IConfigSource config) { if (config.Configs["Messaging"] != null) { if (config.Configs["Messaging"].GetString( - "LureModule", "LureModule") != + "LureModule", "LureModule") == "LureModule") - m_Enabled = false; + { + m_Enabled = true; + m_log.DebugFormat("[LURE MODULE]: {0} enabled", Name); + } } } @@ -74,6 +77,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure public void RegionLoaded(Scene scene) { + if (!m_Enabled) + return; + if (m_TransferModule == null) { m_TransferModule = @@ -96,6 +102,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure public void RemoveRegion(Scene scene) { + if (!m_Enabled) + return; + lock (m_scenes) { m_scenes.Remove(scene); diff --git a/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs b/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs new file mode 100644 index 0000000000..079e1b6b0a --- /dev/null +++ b/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs @@ -0,0 +1,173 @@ +/* + * 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")] + public class BasicProfileModule : 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) + { + if (config.Configs["Profile"] != null) + { + if (config.Configs["Profile"].GetString("Module", string.Empty) != "BasicProfileModule") + return; + } + + 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; + } + } + } + + 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 null; } + } + + #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; + + Byte[] charterMember = Utils.StringToBytes("Avatar"); + + 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(0).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); + } + + } +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 1fb346e3e3..02efcd87d8 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -52,6 +52,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer protected bool m_Enabled = false; protected Scene m_aScene; + protected List m_Scenes = new List(); protected List m_agentsInTransit; private ExpiringCache> m_bannedRegions = new ExpiringCache>(); @@ -96,13 +97,15 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer if (m_aScene == null) m_aScene = scene; + m_Scenes.Add(scene); scene.RegisterModuleInterface(this); scene.EventManager.OnNewClient += OnNewClient; } protected virtual void OnNewClient(IClientAPI client) { - client.OnTeleportHomeRequest += TeleportHomeFired; + client.OnTeleportHomeRequest += TriggerTeleportHome; + client.OnTeleportLandmarkRequest += RequestTeleportLandmark; } public virtual void Close() @@ -118,6 +121,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer return; if (scene == m_aScene) m_aScene = null; + + m_Scenes.Remove(scene); } public virtual void RegionLoaded(Scene scene) @@ -127,7 +132,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } - #endregion #region Agent Teleports @@ -249,7 +253,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } } - protected void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination, Vector3 position, Vector3 lookAt, uint teleportFlags, IEventQueue eq) + public void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination, Vector3 position, Vector3 lookAt, uint teleportFlags, IEventQueue eq) { if (reg == null || finalDestination == null) { @@ -557,9 +561,32 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer #endregion + #region Landmark Teleport + /// + /// Tries to teleport agent to landmark. + /// + /// + /// + /// + public virtual void RequestTeleportLandmark(IClientAPI remoteClient, AssetLandmark lm) + { + GridRegion info = m_aScene.GridService.GetRegionByUUID(UUID.Zero, lm.RegionID); + + if (info == null) + { + // can't find the region: Tell viewer and abort + remoteClient.SendTeleportFailed("The teleport destination could not be found."); + return; + } + ((Scene)(remoteClient.Scene)).RequestTeleportLocation(remoteClient, info.RegionHandle, lm.Position, + Vector3.Zero, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaLandmark)); + } + + #endregion + #region Teleport Home - public void TeleportHomeFired(UUID id, IClientAPI client) + public virtual void TriggerTeleportHome(UUID id, IClientAPI client) { TeleportHome(id, client); } diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs index 1ccbcfd4ae..8858ad57c3 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs @@ -86,7 +86,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer protected override void OnNewClient(IClientAPI client) { - client.OnTeleportHomeRequest += TeleportHomeFired; + client.OnTeleportHomeRequest += TriggerTeleportHome; + client.OnTeleportLandmarkRequest += RequestTeleportLandmark; client.OnConnectionClosed += new Action(OnConnectionClosed); } @@ -146,8 +147,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer { base.AgentHasMovedAway(sp, logout); if (logout) + { // Log them out of this grid m_aScene.PresenceService.LogoutAgent(sp.ControllingClient.SessionId); + } } protected override bool CreateAgent(ScenePresence sp, GridRegion reg, GridRegion finalDestination, AgentCircuitData agentCircuit, uint teleportFlags, out string reason, out bool logout) @@ -178,7 +181,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer return m_aScene.SimulationService.CreateAgent(reg, agentCircuit, teleportFlags, out reason); } - public void TeleportHomeFired(UUID id, IClientAPI client) + public void TriggerTeleportHome(UUID id, IClientAPI client) { TeleportHome(id, client); } @@ -233,6 +236,57 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer DoTeleport(sp, homeGatekeeper, finalDestination, position, lookAt, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaHome), eq); return true; } + + /// + /// Tries to teleport agent to landmark. + /// + /// + /// + /// + public override void RequestTeleportLandmark(IClientAPI remoteClient, AssetLandmark lm) + { + m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Teleporting agent via landmark to {0} region {1} position {2}", + (lm.Gatekeeper == string.Empty) ? "local" : lm.Gatekeeper, lm.RegionID, lm.Position); + if (lm.Gatekeeper == string.Empty) + { + base.RequestTeleportLandmark(remoteClient, lm); + return; + } + + GridRegion info = m_aScene.GridService.GetRegionByUUID(UUID.Zero, lm.RegionID); + + // Local region? + if (info != null) + { + ((Scene)(remoteClient.Scene)).RequestTeleportLocation(remoteClient, info.RegionHandle, lm.Position, + Vector3.Zero, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaLandmark)); + return; + } + else + { + // Foreign region + Scene scene = (Scene)(remoteClient.Scene); + GatekeeperServiceConnector gConn = new GatekeeperServiceConnector(); + GridRegion gatekeeper = new GridRegion(); + gatekeeper.ServerURI = lm.Gatekeeper; + GridRegion finalDestination = gConn.GetHyperlinkRegion(gatekeeper, new UUID(lm.RegionID)); + if (finalDestination != null) + { + ScenePresence sp = scene.GetScenePresence(remoteClient.AgentId); + IEntityTransferModule transferMod = scene.RequestModuleInterface(); + IEventQueue eq = sp.Scene.RequestModuleInterface(); + if (transferMod != null && sp != null && eq != null) + transferMod.DoTeleport(sp, gatekeeper, finalDestination, lm.Position, + Vector3.UnitX, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaLandmark), eq); + } + + } + + // can't find the region: Tell viewer and abort + remoteClient.SendTeleportFailed("The teleport destination could not be found."); + + } + #endregion #region IUserAgentVerificationModule diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs index 52791cb046..49d484b0e8 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs @@ -56,6 +56,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess private string m_ProfileServerURI; private bool m_OutboundPermission; + private string m_ThisGatekeeper; // private bool m_Initialized = false; @@ -85,6 +86,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess { m_ProfileServerURI = thisModuleConfig.GetString("ProfileServerURI", string.Empty); m_OutboundPermission = thisModuleConfig.GetBoolean("OutboundPermission", true); + m_ThisGatekeeper = thisModuleConfig.GetString("Gatekeeper", string.Empty); } else m_log.Warn("[HG INVENTORY ACCESS MODULE]: HGInventoryAccessModule configs not found. ProfileServerURI not set!"); @@ -110,7 +112,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess public void UploadInventoryItem(UUID avatarID, UUID assetID, string name, int userlevel) { string userAssetServer = string.Empty; - if (IsForeignUser(avatarID, out userAssetServer) && m_OutboundPermission) + if (IsForeignUser(avatarID, out userAssetServer) && userAssetServer != string.Empty && m_OutboundPermission) { Util.FireAndForget(delegate { m_assMapper.Post(assetID, avatarID, userAssetServer); }); } @@ -119,6 +121,24 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess #endregion #region Overrides of Basic Inventory Access methods + + protected override string GenerateLandmark(ScenePresence presence, out string prefix, out string suffix) + { + UserAccount account = m_Scene.UserAccountService.GetUserAccount(m_Scene.RegionInfo.ScopeID, presence.UUID); + if (account == null) + prefix = "HG "; + else + prefix = string.Empty; + suffix = " @ " + m_ThisGatekeeper; + Vector3 pos = presence.AbsolutePosition; + return String.Format("Landmark version 2\nregion_id {0}\nlocal_pos {1} {2} {3}\nregion_handle {4}\ngatekeeper {5}\n", + presence.Scene.RegionInfo.RegionID, + pos.X, pos.Y, pos.Z, + presence.RegionHandle, + m_ThisGatekeeper); + } + + /// /// CapsUpdateInventoryItemAsset /// @@ -180,10 +200,10 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess public override void TransferInventoryAssets(InventoryItemBase item, UUID sender, UUID receiver) { string userAssetServer = string.Empty; - if (IsForeignUser(sender, out userAssetServer)) + if (IsForeignUser(sender, out userAssetServer) && userAssetServer != string.Empty) m_assMapper.Get(item.AssetID, sender, userAssetServer); - if (IsForeignUser(receiver, out userAssetServer) && m_OutboundPermission) + if (IsForeignUser(receiver, out userAssetServer) && userAssetServer != string.Empty && m_OutboundPermission) m_assMapper.Post(item.AssetID, receiver, userAssetServer); } @@ -203,9 +223,15 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess if (aCircuit.ServiceURLs.ContainsKey("AssetServerURI")) { assetServerURL = aCircuit.ServiceURLs["AssetServerURI"].ToString(); - assetServerURL = assetServerURL.Trim(new char[] { '/' }); return true; + assetServerURL = assetServerURL.Trim(new char[] { '/' }); } } + else + { + assetServerURL = UserManagementModule.GetUserServerURL(userID, "AssetServerURI"); + assetServerURL = assetServerURL.Trim(new char[] { '/' }); + } + return true; } return false; diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index 184b2232f7..7bad814db4 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -30,6 +30,7 @@ using System.Collections.Generic; using System.Net; using System.Xml; using System.Reflection; +using System.Text; using System.Threading; using OpenSim.Framework; @@ -128,7 +129,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess protected virtual void OnNewClient(IClientAPI client) { - + client.OnCreateNewInventoryItem += CreateNewInventoryItem; } public virtual void Close() @@ -156,6 +157,87 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess #region Inventory Access + /// + /// Create a new inventory item. Called when the client creates a new item directly within their + /// inventory (e.g. by selecting a context inventory menu option). + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public void CreateNewInventoryItem(IClientAPI remoteClient, UUID transactionID, UUID folderID, + uint callbackID, string description, string name, sbyte invType, + sbyte assetType, + byte wearableType, uint nextOwnerMask, int creationDate) + { + m_log.DebugFormat("[AGENT INVENTORY]: Received request to create inventory item {0} in folder {1}", name, folderID); + + if (!m_Scene.Permissions.CanCreateUserInventory(invType, remoteClient.AgentId)) + return; + + InventoryFolderBase f = new InventoryFolderBase(folderID, remoteClient.AgentId); + InventoryFolderBase folder = m_Scene.InventoryService.GetFolder(f); + + if (folder == null || folder.Owner != remoteClient.AgentId) + return; + + if (transactionID == UUID.Zero) + { + ScenePresence presence; + if (m_Scene.TryGetScenePresence(remoteClient.AgentId, out presence)) + { + byte[] data = null; + + if (invType == (sbyte)InventoryType.Landmark && presence != null) + { + string suffix = string.Empty, prefix = string.Empty; + string strdata = GenerateLandmark(presence, out prefix, out suffix); + data = Encoding.ASCII.GetBytes(strdata); + name = prefix + name; + description += suffix; + } + + AssetBase asset = m_Scene.CreateAsset(name, description, assetType, data, remoteClient.AgentId); + m_Scene.AssetService.Store(asset); + + m_Scene.CreateNewInventoryItem(remoteClient, remoteClient.AgentId.ToString(), string.Empty, folderID, asset.Name, 0, callbackID, asset, invType, nextOwnerMask, creationDate); + } + else + { + m_log.ErrorFormat( + "ScenePresence for agent uuid {0} unexpectedly not found in CreateNewInventoryItem", + remoteClient.AgentId); + } + } + else + { + IAgentAssetTransactions agentTransactions = m_Scene.RequestModuleInterface(); + if (agentTransactions != null) + { + agentTransactions.HandleItemCreationFromTransaction( + remoteClient, transactionID, folderID, callbackID, description, + name, invType, assetType, wearableType, nextOwnerMask); + } + } + } + + protected virtual string GenerateLandmark(ScenePresence presence, out string prefix, out string suffix) + { + prefix = string.Empty; + suffix = string.Empty; + Vector3 pos = presence.AbsolutePosition; + return String.Format("Landmark version 2\nregion_id {0}\nlocal_pos {1} {2} {3}\nregion_handle {4}\n", + presence.Scene.RegionInfo.RegionID, + pos.X, pos.Y, pos.Z, + presence.RegionHandle); + } + /// /// Capability originating call to update the asset of an item in an agent's inventory /// diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs index 4cc6905a0f..accd09443c 100644 --- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs +++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs @@ -30,11 +30,13 @@ using System.IO; using System.Reflection; using OpenSim.Framework; +using OpenSim.Framework.Console; using OpenSim.Region.Framework; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; using OpenSim.Services.Interfaces; +using OpenSim.Services.Connectors.Hypergrid; using OpenMetaverse; using log4net; @@ -47,7 +49,8 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement public UUID Id; public string FirstName; public string LastName; - public string ProfileURL; + public string HomeURL; + public Dictionary ServerURLs; } public class UserManagementModule : ISharedRegionModule, IUserManagement @@ -78,6 +81,14 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement // } // } //} + MainConsole.Instance.Commands.AddCommand("grid", true, + "show names", + "show names", + "Show the bindings between user UUIDs and user names", + String.Empty, + HandleShowUsers); + + } public bool IsSharedModule @@ -101,6 +112,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement scene.RegisterModuleInterface(this); scene.EventManager.OnNewClient += new EventManager.OnNewClientDelegate(EventManager_OnNewClient); + scene.EventManager.OnPrimsLoaded += new EventManager.PrimsLoaded(EventManager_OnPrimsLoaded); } public void RemoveRegion(Scene scene) @@ -109,18 +121,12 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement m_Scenes.Remove(scene); } - public void RegionLoaded(Scene scene) + public void RegionLoaded(Scene s) { } public void PostInitialise() { - foreach (Scene s in m_Scenes) - { - // let's sniff all the user names referenced by objects in the scene - m_log.DebugFormat("[USER MANAGEMENT MODULE]: Caching creators' data from {0} ({1} objects)...", s.RegionInfo.RegionName, s.GetEntities().Length); - s.ForEachSOG(delegate(SceneObjectGroup sog) { CacheCreators(sog); }); - } } public void Close() @@ -134,6 +140,14 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement #region Event Handlers + void EventManager_OnPrimsLoaded(Scene s) + { + // let's sniff all the user names referenced by objects in the scene + m_log.DebugFormat("[USER MANAGEMENT MODULE]: Caching creators' data from {0} ({1} objects)...", s.RegionInfo.RegionName, s.GetEntities().Length); + s.ForEachSOG(delegate(SceneObjectGroup sog) { CacheCreators(sog); }); + } + + void EventManager_OnNewClient(IClientAPI client) { client.OnNameFromUUIDRequest += new UUIDNameRequest(HandleUUIDNameRequest); @@ -150,6 +164,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement string[] names = GetUserNames(uuid); if (names.Length == 2) { + //m_log.DebugFormat("[XXX] HandleUUIDNameRequest {0} is {1} {2}", uuid, names[0], names[1]); remote_client.SendNameReply(uuid, names[0], names[1]); } @@ -210,6 +225,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement public string GetUserName(UUID uuid) { + //m_log.DebugFormat("[XXX] GetUserName {0}", uuid); string[] names = GetUserNames(uuid); if (names.Length == 2) { @@ -222,6 +238,60 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement return "(hippos)"; } + public string GetUserHomeURL(UUID userID) + { + if (m_UserCache.ContainsKey(userID)) + return m_UserCache[userID].HomeURL; + + return string.Empty; + } + + public string GetUserServerURL(UUID userID, string serverType) + { + if (m_UserCache.ContainsKey(userID)) + { + UserData userdata = m_UserCache[userID]; + if (userdata.ServerURLs != null && userdata.ServerURLs.ContainsKey(serverType) && userdata.ServerURLs[serverType] != null) + return userdata.ServerURLs[serverType].ToString(); + + if (userdata.HomeURL != string.Empty) + { + UserAgentServiceConnector uConn = new UserAgentServiceConnector(userdata.HomeURL); + userdata.ServerURLs = uConn.GetServerURLs(userID); + if (userdata.ServerURLs != null && userdata.ServerURLs.ContainsKey(serverType) && userdata.ServerURLs[serverType] != null) + return userdata.ServerURLs[serverType].ToString(); + } + } + + return string.Empty; + } + + public string GetUserUUI(UUID userID) + { + UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, userID); + if (account != null) + return userID.ToString(); + + if (m_UserCache.ContainsKey(userID)) + { + UserData ud = m_UserCache[userID]; + string homeURL = ud.HomeURL; + string first = ud.FirstName, last = ud.LastName; + if (ud.LastName.StartsWith("@")) + { + string[] parts = ud.FirstName.Split('.'); + if (parts.Length >= 2) + { + first = parts[0]; + last = parts[1]; + } + return userID + ";" + homeURL + ";" + first + " " + last; + } + } + + return userID.ToString(); + } + public void AddUser(UUID id, string creatorData) { if (m_UserCache.ContainsKey(id)) @@ -247,13 +317,13 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement string[] parts = creatorData.Split(';'); if (parts.Length >= 1) { - user.ProfileURL = parts[0]; + user.HomeURL = parts[0]; try { Uri uri = new Uri(parts[0]); user.LastName = "@" + uri.Authority; } - catch + catch (UriFormatException) { m_log.DebugFormat("[SCENE]: Unable to parse Uri {0}", parts[0]); user.LastName = "@unknown"; @@ -272,7 +342,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement lock (m_UserCache) m_UserCache[id] = user; - m_log.DebugFormat("[USER MANAGEMENT MODULE]: Added user {0} {1} {2} {3}", user.Id, user.FirstName, user.LastName, user.ProfileURL); + m_log.DebugFormat("[USER MANAGEMENT MODULE]: Added user {0} {1} {2} {3}", user.Id, user.FirstName, user.LastName, user.HomeURL); } public void AddUser(UUID uuid, string first, string last, string profileURL) @@ -311,5 +381,25 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement //} #endregion IUserManagement + + private void HandleShowUsers(string module, string[] cmd) + { + if (m_UserCache.Count == 0) + { + MainConsole.Instance.Output("No users not found"); + return; + } + + MainConsole.Instance.Output("UUID User Name"); + MainConsole.Instance.Output("-----------------------------------------------------------------------------"); + foreach (KeyValuePair kvp in m_UserCache) + { + MainConsole.Instance.Output(String.Format("{0} {1} {2}", + kvp.Key, kvp.Value.FirstName, kvp.Value.LastName)); + } + return; + } + + } } diff --git a/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs b/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs index 5ab334ffaf..0c60391fe2 100644 --- a/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs +++ b/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs @@ -25,6 +25,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +using System; using System.Collections.Generic; using System.Reflection; using log4net; @@ -40,7 +41,10 @@ namespace OpenSim.Region.CoreModules.Hypergrid { public class HGWorldMapModule : WorldMapModule { - //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + // Remember the map area that each client has been exposed to in this region + private Dictionary> m_SeenMapBlocks = new Dictionary>(); #region INonSharedRegionModule Members @@ -51,6 +55,13 @@ namespace OpenSim.Region.CoreModules.Hypergrid m_Enabled = true; } + public override void AddRegion(Scene scene) + { + base.AddRegion(scene); + + scene.EventManager.OnClientClosed += new EventManager.ClientClosed(EventManager_OnClientClosed); + } + public override string Name { get { return "HGWorldMap"; } @@ -58,47 +69,70 @@ namespace OpenSim.Region.CoreModules.Hypergrid #endregion - protected override void GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) + void EventManager_OnClientClosed(UUID clientID, Scene scene) { - List mapBlocks = new List(); - List regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, - minX * (int)Constants.RegionSize, maxX * (int)Constants.RegionSize, - minY * (int)Constants.RegionSize, maxY * (int)Constants.RegionSize); - - foreach (GridRegion r in regions) + ScenePresence sp = scene.GetScenePresence(clientID); + if (sp != null) { - MapBlockData block = new MapBlockData(); - MapBlockFromGridRegion(block, r); - mapBlocks.Add(block); - } - - // Different from super - FillInMap(mapBlocks, minX, minY, maxX, maxY); - // - - remoteClient.SendMapBlock(mapBlocks, 0); - } - - - private void FillInMap(List mapBlocks, int minX, int minY, int maxX, int maxY) - { - for (int x = minX; x <= maxX; x++) - { - for (int y = minY; y <= maxY; y++) + if (m_SeenMapBlocks.ContainsKey(clientID)) { - MapBlockData mblock = mapBlocks.Find(delegate(MapBlockData mb) { return ((mb.X == x) && (mb.Y == y)); }); - if (mblock == null) + List mapBlocks = m_SeenMapBlocks[clientID]; + foreach (MapBlockData b in mapBlocks) { - mblock = new MapBlockData(); - mblock.X = (ushort)x; - mblock.Y = (ushort)y; - mblock.Name = ""; - mblock.Access = 254; // means 'simulator is offline'. We need this because the viewer ignores 255's - mblock.MapImageId = UUID.Zero; - mapBlocks.Add(mblock); + b.Name = string.Empty; + b.Access = 254; // means 'simulator is offline'. We need this because the viewer ignores 255's } + + m_log.DebugFormat("[HG MAP]: Reseting {0} blocks", mapBlocks.Count); + sp.ControllingClient.SendMapBlock(mapBlocks, 0); + m_SeenMapBlocks.Remove(clientID); } } } + + protected override List GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) + { + List mapBlocks = base.GetAndSendBlocks(remoteClient, minX, minY, maxX, maxY, flag); + lock (m_SeenMapBlocks) + { + if (!m_SeenMapBlocks.ContainsKey(remoteClient.AgentId)) + { + m_SeenMapBlocks.Add(remoteClient.AgentId, mapBlocks); + } + else + { + List seen = m_SeenMapBlocks[remoteClient.AgentId]; + List newBlocks = new List(); + foreach (MapBlockData b in mapBlocks) + if (seen.Find(delegate(MapBlockData bdata) { return bdata.X == b.X && bdata.Y == b.Y; }) == null) + newBlocks.Add(b); + seen.AddRange(newBlocks); + } + } + + return mapBlocks; + } + + } + + class MapArea + { + public int minX; + public int minY; + public int maxX; + public int maxY; + + public MapArea(int mix, int miy, int max, int may) + { + minX = mix; + minY = miy; + maxX = max; + maxY = may; + } + + public void Print() + { + Console.WriteLine(String.Format(" --> Area is minX={0} minY={1} minY={2} maxY={3}", minX, minY, maxY, maxY)); + } } } diff --git a/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml b/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml index 8a6735f378..e22fd38107 100644 --- a/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml +++ b/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml @@ -24,6 +24,7 @@ + diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs index d2343c994e..a5b5637961 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs @@ -113,8 +113,10 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Hypergrid ISimulationService simService = scene.RequestModuleInterface(); m_HypergridHandler = new GatekeeperServiceInConnector(m_Config, MainServer.Instance, simService); - new UserAgentServerConnector(m_Config, MainServer.Instance); + IFriendsSimConnector friendsConn = scene.RequestModuleInterface(); + new UserAgentServerConnector(m_Config, MainServer.Instance, friendsConn); new HeloServiceInConnector(m_Config, MainServer.Instance, "HeloService"); + new HGFriendsServerConnector(m_Config, MainServer.Instance, "HGFriendsService"); } scene.RegisterModuleInterface(m_HypergridHandler.GateKeeper); } diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/MapImage/MapImageServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/MapImage/MapImageServiceInConnectorModule.cs new file mode 100644 index 0000000000..b570155048 --- /dev/null +++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/MapImage/MapImageServiceInConnectorModule.cs @@ -0,0 +1,111 @@ +/* + * 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.Reflection; +using System.Collections.Generic; +using log4net; +using Mono.Addins; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Server.Base; +using OpenSim.Server.Handlers.Base; +using OpenSim.Server.Handlers.MapImage; +using OpenSim.Services.Interfaces; + +namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.MapImage +{ + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] + public class MapImageServiceInConnectorModule : ISharedRegionModule + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private static bool m_Enabled = false; + + private IConfigSource m_Config; + bool m_Registered = false; + + #region IRegionModule interface + + public void Initialise(IConfigSource config) + { + m_Config = config; + IConfig moduleConfig = config.Configs["Modules"]; + if (moduleConfig != null) + { + m_Enabled = moduleConfig.GetBoolean("MapImageServiceInConnector", false); + if (m_Enabled) + { + m_log.Info("[MAP SERVICE IN CONNECTOR]: MapImage Service In Connector enabled"); + new MapGetServiceConnector(m_Config, MainServer.Instance, "MapImageService"); + } + + } + + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public Type ReplaceableInterface + { + get { return null; } + } + + public string Name + { + get { return "MapImageServiceIn"; } + } + + public void AddRegion(Scene scene) + { + if (!m_Enabled) + return; + } + + public void RemoveRegion(Scene scene) + { + if (!m_Enabled) + return; + } + + public void RegionLoaded(Scene scene) + { + if (!m_Enabled) + return; + } + + #endregion + + } +} diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionInfoCache.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionInfoCache.cs new file mode 100644 index 0000000000..786e0b5737 --- /dev/null +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionInfoCache.cs @@ -0,0 +1,137 @@ +/* + * 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.Reflection; +using System.Collections.Generic; +using OpenSim.Framework; +using OpenSim.Services.Interfaces; +using OpenMetaverse; +using log4net; +using GridRegion = OpenSim.Services.Interfaces.GridRegion; + +namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid +{ + public class RegionInfoCache + { + private const double CACHE_EXPIRATION_SECONDS = 300.0; // 5 minutes + +// private static readonly ILog m_log = +// LogManager.GetLogger( +// MethodBase.GetCurrentMethod().DeclaringType); + + internal struct ScopedRegionUUID + { + public UUID m_scopeID; + public UUID m_regionID; + public ScopedRegionUUID(UUID scopeID, UUID regionID) + { + m_scopeID = scopeID; + m_regionID = regionID; + } + } + + internal struct ScopedRegionName + { + public UUID m_scopeID; + public string m_name; + public ScopedRegionName(UUID scopeID, string name) + { + m_scopeID = scopeID; + m_name = name; + } + } + + private ExpiringCache m_UUIDCache; + private ExpiringCache m_NameCache; + + public RegionInfoCache() + { + m_UUIDCache = new ExpiringCache(); + m_NameCache = new ExpiringCache(); + } + + public void Cache(GridRegion rinfo) + { + if (rinfo != null) + this.Cache(rinfo.ScopeID,rinfo.RegionID,rinfo); + } + + public void Cache(UUID scopeID, UUID regionID, GridRegion rinfo) + { + // for now, do not cache negative results; this is because + // we need to figure out how to handle regions coming online + // in a timely way + if (rinfo == null) + return; + + ScopedRegionUUID id = new ScopedRegionUUID(scopeID,regionID); + + // Cache even null accounts + m_UUIDCache.AddOrUpdate(id, rinfo, CACHE_EXPIRATION_SECONDS); + if (rinfo != null) + { + ScopedRegionName name = new ScopedRegionName(scopeID,rinfo.RegionName); + m_NameCache.AddOrUpdate(name, id, CACHE_EXPIRATION_SECONDS); + } + } + + public GridRegion Get(UUID scopeID, UUID regionID, out bool inCache) + { + inCache = false; + + GridRegion rinfo = null; + ScopedRegionUUID id = new ScopedRegionUUID(scopeID,regionID); + if (m_UUIDCache.TryGetValue(id, out rinfo)) + { + inCache = true; + return rinfo; + } + + return null; + } + + public GridRegion Get(UUID scopeID, string name, out bool inCache) + { + inCache = false; + + ScopedRegionName sname = new ScopedRegionName(scopeID,name); + + ScopedRegionUUID id; + if (m_NameCache.TryGetValue(sname, out id)) + { + GridRegion rinfo = null; + if (m_UUIDCache.TryGetValue(id, out rinfo)) + { + inCache = true; + return rinfo; + } + } + + return null; + } + } +} diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs index 33cc838322..6f364ae4c8 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs @@ -53,6 +53,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid private IGridService m_LocalGridService; private IGridService m_RemoteGridService; + private RegionInfoCache m_RegionInfoCache = new RegionInfoCache(); + public RemoteGridServicesConnector() { } @@ -169,10 +171,16 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid public GridRegion GetRegionByUUID(UUID scopeID, UUID regionID) { - GridRegion rinfo = m_LocalGridService.GetRegionByUUID(scopeID, regionID); + bool inCache = false; + GridRegion rinfo = m_RegionInfoCache.Get(scopeID,regionID,out inCache); + if (inCache) + return rinfo; + + rinfo = m_LocalGridService.GetRegionByUUID(scopeID, regionID); if (rinfo == null) rinfo = m_RemoteGridService.GetRegionByUUID(scopeID, regionID); + m_RegionInfoCache.Cache(scopeID,regionID,rinfo); return rinfo; } @@ -187,10 +195,17 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid public GridRegion GetRegionByName(UUID scopeID, string regionName) { - GridRegion rinfo = m_LocalGridService.GetRegionByName(scopeID, regionName); + bool inCache = false; + GridRegion rinfo = m_RegionInfoCache.Get(scopeID,regionName, out inCache); + if (inCache) + return rinfo; + + rinfo = m_LocalGridService.GetRegionByName(scopeID, regionName); if (rinfo == null) rinfo = m_RemoteGridService.GetRegionByName(scopeID, regionName); + // can't cache negative results for name lookups + m_RegionInfoCache.Cache(rinfo); return rinfo; } @@ -204,8 +219,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid { //m_log.DebugFormat("[REMOTE GRID CONNECTOR]: Remote GetRegionsByName {0} found {1} regions", name, grinfo.Count); foreach (GridRegion r in grinfo) + { + m_RegionInfoCache.Cache(r); if (rinfo.Find(delegate(GridRegion gr) { return gr.RegionID == r.RegionID; }) == null) rinfo.Add(r); + } } return rinfo; @@ -221,8 +239,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid { //m_log.DebugFormat("[REMOTE GRID CONNECTOR]: Remote GetRegionRange {0} found {1} regions", name, grinfo.Count); foreach (GridRegion r in grinfo) + { + m_RegionInfoCache.Cache(r); if (rinfo.Find(delegate(GridRegion gr) { return gr.RegionID == r.RegionID; }) == null) rinfo.Add(r); + } } return rinfo; @@ -238,8 +259,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid { //m_log.DebugFormat("[REMOTE GRID CONNECTOR]: Remote GetDefaultRegions {0} found {1} regions", name, grinfo.Count); foreach (GridRegion r in grinfo) + { + m_RegionInfoCache.Cache(r); if (rinfo.Find(delegate(GridRegion gr) { return gr.RegionID == r.RegionID; }) == null) rinfo.Add(r); + } } return rinfo; @@ -255,8 +279,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid { //m_log.DebugFormat("[REMOTE GRID CONNECTOR]: Remote GetFallbackRegions {0} found {1} regions", name, grinfo.Count); foreach (GridRegion r in grinfo) + { + m_RegionInfoCache.Cache(r); if (rinfo.Find(delegate(GridRegion gr) { return gr.RegionID == r.RegionID; }) == null) rinfo.Add(r); + } } return rinfo; @@ -272,8 +299,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid { //m_log.DebugFormat("[REMOTE GRID CONNECTOR]: Remote GetHyperlinks {0} found {1} regions", name, grinfo.Count); foreach (GridRegion r in grinfo) + { + m_RegionInfoCache.Cache(r); if (rinfo.Find(delegate(GridRegion gr) { return gr.RegionID == r.RegionID; }) == null) rinfo.Add(r); + } } return rinfo; diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs index 3f63db371f..698fd569e4 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs @@ -58,6 +58,17 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory private List m_Scenes = new List(); + protected IUserManagement m_UserManagement; + protected IUserManagement UserManagementModule + { + get + { + if (m_UserManagement == null) + m_UserManagement = m_Scenes[0].RequestModuleInterface(); + return m_UserManagement; + } + } + public Type ReplaceableInterface { get { return null; } @@ -207,6 +218,18 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory } } } + if (sp == null) + { + inventoryURL = UserManagementModule.GetUserServerURL(userID, "InventoryServerURI"); + if (inventoryURL != null && inventoryURL != string.Empty) + { + inventoryURL = inventoryURL.Trim(new char[] { '/' }); + m_InventoryURLs.Add(userID, inventoryURL); + m_log.DebugFormat("[HG INVENTORY CONNECTOR]: Added {0} to the cache of inventory URLs", inventoryURL); + } + + } + } } diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs new file mode 100644 index 0000000000..e224670756 --- /dev/null +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs @@ -0,0 +1,242 @@ +/* + * 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.Generic; +using System.Reflection; +using System.Net; +using System.IO; +using System.Timers; +using System.Drawing; +using System.Drawing.Imaging; + +using log4net; +using Mono.Addins; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; +using OpenSim.Server.Base; +using OpenMetaverse; +using OpenMetaverse.StructuredData; + +namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage +{ + /// + /// + /// + /// + + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] + public class MapImageServiceModule : ISharedRegionModule + { + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private bool m_enabled = false; + private IMapImageService m_MapService; + + private string m_serverUrl = String.Empty; + private Dictionary m_scenes = new Dictionary(); + + private int m_refreshtime = 0; + private int m_lastrefresh = 0; + private System.Timers.Timer m_refreshTimer = new System.Timers.Timer(); + + #region ISharedRegionModule + + public Type ReplaceableInterface { get { return null; } } + public string Name { get { return "MapImageServiceModule"; } } + public void RegionLoaded(Scene scene) { } + public void Close() { } + public void PostInitialise() { } + + + /// + /// + /// + public void Initialise(IConfigSource source) + { + IConfig moduleConfig = source.Configs["Modules"]; + if (moduleConfig != null) + { + string name = moduleConfig.GetString("MapImageService", ""); + if (name != Name) + return; + } + + IConfig config = source.Configs["MapImageService"]; + if (config == null) + return; + + int refreshminutes = Convert.ToInt32(config.GetString("RefreshTime")); + if (refreshminutes <= 0) + { + m_log.WarnFormat("[MAP IMAGE SERVICE MODULE]: No refresh time given in config. Module disabled."); + return; + } + + m_refreshtime = refreshminutes * 60 * 1000; // convert from minutes to ms + + string service = config.GetString("LocalServiceModule", string.Empty); + if (service == string.Empty) + { + m_log.WarnFormat("[MAP IMAGE SERVICE MODULE]: No service dll given in config. Unable to proceed."); + return; + } + + Object[] args = new Object[] { source }; + m_MapService = ServerUtils.LoadPlugin(service, args); + if (m_MapService == null) + { + m_log.WarnFormat("[MAP IMAGE SERVICE MODULE]: Unable to load LocalServiceModule from {0}. MapService module disabled. Please fix the configuration.", service); + return; + } + + m_refreshTimer.Enabled = true; + m_refreshTimer.AutoReset = true; + m_refreshTimer.Interval = m_refreshtime; + m_refreshTimer.Elapsed += new ElapsedEventHandler(HandleMaptileRefresh); + + m_log.InfoFormat("[MAP IMAGE SERVICE MODULE]: enabled with refresh time {0}min and service object {1}", + refreshminutes, service); + + m_enabled = true; + } + + /// + /// + /// + + + /// + /// + /// + public void AddRegion(Scene scene) + { + if (! m_enabled) + return; + + // Every shared region module has to maintain an indepedent list of + // currently running regions + lock (m_scenes) + m_scenes[scene.RegionInfo.RegionID] = scene; + + scene.EventManager.OnPrimsLoaded += new EventManager.PrimsLoaded(EventManager_OnPrimsLoaded); + } + + /// + /// + /// + public void RemoveRegion(Scene scene) + { + if (! m_enabled) + return; + + lock (m_scenes) + m_scenes.Remove(scene.RegionInfo.RegionID); + } + + #endregion ISharedRegionModule + + void EventManager_OnPrimsLoaded(Scene s) + { + UploadMapTile(s); + } + + + /// + /// + /// + private void HandleMaptileRefresh(object sender, EventArgs ea) + { + // this approach is a bit convoluted becase we want to wait for the + // first upload to happen on startup but after all the objects are + // loaded and initialized + if (m_lastrefresh > 0 && Util.EnvironmentTickCountSubtract(m_lastrefresh) < m_refreshtime) + return; + + m_log.DebugFormat("[MAP IMAGE SERVICE MODULE]: map refresh!"); + lock (m_scenes) + { + foreach (IScene scene in m_scenes.Values) + { + try + { + UploadMapTile(scene); + } + catch (Exception ex) + { + m_log.WarnFormat("[MAP IMAGE SERVICE MODULE]: something bad happened {0}", ex.Message); + } + } + } + + m_lastrefresh = Util.EnvironmentTickCount(); + } + + /// + /// + /// + private void UploadMapTile(IScene scene) + { + m_log.DebugFormat("[MAP IMAGE SERVICE MODULE]: upload maptile for {0}", scene.RegionInfo.RegionName); + + // Create a JPG map tile and upload it to the AddMapTile API + byte[] jpgData = Utils.EmptyBytes; + IMapImageGenerator tileGenerator = scene.RequestModuleInterface(); + if (tileGenerator == null) + { + m_log.Warn("[MAP IMAGE SERVICE MODULE]: Cannot upload PNG map tile without an ImageGenerator"); + return; + } + + using (Image mapTile = tileGenerator.CreateMapTile()) + { + using (MemoryStream stream = new MemoryStream()) + { + mapTile.Save(stream, ImageFormat.Jpeg); + jpgData = stream.ToArray(); + } + } + + if (jpgData == Utils.EmptyBytes) + { + m_log.WarnFormat("[MAP IMAGE SERVICE MODULE]: Tile image generation failed"); + return; + } + + string reason = string.Empty; + if (!m_MapService.AddMapTile((int)scene.RegionInfo.RegionLocX, (int)scene.RegionInfo.RegionLocY, jpgData, out reason)) + { + m_log.DebugFormat("[MAP IMAGE SERVICE MODULE]: Unable to upload tile image for {0} at {1}-{2}: {3}", + scene.RegionInfo.RegionName, scene.RegionInfo.RegionLocX, scene.RegionInfo.RegionLocY, reason); + } + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs index d11d6775af..f85a91701c 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs @@ -506,6 +506,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver currentRegionSettings.Elevation2SE = loadedRegionSettings.Elevation2SE; currentRegionSettings.Elevation2SW = loadedRegionSettings.Elevation2SW; currentRegionSettings.FixedSun = loadedRegionSettings.FixedSun; + currentRegionSettings.SunPosition = loadedRegionSettings.SunPosition; currentRegionSettings.ObjectBonus = loadedRegionSettings.ObjectBonus; currentRegionSettings.RestrictPushing = loadedRegionSettings.RestrictPushing; currentRegionSettings.TerrainLowerLimit = loadedRegionSettings.TerrainLowerLimit; @@ -518,6 +519,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver currentRegionSettings.WaterHeight = loadedRegionSettings.WaterHeight; currentRegionSettings.Save(); + + m_scene.TriggerEstateSunUpdate(); IEstateModule estateModule = m_scene.RequestModuleInterface(); diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs index 5da165666d..f8f3713f8f 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs @@ -198,11 +198,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver m_log.ErrorFormat( "[ARCHIVER]: (... {0} more not shown)", uuids.Count - MAX_UUID_DISPLAY_ON_TIMEOUT); - m_log.Error("[ARCHIVER]: OAR save aborted. PLEASE DO NOT USE THIS OAR, IT WILL BE INCOMPLETE."); + m_log.Error("[ARCHIVER]: Archive save aborted. PLEASE DO NOT USE THIS ARCHIVE, IT WILL BE INCOMPLETE."); } catch (Exception e) { - m_log.ErrorFormat("[ARCHIVER]: Timeout handler exception {0}", e); + m_log.ErrorFormat("[ARCHIVER]: Timeout handler exception {0}{1}", e.Message, e.StackTrace); } finally { @@ -230,6 +230,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// public void AssetRequestCallback(string id, object sender, AssetBase asset) { + Culture.SetCurrentCulture(); + try { lock (this) @@ -289,6 +291,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// protected void PerformAssetsRequestCallback(object o) { + Culture.SetCurrentCulture(); + try { m_assetsRequestCallback(m_foundAssetUuids, m_notFoundAssetUuids); diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs index 34e2e23a01..6ba3459747 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs @@ -440,6 +440,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests rs.Elevation2SE = 9.2; rs.Elevation2SW = 2.1; rs.FixedSun = true; + rs.SunPosition = 12.0; rs.ObjectBonus = 1.4; rs.RestrictPushing = true; rs.TerrainLowerLimit = 0.4; @@ -485,6 +486,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests Assert.That(loadedRs.Elevation2SE, Is.EqualTo(9.2)); Assert.That(loadedRs.Elevation2SW, Is.EqualTo(2.1)); Assert.That(loadedRs.FixedSun, Is.True); + Assert.AreEqual(12.0, loadedRs.SunPosition); Assert.That(loadedRs.ObjectBonus, Is.EqualTo(1.4)); Assert.That(loadedRs.RestrictPushing, Is.True); Assert.That(loadedRs.TerrainLowerLimit, Is.EqualTo(0.4)); diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs index a098ff6078..43b37c7d35 100644 --- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs +++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs @@ -548,18 +548,18 @@ namespace OpenSim.Region.CoreModules.World.Permissions // libomv will moan about PrimFlags.ObjectYouOfficer being // deprecated - #pragma warning disable 0612 +#pragma warning disable 0612 objflags &= (uint) ~(PrimFlags.ObjectCopy | // Tells client you can copy the object - PrimFlags.ObjectModify | // tells client you can modify the object - PrimFlags.ObjectMove | // tells client that you can move the object (only, no mod) - PrimFlags.ObjectTransfer | // tells the client that you can /take/ the object if you don't own it - PrimFlags.ObjectYouOwner | // Tells client that you're the owner of the object - PrimFlags.ObjectAnyOwner | // Tells client that someone owns the object - PrimFlags.ObjectOwnerModify | // Tells client that you're the owner of the object - PrimFlags.ObjectYouOfficer // Tells client that you've got group object editing permission. Used when ObjectGroupOwned is set + PrimFlags.ObjectModify | // tells client you can modify the object + PrimFlags.ObjectMove | // tells client that you can move the object (only, no mod) + PrimFlags.ObjectTransfer | // tells the client that you can /take/ the object if you don't own it + PrimFlags.ObjectYouOwner | // Tells client that you're the owner of the object + PrimFlags.ObjectAnyOwner | // Tells client that someone owns the object + PrimFlags.ObjectOwnerModify | // Tells client that you're the owner of the object + PrimFlags.ObjectYouOfficer // Tells client that you've got group object editing permission. Used when ObjectGroupOwned is set ); - #pragma warning restore 0612 +#pragma warning restore 0612 // Creating the three ObjectFlags options for this method to choose from. // Customize the OwnerMask @@ -576,22 +576,27 @@ namespace OpenSim.Region.CoreModules.World.Permissions if (m_bypassPermissions) return objectOwnerMask; - + // Object owners should be able to edit their own content if (user == objectOwner) return objectOwnerMask; - - if (IsFriendWithPerms(user, objectOwner)) - return objectOwnerMask; + if (IsFriendWithPerms(user, objectOwner)) + { + return objectOwnerMask; + } // Estate users should be able to edit anything in the sim if RegionOwnerIsGod is set if (m_RegionOwnerIsGod && IsEstateManager(user) && !IsAdministrator(objectOwner)) + { return objectOwnerMask; + } // Admin should be able to edit anything in the sim (including admin objects) if (IsAdministrator(user)) + { return objectOwnerMask; - + } + // Users should be able to edit what is over their land. Vector3 taskPos = task.AbsolutePosition; ILandObject parcel = m_scene.LandChannel.GetLandObject(taskPos.X, taskPos.Y); @@ -599,13 +604,15 @@ namespace OpenSim.Region.CoreModules.World.Permissions { // Admin objects should not be editable by the above if (!IsAdministrator(objectOwner)) + { return objectOwnerMask; + } } // Group permissions if ((task.GroupID != UUID.Zero) && IsGroupMember(task.GroupID, user, 0)) return objectGroupMask | objectEveryoneMask; - + return objectEveryoneMask; } @@ -673,7 +680,6 @@ namespace OpenSim.Region.CoreModules.World.Permissions // // Nobody but the object owner can set permissions on an object // - if (locked && (!IsAdministrator(currentUser)) && denyOnLocked) { return false; @@ -704,6 +710,11 @@ namespace OpenSim.Region.CoreModules.World.Permissions // Return immediately, so that the administrator can shares group objects return true; } + + // Friends with benefits should be able to edit the objects too + if (IsFriendWithPerms(currentUser, objectOwner)) + // Return immediately, so that the administrator can share objects with friends + return true; // Users should be able to edit what is over their land. ILandObject parcel = m_scene.LandChannel.GetLandObject(group.AbsolutePosition.X, group.AbsolutePosition.Y); diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/MapImageModule.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/MapImageModule.cs index 6eb57eb424..6163fd12fe 100644 --- a/OpenSim/Region/CoreModules/World/Warp3DMap/MapImageModule.cs +++ b/OpenSim/Region/CoreModules/World/Warp3DMap/MapImageModule.cs @@ -52,7 +52,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap public class Warp3DImageModule : IMapImageGenerator, INonSharedRegionModule { private static readonly UUID TEXTURE_METADATA_MAGIC = new UUID("802dc0e0-f080-4931-8b57-d1be8611c4f3"); - private static readonly Color4 WATER_COLOR = new Color4(29, 71, 95, 216); + private static readonly Color4 WATER_COLOR = new Color4(29, 72, 96, 216); private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -61,7 +61,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap private IRendering m_primMesher; private IConfigSource m_config; private Dictionary m_colors = new Dictionary(); - private bool m_useAntiAliasing = true; // TODO: Make this a config option + private bool m_useAntiAliasing = false; // TODO: Make this a config option private bool m_Enabled = false; #region IRegionModule Members @@ -192,8 +192,8 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap #endregion Camera - renderer.Scene.addLight("Light1", new warp_Light(new warp_Vector(0.2f, 0.2f, 1f), 0xffffff, 320, 80)); - renderer.Scene.addLight("Light2", new warp_Light(new warp_Vector(-1f, -1f, 1f), 0xffffff, 100, 40)); + renderer.Scene.addLight("Light1", new warp_Light(new warp_Vector(1.0f, 0.5f, 1f), 0xffffff, 0, 320, 40)); + renderer.Scene.addLight("Light2", new warp_Light(new warp_Vector(-1f, -1f, 1f), 0xffffff, 0, 100, 40)); CreateWater(renderer); CreateTerrain(renderer, textureTerrain); @@ -237,6 +237,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap renderer.Scene.sceneobject("Water").setPos(127.5f, waterHeight, 127.5f); renderer.AddMaterial("WaterColor", ConvertColor(WATER_COLOR)); + renderer.Scene.material("WaterColor").setReflectivity(0); // match water color with standard map module thanks lkalif renderer.Scene.material("WaterColor").setTransparency((byte)((1f - WATER_COLOR.A) * 255f)); renderer.SetObjectMaterial("Water", "WaterColor"); } @@ -322,6 +323,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap warp_Material material = new warp_Material(texture); material.setReflectivity(50); renderer.Scene.addMaterial("TerrainColor", material); + renderer.Scene.material("TerrainColor").setReflectivity(0); // reduces tile seams a bit thanks lkalif renderer.SetObjectMaterial("Terrain", "TerrainColor"); } @@ -653,4 +655,4 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap return result; } } -} +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs index cd40c5d477..ca5529d93b 100644 --- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs +++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs @@ -208,52 +208,65 @@ namespace OpenSim.Region.CoreModules.World.WorldMap //m_log.DebugFormat("[MAPLAYER]: path: {0}, param: {1}, agent:{2}", // path, param, agentID.ToString()); - // this is here because CAPS map requests work even beyond the 10,000 limit. - ScenePresence avatarPresence = null; + // There is a major hack going on in this method. The viewer doesn't request + // map blocks (RequestMapBlocks) above 2048. That means that if we don't hack, + // grids above that cell don't have a map at all. So, here's the hack: we wait + // for this CAP request to come, and we inject the map blocks at this point. + // In a normal scenario, this request simply sends back the MapLayer (the blue color). + // In the hacked scenario, it also sends the map blocks via UDP. + // + // 6/8/2011 -- I'm adding an explicit 2048 check, so that we never forget that there is + // a hack here, and so that regions below 4096 don't get spammed with unnecessary map blocks. - m_scene.TryGetScenePresence(agentID, out avatarPresence); - - if (avatarPresence != null) + if (m_scene.RegionInfo.RegionLocX >= 2048 || m_scene.RegionInfo.RegionLocY >= 2048) { - bool lookup = false; + ScenePresence avatarPresence = null; - lock (cachedMapBlocks) + m_scene.TryGetScenePresence(agentID, out avatarPresence); + + if (avatarPresence != null) { - if (cachedMapBlocks.Count > 0 && ((cachedTime + 1800) > Util.UnixTimeSinceEpoch())) - { - List mapBlocks; - - mapBlocks = cachedMapBlocks; - avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0); - } - else - { - lookup = true; - } - } - if (lookup) - { - List mapBlocks = new List(); ; - - List regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, - (int)(m_scene.RegionInfo.RegionLocX - 8) * (int)Constants.RegionSize, - (int)(m_scene.RegionInfo.RegionLocX + 8) * (int)Constants.RegionSize, - (int)(m_scene.RegionInfo.RegionLocY - 8) * (int)Constants.RegionSize, - (int)(m_scene.RegionInfo.RegionLocY + 8) * (int)Constants.RegionSize); - foreach (GridRegion r in regions) - { - MapBlockData block = new MapBlockData(); - MapBlockFromGridRegion(block, r); - mapBlocks.Add(block); - } - avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0); + bool lookup = false; lock (cachedMapBlocks) - cachedMapBlocks = mapBlocks; + { + if (cachedMapBlocks.Count > 0 && ((cachedTime + 1800) > Util.UnixTimeSinceEpoch())) + { + List mapBlocks; - cachedTime = Util.UnixTimeSinceEpoch(); + mapBlocks = cachedMapBlocks; + avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0); + } + else + { + lookup = true; + } + } + if (lookup) + { + List mapBlocks = new List(); ; + + List regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, + (int)(m_scene.RegionInfo.RegionLocX - 8) * (int)Constants.RegionSize, + (int)(m_scene.RegionInfo.RegionLocX + 8) * (int)Constants.RegionSize, + (int)(m_scene.RegionInfo.RegionLocY - 8) * (int)Constants.RegionSize, + (int)(m_scene.RegionInfo.RegionLocY + 8) * (int)Constants.RegionSize); + foreach (GridRegion r in regions) + { + MapBlockData block = new MapBlockData(); + MapBlockFromGridRegion(block, r); + mapBlocks.Add(block); + } + avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0); + + lock (cachedMapBlocks) + cachedMapBlocks = mapBlocks; + + cachedTime = Util.UnixTimeSinceEpoch(); + } } } + LLSDMapLayerResponse mapResponse = new LLSDMapLayerResponse(); mapResponse.LayerData.Array.Add(GetOSDMapLayerResponse()); return mapResponse.ToString(); @@ -823,7 +836,10 @@ namespace OpenSim.Region.CoreModules.World.WorldMap block.Access = 254; // means 'simulator is offline' response.Add(block); } - remoteClient.SendMapBlock(response, 0); + if ((flag & 2) == 2) // V2 !!! + remoteClient.SendMapBlock(response, 2); + else + remoteClient.SendMapBlock(response, 0); } else { @@ -832,7 +848,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap } } - protected virtual void GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) + protected virtual List GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) { List mapBlocks = new List(); List regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, @@ -846,7 +862,12 @@ namespace OpenSim.Region.CoreModules.World.WorldMap MapBlockFromGridRegion(block, r); mapBlocks.Add(block); } - remoteClient.SendMapBlock(mapBlocks, 0); + if ((flag & 2) == 2) // V2 !!! + remoteClient.SendMapBlock(mapBlocks, 2); + else + remoteClient.SendMapBlock(mapBlocks, 0); + + return mapBlocks; } protected void MapBlockFromGridRegion(MapBlockData block, GridRegion r) diff --git a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs index b3bdff3949..cdce36eda7 100644 --- a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs +++ b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs @@ -540,7 +540,7 @@ namespace OpenSim.Region.Examples.SimpleModule { } - public virtual void SendDialog(string objectname, UUID objectID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch, string[] buttonlabels) + public virtual void SendDialog(string objectname, UUID objectID, UUID ownerID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch, string[] buttonlabels) { } diff --git a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs index 3eb38b883e..c38ecd9baa 100644 --- a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs @@ -42,6 +42,9 @@ namespace OpenSim.Region.Framework.Interfaces bool TeleportHome(UUID id, IClientAPI client); + void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination, + Vector3 position, Vector3 lookAt, uint teleportFlags, IEventQueue eq); + bool Cross(ScenePresence agent, bool isFlying); void AgentArrivedAtDestination(UUID agent); diff --git a/OpenSim/Region/Framework/Interfaces/IFriendsModule.cs b/OpenSim/Region/Framework/Interfaces/IFriendsModule.cs index 0ff7deeb30..d4a6857188 100644 --- a/OpenSim/Region/Framework/Interfaces/IFriendsModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IFriendsModule.cs @@ -34,6 +34,6 @@ namespace OpenSim.Region.Framework.Interfaces public interface IFriendsModule { uint GetFriendPerms(UUID PrincipalID, UUID FriendID); - void SendFriendsOnlineIfNeeded(IClientAPI client); + bool SendFriendsOnlineIfNeeded(IClientAPI client); } } diff --git a/OpenSim/Region/Framework/Interfaces/IUserManagement.cs b/OpenSim/Region/Framework/Interfaces/IUserManagement.cs index 2904ee87dc..5d30aa8e24 100644 --- a/OpenSim/Region/Framework/Interfaces/IUserManagement.cs +++ b/OpenSim/Region/Framework/Interfaces/IUserManagement.cs @@ -8,6 +8,9 @@ namespace OpenSim.Region.Framework.Interfaces public interface IUserManagement { string GetUserName(UUID uuid); + string GetUserHomeURL(UUID uuid); + string GetUserUUI(UUID uuid); + string GetUserServerURL(UUID uuid, string serverType); void AddUser(UUID uuid, string userData); void AddUser(UUID uuid, string firstName, string lastName, string profileURL); } diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index d326141016..3ec4e59f1b 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -393,6 +393,12 @@ namespace OpenSim.Region.Framework.Scenes public delegate void RegionUp(GridRegion region); public event RegionUp OnRegionUp; + public delegate void LoginsEnabled(string regionName); + public event LoginsEnabled OnLoginsEnabled; + + public delegate void PrimsLoaded(Scene s); + public event PrimsLoaded OnPrimsLoaded; + public class MoneyTransferArgs : EventArgs { public UUID sender; @@ -2242,5 +2248,47 @@ namespace OpenSim.Region.Framework.Scenes } } } + + public void TriggerLoginsEnabled (string regionName) + { + LoginsEnabled handler = OnLoginsEnabled; + + if ( handler != null) + { + foreach (LoginsEnabled d in handler.GetInvocationList()) + { + try + { + d(regionName); + } + catch (Exception e) + { + m_log.ErrorFormat("[EVENT MANAGER]: Delegate for LoginsEnabled failed - continuing {0} - {1}", + e.Message, e.StackTrace); + } + } + } + } + + public void TriggerPrimsLoaded(Scene s) + { + PrimsLoaded handler = OnPrimsLoaded; + + if (handler != null) + { + foreach (PrimsLoaded d in handler.GetInvocationList()) + { + try + { + d(s); + } + catch (Exception e) + { + m_log.ErrorFormat("[EVENT MANAGER]: Delegate for PrimsLoaded failed - continuing {0} - {1}", + e.Message, e.StackTrace); + } + } + } + } } } diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 0b928180d4..c04bbb4c5a 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -408,192 +408,198 @@ namespace OpenSim.Region.Framework.Scenes InventoryItemBase item = new InventoryItemBase(itemId, senderId); item = InventoryService.GetItem(item); - if ((item != null) && (item.Owner == senderId)) + if (item == null) { - IUserManagement uman = RequestModuleInterface(); - if (uman != null) - uman.AddUser(item.CreatorIdAsUuid, item.CreatorData); - - if (!Permissions.BypassPermissions()) - { - if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0) - return null; - } - - // Insert a copy of the item into the recipient - InventoryItemBase itemCopy = new InventoryItemBase(); - itemCopy.Owner = recipient; - itemCopy.CreatorId = item.CreatorId; - itemCopy.CreatorData = item.CreatorData; - itemCopy.ID = UUID.Random(); - itemCopy.AssetID = item.AssetID; - itemCopy.Description = item.Description; - itemCopy.Name = item.Name; - itemCopy.AssetType = item.AssetType; - itemCopy.InvType = item.InvType; - itemCopy.Folder = recipientFolderId; - - if (Permissions.PropagatePermissions() && recipient != senderId) - { - // Trying to do this right this time. This is evil. If - // you believe in Good, go elsewhere. Vampires and other - // evil creatores only beyond this point. You have been - // warned. - - // We're going to mask a lot of things by the next perms - // Tweak the next perms to be nicer to our data - // - // In this mask, all the bits we do NOT want to mess - // with are set. These are: - // - // Transfer - // Copy - // Modufy - uint permsMask = ~ ((uint)PermissionMask.Copy | - (uint)PermissionMask.Transfer | - (uint)PermissionMask.Modify); - - // Now, reduce the next perms to the mask bits - // relevant to the operation - uint nextPerms = permsMask | (item.NextPermissions & - ((uint)PermissionMask.Copy | - (uint)PermissionMask.Transfer | - (uint)PermissionMask.Modify)); - - // nextPerms now has all bits set, except for the actual - // next permission bits. - - // This checks for no mod, no copy, no trans. - // This indicates an error or messed up item. Do it like - // SL and assume trans - if (nextPerms == permsMask) - nextPerms |= (uint)PermissionMask.Transfer; - - // Inventory owner perms are the logical AND of the - // folded perms and the root prim perms, however, if - // the root prim is mod, the inventory perms will be - // mod. This happens on "take" and is of little concern - // here, save for preventing escalation - - // This hack ensures that items previously permalocked - // get unlocked when they're passed or rezzed - uint basePerms = item.BasePermissions | - (uint)PermissionMask.Move; - uint ownerPerms = item.CurrentPermissions; - - // If this is an object, root prim perms may be more - // permissive than folded perms. Use folded perms as - // a mask - if (item.InvType == (int)InventoryType.Object) - { - // Create a safe mask for the current perms - uint foldedPerms = (item.CurrentPermissions & 7) << 13; - foldedPerms |= permsMask; - - bool isRootMod = (item.CurrentPermissions & - (uint)PermissionMask.Modify) != 0 ? - true : false; - - // Mask the owner perms to the folded perms - ownerPerms &= foldedPerms; - basePerms &= foldedPerms; - - // If the root was mod, let the mask reflect that - // We also need to adjust the base here, because - // we should be able to edit in-inventory perms - // for the root prim, if it's mod. - if (isRootMod) - { - ownerPerms |= (uint)PermissionMask.Modify; - basePerms |= (uint)PermissionMask.Modify; - } - } - - // These will be applied to the root prim at next rez. - // The slam bit (bit 3) and folded permission (bits 0-2) - // are preserved due to the above mangling - ownerPerms &= nextPerms; - - // Mask the base permissions. This is a conservative - // approach altering only the three main perms - basePerms &= nextPerms; - - // Assign to the actual item. Make sure the slam bit is - // set, if it wasn't set before. - itemCopy.BasePermissions = basePerms; - itemCopy.CurrentPermissions = ownerPerms; - itemCopy.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm; - - itemCopy.NextPermissions = item.NextPermissions; - - // This preserves "everyone can move" - itemCopy.EveryOnePermissions = item.EveryOnePermissions & - nextPerms; - - // Intentionally killing "share with group" here, as - // the recipient will not have the group this is - // set to - itemCopy.GroupPermissions = 0; - } - else - { - itemCopy.CurrentPermissions = item.CurrentPermissions; - itemCopy.NextPermissions = item.NextPermissions; - itemCopy.EveryOnePermissions = item.EveryOnePermissions & item.NextPermissions; - itemCopy.GroupPermissions = item.GroupPermissions & item.NextPermissions; - itemCopy.BasePermissions = item.BasePermissions; - } - - if (itemCopy.Folder == UUID.Zero) - { - InventoryFolderBase folder = InventoryService.GetFolderForType(recipient, (AssetType)itemCopy.AssetType); - - if (folder != null) - { - itemCopy.Folder = folder.ID; - } - else - { - InventoryFolderBase root = InventoryService.GetRootFolder(recipient); - - if (root != null) - itemCopy.Folder = root.ID; - else - return null; // No destination - } - } - - itemCopy.GroupID = UUID.Zero; - itemCopy.GroupOwned = false; - itemCopy.Flags = item.Flags; - itemCopy.SalePrice = item.SalePrice; - itemCopy.SaleType = item.SaleType; - - if (AddInventoryItem(itemCopy)) - { - IInventoryAccessModule invAccess = RequestModuleInterface(); - if (invAccess != null) - invAccess.TransferInventoryAssets(itemCopy, senderId, recipient); - } - - if (!Permissions.BypassPermissions()) - { - if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) - { - List items = new List(); - items.Add(itemId); - InventoryService.DeleteItems(senderId, items); - } - } - - return itemCopy; - } - else - { - m_log.WarnFormat("[AGENT INVENTORY]: Failed to find item {0} or item does not belong to giver ", itemId); + m_log.WarnFormat( + "[AGENT INVENTORY]: Failed to find item {0} sent by {1} to {2}", itemId, senderId, recipient); return null; } + if (item.Owner != senderId) + { + m_log.WarnFormat( + "[AGENT INVENTORY]: Attempt to send item {0} {1} to {2} failed because sender {3} did not match item owner {4}", + item.Name, item.ID, recipient, senderId, item.Owner); + return null; + } + + IUserManagement uman = RequestModuleInterface(); + if (uman != null) + uman.AddUser(item.CreatorIdAsUuid, item.CreatorData); + + if (!Permissions.BypassPermissions()) + { + if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0) + return null; + } + + // Insert a copy of the item into the recipient + InventoryItemBase itemCopy = new InventoryItemBase(); + itemCopy.Owner = recipient; + itemCopy.CreatorId = item.CreatorId; + itemCopy.CreatorData = item.CreatorData; + itemCopy.ID = UUID.Random(); + itemCopy.AssetID = item.AssetID; + itemCopy.Description = item.Description; + itemCopy.Name = item.Name; + itemCopy.AssetType = item.AssetType; + itemCopy.InvType = item.InvType; + itemCopy.Folder = recipientFolderId; + + if (Permissions.PropagatePermissions() && recipient != senderId) + { + // Trying to do this right this time. This is evil. If + // you believe in Good, go elsewhere. Vampires and other + // evil creatores only beyond this point. You have been + // warned. + + // We're going to mask a lot of things by the next perms + // Tweak the next perms to be nicer to our data + // + // In this mask, all the bits we do NOT want to mess + // with are set. These are: + // + // Transfer + // Copy + // Modufy + uint permsMask = ~ ((uint)PermissionMask.Copy | + (uint)PermissionMask.Transfer | + (uint)PermissionMask.Modify); + + // Now, reduce the next perms to the mask bits + // relevant to the operation + uint nextPerms = permsMask | (item.NextPermissions & + ((uint)PermissionMask.Copy | + (uint)PermissionMask.Transfer | + (uint)PermissionMask.Modify)); + + // nextPerms now has all bits set, except for the actual + // next permission bits. + + // This checks for no mod, no copy, no trans. + // This indicates an error or messed up item. Do it like + // SL and assume trans + if (nextPerms == permsMask) + nextPerms |= (uint)PermissionMask.Transfer; + + // Inventory owner perms are the logical AND of the + // folded perms and the root prim perms, however, if + // the root prim is mod, the inventory perms will be + // mod. This happens on "take" and is of little concern + // here, save for preventing escalation + + // This hack ensures that items previously permalocked + // get unlocked when they're passed or rezzed + uint basePerms = item.BasePermissions | + (uint)PermissionMask.Move; + uint ownerPerms = item.CurrentPermissions; + + // If this is an object, root prim perms may be more + // permissive than folded perms. Use folded perms as + // a mask + if (item.InvType == (int)InventoryType.Object) + { + // Create a safe mask for the current perms + uint foldedPerms = (item.CurrentPermissions & 7) << 13; + foldedPerms |= permsMask; + + bool isRootMod = (item.CurrentPermissions & + (uint)PermissionMask.Modify) != 0 ? + true : false; + + // Mask the owner perms to the folded perms + ownerPerms &= foldedPerms; + basePerms &= foldedPerms; + + // If the root was mod, let the mask reflect that + // We also need to adjust the base here, because + // we should be able to edit in-inventory perms + // for the root prim, if it's mod. + if (isRootMod) + { + ownerPerms |= (uint)PermissionMask.Modify; + basePerms |= (uint)PermissionMask.Modify; + } + } + + // These will be applied to the root prim at next rez. + // The slam bit (bit 3) and folded permission (bits 0-2) + // are preserved due to the above mangling + ownerPerms &= nextPerms; + + // Mask the base permissions. This is a conservative + // approach altering only the three main perms + basePerms &= nextPerms; + + // Assign to the actual item. Make sure the slam bit is + // set, if it wasn't set before. + itemCopy.BasePermissions = basePerms; + itemCopy.CurrentPermissions = ownerPerms; + itemCopy.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm; + + itemCopy.NextPermissions = item.NextPermissions; + + // This preserves "everyone can move" + itemCopy.EveryOnePermissions = item.EveryOnePermissions & + nextPerms; + + // Intentionally killing "share with group" here, as + // the recipient will not have the group this is + // set to + itemCopy.GroupPermissions = 0; + } + else + { + itemCopy.CurrentPermissions = item.CurrentPermissions; + itemCopy.NextPermissions = item.NextPermissions; + itemCopy.EveryOnePermissions = item.EveryOnePermissions & item.NextPermissions; + itemCopy.GroupPermissions = item.GroupPermissions & item.NextPermissions; + itemCopy.BasePermissions = item.BasePermissions; + } + + if (itemCopy.Folder == UUID.Zero) + { + InventoryFolderBase folder = InventoryService.GetFolderForType(recipient, (AssetType)itemCopy.AssetType); + + if (folder != null) + { + itemCopy.Folder = folder.ID; + } + else + { + InventoryFolderBase root = InventoryService.GetRootFolder(recipient); + + if (root != null) + itemCopy.Folder = root.ID; + else + return null; // No destination + } + } + + itemCopy.GroupID = UUID.Zero; + itemCopy.GroupOwned = false; + itemCopy.Flags = item.Flags; + itemCopy.SalePrice = item.SalePrice; + itemCopy.SaleType = item.SaleType; + + if (AddInventoryItem(itemCopy)) + { + IInventoryAccessModule invAccess = RequestModuleInterface(); + if (invAccess != null) + invAccess.TransferInventoryAssets(itemCopy, senderId, recipient); + } + + if (!Permissions.BypassPermissions()) + { + if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) + { + List items = new List(); + items.Add(itemId); + InventoryService.DeleteItems(senderId, items); + } + } + + return itemCopy; } /// @@ -781,7 +787,7 @@ namespace OpenSim.Region.Framework.Scenes /// /// /// - private void CreateNewInventoryItem(IClientAPI remoteClient, string creatorID, string creatorData, UUID folderID, string name, uint flags, uint callbackID, + public void CreateNewInventoryItem(IClientAPI remoteClient, string creatorID, string creatorData, UUID folderID, string name, uint flags, uint callbackID, AssetBase asset, sbyte invType, uint nextOwnerMask, int creationDate) { CreateNewInventoryItem( @@ -835,78 +841,6 @@ namespace OpenSim.Region.Framework.Scenes } } - /// - /// Create a new inventory item. Called when the client creates a new item directly within their - /// inventory (e.g. by selecting a context inventory menu option). - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - public void CreateNewInventoryItem(IClientAPI remoteClient, UUID transactionID, UUID folderID, - uint callbackID, string description, string name, sbyte invType, - sbyte assetType, - byte wearableType, uint nextOwnerMask, int creationDate) - { - m_log.DebugFormat("[AGENT INVENTORY]: Received request to create inventory item {0} in folder {1}", name, folderID); - - if (!Permissions.CanCreateUserInventory(invType, remoteClient.AgentId)) - return; - - InventoryFolderBase f = new InventoryFolderBase(folderID, remoteClient.AgentId); - InventoryFolderBase folder = InventoryService.GetFolder(f); - - if (folder == null || folder.Owner != remoteClient.AgentId) - return; - - if (transactionID == UUID.Zero) - { - ScenePresence presence; - if (TryGetScenePresence(remoteClient.AgentId, out presence)) - { - byte[] data = null; - - if (invType == (sbyte)InventoryType.Landmark && presence != null) - { - Vector3 pos = presence.AbsolutePosition; - string strdata = String.Format( - "Landmark version 2\nregion_id {0}\nlocal_pos {1} {2} {3}\nregion_handle {4}\n", - presence.Scene.RegionInfo.RegionID, - pos.X, pos.Y, pos.Z, - presence.RegionHandle); - data = Encoding.ASCII.GetBytes(strdata); - } - - AssetBase asset = CreateAsset(name, description, assetType, data, remoteClient.AgentId); - AssetService.Store(asset); - - CreateNewInventoryItem(remoteClient, remoteClient.AgentId.ToString(), string.Empty, folderID, asset.Name, 0, callbackID, asset, invType, nextOwnerMask, creationDate); - } - else - { - m_log.ErrorFormat( - "ScenePresence for agent uuid {0} unexpectedly not found in CreateNewInventoryItem", - remoteClient.AgentId); - } - } - else - { - IAgentAssetTransactions agentTransactions = this.RequestModuleInterface(); - if (agentTransactions != null) - { - agentTransactions.HandleItemCreationFromTransaction( - remoteClient, transactionID, folderID, callbackID, description, - name, invType, assetType, wearableType, nextOwnerMask); - } - } - } - /// /// Link an inventory item to an existing item. /// diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 254ad055b2..1575e50fda 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -95,7 +95,10 @@ namespace OpenSim.Region.Framework.Scenes public bool m_strictAccessControl = true; public bool m_seeIntoBannedRegion = false; public int MaxUndoCount = 5; + // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet; + public bool LoginLock = false; public bool LoginsDisabled = true; + public bool StartDisabled = false; public bool LoadingPrims; public IXfer XferManager; @@ -1399,10 +1402,26 @@ namespace OpenSim.Region.Framework.Scenes IConfig startupConfig = m_config.Configs["Startup"]; if (startupConfig == null || !startupConfig.GetBoolean("StartDisabled", false)) { + // This handles a case of a region having no scripts for the RegionReady module + if (m_sceneGraph.GetActiveScriptsCount() == 0) + { + // need to be able to tell these have changed in RegionReady + LoginLock = false; + EventManager.TriggerLoginsEnabled(RegionInfo.RegionName); + } m_log.DebugFormat("[REGION]: Enabling logins for {0}", RegionInfo.RegionName); - LoginsDisabled = false; + // For RegionReady lockouts + if( LoginLock == false) + { + LoginsDisabled = false; + } m_sceneGridService.InformNeighborsThatRegionisUp(RequestModuleInterface(), RegionInfo); } + else + { + StartDisabled = true; + LoginsDisabled = true; + } } } catch (NotImplementedException) @@ -1765,6 +1784,7 @@ namespace OpenSim.Region.Framework.Scenes m_log.Info("[SCENE]: Loaded " + PrimsFromDB.Count.ToString() + " SceneObject(s)"); LoadingPrims = false; + EventManager.TriggerPrimsLoaded(this); } @@ -1930,6 +1950,10 @@ namespace OpenSim.Region.Framework.Scenes sceneObject.SetGroup(groupID, null); } + IUserManagement uman = RequestModuleInterface(); + if (uman != null) + sceneObject.RootPart.CreatorIdentification = uman.GetUserUUI(ownerID); + sceneObject.ScheduleGroupForFullUpdate(); return sceneObject; @@ -2658,6 +2682,10 @@ namespace OpenSim.Region.Framework.Scenes if (TryGetScenePresence(client.AgentId, out presence)) { m_LastLogin = Util.EnvironmentTickCount(); + + // Cache the user's name + CacheUserName(aCircuit); + EventManager.TriggerOnNewClient(client); if (vialogin) { @@ -2671,6 +2699,28 @@ namespace OpenSim.Region.Framework.Scenes } } + private void CacheUserName(AgentCircuitData aCircuit) + { + IUserManagement uMan = RequestModuleInterface(); + if (uMan != null) + { + string homeURL = string.Empty; + string first = aCircuit.firstname, last = aCircuit.lastname; + if (aCircuit.ServiceURLs.ContainsKey("HomeURI")) + homeURL = aCircuit.ServiceURLs["HomeURI"].ToString(); + if (aCircuit.lastname.StartsWith("@")) + { + string[] parts = aCircuit.firstname.Split('.'); + if (parts.Length >= 2) + { + first = parts[0]; + last = parts[1]; + } + } + uMan.AddUser(aCircuit.AgentID, first, last, homeURL); + } + } + private bool VerifyClient(AgentCircuitData aCircuit, System.Net.IPEndPoint ep, out bool vialogin) { vialogin = false; @@ -2813,7 +2863,7 @@ namespace OpenSim.Region.Framework.Scenes public virtual void SubscribeToClientInventoryEvents(IClientAPI client) { - client.OnCreateNewInventoryItem += CreateNewInventoryItem; + client.OnLinkInventoryItem += HandleLinkInventoryItem; client.OnCreateNewInventoryFolder += HandleCreateInventoryFolder; client.OnUpdateInventoryFolder += HandleUpdateInventoryFolder; @@ -2837,7 +2887,6 @@ namespace OpenSim.Region.Framework.Scenes public virtual void SubscribeToClientTeleportEvents(IClientAPI client) { client.OnTeleportLocationRequest += RequestTeleportLocation; - client.OnTeleportLandmarkRequest += RequestTeleportLandmark; } public virtual void SubscribeToClientScriptEvents(IClientAPI client) @@ -2941,7 +2990,7 @@ namespace OpenSim.Region.Framework.Scenes public virtual void UnSubscribeToClientInventoryEvents(IClientAPI client) { - client.OnCreateNewInventoryItem -= CreateNewInventoryItem; + client.OnCreateNewInventoryFolder -= HandleCreateInventoryFolder; client.OnUpdateInventoryFolder -= HandleUpdateInventoryFolder; client.OnMoveInventoryFolder -= HandleMoveInventoryFolder; // 2; //!! @@ -2963,7 +3012,7 @@ namespace OpenSim.Region.Framework.Scenes public virtual void UnSubscribeToClientTeleportEvents(IClientAPI client) { client.OnTeleportLocationRequest -= RequestTeleportLocation; - client.OnTeleportLandmarkRequest -= RequestTeleportLandmark; + //client.OnTeleportLandmarkRequest -= RequestTeleportLandmark; //client.OnTeleportHomeRequest -= TeleportClientHome; } @@ -4064,26 +4113,6 @@ namespace OpenSim.Region.Framework.Scenes } } - /// - /// Tries to teleport agent to landmark. - /// - /// - /// - /// - public void RequestTeleportLandmark(IClientAPI remoteClient, UUID regionID, Vector3 position) - { - GridRegion info = GridService.GetRegionByUUID(UUID.Zero, regionID); - - if (info == null) - { - // can't find the region: Tell viewer and abort - remoteClient.SendTeleportFailed("The teleport destination could not be found."); - return; - } - - RequestTeleportLocation(remoteClient, info.RegionHandle, position, Vector3.Zero, (uint)(TPFlags.SetLastToTarget | TPFlags.ViaLandmark)); - } - public bool CrossAgentToNewRegion(ScenePresence agent, bool isFlying) { if (m_teleportModule != null) diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index c0236f44c5..39d4a2950f 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -1584,7 +1584,7 @@ namespace OpenSim.Region.Framework.Scenes } /// - /// + /// Handle a prim description set request from a viewer. /// /// /// @@ -1601,8 +1601,17 @@ namespace OpenSim.Region.Framework.Scenes } } + /// + /// Set a click action for the prim. + /// + /// + /// + /// protected internal void PrimClickAction(IClientAPI remoteClient, uint primLocalID, string clickAction) { +// m_log.DebugFormat( +// "[SCENEGRAPH]: User {0} set click action for {1} to {2}", remoteClient.Name, primLocalID, clickAction); + SceneObjectGroup group = GetGroupByPrim(primLocalID); if (group != null) { diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 74d24a6884..482597df0f 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -563,6 +563,11 @@ namespace OpenSim.Region.Framework.Scenes #endregion +// ~SceneObjectGroup() +// { +// m_log.DebugFormat("[SCENE OBJECT GROUP]: Destructor called for {0}, local id {1}", Name, LocalId); +// } + #region Constructors /// diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index cb321aa36b..e3744bd306 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -357,6 +357,13 @@ namespace OpenSim.Region.Framework.Scenes #endregion Fields +// ~SceneObjectPart() +// { +// m_log.DebugFormat( +// "[SCENE OBJECT PART]: Destructor called for {0}, local id {1}, parent {2} {3}", +// Name, LocalId, ParentGroup.Name, ParentGroup.LocalId); +// } + #region Constructors /// @@ -1636,7 +1643,6 @@ namespace OpenSim.Region.Framework.Scenes { PhysActor.SOPName = this.Name; // save object name and desc into the PhysActor so ODE internals know the joint/body info PhysActor.SOPDescription = this.Description; - PhysActor.LocalID = LocalId; DoPhysicsPropertyUpdate(RigidBody, true); PhysActor.SetVolumeDetect(VolumeDetectActive ? 1 : 0); } @@ -4428,6 +4434,7 @@ namespace OpenSim.Region.Framework.Scenes { // It's not phantom anymore. So make sure the physics engine get's knowledge of it PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape( + LocalId, string.Format("{0}/{1}", Name, UUID), Shape, AbsolutePosition, @@ -4439,7 +4446,6 @@ namespace OpenSim.Region.Framework.Scenes pa = PhysActor; if (pa != null) { - pa.LocalID = LocalId; DoPhysicsPropertyUpdate(UsePhysics, true); if (m_parentGroup != null) { diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs index 95ded7f052..91740707d0 100644 --- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs +++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs @@ -121,7 +121,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization } } - /// /// Serialize a scene object to the original xml format /// @@ -572,7 +571,13 @@ namespace OpenSim.Region.Framework.Scenes.Serialization private static void ProcessShape(SceneObjectPart obj, XmlTextReader reader) { - obj.Shape = ReadShape(reader, "Shape"); + bool errors = false; + obj.Shape = ReadShape(reader, "Shape", out errors); + + if (errors) + m_log.DebugFormat( + "[SceneObjectSerializer]: Parsing PrimitiveBaseShape for object part {0} {1} encountered errors. Please see earlier log entries.", + obj.Name, obj.UUID); } private static void ProcessScale(SceneObjectPart obj, XmlTextReader reader) @@ -1173,7 +1178,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization writer.WriteElementString("R", sop.Color.R.ToString(Utils.EnUsCulture)); writer.WriteElementString("G", sop.Color.G.ToString(Utils.EnUsCulture)); writer.WriteElementString("B", sop.Color.B.ToString(Utils.EnUsCulture)); - writer.WriteElementString("A", sop.Color.G.ToString(Utils.EnUsCulture)); + writer.WriteElementString("A", sop.Color.A.ToString(Utils.EnUsCulture)); writer.WriteEndElement(); writer.WriteElementString("Text", sop.Text); @@ -1479,7 +1484,9 @@ namespace OpenSim.Region.Framework.Scenes.Serialization } catch (Exception e) { - m_log.DebugFormat("[SceneObjectSerializer]: exception while parsing {0}: {1}", nodeName, e); + m_log.DebugFormat( + "[SceneObjectSerializer]: exception while parsing {0} in object {1} {2}: {3}{4}", + obj.Name, obj.UUID, nodeName, e.Message, e.StackTrace); if (reader.NodeType == XmlNodeType.EndElement) reader.Read(); } @@ -1531,8 +1538,17 @@ namespace OpenSim.Region.Framework.Scenes.Serialization return tinv; } - static PrimitiveBaseShape ReadShape(XmlTextReader reader, string name) + /// + /// Read a shape from xml input + /// + /// + /// The name of the xml element containing the shape + /// true if any errors were encountered during parsing, false otherwise + /// The shape parsed + static PrimitiveBaseShape ReadShape(XmlTextReader reader, string name, out bool errors) { + errors = false; + PrimitiveBaseShape shape = new PrimitiveBaseShape(); reader.ReadStartElement(name, String.Empty); // Shape @@ -1551,7 +1567,11 @@ namespace OpenSim.Region.Framework.Scenes.Serialization } catch (Exception e) { - m_log.DebugFormat("[SceneObjectSerializer]: exception while parsing Shape {0}: {1}", nodeName, e); + errors = true; + m_log.DebugFormat( + "[SceneObjectSerializer]: exception while parsing Shape property {0}: {1}{2}", + nodeName, e.Message, e.StackTrace); + if (reader.NodeType == XmlNodeType.EndElement) reader.Read(); } diff --git a/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs new file mode 100644 index 0000000000..abca792b8d --- /dev/null +++ b/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs @@ -0,0 +1,110 @@ +/* + * 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.Generic; +using System.Reflection; +using System.Text; +using System.Threading; +using System.Timers; +using Timer=System.Timers.Timer; +using Nini.Config; +using NUnit.Framework; +using OpenMetaverse; +using OpenMetaverse.Assets; +using OpenSim.Framework; +using OpenSim.Framework.Communications; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.CoreModules.Avatar.Inventory.Archiver; +using OpenSim.Region.CoreModules.World.Serialiser; +using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; +using OpenSim.Services.Interfaces; +using OpenSim.Tests.Common; +using OpenSim.Tests.Common.Mock; + +namespace OpenSim.Region.Framework.Tests +{ + [TestFixture] + public class UserInventoryTests + { + [Test] + public void TestGiveInventoryItem() + { + TestHelper.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + Scene scene = SceneSetupHelpers.SetupScene(); + UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene, 1001); + UserAccount user2 = UserAccountHelpers.CreateUserWithInventory(scene, 1002); + InventoryItemBase item1 = UserInventoryHelpers.CreateInventoryItem(scene, "item1", user1.PrincipalID); + + scene.GiveInventoryItem(user2.PrincipalID, user1.PrincipalID, item1.ID); + + InventoryItemBase retrievedItem1 + = UserInventoryHelpers.GetInventoryItem(scene.InventoryService, user2.PrincipalID, "Notecards/item1"); + + Assert.That(retrievedItem1, Is.Not.Null); + + // Try giving back the freshly received item + scene.GiveInventoryItem(user1.PrincipalID, user2.PrincipalID, retrievedItem1.ID); + + List reretrievedItems + = UserInventoryHelpers.GetInventoryItems(scene.InventoryService, user1.PrincipalID, "Notecards/item1"); + + Assert.That(reretrievedItems.Count, Is.EqualTo(2)); + } + + [Test] + public void TestGiveInventoryFolder() + { + TestHelper.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + Scene scene = SceneSetupHelpers.SetupScene(); + UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene, 1001); + UserAccount user2 = UserAccountHelpers.CreateUserWithInventory(scene, 1002); + InventoryFolderBase folder1 + = UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, user1.PrincipalID, "folder1"); + + scene.GiveInventoryFolder(user2.PrincipalID, user1.PrincipalID, folder1.ID, UUID.Zero); + + InventoryFolderBase retrievedFolder1 + = UserInventoryHelpers.GetInventoryFolder(scene.InventoryService, user2.PrincipalID, "folder1"); + + Assert.That(retrievedFolder1, Is.Not.Null); + + // Try giving back the freshly received folder + scene.GiveInventoryFolder(user1.PrincipalID, user2.PrincipalID, retrievedFolder1.ID, UUID.Zero); + + List reretrievedFolders + = UserInventoryHelpers.GetInventoryFolders(scene.InventoryService, user1.PrincipalID, "folder1"); + + Assert.That(reretrievedFolders.Count, Is.EqualTo(2)); + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs index 07af201cbb..4045507c36 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs @@ -1183,7 +1183,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server IRC_SendChannelPrivmsg(objectname,url); } - public void SendDialog(string objectname, UUID objectID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch, string[] buttonlabels) + public void SendDialog(string objectname, UUID objectID, UUID ownerID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch, string[] buttonlabels) { } diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs index 1c791b9d36..630fcabac3 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs @@ -1223,6 +1223,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups /// /// Get a list of groups memberships for the agent that are marked "ListInProfile" + /// (unless that agent has a godLike aspect, in which case get all groups) /// /// /// @@ -1231,20 +1232,32 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups List membershipData = m_groupData.GetAgentGroupMemberships(requestingClient.AgentId, dataForAgentID); GroupMembershipData[] membershipArray; - if (requestingClient.AgentId != dataForAgentID) - { - Predicate showInProfile = delegate(GroupMembershipData membership) - { - return membership.ListInProfile; - }; + // cScene and property accessor 'isGod' are in support of the opertions to bypass 'hidden' group attributes for + // those with a GodLike aspect. + Scene cScene = (Scene)requestingClient.Scene; + bool isGod = cScene.Permissions.IsGod(requestingClient.AgentId); - membershipArray = membershipData.FindAll(showInProfile).ToArray(); - } - else + if (isGod) { membershipArray = membershipData.ToArray(); } + else + { + if (requestingClient.AgentId != dataForAgentID) + { + Predicate showInProfile = delegate(GroupMembershipData membership) + { + return membership.ListInProfile; + }; + membershipArray = membershipData.FindAll(showInProfile).ToArray(); + } + else + { + membershipArray = membershipData.ToArray(); + } + } + if (m_debugEnabled) { m_log.InfoFormat("[GROUPS]: Get group membership information for {0} requested by {1}", dataForAgentID, requestingClient.AgentId); @@ -1257,6 +1270,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return membershipArray; } + private void SendAgentDataUpdate(IClientAPI remoteClient, UUID dataForAgentID, UUID activeGroupID, string activeGroupName, ulong activeGroupPowers, string activeGroupTitle) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/AuraMetaEntity.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/AuraMetaEntity.cs deleted file mode 100644 index 4a402bf2bd..0000000000 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/AuraMetaEntity.cs +++ /dev/null @@ -1,161 +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. - */ - -#region Header - -// AuraMetaEntity.cs created with MonoDevelop -// User: bongiojp at 3:03 PM 8/6/2008 -// -// To change standard headers go to Edit->Preferences->Coding->Standard Headers -// - -#endregion Header - -using System; -using System.Collections.Generic; -using System.Drawing; - -using OpenMetaverse; - -using Nini.Config; - -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.OptionalModules.ContentManagement -{ - public class AuraMetaEntity : PointMetaEntity - { - #region Constructors - - //transparency of root part, NOT particle system. Should probably add support for changing particle system transparency. - public AuraMetaEntity(Scene scene, Vector3 groupPos, float transparency, Vector3 color, Vector3 scale) - : base(scene, groupPos, transparency) - { - SetAura(color, scale); - } - - public AuraMetaEntity(Scene scene, UUID uuid, Vector3 groupPos, float transparency, Vector3 color, Vector3 scale) - : base(scene, uuid, groupPos, transparency) - { - SetAura(color, scale); - } - - #endregion Constructors - - #region Private Methods - - private float Average(Vector3 values) - { - return (values.X + values.Y + values.Z)/3f; - } - - #endregion Private Methods - - #region Public Methods - - public void SetAura(Vector3 color, Vector3 scale) - { - SetAura(color, Average(scale) * 2.0f); - } - - public void SetAura(Vector3 color, float radius) - { - SceneObjectPart From = m_Entity.RootPart; - - //m_log.Debug("[META ENTITY] BEFORE: radius = " + radius); - float burstRadius = 0.1f; - Primitive.ParticleSystem.SourcePattern patternFlags = Primitive.ParticleSystem.SourcePattern.None; - float age = 1.5f; - float burstRate = 0.4f; - if (radius >= 8.0f) - { - //float sizeOfObject = radius / 2.0f; - burstRadius = (radius - 8.0f)/3f; - burstRate = 1.5f; - radius = 7.99f; - patternFlags = Primitive.ParticleSystem.SourcePattern.Explode; - age = 4.0f; - } - SetAura(From, color, radius, burstRadius, age, burstRate, patternFlags); - } - - public void SetAura(SceneObjectPart From, Vector3 color, float radius, float burstRadius, float age, float burstRate, Primitive.ParticleSystem.SourcePattern patternFlags) - { - Primitive.ParticleSystem prules = new Primitive.ParticleSystem(); - //prules.PartDataFlags = Primitive.ParticleSystem.ParticleDataFlags.Emissive | - // Primitive.ParticleSystem.ParticleDataFlags.FollowSrc; //PSYS_PART_FLAGS - //prules.PartDataFlags = Primitive.ParticleSystem.ParticleDataFlags.Beam | - // Primitive.ParticleSystem.ParticleDataFlags.TargetPos; - prules.PartStartColor.R = color.X; //PSYS_PART_START_COLOR - prules.PartStartColor.G = color.Y; - prules.PartStartColor.B = color.Z; - prules.PartStartColor.A = 0.5f; //PSYS_PART_START_ALPHA, transparency - prules.PartEndColor.R = color.X; //PSYS_PART_END_COLOR - prules.PartEndColor.G = color.Y; - prules.PartEndColor.B = color.Z; - prules.PartEndColor.A = 0.5f; //PSYS_PART_END_ALPHA, transparency - /*prules.PartStartScaleX = 0.5f; //PSYS_PART_START_SCALE - prules.PartStartScaleY = 0.5f; - prules.PartEndScaleX = 0.5f; //PSYS_PART_END_SCALE - prules.PartEndScaleY = 0.5f; - */ - prules.PartStartScaleX = radius; //PSYS_PART_START_SCALE - prules.PartStartScaleY = radius; - prules.PartEndScaleX = radius; //PSYS_PART_END_SCALE - prules.PartEndScaleY = radius; - prules.PartMaxAge = age; //PSYS_PART_MAX_AGE - prules.PartAcceleration.X = 0.0f; //PSYS_SRC_ACCEL - prules.PartAcceleration.Y = 0.0f; - prules.PartAcceleration.Z = 0.0f; - prules.Pattern = patternFlags; //PSYS_SRC_PATTERN - //prules.Texture = UUID.Zero;//= UUID //PSYS_SRC_TEXTURE, default used if blank - prules.BurstRate = burstRate; //PSYS_SRC_BURST_RATE - prules.BurstPartCount = 2; //PSYS_SRC_BURST_PART_COUNT - //prules.BurstRadius = radius; //PSYS_SRC_BURST_RADIUS - prules.BurstRadius = burstRadius; //PSYS_SRC_BURST_RADIUS - prules.BurstSpeedMin = 0.001f; //PSYS_SRC_BURST_SPEED_MIN - prules.BurstSpeedMax = 0.001f; //PSYS_SRC_BURST_SPEED_MAX - prules.MaxAge = 0.0f; //PSYS_SRC_MAX_AGE - //prules.Target = To; //PSYS_SRC_TARGET_KEY - prules.AngularVelocity.X = 0.0f; //PSYS_SRC_OMEGA - prules.AngularVelocity.Y = 0.0f; - prules.AngularVelocity.Z = 0.0f; - prules.InnerAngle = 0.0f; //PSYS_SRC_ANGLE_BEGIN - prules.OuterAngle = 0.0f; //PSYS_SRC_ANGLE_END - - prules.CRC = 1; //activates the particle system?? - From.AddNewParticleSystem(prules); - } - - #endregion Public Methods - } -} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/BeamMetaEntity.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/BeamMetaEntity.cs deleted file mode 100644 index 6966de0cab..0000000000 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/BeamMetaEntity.cs +++ /dev/null @@ -1,139 +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. - */ - -#region Header - -// BeamMetaEntity.cs created with MonoDevelop -// User: bongiojp at 3:03 PM 8/6/2008 -// -// To change standard headers go to Edit->Preferences->Coding->Standard Headers -// - -#endregion Header - -using System; -using System.Collections.Generic; -using System.Drawing; - -using OpenMetaverse; - -using Nini.Config; - -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.OptionalModules.ContentManagement -{ - public class BeamMetaEntity : PointMetaEntity - { - #region Constructors - - public BeamMetaEntity(Scene scene, Vector3 groupPos, float transparency, SceneObjectPart To, Vector3 color) - : base(scene, groupPos, transparency) - { - SetBeamToUUID(To, color); - } - - public BeamMetaEntity(Scene scene, UUID uuid, Vector3 groupPos, float transparency, SceneObjectPart To, Vector3 color) - : base(scene, uuid, groupPos, transparency) - { - SetBeamToUUID(To, color); - } - - #endregion Constructors - - #region Public Methods - - public void SetBeamToUUID(SceneObjectPart To, Vector3 color) - { - SceneObjectPart From = m_Entity.RootPart; - //Scale size of particles to distance objects are apart (for better visibility) - Vector3 FromPos = From.GetWorldPosition(); - Vector3 ToPos = From.GetWorldPosition(); - // UUID toUUID = To.UUID; - float distance = (float) (Math.Sqrt(Math.Pow(FromPos.X-ToPos.X, 2) + - Math.Pow(FromPos.X-ToPos.Y, 2) + - Math.Pow(FromPos.X-ToPos.Z, 2) - ) - ); - //float rate = (float) (distance/4f); - float rate = 0.5f; - float scale = (float) (distance/128f); - float speed = (float) (2.0f - distance/128f); - - SetBeamToUUID(From, To, color, rate, scale, speed); - } - - public void SetBeamToUUID(SceneObjectPart From, SceneObjectPart To, Vector3 color, float rate, float scale, float speed) - { - Primitive.ParticleSystem prules = new Primitive.ParticleSystem(); - //prules.PartDataFlags = Primitive.ParticleSystem.ParticleDataFlags.Emissive | - // Primitive.ParticleSystem.ParticleDataFlags.FollowSrc; //PSYS_PART_FLAGS - prules.PartDataFlags = Primitive.ParticleSystem.ParticleDataFlags.Beam | - Primitive.ParticleSystem.ParticleDataFlags.TargetPos; - prules.PartStartColor.R = color.X; //PSYS_PART_START_COLOR - prules.PartStartColor.G = color.Y; - prules.PartStartColor.B = color.Z; - prules.PartStartColor.A = 1.0f; //PSYS_PART_START_ALPHA, transparency - prules.PartEndColor.R = color.X; //PSYS_PART_END_COLOR - prules.PartEndColor.G = color.Y; - prules.PartEndColor.B = color.Z; - prules.PartEndColor.A = 1.0f; //PSYS_PART_END_ALPHA, transparency - prules.PartStartScaleX = scale; //PSYS_PART_START_SCALE - prules.PartStartScaleY = scale; - prules.PartEndScaleX = scale; //PSYS_PART_END_SCALE - prules.PartEndScaleY = scale; - prules.PartMaxAge = 1.0f; //PSYS_PART_MAX_AGE - prules.PartAcceleration.X = 0.0f; //PSYS_SRC_ACCEL - prules.PartAcceleration.Y = 0.0f; - prules.PartAcceleration.Z = 0.0f; - //prules.Pattern = Primitive.ParticleSystem.SourcePattern.Explode; //PSYS_SRC_PATTERN - //prules.Texture = UUID.Zero;//= UUID //PSYS_SRC_TEXTURE, default used if blank - prules.BurstRate = rate; //PSYS_SRC_BURST_RATE - prules.BurstPartCount = 1; //PSYS_SRC_BURST_PART_COUNT - prules.BurstRadius = 0.5f; //PSYS_SRC_BURST_RADIUS - prules.BurstSpeedMin = speed; //PSYS_SRC_BURST_SPEED_MIN - prules.BurstSpeedMax = speed; //PSYS_SRC_BURST_SPEED_MAX - prules.MaxAge = 0.0f; //PSYS_SRC_MAX_AGE - prules.Target = To.UUID; //PSYS_SRC_TARGET_KEY - prules.AngularVelocity.X = 0.0f; //PSYS_SRC_OMEGA - prules.AngularVelocity.Y = 0.0f; - prules.AngularVelocity.Z = 0.0f; - prules.InnerAngle = 0.0f; //PSYS_SRC_ANGLE_BEGIN - prules.OuterAngle = 0.0f; //PSYS_SRC_ANGLE_END - - prules.CRC = 1; //activates the particle system?? - From.AddNewParticleSystem(prules); - } - - #endregion Public Methods - } -} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMController.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMController.cs deleted file mode 100644 index 8d6c41df63..0000000000 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMController.cs +++ /dev/null @@ -1,756 +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. - */ - -#region Header - -// CMController.cs -// User: bongiojp -// - -#endregion Header - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics; -using System.Threading; - -using OpenMetaverse; - -using OpenSim; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.OptionalModules.ContentManagement -{ - /// - /// The controller in a Model-View-Controller framework. This controller catches actions by the avatars, creates work packets, loops through these work packets in a separate thread, - /// then dictates to the model how the data should change and dictates to the view which data should be displayed. The main mechanism for interaction is through the simchat system. - /// - public class CMController - { - #region Static Fields - - private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - - /// - /// The queue that keeps track of which actions have happened. The MainLoop thread eats through this queue. - /// - private static OpenSim.Framework.BlockingQueue m_WorkQueue = new OpenSim.Framework.BlockingQueue(); - - #endregion Static Fields - - #region Fields - - //bool init = false; - int m_channel = -1; - - /// - /// The estate module is used to identify which clients are estateManagers. Presently, the controller only pays attention to estate managers. - /// - IEstateModule m_estateModule = null; - - //These have to be global variables, threading doesn't allow for passing parameters. (Used in MainLoop) - CMModel m_model = null; - - /// - /// A list of all the scenes that should be revisioned. Controller is the only class that keeps track of all scenes in the region. - /// - Hashtable m_sceneList = Hashtable.Synchronized(new Hashtable()); - State m_state = State.NONE; - CMView m_view = null; - - #endregion Fields - - #region Constructors - - /// - /// Initializes a work thread with an initial scene. Additional scenes should be added through the RegisterNewRegion method. - /// - /// - /// - /// - /// - /// - /// - /// - /// The first scene to keep track of. - /// - /// - /// The simchat channel number to listen to for instructions - /// - public CMController(CMModel model, CMView view, Scene scene, int channel) - { - m_model = model; m_view = view; m_channel = channel; - RegisterNewRegion(scene); - Initialize(model, view, scene, channel); - } - - #endregion Constructors - - #region Private Methods - - //------------------------------------------------ EVENTS ----------------------------------------------------// -// private void AvatarEnteringParcel(ScenePresence avatar, int localLandID, LLUUID regionID) -// { -// } - - /// - /// Searches in all scenes for a SceneObjectGroup that contains a part with a specific localID. If found, the object is returned. Else null is returned. - /// - private SceneObjectGroup GetGroupByPrim(uint localID) - { - foreach (Object currScene in m_sceneList.Values) - { - foreach (EntityBase ent in ((Scene)currScene).GetEntities()) - { - if (ent is SceneObjectGroup) - { - if (((SceneObjectGroup)ent).HasChildPrim(localID)) - return (SceneObjectGroup)ent; - } - } - } - return null; - } - - private void Initialize(CMModel model, CMView view, Scene scene, int channel) - { - lock (this) - { - m_estateModule = scene.RequestModuleInterface(); - Watchdog.StartThread(MainLoop, "Content Management", ThreadPriority.Normal, true); - m_state = State.NONE; - } - } - - /// - /// Run in a thread of its own. A endless loop that consumes (or blocks on) and work queue. Thw work queue is filled through client actions. - /// - private void MainLoop() - { - try - { - CMModel model = m_model; CMView view = m_view; int channel = m_channel; - Work currentJob = new Work(); - while (true) - { - currentJob = m_WorkQueue.Dequeue(); - m_log.Debug("[CONTENT MANAGEMENT] MAIN LOOP -- DeQueued a request"); - m_log.Debug("[CONTENT MANAGEMENT] MAIN LOOP -- Work type: " + currentJob.Type); - switch (currentJob.Type) - { - case WorkType.NONE: - break; - case WorkType.OBJECTATTRIBUTECHANGE: - ObjectAttributeChanged(model, view, currentJob.LocalId); - break; - case WorkType.PRIMITIVEADDED: - PrimitiveAdded(model, view, currentJob); - break; - case WorkType.OBJECTDUPLICATED: - ObjectDuplicated(model, view, currentJob.LocalId); - break; - case WorkType.OBJECTKILLED: - ObjectKilled(model, view, (SceneObjectGroup) currentJob.Data1); - break; - case WorkType.UNDODID: - UndoDid(model, view, currentJob.UUID); - break; - case WorkType.NEWCLIENT: - NewClient(view, (IClientAPI) currentJob.Data1); - break; - case WorkType.SIMCHAT: - m_log.Debug("[CONTENT MANAGEMENT] MAIN LOOP -- Message received: " + ((OSChatMessage) currentJob.Data1).Message); - SimChat(model, view, (OSChatMessage) currentJob.Data1, channel); - break; - default: - m_log.Debug("[CONTENT MANAGEMENT] MAIN LOOP -- uuuuuuuuuh, what?"); - break; - } - - Watchdog.UpdateThread(); - } - } - catch (Exception e) - { - // TODO: Let users in the sim and those entering it and possibly an external watchdog know what has happened - m_log.ErrorFormat( - "[CONTENT MANAGEMENT]: Content management thread terminating with exception. PLEASE REBOOT YOUR SIM - CONTENT MANAGEMENT WILL NOT BE AVAILABLE UNTIL YOU DO. Exception is {0}", - e); - } - - Watchdog.RemoveThread(); - } - - /// - /// Only called by the MainLoop. Updates the view of a new client with metaentities if diff-mode is currently enabled. - /// - private void NewClient(CMView view, IClientAPI client) - { - if ((m_state & State.SHOWING_CHANGES) > 0) - view.SendMetaEntitiesToNewClient(client); - } - - /// - /// Only called by the MainLoop. - /// - private void ObjectAttributeChanged(CMModel model, CMView view, uint LocalId) - { - SceneObjectGroup group = null; - if ((m_state & State.SHOWING_CHANGES) > 0) - { - group = GetGroupByPrim(LocalId); - if (group != null) - { - view.DisplayAuras(model.UpdateNormalEntityEffects(group)); //Might be a normal entity (green aura) - m_view.DisplayMetaEntity(group.UUID); //Might be a meta entity (blue aura) - } - } - } - - /// - /// Only called by the MainLoop. Displays new green auras over the newly created part when a part is shift copied. - /// - private void ObjectDuplicated(CMModel model, CMView view, uint localId) - { - if ((m_state & State.SHOWING_CHANGES) > 0) - view.DisplayAuras(model.CheckForNewEntitiesMissingAuras(GetGroupByPrim(localId).Scene)); - } - - /// - /// Only called by the MainLoop. - /// - private void ObjectKilled(CMModel model, CMView view, SceneObjectGroup group) - { - if ((m_state & State.SHOWING_CHANGES) > 0) - { - view.RemoveOrUpdateDeletedEntity(group); - model.RemoveOrUpdateDeletedEntity(group); - } - } - - /// - /// Only called by the MainLoop. - /// - private void PrimitiveAdded(CMModel model, CMView view, Work currentJob) - { - if ((m_state & State.SHOWING_CHANGES) > 0) - { - foreach (Object scene in m_sceneList.Values) - m_view.DisplayAuras(model.CheckForNewEntitiesMissingAuras((Scene) scene)); - } - } - - /// - /// Only called by the MainLoop. - /// - private void UndoDid(CMModel model, CMView view, UUID uuid) - { - if ((m_state & State.SHOWING_CHANGES) > 0) - { - ContentManagementEntity ent = model.FindMetaEntityAffectedByUndo(uuid); - if (ent != null) - view.DisplayEntity(ent); - } - } - - #endregion Private Methods - - #region Protected Methods - - protected void GroupBeingDeleted(SceneObjectGroup group) - { - m_log.Debug("[CONTENT MANAGEMENT] Something was deleted!!!"); - Work moreWork = new Work(); - moreWork.Type = WorkType.OBJECTKILLED; - moreWork.Data1 = group.Copy(); - m_WorkQueue.Enqueue(moreWork); - } - - protected void ObjectDuplicated(uint localID, Vector3 offset, uint dupeFlags, UUID AgentID, UUID GroupID) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.OBJECTDUPLICATED; - moreWork.LocalId = localID; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT] dup queue"); - } - - protected void ObjectDuplicatedOnRay(uint localID, uint dupeFlags, UUID AgentID, UUID GroupID, - UUID RayTargetObj, Vector3 RayEnd, Vector3 RayStart, - bool BypassRaycast, bool RayEndIsIntersection, bool CopyCenters, bool CopyRotates) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.OBJECTDUPLICATED; - moreWork.LocalId = localID; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT] dup queue"); - } - - protected void OnNewClient(IClientAPI client) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.NEWCLIENT; - moreWork.Data1 = client; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT] new client"); - } - - protected void OnUnDid(IClientAPI remoteClient, UUID primId) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.UNDODID; - moreWork.UUID = primId; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT] undid"); - } - - /// - /// Takes a list of scenes and forms a new orderd list according to the proximity of scenes to the second argument. - /// - protected static System.Collections.Generic.List ScenesInOrderOfProximity(Hashtable sceneList, Scene scene) - { - int somethingAddedToList = 1; - System.Collections.Generic.List newList = new List(); - newList.Add(scene); - - if (!sceneList.ContainsValue(scene)) - { - foreach (Object sceneObj in sceneList) - newList.Add((Scene) sceneObj); - return newList; - } - - while (somethingAddedToList > 0) - { - somethingAddedToList = 0; - for (int i = 0; i < newList.Count; i++) - { - foreach (Object sceneObj in sceneList.Values) - { - if (newList[i].CheckNeighborRegion(((Scene)sceneObj).RegionInfo) && (!newList.Contains((Scene)sceneObj))) - { - newList.Add((Scene)sceneObj); - somethingAddedToList++; - } - } - } - } - - foreach (Object sceneObj in sceneList.Values) - if (!newList.Contains((Scene)sceneObj)) - newList.Add((Scene)sceneObj); - - return newList; - } - - //This is stupid, the same information is contained in the first and second argument - protected void SimChatSent(Object x, OSChatMessage e) - { - m_log.Debug("[CONTENT MANAGEMENT] SIMCHAT SENT !!!!!!!"); - m_log.Debug("[CONTENT MANAGEMENT] message was: " + e.Message); - Work moreWork = new Work(); - moreWork.Type = WorkType.SIMCHAT; - moreWork.Data1 = e; - m_WorkQueue.Enqueue(moreWork); - } - - /// - /// Adds extra handlers to a number of events so that the controller can produce work based on the client's actions. - /// - protected void StartManaging(IClientAPI client) - { - m_log.Debug("[CONTENT MANAGEMENT] Registering channel with chat services."); - // client.OnChatFromClient += SimChatSent; - //init = true; - - OnNewClient(client); - - m_log.Debug("[CONTENT MANAGEMENT] Adding handlers to client."); - client.OnUpdatePrimScale += UpdateSingleScale; - client.OnUpdatePrimGroupScale += UpdateMultipleScale; - client.OnUpdatePrimGroupPosition += UpdateMultiplePosition; - client.OnUpdatePrimSinglePosition += UpdateSinglePosition; - client.OnUpdatePrimGroupRotation += UpdateMultipleRotation; - client.OnUpdatePrimSingleRotation += UpdateSingleRotation; - client.OnAddPrim += UpdateNewParts; - client.OnObjectDuplicate += ObjectDuplicated; - client.OnObjectDuplicateOnRay += ObjectDuplicatedOnRay; - client.OnUndo += OnUnDid; - //client.OnUpdatePrimGroupMouseRotation += m_innerScene.UpdatePrimRotation; - } - - /// - /// - /// - protected void StopManaging(UUID clientUUID) - { - foreach (Object sceneobj in m_sceneList.Values) - { - ScenePresence presence = ((Scene)sceneobj).GetScenePresence(clientUUID); - if (presence != null) - { - IClientAPI client = presence.ControllingClient; - m_log.Debug("[CONTENT MANAGEMENT] Unregistering channel with chat services."); - // client.OnChatFromViewer -= SimChatSent; - - m_log.Debug("[CONTENT MANAGEMENT] Removing handlers to client"); - client.OnUpdatePrimScale -= UpdateSingleScale; - client.OnUpdatePrimGroupScale -= UpdateMultipleScale; - client.OnUpdatePrimGroupPosition -= UpdateMultiplePosition; - client.OnUpdatePrimSinglePosition -= UpdateSinglePosition; - client.OnUpdatePrimGroupRotation -= UpdateMultipleRotation; - client.OnUpdatePrimSingleRotation -= UpdateSingleRotation; - client.OnAddPrim -= UpdateNewParts; - client.OnObjectDuplicate -= ObjectDuplicated; - client.OnObjectDuplicateOnRay -= ObjectDuplicatedOnRay; - client.OnUndo -= OnUnDid; - //client.OnUpdatePrimGroupMouseRotation += m_innerScene.UpdatePrimRotation; - return; - } - } - } - - protected void UpdateMultiplePosition(uint localID, Vector3 pos, IClientAPI remoteClient) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE; - moreWork.LocalId = localID; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT] pos"); - } - - protected void UpdateMultipleRotation(uint localID, Quaternion rot, IClientAPI remoteClient) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE; - moreWork.LocalId = localID; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT] rot"); - } - - protected void UpdateMultipleScale(uint localID, Vector3 scale, IClientAPI remoteClient) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE; - moreWork.LocalId = localID; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT]scale"); - } - - protected void UpdateNewParts(UUID ownerID, UUID groupID, Vector3 RayEnd, Quaternion rot, PrimitiveBaseShape shape, - byte bypassRaycast, Vector3 RayStart, UUID RayTargetID, - byte RayEndIsIntersection) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.PRIMITIVEADDED; - moreWork.UUID = ownerID; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT] new parts"); - } - - protected void UpdateSinglePosition(uint localID, Vector3 pos, IClientAPI remoteClient) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE; - moreWork.LocalId = localID; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT] move"); - } - - /// - /// - /// - protected void UpdateSingleRotation(uint localID, Quaternion rot, IClientAPI remoteClient) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE; - moreWork.LocalId = localID; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT] rot"); - } - - protected void UpdateSingleScale(uint localID, Vector3 scale, IClientAPI remoteClient) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE; - moreWork.LocalId = localID; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT] scale"); - } - - /// - /// Only called from within the SimChat method. - /// - protected void commit(string message, Scene scene, CMModel model, CMView view) - { - System.Collections.Generic.List proximitySceneList = ScenesInOrderOfProximity(m_sceneList, scene); - - string[] args = message.Split(new char[] {' '}); - - char[] logMessage = {' '}; - if (args.Length > 1) - { - logMessage = new char[message.Length - (args[0].Length)]; - message.CopyTo(args[0].Length, logMessage, 0, message.Length - (args[0].Length)); - } - - m_log.Debug("[CONTENT MANAGEMENT] Saving terrain and objects of region."); - foreach (Scene currScene in proximitySceneList) - { - model.CommitRegion(currScene, new String(logMessage)); - view.SendSimChatMessage(scene, "Region Saved Successfully: " + currScene.RegionInfo.RegionName); - } - - view.SendSimChatMessage(scene, "Successfully saved all regions."); - m_state |= State.DIRTY; - - if ((m_state & State.SHOWING_CHANGES) > 0) //DISPLAY NEW CHANGES INSTEAD OF OLD CHANGES - { - view.SendSimChatMessage(scene, "Updating differences between new revision and current environment."); - //Hide objects from users and Forget about them - view.HideAllMetaEntities(); - view.HideAllAuras(); - model.DeleteAllMetaObjects(); - - //Recreate them from backend files - foreach (Scene currScene in proximitySceneList) - { - model.UpdateCMEntities(currScene); - view.SendSimChatMessage(scene, "Finished updating differences between current scene and last revision: " + currScene.RegionInfo.RegionName); - } - - //Display new objects to users1 - view.DisplayRecentChanges(); - view.SendSimChatMessage(scene, "Finished updating for DIFF-MODE."); - m_state &= ~(State.DIRTY); - m_state |= State.SHOWING_CHANGES; - } - } - - /// - /// Only called from within the SimChat method. - /// - protected void diffmode(Scene scene, CMModel model, CMView view) - { - System.Collections.Generic.List proximitySceneList = ScenesInOrderOfProximity(m_sceneList, scene); - - if ((m_state & State.SHOWING_CHANGES) > 0) // TURN OFF - { - view.SendSimChatMessage(scene, "Hiding all meta objects."); - view.HideAllMetaEntities(); - view.HideAllAuras(); - view.SendSimChatMessage(scene, "Diff-mode = OFF"); - - m_state &= ~State.SHOWING_CHANGES; - return; - } - else // TURN ON - { - if ((m_state & State.DIRTY) != 0 || m_state == State.NONE) - { - view.SendSimChatMessage(scene, "Hiding meta objects and replacing with latest revision"); - //Hide objects from users and Forget about them - view.HideAllMetaEntities(); - view.HideAllAuras(); - model.DeleteAllMetaObjects(); - //Recreate them from backend files - foreach (Object currScene in m_sceneList.Values) - model.UpdateCMEntities((Scene) currScene); - } - else if ((m_state & State.DIRTY) != 0) { - view.SendSimChatMessage(scene, "Forming list of meta entities with latest revision"); - foreach (Scene currScene in proximitySceneList) - model.UpdateCMEntities(currScene); - } - - view.SendSimChatMessage(scene, "Displaying differences between last revision and current environment"); - foreach (Scene currScene in proximitySceneList) - model.CheckForNewEntitiesMissingAuras(currScene); - view.DisplayRecentChanges(); - - view.SendSimChatMessage(scene, "Diff-mode = ON"); - m_state |= State.SHOWING_CHANGES; - m_state &= ~State.DIRTY; - } - } - - /// - /// Only called from within the SimChat method. Hides all auras and meta entities, - /// retrieves the current scene object list with the most recent revision retrieved from the model for each scene, - /// then lets the view update the clients of the new objects. - /// - protected void rollback(Scene scene, CMModel model, CMView view) - { - if ((m_state & State.SHOWING_CHANGES) > 0) - { - view.HideAllAuras(); - view.HideAllMetaEntities(); - } - - System.Collections.Generic.List proximitySceneList = ScenesInOrderOfProximity(m_sceneList, scene); - foreach (Scene currScene in proximitySceneList) - model.RollbackRegion(currScene); - - if ((m_state & State.DIRTY) != 0) - { - model.DeleteAllMetaObjects(); - foreach (Scene currScene in proximitySceneList) - model.UpdateCMEntities(currScene); - } - - if ((m_state & State.SHOWING_CHANGES) > 0) - view.DisplayRecentChanges(); - } - - #endregion Protected Methods - - #region Public Methods - - /// - /// Register a new scene object to keep track of for revisioning. Starts the controller monitoring actions of clients within the given scene. - /// - /// - /// A - /// - public void RegisterNewRegion(Scene scene) - { - m_sceneList.Add(scene.RegionInfo.RegionID, scene); - - m_log.Debug("[CONTENT MANAGEMENT] Registering new region: " + scene.RegionInfo.RegionID); - m_log.Debug("[CONTENT MANAGEMENT] Initializing Content Management System."); - - scene.EventManager.OnNewClient += StartManaging; - scene.EventManager.OnChatFromClient += SimChatSent; - scene.EventManager.OnRemovePresence += StopManaging; - // scene.EventManager.OnAvatarEnteringNewParcel += AvatarEnteringParcel; - scene.EventManager.OnObjectBeingRemovedFromScene += GroupBeingDeleted; - } - - /// - /// Only called by the MainLoop. Takes the message from a user sent to the channel and executes the proper command. - /// - public void SimChat(CMModel model, CMView view, OSChatMessage e, int channel) - { - if (e.Channel != channel) - return; - if (e.Sender == null) - return; - - m_log.Debug("[CONTENT MANAGEMENT] Message received: " + e.Message); - - IClientAPI client = e.Sender; - Scene scene = (Scene) e.Scene; - string message = e.Message; - string[] args = e.Message.Split(new char[] {' '}); - - ScenePresence avatar = scene.GetScenePresence(client.AgentId); - - if (!(m_estateModule.IsManager(avatar.UUID))) - { - m_log.Debug("[CONTENT MANAGEMENT] Message sent from non Estate Manager ... ignoring."); - view.SendSimChatMessage(scene, "You must be an estate manager to perform that action."); - return; - } - - switch (args[0]) - { - case "ci": - case "commit": - commit(message, scene, model, view); - break; - case "dm": - case "diff-mode": - diffmode(scene, model, view); - break; - case "rb": - case "rollback": - rollback(scene, model, view); - break; - case "help": - m_view.DisplayHelpMenu(scene); - break; - default: - view.SendSimChatMessage(scene, "Command not found: " + args[0]); - break; - } - } - - #endregion Public Methods - - #region Other - - /// - /// Used to keep track of whether a list has been produced yet and whether that list is up-to-date compard to latest revision on disk. - /// - [Flags] - private enum State - { - NONE = 0, - DIRTY = 1, // The meta entities may not correctly represent the last revision. - SHOWING_CHANGES = 1<<1 // The meta entities are being shown to user. - } - - /// - /// The structure that defines the basic unit of work which is produced when a user sends commands to the ContentMangaementSystem. - /// - private struct Work - { - #region Fields - - public Object Data1; //Just space for holding data. - public Object Data2; //Just more space for holding data. - public uint LocalId; //Convenient - public WorkType Type; - public UUID UUID; //Convenient - - #endregion Fields - } - - /// - /// Identifies what the data in struct Work should be used for. - /// - private enum WorkType - { - NONE, - OBJECTATTRIBUTECHANGE, - PRIMITIVEADDED, - OBJECTDUPLICATED, - OBJECTKILLED, - UNDODID, - NEWCLIENT, - SIMCHAT - } - - #endregion Other - } -} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMEntityCollection.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMEntityCollection.cs deleted file mode 100644 index 7f64ebdbf7..0000000000 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMEntityCollection.cs +++ /dev/null @@ -1,193 +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. - */ - -#region Header - -// CMEntityCollection.cs created with MonoDevelop -// User: bongiojp at 10:09 AM 7/7/2008 -// -// Creates, Deletes, Stores ContentManagementEntities -// - -#endregion Header - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Threading; - -using OpenMetaverse; - -using Nini.Config; - -using OpenSim; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.OptionalModules.ContentManagement -{ - public class CMEntityCollection - { - #region Fields - - // private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - // Any ContentManagementEntities that represent old versions of current SceneObjectGroups or - // old versions of deleted SceneObjectGroups will be stored in this hash table. - // The UUID keys are from the SceneObjectGroup RootPart UUIDs - protected Hashtable m_CMEntityHash = Hashtable.Synchronized(new Hashtable()); //UUID to ContentManagementEntity - - // SceneObjectParts that have not been revisioned will be given green auras stored in this hashtable - // The UUID keys are from the SceneObjectPart that they are supposed to be on. - protected Hashtable m_NewlyCreatedEntityAura = Hashtable.Synchronized(new Hashtable()); //UUID to AuraMetaEntity - - #endregion Fields - - #region Constructors - - public CMEntityCollection() - { - } - - #endregion Constructors - - #region Public Properties - - public Hashtable Auras - { - get {return m_NewlyCreatedEntityAura; } - } - - public Hashtable Entities - { - get { return m_CMEntityHash; } - } - - #endregion Public Properties - - #region Public Methods - - public bool AddAura(ContentManagementEntity aura) - { - if (m_NewlyCreatedEntityAura.ContainsKey(aura.UUID)) - return false; - m_NewlyCreatedEntityAura.Add(aura.UUID, aura); - return true; - } - - public bool AddEntity(ContentManagementEntity ent) - { - if (m_CMEntityHash.ContainsKey(ent.UUID)) - return false; - m_CMEntityHash.Add(ent.UUID, ent); - return true; - } - - // Check if there are SceneObjectGroups in the list that do not have corresponding ContentManagementGroups in the CMEntityHash - public System.Collections.ArrayList CheckForMissingEntities(EntityBase[] currList) - { - System.Collections.ArrayList missingList = new System.Collections.ArrayList(); - SceneObjectGroup temp = null; - foreach (EntityBase currObj in currList) - { - if (!(currObj is SceneObjectGroup)) - continue; - temp = (SceneObjectGroup) currObj; - - if (m_CMEntityHash.ContainsKey(temp.UUID)) - { - foreach (SceneObjectPart part in temp.Parts) - if (!((ContentManagementEntity)m_CMEntityHash[temp.UUID]).HasChildPrim(part.UUID)) - missingList.Add(part); - } - else //Entire group is missing from revision. (and is a new part in region) - { - foreach (SceneObjectPart part in temp.Parts) - missingList.Add(part); - } - } - return missingList; - } - - public void ClearAll() - { - m_CMEntityHash.Clear(); - m_NewlyCreatedEntityAura.Clear(); - } - - // Old uuid and new sceneobjectgroup - public AuraMetaEntity CreateAuraForNewlyCreatedEntity(SceneObjectPart part) - { - AuraMetaEntity ent = new AuraMetaEntity(part.ParentGroup.Scene, - part.GetWorldPosition(), - MetaEntity.TRANSLUCENT, - new Vector3(0,254,0), - part.Scale - ); - m_NewlyCreatedEntityAura.Add(part.UUID, ent); - return ent; - } - - // Old uuid and new sceneobjectgroup - public ContentManagementEntity CreateNewEntity(SceneObjectGroup group) - { - ContentManagementEntity ent = new ContentManagementEntity(group, false); - m_CMEntityHash.Add(group.UUID, ent); - return ent; - } - - public ContentManagementEntity CreateNewEntity(String xml, Scene scene) - { - ContentManagementEntity ent = new ContentManagementEntity(xml, scene, false); - if (ent == null) - return null; - m_CMEntityHash.Add(ent.UnchangedEntity.UUID, ent); - return ent; - } - - public bool RemoveEntity(UUID uuid) - { - if (!m_CMEntityHash.ContainsKey(uuid)) - return false; - m_CMEntityHash.Remove(uuid); - return true; - } - - public bool RemoveNewlyCreatedEntityAura(UUID uuid) - { - if (!m_NewlyCreatedEntityAura.ContainsKey(uuid)) - return false; - m_NewlyCreatedEntityAura.Remove(uuid); - return true; - } - - #endregion Public Methods - } -} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMModel.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMModel.cs deleted file mode 100644 index 84c7f292b9..0000000000 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMModel.cs +++ /dev/null @@ -1,366 +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.Diagnostics; - -using OpenMetaverse; - -using OpenSim; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Framework.Scenes.Serialization; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.OptionalModules.ContentManagement -{ - public class CMModel - { - #region Static Fields - - static float TimeToUpdate = 0; - static float TimeToConvertXml = 0; - private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - - #endregion Static Fields - - #region Fields - - /// - /// The class that contains all auras and metaentities used in the CMS. - /// - CMEntityCollection m_MetaEntityCollection = new CMEntityCollection(); - IContentDatabase m_database = null; - - #endregion Fields - - #region Constructors - - public CMModel() - { - } - - #endregion Constructors - - #region Public Properties - - public CMEntityCollection MetaEntityCollection - { - get { return m_MetaEntityCollection; } - } - - #endregion Public Properties - - #region Public Methods - - /// - /// Compares the scene's object group list to the list of meta entities. If there is an object group that does not have a corresponding meta entity - /// it is a new part that must have a green aura (for diff mode). - /// Returns list of ContentManagementEntities - /// - public ArrayList CheckForNewEntitiesMissingAuras(Scene scene) - { - ArrayList missingList = null; - ArrayList newList = new ArrayList(); - - m_log.Debug("[CONTENT MANAGEMENT] Checking for new scene object parts in scene: " + scene.RegionInfo.RegionName); - - //Check if the current scene has groups not included in the current list of MetaEntities - //If so, then the current scene's parts that are new should be marked green. - missingList = m_MetaEntityCollection.CheckForMissingEntities(scene.GetEntities()); - - foreach (Object missingPart in missingList) - { - if (m_MetaEntityCollection.Auras.ContainsKey(((SceneObjectPart)missingPart).UUID)) - continue; - newList.Add(m_MetaEntityCollection.CreateAuraForNewlyCreatedEntity((SceneObjectPart)missingPart)); - } - m_log.Info("Number of missing objects found: " + newList.Count); - return newList; - } - - /// - /// Uses the database to serialize all current scene objects into xml and save into a database with an accompanying log message. - /// - public void CommitRegion(Scene scene, String logMessage) - { - m_log.Debug("[CONTENT MANAG] saving " + scene.RegionInfo.RegionName + " with log message: " + logMessage + " length of message: " + logMessage.Length); - m_database.SaveRegion(scene.RegionInfo.RegionID, scene.RegionInfo.RegionName, logMessage); - m_log.Debug("[CONTENT MANAG] the region name we are dealing with heeeeeeeere: " + scene.RegionInfo.RegionName); - } - - public void DeleteAllMetaObjects() - { - m_MetaEntityCollection.ClearAll(); - } - - public ContentManagementEntity FindMetaEntityAffectedByUndo(UUID uuid) - { - ContentManagementEntity ent = GetMetaGroupByPrim(uuid); - return ent; - } - - //-------------------------------- HELPERS --------------------------------------------------------------------// - public ContentManagementEntity GetMetaGroupByPrim(UUID uuid) - { - foreach (Object ent in m_MetaEntityCollection.Entities.Values) - { - if (((ContentManagementEntity)ent).HasChildPrim(uuid)) - return (ContentManagementEntity)ent; - } - return null; - } - - public void Initialise(string database) - { - if (database == "FileSystemDatabase") - m_database = new FileSystemDatabase(); - else if (database == "GitDatabase") - m_database = new GitDatabase(); - } - - public void InitialiseDatabase(Scene scene, string dir) - { - m_database.Initialise(scene, dir); - } - - /// - /// Should be called just once to finish initializing the database. - /// - public void PostInitialise() - { - m_database.PostInitialise(); - } - - /// - /// Removes the green aura when an a new scene object group is deleted. - /// - public void RemoveOrUpdateDeletedEntity(SceneObjectGroup group) - { - // Deal with new parts not revisioned that have been deleted. - SceneObjectPart[] parts = group.Parts; - for (int i = 0; i < parts.Length; i++) - { - if (m_MetaEntityCollection.Auras.ContainsKey(parts[i].UUID)) - m_MetaEntityCollection.RemoveNewlyCreatedEntityAura(parts[i].UUID); - } - } - - /// - /// Retrieves the latest revision of a region in xml form, - /// converts it to scene object groups and scene presences, - /// swaps the current scene's entity list with the revision's list. - /// Note: Since deleted objects while - /// - public void RollbackRegion(Scene scene) - { - System.Collections.ArrayList xmllist = null; - SceneObjectGroup temp = null; - System.Collections.Hashtable deleteListUUIDs = new Hashtable(); -// Dictionary SearchList = new Dictionary(); - Dictionary ReplacementList = new Dictionary(); - int revision = m_database.GetMostRecentRevision(scene.RegionInfo.RegionID); -// EntityBase[] searchArray; - - xmllist = m_database.GetRegionObjectXMLList(scene.RegionInfo.RegionID, revision); - if (xmllist == null) - { - m_log.Info("[CMMODEL]: Region (" + scene.RegionInfo.RegionID + ") does not have given revision number (" + revision + ")."); - return; - } - - m_log.Info("[CMMODEL]: Region (" + scene.RegionInfo.RegionID + ") revision number (" + revision + ")."); - m_log.Info("[CMMODEL]: Scene Objects = " + xmllist.Count); - m_log.Info("[CMMODEL]: Converting scene entities list to specified revision."); - - m_log.ErrorFormat("[CMMODEL]: 1"); - - foreach (string xml in xmllist) - { - try - { - temp = SceneObjectSerializer.FromXml2Format(xml); - temp.SetScene(scene); - - SceneObjectPart[] parts = temp.Parts; - for (int i = 0; i < parts.Length; i++) - parts[i].RegionHandle = scene.RegionInfo.RegionHandle; - - ReplacementList.Add(temp.UUID, (EntityBase)temp); - } - catch (Exception e) - { - m_log.Info("[CMMODEL]: Error while creating replacement list for rollback: " + e); - } - } - - //If in scene but not in revision and not a client, remove them - while (true) - { - try - { - foreach (EntityBase entity in scene.GetEntities()) - { - if (entity == null) - continue; - - if (entity is ScenePresence) - { - ReplacementList.Add(entity.UUID, entity); - continue; - } - else //if (!ReplacementList.ContainsKey(entity.UUID)) - deleteListUUIDs.Add(entity.UUID, 0); - } - } - catch(Exception e) - { - m_log.ErrorFormat("[CMMODEL]: " + e); - deleteListUUIDs.Clear(); - ReplacementList.Clear(); - continue; - } - break; - } - - foreach (UUID uuid in deleteListUUIDs.Keys) - { - try - { - // I thought that the DeleteGroup() function would handle all of this, but it doesn't. I'm not sure WHAT it handles. - ((SceneObjectGroup)scene.Entities[uuid]).DetachFromBackup(); - scene.PhysicsScene.RemovePrim(((SceneObjectGroup)scene.Entities[uuid]).RootPart.PhysActor); - scene.SendKillObject(new List() { scene.Entities[uuid].LocalId }); - scene.SceneGraph.DeleteSceneObject(uuid, false); - ((SceneObjectGroup)scene.Entities[uuid]).DeleteGroupFromScene(false); - scene.SendKillObject(new List() { ((SceneObjectGroup)scene.Entities[uuid]).LocalId }); - } - catch(Exception e) - { - m_log.ErrorFormat("[CMMODEL]: Error while removing objects from scene: " + e); - } - } - - lock (scene) - { - scene.Entities.Clear(); - - foreach (KeyValuePair kvp in ReplacementList) - { - scene.Entities.Add(kvp.Value); - } - } - - foreach (EntityBase ent in ReplacementList.Values) - { - try - { - if (!(ent is SceneObjectGroup)) - continue; - - if ((((SceneObjectGroup)ent).RootPart.GetEffectiveObjectFlags() & (uint) PrimFlags.Phantom) == 0) - ((SceneObjectGroup)ent).ApplyPhysics(true); - ((SceneObjectGroup)ent).AttachToBackup(); - ((SceneObjectGroup)ent).HasGroupChanged = true; // If not true, then attaching to backup does nothing because no change is detected. - ((SceneObjectGroup)ent).ScheduleGroupForFullUpdate(); - } - catch(Exception e) - { - m_log.ErrorFormat("[CMMODEL]: Error while attaching new scene entities to backup and scheduling for a full update: " + e); - } - } - m_log.Info("[CMMODEL]: Scheduling a backup of new scene object groups to backup."); - scene.Backup(true); - } - - /// - /// Downloads the latest revision of the given scene and converts the xml file to CMEntities. After this method, the view can find the differences - /// and display the differences to clients. - /// - public void UpdateCMEntities(Scene scene) - { - Stopwatch x = new Stopwatch(); - x.Start(); - - System.Collections.ArrayList xmllist = null; - m_log.Debug("[CONTENT MANAGEMENT] Retrieving object xml files for region: " + scene.RegionInfo.RegionID); - xmllist = m_database.GetRegionObjectXMLList(scene.RegionInfo.RegionID); - m_log.Info("[FSDB]: got list"); - if (xmllist == null) - return; - - Stopwatch y = new Stopwatch(); - y.Start(); - foreach (string xml in xmllist) - m_MetaEntityCollection.CreateNewEntity(xml, scene); - y.Stop(); - TimeToConvertXml += y.ElapsedMilliseconds; - m_log.Info("[FileSystemDatabase] Time spent converting xml to metaentities for " + scene.RegionInfo.RegionName + ": " + y.ElapsedMilliseconds); - m_log.Info("[FileSystemDatabase] Time spent converting xml to metaentities so far: " + TimeToConvertXml); - - m_log.Info("[FSDB]: checking for new scene object parts missing green auras and create the auras"); - CheckForNewEntitiesMissingAuras(scene); - - x.Stop(); - TimeToUpdate += x.ElapsedMilliseconds; - m_log.Info("[FileSystemDatabase] Time spent Updating entity list for " + scene.RegionInfo.RegionName + ": " + x.ElapsedMilliseconds); - m_log.Info("[FileSystemDatabase] Time spent Updating so far: " + TimeToUpdate); - } - - /// - /// Detects if a scene object group from the scene list has moved or changed scale. The green aura - /// that surrounds the object is then moved or scaled with the group. - /// - public System.Collections.ArrayList UpdateNormalEntityEffects(SceneObjectGroup group) - { - System.Collections.ArrayList auraList = new System.Collections.ArrayList(); - if (group == null) - return null; - - SceneObjectPart[] parts = group.Parts; - for (int i = 0; i < parts.Length; i++) - { - SceneObjectPart part = parts[i]; - if (m_MetaEntityCollection.Auras.ContainsKey(part.UUID)) - { - ((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]).SetAura(new Vector3(0, 254, 0), part.Scale); - ((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]).RootPart.GroupPosition = part.GetWorldPosition(); - auraList.Add((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]); - } - } - - return auraList; - } - - #endregion Public Methods - } -} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMView.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMView.cs deleted file mode 100644 index 3807ccda47..0000000000 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMView.cs +++ /dev/null @@ -1,206 +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. - */ - -#region Header - -// CMView.cs created with MonoDevelop -// User: bongiojp at 11:57 AM 7/3/2008 -// -// To change standard headers go to Edit->Preferences->Coding->Standard Headers -// - -#endregion Header - -using System; -using System.Collections; -using System.Collections.Generic; - -using OpenMetaverse; - -using OpenSim; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.OptionalModules.ContentManagement -{ - public class CMView - { - #region Static Fields - - private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - - #endregion Static Fields - - #region Fields - - CMModel m_model = null; - - #endregion Fields - - #region Constructors - - public CMView() - { - } - - #endregion Constructors - - #region Public Methods - - // Auras To - public void DisplayAuras(CMEntityCollection auraCollection) - { - foreach (Object ent in auraCollection.Auras.Values) - ((AuraMetaEntity)ent).SendFullUpdateToAll(); - } - - // Auras To Client - public void DisplayAuras(CMEntityCollection auraCollection, IClientAPI client) - { - foreach (Object ent in auraCollection.Auras.Values) - ((AuraMetaEntity)ent).SendFullUpdate(client); - } - - // Auras from List To ALL - public void DisplayAuras(ArrayList list) - { - foreach (Object ent in list) - { - m_log.Debug("[CONTENT MANAGEMENT] displaying new aura riiiiiiiiiiiight NOW"); - ((AuraMetaEntity)ent).SendFullUpdateToAll(); - } - } - - // Entities to ALL - public void DisplayEntities(CMEntityCollection entityCollection) - { - foreach (Object ent in entityCollection.Entities.Values) - ((ContentManagementEntity)ent).SendFullDiffUpdateToAll(); - } - - // Entities to Client - public void DisplayEntities(CMEntityCollection entityCollection, IClientAPI client) - { - foreach (Object ent in entityCollection.Entities.Values) - ((ContentManagementEntity)ent).SendFullDiffUpdate(client); - } - - // Entities from List to ALL - public void DisplayEntities(ArrayList list) - { - foreach (Object ent in list) - ((ContentManagementEntity)ent).SendFullDiffUpdateToAll(); - } - - // Entity to ALL - public void DisplayEntity(ContentManagementEntity ent) - { - ent.SendFullDiffUpdateToAll(); - } - - public void DisplayHelpMenu(Scene scene) - { - string menu = "Menu:\n"; - menu += "commit (ci) - saves current state of the region to a database on the server\n"; - menu += "diff-mode (dm) - displays those aspects of region that have not been saved but changed since the very last revision. Will dynamically update as you change environment.\n"; - SendSimChatMessage(scene, menu); - } - - public void DisplayMetaEntity(UUID uuid) - { - ContentManagementEntity group = m_model.GetMetaGroupByPrim(uuid); - if (group != null) - group.SendFullDiffUpdateToAll(); - } - - /// - /// update all clients of red/green/blue auras and meta entities that the model knows about. - /// - public void DisplayRecentChanges() - { - m_log.Debug("[CONTENT MANAGEMENT] Sending update to clients for " + m_model.MetaEntityCollection.Entities.Count + " objects."); - DisplayEntities(m_model.MetaEntityCollection); - DisplayAuras(m_model.MetaEntityCollection); - } - - public void Hide(ContentManagementEntity ent) - { - ent.HideFromAll(); - } - - public void HideAllAuras() - { - foreach (Object obj in m_model.MetaEntityCollection.Auras.Values) - ((MetaEntity)obj).HideFromAll(); - } - - public void HideAllMetaEntities() - { - foreach (Object obj in m_model.MetaEntityCollection.Entities.Values) - ((ContentManagementEntity)obj).HideFromAll(); - } - - public void Initialise(CMModel model) - { - m_model = model; - } - - /// - /// Figures out if the part deleted was a new scene object part or a revisioned part that's been deleted. - /// If it's a new scene object, any green aura attached to it is deleted. - /// If a revisioned part is deleted, a new full update is sent to the environment of the meta entity, which will - /// figure out that there should be a red aura and not a blue aura/beam. - /// - public void RemoveOrUpdateDeletedEntity(SceneObjectGroup group) - { - // Deal with revisioned parts that have been deleted. - if (m_model.MetaEntityCollection.Entities.ContainsKey(group.UUID)) - ((ContentManagementEntity)m_model.MetaEntityCollection.Entities[group.UUID]).SendFullDiffUpdateToAll(); - - // Deal with new parts not revisioned that have been deleted. - foreach (SceneObjectPart part in group.Parts) - if (m_model.MetaEntityCollection.Auras.ContainsKey(part.UUID)) - ((AuraMetaEntity)m_model.MetaEntityCollection.Auras[part.UUID]).HideFromAll(); - } - - public void SendMetaEntitiesToNewClient(IClientAPI client) - { - } - - public void SendSimChatMessage(Scene scene, string message) - { - scene.SimChat(Utils.StringToBytes(message), - ChatTypeEnum.Broadcast, 0, new Vector3(0,0,0), "Content Manager", UUID.Zero, false); - } - - #endregion Public Methods - } -} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementEntity.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementEntity.cs deleted file mode 100644 index 0248f368f2..0000000000 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementEntity.cs +++ /dev/null @@ -1,375 +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.Generic; -using System.Drawing; - -using OpenMetaverse; - -using Nini.Config; - -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Framework.Scenes.Serialization; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.OptionalModules.ContentManagement -{ - public class ContentManagementEntity : MetaEntity - { - #region Static Fields - -// static float TimeToDiff = 0; -// static float TimeToCreateEntities = 0; - - #endregion Static Fields - - #region Fields - - protected Dictionary m_AuraEntities = new Dictionary(); - protected Dictionary m_BeamEntities = new Dictionary(); - - // The LinkNum of parts in m_Entity and m_UnchangedEntity are the same though UUID and LocalId are different. - // This can come in handy. - protected SceneObjectGroup m_UnchangedEntity = null; - - /// - /// Should be set to true when there is a difference between m_UnchangedEntity and the corresponding scene object group in the scene entity list. - /// - bool DiffersFromSceneGroup = false; - - #endregion Fields - - #region Constructors - - public ContentManagementEntity(SceneObjectGroup Unchanged, bool physics) - : base(Unchanged, false) - { - m_UnchangedEntity = Unchanged.Copy(false); - } - - public ContentManagementEntity(string objectXML, Scene scene, bool physics) - : base(objectXML, scene, false) - { - m_UnchangedEntity = SceneObjectSerializer.FromXml2Format(objectXML); - } - - #endregion Constructors - - #region Public Properties - - public SceneObjectGroup UnchangedEntity - { - get { return m_UnchangedEntity; } - } - - #endregion Public Properties - - #region Private Methods - - /// - /// Check if an entitybase list (like that returned by scene.GetEntities()) contains a group with the rootpart uuid that matches the current uuid. - /// - private bool ContainsKey(List list, UUID uuid) - { - foreach (EntityBase part in list) - if (part.UUID == uuid) - return true; - return false; - } - - private SceneObjectGroup GetGroupByUUID(System.Collections.Generic.List list, UUID uuid) - { - foreach (EntityBase ent in list) - { - if (ent is SceneObjectGroup) - if (ent.UUID == uuid) - return (SceneObjectGroup)ent; - } - return null; - } - - #endregion Private Methods - - #region Public Methods - - /// - /// Search for a corresponding group UUID in the scene. If not found, then the revisioned group this CMEntity represents has been deleted. Mark the metaentity appropriately. - /// If a matching UUID is found in a scene object group, compare the two for differences. If differences exist, Mark the metaentity appropriately. - /// - public void FindDifferences() - { - List sceneEntityList = new List(m_Entity.Scene.GetEntities()); - DiffersFromSceneGroup = false; - // if group is not contained in scene's list - if (!ContainsKey(sceneEntityList, m_UnchangedEntity.UUID)) - { - foreach (SceneObjectPart part in m_UnchangedEntity.Parts) - { - // if scene list no longer contains this part, display translucent part and mark with red aura - if (!ContainsKey(sceneEntityList, part.UUID)) - { - // if already displaying a red aura over part, make sure its red - if (m_AuraEntities.ContainsKey(part.UUID)) - { - m_AuraEntities[part.UUID].SetAura(new Vector3(254, 0, 0), part.Scale); - } - else - { - AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene, - part.GetWorldPosition(), - MetaEntity.TRANSLUCENT, - new Vector3(254, 0, 0), - part.Scale - ); - m_AuraEntities.Add(part.UUID, auraGroup); - } - SceneObjectPart metaPart = m_Entity.GetLinkNumPart(part.LinkNum); - SetPartTransparency(metaPart, MetaEntity.TRANSLUCENT); - } - // otherwise, scene will not contain the part. note: a group can not remove a part without changing group id - } - - // a deleted part has no where to point a beam particle system, - // if a metapart had a particle system (maybe it represented a moved part) remove it - if (m_BeamEntities.ContainsKey(m_UnchangedEntity.RootPart.UUID)) - { - m_BeamEntities[m_UnchangedEntity.RootPart.UUID].HideFromAll(); - m_BeamEntities.Remove(m_UnchangedEntity.RootPart.UUID); - } - - DiffersFromSceneGroup = true; - } - // if scene list does contain group, compare each part in group for differences and display beams and auras appropriately - else - { - MarkWithDifferences((SceneObjectGroup)GetGroupByUUID(sceneEntityList, m_UnchangedEntity.UUID)); - } - } - - /// - /// Check if the revisioned scene object group that this CMEntity is based off of contains a child with the given UUID. - /// - public bool HasChildPrim(UUID uuid) - { - return m_UnchangedEntity.ContainsPart(uuid); - } - - /// - /// Check if the revisioned scene object group that this CMEntity is based off of contains a child with the given LocalId. - /// - public bool HasChildPrim(uint localID) - { - foreach (SceneObjectPart part in m_UnchangedEntity.Parts) - if (part.LocalId == localID) - return true; - - return false; - } - - public override void Hide(IClientAPI client) - { - base.Hide(client); - foreach (MetaEntity group in m_AuraEntities.Values) - group.Hide(client); - foreach (MetaEntity group in m_BeamEntities.Values) - group.Hide(client); - } - - public override void HideFromAll() - { - base.HideFromAll(); - foreach (MetaEntity group in m_AuraEntities.Values) - group.HideFromAll(); - foreach (MetaEntity group in m_BeamEntities.Values) - group.HideFromAll(); - } - - /// - /// Returns true if there was a change between meta entity and the entity group, false otherwise. - /// If true is returned, it is assumed the metaentity's appearance has changed to reflect the difference (though clients haven't been updated). - /// - public bool MarkWithDifferences(SceneObjectGroup sceneEntityGroup) - { - SceneObjectPart sceneEntityPart; - SceneObjectPart metaEntityPart; - Diff differences; - bool changed = false; - - // Use "UnchangedEntity" to do comparisons because its text, transparency, and other attributes will be just as the user - // had originally saved. - // m_Entity will NOT necessarily be the same entity as the user had saved. - foreach (SceneObjectPart UnchangedPart in m_UnchangedEntity.Parts) - { - //This is the part that we use to show changes. - metaEntityPart = m_Entity.GetLinkNumPart(UnchangedPart.LinkNum); - if (sceneEntityGroup.ContainsPart(UnchangedPart.UUID)) - { - sceneEntityPart = sceneEntityGroup.GetChildPart(UnchangedPart.UUID); - differences = Difference.FindDifferences(UnchangedPart, sceneEntityPart); - if (differences != Diff.NONE) - metaEntityPart.Text = "CHANGE: " + differences.ToString(); - if (differences != 0) - { - // Root Part that has been modified - if ((differences & Diff.POSITION) > 0) - { - // If the position of any part has changed, make sure the RootPart of the - // meta entity is pointing with a beam particle system - if (m_BeamEntities.ContainsKey(m_UnchangedEntity.RootPart.UUID)) - { - m_BeamEntities[m_UnchangedEntity.RootPart.UUID].HideFromAll(); - m_BeamEntities.Remove(m_UnchangedEntity.RootPart.UUID); - } - BeamMetaEntity beamGroup = new BeamMetaEntity(m_Entity.Scene, - m_UnchangedEntity.RootPart.GetWorldPosition(), - MetaEntity.TRANSLUCENT, - sceneEntityPart, - new Vector3(0, 0, 254) - ); - m_BeamEntities.Add(m_UnchangedEntity.RootPart.UUID, beamGroup); - } - - if (m_AuraEntities.ContainsKey(UnchangedPart.UUID)) - { - m_AuraEntities[UnchangedPart.UUID].HideFromAll(); - m_AuraEntities.Remove(UnchangedPart.UUID); - } - AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene, - UnchangedPart.GetWorldPosition(), - MetaEntity.TRANSLUCENT, - new Vector3(0, 0, 254), - UnchangedPart.Scale - ); - m_AuraEntities.Add(UnchangedPart.UUID, auraGroup); - SetPartTransparency(metaEntityPart, MetaEntity.TRANSLUCENT); - - DiffersFromSceneGroup = true; - } - else // no differences between scene part and meta part - { - if (m_BeamEntities.ContainsKey(m_UnchangedEntity.RootPart.UUID)) - { - m_BeamEntities[m_UnchangedEntity.RootPart.UUID].HideFromAll(); - m_BeamEntities.Remove(m_UnchangedEntity.RootPart.UUID); - } - if (m_AuraEntities.ContainsKey(UnchangedPart.UUID)) - { - m_AuraEntities[UnchangedPart.UUID].HideFromAll(); - m_AuraEntities.Remove(UnchangedPart.UUID); - } - SetPartTransparency(metaEntityPart, MetaEntity.NONE); - } - } - else //The entity currently in the scene is missing parts from the metaentity saved, so mark parts red as deleted. - { - if (m_AuraEntities.ContainsKey(UnchangedPart.UUID)) - { - m_AuraEntities[UnchangedPart.UUID].HideFromAll(); - m_AuraEntities.Remove(UnchangedPart.UUID); - } - AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene, - UnchangedPart.GetWorldPosition(), - MetaEntity.TRANSLUCENT, - new Vector3(254, 0, 0), - UnchangedPart.Scale - ); - m_AuraEntities.Add(UnchangedPart.UUID, auraGroup); - SetPartTransparency(metaEntityPart, MetaEntity.TRANSLUCENT); - - DiffersFromSceneGroup = true; - } - } - - return changed; - } - - public void SendFullAuraUpdate(IClientAPI client) - { - if (DiffersFromSceneGroup) - { - foreach (AuraMetaEntity group in m_AuraEntities.Values) - group.SendFullUpdate(client); - } - } - - public void SendFullAuraUpdateToAll() - { - if (DiffersFromSceneGroup) - { - foreach (AuraMetaEntity group in m_AuraEntities.Values) - group.SendFullUpdateToAll(); - } - } - - public void SendFullBeamUpdate(IClientAPI client) - { - if (DiffersFromSceneGroup) - { - foreach (BeamMetaEntity group in m_BeamEntities.Values) - group.SendFullUpdate(client); - } - } - - public void SendFullBeamUpdateToAll() - { - if (DiffersFromSceneGroup) - { - foreach (BeamMetaEntity group in m_BeamEntities.Values) - group.SendFullUpdateToAll(); - } - } - - public void SendFullDiffUpdate(IClientAPI client) - { - FindDifferences(); - if (DiffersFromSceneGroup) - { - SendFullUpdate(client); - SendFullAuraUpdate(client); - SendFullBeamUpdate(client); - } - } - - public void SendFullDiffUpdateToAll() - { - FindDifferences(); - if (DiffersFromSceneGroup) - { - SendFullUpdateToAll(); - SendFullAuraUpdateToAll(); - SendFullBeamUpdateToAll(); - } - } - - #endregion Public Methods - } -} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementModule.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementModule.cs deleted file mode 100644 index 3d1c346dc8..0000000000 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementModule.cs +++ /dev/null @@ -1,163 +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. - */ - -#region Header - -// ContentManagementModule.cs -// User: bongiojp - -#endregion Header - -using System; -using System.Collections.Generic; -using System.Threading; - -using OpenMetaverse; - -using Nini.Config; - -using OpenSim; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.OptionalModules.ContentManagement -{ - public class ContentManagementModule : IRegionModule - { - #region Static Fields - - private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - - #endregion Static Fields - - #region Fields - - bool initialised = false; - CMController m_control = null; - bool m_enabled = false; - CMModel m_model = null; - bool m_posted = false; - CMView m_view = null; - - #endregion Fields - - #region Public Properties - - public bool IsSharedModule - { - get { return true; } - } - - public string Name - { - get { return "ContentManagementModule"; } - } - - #endregion Public Properties - - #region Public Methods - - public void Close() - { - } - - public void Initialise(Scene scene, IConfigSource source) - { - string databaseDir = "./"; - string database = "FileSystemDatabase"; - int channel = 345; - try - { - if (source.Configs["CMS"] == null) - return; - - m_enabled = source.Configs["CMS"].GetBoolean("enabled", false); - databaseDir = source.Configs["CMS"].GetString("directory", databaseDir); - database = source.Configs["CMS"].GetString("database", database); - channel = source.Configs["CMS"].GetInt("channel", channel); - - if (database != "FileSystemDatabase" && database != "GitDatabase") - { - m_log.ErrorFormat("[Content Management]: The Database attribute must be defined as either FileSystemDatabase or GitDatabase"); - m_enabled = false; - } - } - catch (Exception e) - { - m_log.ErrorFormat("[Content Management]: Exception thrown while reading parameters from configuration file. Message: " + e); - m_enabled = false; - } - - if (!m_enabled) - { - m_log.Info("[Content Management]: Content Management System is not Enabled."); - return; - } - - lock (this) - { - if (!initialised) //only init once - { - m_view = new CMView(); - m_model = new CMModel(); - m_control = new CMController(m_model, m_view, scene, channel); - m_model.Initialise(database); - m_view.Initialise(m_model); - - initialised = true; - m_model.InitialiseDatabase(scene, databaseDir); - } - else - { - m_model.InitialiseDatabase(scene, databaseDir); - m_control.RegisterNewRegion(scene); - } - } - } - - public void PostInitialise() - { - if (! m_enabled) - return; - - lock (this) - { - if (!m_posted) //only post once - { - m_model.PostInitialise(); - m_posted = true; - } - } - } - - #endregion Public Methods - } -} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/FileSystemDatabase.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/FileSystemDatabase.cs deleted file mode 100644 index a3d7977006..0000000000 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/FileSystemDatabase.cs +++ /dev/null @@ -1,317 +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. - */ - -#region Header - -// FileSystemDatabase.cs -// User: bongiojp - -#endregion Header - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using Slash = System.IO.Path; -using System.Reflection; -using System.Xml; - -using OpenMetaverse; - -using Nini.Config; - -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.CoreModules.World.Serialiser; -using OpenSim.Region.CoreModules.World.Terrain; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.OptionalModules.ContentManagement -{ - public class FileSystemDatabase : IContentDatabase - { - #region Static Fields - - public static float TimeToDownload = 0; - public static float TimeToSave = 0; - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - #endregion Static Fields - - #region Fields - - private string m_repodir = null; - private Dictionary m_scenes = new Dictionary(); - private Dictionary m_serialiser = new Dictionary(); - - #endregion Fields - - #region Constructors - - public FileSystemDatabase() - { - } - - #endregion Constructors - - #region Private Methods - - // called by postinitialise - private void CreateDirectory() - { - string scenedir; - if (!Directory.Exists(m_repodir)) - Directory.CreateDirectory(m_repodir); - - foreach (UUID region in m_scenes.Keys) - { - scenedir = m_repodir + Slash.DirectorySeparatorChar + region + Slash.DirectorySeparatorChar; - if (!Directory.Exists(scenedir)) - Directory.CreateDirectory(scenedir); - } - } - - // called by postinitialise - private void SetupSerialiser() - { - if (m_serialiser.Count == 0) - { - foreach (UUID region in m_scenes.Keys) - { - m_serialiser.Add(region, m_scenes[region].RequestModuleInterface()); - } - } - } - - #endregion Private Methods - - #region Public Methods - - public int GetMostRecentRevision(UUID regionid) - { - return NumOfRegionRev(regionid); - } - - public string GetRegionObjectHeightMap(UUID regionid) - { - String filename = m_repodir + Slash.DirectorySeparatorChar + regionid + - Slash.DirectorySeparatorChar + "heightmap.r32"; - FileStream fs = new FileStream(filename, FileMode.Open); - StreamReader sr = new StreamReader(fs); - String result = sr.ReadToEnd(); - sr.Close(); - fs.Close(); - return result; - } - - public string GetRegionObjectHeightMap(UUID regionid, int revision) - { - String filename = m_repodir + Slash.DirectorySeparatorChar + regionid + - Slash.DirectorySeparatorChar + "heightmap.r32"; - FileStream fs = new FileStream(filename, FileMode.Open); - StreamReader sr = new StreamReader(fs); - String result = sr.ReadToEnd(); - sr.Close(); - fs.Close(); - return result; - } - - public System.Collections.ArrayList GetRegionObjectXMLList(UUID regionid, int revision) - { - System.Collections.ArrayList objectList = new System.Collections.ArrayList(); - string filename = m_repodir + Slash.DirectorySeparatorChar + regionid + Slash.DirectorySeparatorChar + - + revision + Slash.DirectorySeparatorChar + "objects.xml"; - XmlDocument doc = new XmlDocument(); - XmlNode rootNode; - //int primCount = 0; - //SceneObjectGroup obj = null; - - if (File.Exists(filename)) - { - XmlTextReader reader = new XmlTextReader(filename); - reader.WhitespaceHandling = WhitespaceHandling.None; - doc.Load(reader); - reader.Close(); - rootNode = doc.FirstChild; - foreach (XmlNode aPrimNode in rootNode.ChildNodes) - { - objectList.Add(aPrimNode.OuterXml); - } - return objectList; - } - return null; - } - - public System.Collections.ArrayList GetRegionObjectXMLList(UUID regionid) - { - int revision = NumOfRegionRev(regionid); - m_log.Info("[FSDB]: found revisions:" + revision); - System.Collections.ArrayList xmlList = new System.Collections.ArrayList(); - string filename = m_repodir + Slash.DirectorySeparatorChar + regionid + Slash.DirectorySeparatorChar + - + revision + Slash.DirectorySeparatorChar + "objects.xml"; - XmlDocument doc = new XmlDocument(); - XmlNode rootNode; - - m_log.Info("[FSDB]: Checking if " + filename + " exists."); - if (File.Exists(filename)) - { - Stopwatch x = new Stopwatch(); - x.Start(); - - XmlTextReader reader = new XmlTextReader(filename); - reader.WhitespaceHandling = WhitespaceHandling.None; - doc.Load(reader); - reader.Close(); - rootNode = doc.FirstChild; - - foreach (XmlNode aPrimNode in rootNode.ChildNodes) - { - xmlList.Add(aPrimNode.OuterXml); - } - - x.Stop(); - TimeToDownload += x.ElapsedMilliseconds; - m_log.Info("[FileSystemDatabase] Time spent retrieving xml files so far: " + TimeToDownload); - - return xmlList; - } - return null; - } - - public void Initialise(Scene scene, string dir) - { - lock (this) - { - if (m_repodir == null) - m_repodir = dir; - } - lock (m_scenes) - m_scenes.Add(scene.RegionInfo.RegionID, scene); - } - - public System.Collections.Generic.SortedDictionary ListOfRegionRevisions(UUID regionid) - { - SortedDictionary revisionDict = new SortedDictionary(); - - string scenedir = m_repodir + Slash.DirectorySeparatorChar + regionid + Slash.DirectorySeparatorChar; - string[] directories = Directory.GetDirectories(scenedir); - - FileStream fs = null; - StreamReader sr = null; - String logMessage = ""; - String logLocation = ""; - foreach (string revisionDir in directories) - { - try - { - logLocation = revisionDir + Slash.DirectorySeparatorChar + "log"; - fs = new FileStream(logLocation, FileMode.Open); - sr = new StreamReader(fs); - logMessage = sr.ReadToEnd(); - sr.Close(); - fs.Close(); - revisionDict.Add(revisionDir, logMessage); - } - catch (Exception) - { - } - } - - return revisionDict; - } - - public int NumOfRegionRev(UUID regionid) - { - string scenedir = m_repodir + Slash.DirectorySeparatorChar + regionid + Slash.DirectorySeparatorChar; - m_log.Info("[FSDB]: Reading scene dir: " + scenedir); - string[] directories = Directory.GetDirectories(scenedir); - return directories.Length; - } - - // Run once and only once. - public void PostInitialise() - { - SetupSerialiser(); - - m_log.Info("[FSDB]: Creating repository in " + m_repodir + "."); - CreateDirectory(); - } - - public void SaveRegion(UUID regionid, string regionName, string logMessage) - { - m_log.Info("[FSDB]: ..............................."); - string scenedir = m_repodir + Slash.DirectorySeparatorChar + regionid + Slash.DirectorySeparatorChar; - - m_log.Info("[FSDB]: checking if scene directory exists: " + scenedir); - if (!Directory.Exists(scenedir)) - Directory.CreateDirectory(scenedir); - - int newRevisionNum = GetMostRecentRevision(regionid)+1; - string revisiondir = scenedir + newRevisionNum + Slash.DirectorySeparatorChar; - - m_log.Info("[FSDB]: checking if revision directory exists: " + revisiondir); - if (!Directory.Exists(revisiondir)) - Directory.CreateDirectory(revisiondir); - - try { - Stopwatch x = new Stopwatch(); - x.Start(); - if (m_scenes.ContainsKey(regionid)) - { - m_serialiser[regionid].SerialiseRegion(m_scenes[regionid], revisiondir); - } - x.Stop(); - TimeToSave += x.ElapsedMilliseconds; - m_log.Info("[FileSystemDatabase] Time spent serialising regions to files on disk for " + regionName + ": " + x.ElapsedMilliseconds); - m_log.Info("[FileSystemDatabase] Time spent serialising regions to files on disk so far: " + TimeToSave); - } - catch (Exception e) - { - m_log.ErrorFormat("[FSDB]: Serialisation of region failed: " + e); - return; - } - - try { - // Finish by writing log message. - FileStream file = new FileStream(revisiondir + "log", FileMode.Create, FileAccess.ReadWrite); - StreamWriter sw = new StreamWriter(file); - sw.Write(logMessage); - sw.Close(); - } - catch (Exception e) - { - m_log.ErrorFormat("[FSDB]: Failed trying to save log file " + e); - return; - } - } - - #endregion Public Methods - } -} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/GitDatabase.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/GitDatabase.cs deleted file mode 100644 index 80a0a939d9..0000000000 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/GitDatabase.cs +++ /dev/null @@ -1,167 +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. - */ - -#region Header - -// GitDatabase.cs -// -// -// - -#endregion Header - -using System; -using System.Collections.Generic; -using System.IO; -using Slash = System.IO.Path; -using System.Reflection; -using System.Xml; - -using OpenMetaverse; - -using Nini.Config; - -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.CoreModules.World.Serialiser; -using OpenSim.Region.CoreModules.World.Terrain; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.OptionalModules.ContentManagement -{ - /// - /// Just a stub :-( - /// - public class GitDatabase : IContentDatabase - { - #region Constructors - - public GitDatabase() - { - } - - #endregion Constructors - - #region Public Methods - - public SceneObjectGroup GetMostRecentObjectRevision(UUID id) - { - return null; - } - - public int GetMostRecentRevision(UUID regionid) - { - return 0; - } - - public SceneObjectGroup GetObjectRevision(UUID id, int revision) - { - return null; - } - - public System.Collections.ArrayList GetObjectsFromRegion(UUID regionid, int revision) - { - return null; - } - - public string GetRegionObjectHeightMap(UUID regionid) - { - return null; - } - - public string GetRegionObjectHeightMap(UUID regionid, int revision) - { - return null; - } - - public string GetRegionObjectXML(UUID regionid) - { - return null; - } - - public string GetRegionObjectXML(UUID regionid, int revision) - { - return null; - } - - public System.Collections.ArrayList GetRegionObjectXMLList(UUID regionid) - { - return null; - } - - public System.Collections.ArrayList GetRegionObjectXMLList(UUID regionid, int revision) - { - return null; - } - - public bool InRepository(UUID id) - { - return false; - } - - public void Initialise(Scene scene, String dir) - { - } - - public System.Collections.Generic.SortedDictionary ListOfObjectRevisions(UUID id) - { - return null; - } - - public System.Collections.Generic.SortedDictionary ListOfRegionRevisions(UUID id) - { - return null; - } - - public int NumOfObjectRev(UUID id) - { - return 0; - } - - public int NumOfRegionRev(UUID regionid) - { - return 0; - } - - public void PostInitialise() - { - } - - public void SaveObject(SceneObjectGroup entity) - { - } - - public void SaveRegion(UUID regionid, string regionName, string logMessage) - { - } - - #endregion Public Methods - } -} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/IContentDatabase.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/IContentDatabase.cs deleted file mode 100644 index fc1f1156ca..0000000000 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/IContentDatabase.cs +++ /dev/null @@ -1,94 +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. - */ - -#region Header - -// IContentDatabase.cs -// User: bongiojp -// -// -// - -#endregion Header - -using System; -using OpenMetaverse; -using OpenSim.Region.Framework.Scenes; -using Nini.Config; - -namespace OpenSim.Region.OptionalModules.ContentManagement -{ - public interface IContentDatabase - { - #region Methods - - /// - /// Returns the most recent revision number of a region. - /// - int GetMostRecentRevision(UUID regionid); - - string GetRegionObjectHeightMap(UUID regionid); - - string GetRegionObjectHeightMap(UUID regionid, int revision); - - /// - /// Retrieves the xml that describes each individual object from the last revision or specific revision of the given region. - /// - System.Collections.ArrayList GetRegionObjectXMLList(UUID regionid); - - System.Collections.ArrayList GetRegionObjectXMLList(UUID regionid, int revision); - - /// - /// Similar to the IRegionModule function. This is the function to be called before attempting to interface with the database. - /// Initialise should be called one for each region to be contained in the database. The directory should be the full path - /// to the repository and will only be defined once, regardless of how many times the method is called. - /// - void Initialise(Scene scene, String dir); - - /// - /// Returns a list of the revision numbers and corresponding log messages for a given region. - /// - System.Collections.Generic.SortedDictionary ListOfRegionRevisions(UUID id); - - /// - /// Returns the total number of revisions saved for a specific region. - /// - int NumOfRegionRev(UUID regionid); - - /// - /// Should be called once after Initialise has been called. - /// - void PostInitialise(); - - /// - /// Saves the Region terrain map and objects within the region as xml to the database. - /// - void SaveRegion(UUID regionid, string regionName, string logMessage); - - #endregion Methods - } -} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs deleted file mode 100644 index cd60f4bcfc..0000000000 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs +++ /dev/null @@ -1,270 +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.Generic; -using System.Drawing; - -using OpenMetaverse; - -using Nini.Config; - -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Framework.Scenes.Serialization; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.OptionalModules.ContentManagement -{ - public class MetaEntity - { - #region Constants - - public const float INVISIBLE = .95f; - - // Settings for transparency of metaentity - public const float NONE = 0f; - public const float TRANSLUCENT = .5f; - - #endregion Constants - - #region Static Fields - - //private static readonly ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - - #endregion Static Fields - - #region Fields - - protected SceneObjectGroup m_Entity = null; // The scene object group that represents this meta entity. - protected uint m_metaLocalid; - - #endregion Fields - - #region Constructors - - public MetaEntity() - { - } - - /// - /// Makes a new meta entity by copying the given scene object group. - /// The physics boolean is just a stub right now. - /// - public MetaEntity(SceneObjectGroup orig, bool physics) - { - m_Entity = orig.Copy(false); - Initialize(physics); - } - - /// - /// Takes an XML description of a scene object group and converts it to a meta entity. - /// - public MetaEntity(string objectXML, Scene scene, bool physics) - { - m_Entity = SceneObjectSerializer.FromXml2Format(objectXML); - m_Entity.SetScene(scene); - Initialize(physics); - } - - #endregion Constructors - - #region Public Properties - - public SceneObjectPart[] Parts - { - get { return m_Entity.Parts; } - } - - public uint LocalId - { - get { return m_Entity.LocalId; } - set { m_Entity.LocalId = value; } - } - - public SceneObjectGroup ObjectGroup - { - get { return m_Entity; } - } - - public int PrimCount - { - get { return m_Entity.PrimCount; } - } - - public SceneObjectPart RootPart - { - get { return m_Entity.RootPart; } - } - - public Scene Scene - { - get { return m_Entity.Scene; } - } - - public UUID UUID - { - get { return m_Entity.UUID; } - set { m_Entity.UUID = value; } - } - - #endregion Public Properties - - #region Protected Methods - - // The metaentity objectgroup must have unique localids as well as unique uuids. - // localids are used by the client to refer to parts. - // uuids are sent to the client and back to the server to identify parts on the server side. - /// - /// Changes localids and uuids of m_Entity. - /// - protected void Initialize(bool physics) - { - //make new uuids - Dictionary parts = new Dictionary(); - - foreach (SceneObjectPart part in m_Entity.Parts) - { - part.ResetIDs(part.LinkNum); - parts.Add(part.UUID, part); - } - - //finalize - m_Entity.RootPart.PhysActor = null; - foreach (SceneObjectPart part in parts.Values) - m_Entity.AddPart(part); - } - - #endregion Protected Methods - - #region Public Methods - - /// - /// Hides the metaentity from a single client. - /// - public virtual void Hide(IClientAPI client) - { - //This deletes the group without removing from any databases. - //This is important because we are not IN any database. - //m_Entity.FakeDeleteGroup(); - foreach (SceneObjectPart part in m_Entity.Parts) - client.SendKillObject(m_Entity.RegionHandle, new List() { part.LocalId }); - } - - /// - /// Sends a kill object message to all clients, effectively "hiding" the metaentity even though it's still on the server. - /// - public virtual void HideFromAll() - { - foreach (SceneObjectPart part in m_Entity.Parts) - { - m_Entity.Scene.ForEachClient( - delegate(IClientAPI controller) - { controller.SendKillObject(m_Entity.RegionHandle, new List() { part.LocalId }); } - ); - } - } - - public void SendFullUpdate(IClientAPI client) - { - // Not sure what clientFlags should be but 0 seems to work - SendFullUpdate(client, 0); - } - - public void SendFullUpdate(IClientAPI client, uint clientFlags) - { - m_Entity.SendFullUpdateToClient(client); - } - - public void SendFullUpdateToAll() - { - m_Entity.Scene.ForEachClient( - delegate(IClientAPI controller) - { m_Entity.SendFullUpdateToClient(controller); } - ); - } - - /// - /// Makes a single SceneObjectPart see through. - /// - /// - /// A - /// The part to make see through - /// - /// - /// A - /// The degree of transparency to imbue the part with, 0f being solid and .95f being invisible. - /// - public static void SetPartTransparency(SceneObjectPart part, float transparencyAmount) - { - Primitive.TextureEntry tex = null; - Color4 texcolor; - try - { - tex = part.Shape.Textures; - texcolor = new Color4(); - } - catch(Exception) - { - //m_log.ErrorFormat("[Content Management]: Exception thrown while accessing textures of scene object: " + e); - return; - } - - for (uint i = 0; i < tex.FaceTextures.Length; i++) - { - try { - if (tex.FaceTextures[i] != null) - { - texcolor = tex.FaceTextures[i].RGBA; - texcolor.A = transparencyAmount; - tex.FaceTextures[i].RGBA = texcolor; - } - } - catch (Exception) - { - //m_log.ErrorFormat("[Content Management]: Exception thrown while accessing different face textures of object: " + e); - continue; - } - } - try { - texcolor = tex.DefaultTexture.RGBA; - texcolor.A = transparencyAmount; - tex.DefaultTexture.RGBA = texcolor; - part.Shape.TextureEntry = tex.GetBytes(); - } - catch (Exception) - { - //m_log.Info("[Content Management]: Exception thrown while accessing default face texture of object: " + e); - } - } - - #endregion Public Methods - } -} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/PointMetaEntity.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/PointMetaEntity.cs deleted file mode 100644 index 2c5093f58d..0000000000 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/PointMetaEntity.cs +++ /dev/null @@ -1,104 +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.Generic; -using System.Drawing; - -using OpenMetaverse; - -using Nini.Config; - -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.OptionalModules.ContentManagement -{ - public class PointMetaEntity : MetaEntity - { - #region Constructors - - public PointMetaEntity(Scene scene, Vector3 groupPos, float transparency) - : base() - { - CreatePointEntity(scene, UUID.Random(), groupPos); - SetPartTransparency(m_Entity.RootPart, transparency); - } - - public PointMetaEntity(Scene scene, UUID uuid, Vector3 groupPos, float transparency) - : base() - { - CreatePointEntity(scene, uuid, groupPos); - SetPartTransparency(m_Entity.RootPart, transparency); - } - - #endregion Constructors - - #region Private Methods - - private void CreatePointEntity(Scene scene, UUID uuid, Vector3 groupPos) - { - SceneObjectPart y = new SceneObjectPart(); - - //Initialize part - y.Name = "Very Small Point"; - y.RegionHandle = scene.RegionInfo.RegionHandle; - y.CreationDate = (Int32) (DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds; - y.OwnerID = UUID.Zero; - y.CreatorID = UUID.Zero; - y.LastOwnerID = UUID.Zero; - y.UUID = uuid; - - y.Shape = PrimitiveBaseShape.CreateBox(); - y.Scale = new Vector3(0.01f,0.01f,0.01f); - y.LastOwnerID = UUID.Zero; - y.GroupPosition = groupPos; - y.OffsetPosition = Vector3.Zero; - y.RotationOffset = Quaternion.Identity; - y.Velocity = Vector3.Zero; - y.AngularVelocity = Vector3.Zero; - y.Acceleration = Vector3.Zero; - - y.Flags = 0; - y.TrimPermissions(); - - //Initialize group and add part as root part - SceneObjectGroup x = new SceneObjectGroup(y); - x.SetScene(scene); - x.RegionHandle = scene.RegionInfo.RegionHandle; - x.SetScene(scene); - - m_Entity = x; - } - - #endregion Private Methods - } -} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/README b/OpenSim/Region/OptionalModules/ContentManagementSystem/README deleted file mode 100644 index 1a69fef231..0000000000 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/README +++ /dev/null @@ -1,52 +0,0 @@ -This module is meant to be built alone and not added to the Opensim code base. References are made to required dlls through a -reference file, ContentManagement.mdp. Originally, for development, this project was contained in the Opensim/Region/Modules/ -directory. - -To compile: nant -To use: Copy ContentManagement.dll into the bin directory of your Opensim build. You should find many other dlls in the same directory. - - --------------------------------------------------------------------------------------------------------------------- -To build the libgit.so file: - -#Download GIT git repository -$ git clone git://git2.kernel.org/pub/OpenSim/Region/Environment/Modules/ContentManagementSystem/scm/git/git.git -$ cd git - -#Compile GIT -#Note that we are adding two extra flags to pass to gcc while compiling (-c and -fPIC) -$ autoconf -$ ./configure -$ CFLAGS="-g -O2 -Wall -c -fPIC" make - -#Copy necessary object files (and some not so necessary) to their own directory for shared object file creation -$ mkdir ../libgit-objects -$ cp builtin*.o ../libgit-objects -$ cp xdiff/*.o ../libgit-objects -$ cp libgit.a ../libgit-objects - -#Remove the main symbol from any object files (like git.o) -$ cd ../libgit-objects -$ strip -N main *.o - -#Uncompress the plumbing objects from archive created by git -$ ar x libgit.a - -#Create shared object file from all objects (including the zlib library) -$ ld -shared -soname libgit.so.1 -o libgit.so.1.5.6.3 -lc -lz *.o - - -#You can also just copy the following commands into a file and run as a script inside the git directory - -make clean -autoconf -./configure -CFLAGS="-g -O2 -Wall -c -fPIC" make -mkdir libgit-objects -cp builtin*.o libgit-objects -cp xdiff/*.o libgit-objects -cp libgit.a libgit-objects -cd libgit-objects -strip -N main *.o -ar x libgit.a -ld -shared -soname libgit.so.1 -o libgit.so.1.5.6.3 -lc -lz *.o \ No newline at end of file diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/SceneObjectGroupDiff.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/SceneObjectGroupDiff.cs deleted file mode 100644 index a6afa5ac74..0000000000 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/SceneObjectGroupDiff.cs +++ /dev/null @@ -1,216 +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. - */ - -#region Header - -// SceneObjectGroupDiff.cs -// User: bongiojp - -#endregion Header - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Drawing; - -using OpenMetaverse; - -using Nini.Config; - -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.OptionalModules.ContentManagement -{ - #region Enumerations - - [Flags] - public enum Diff - { - NONE = 0, - FACECOLOR = 1, - SHAPE = 1<<1, - MATERIAL = 1<<2, - TEXTURE = 1<<3, - SCALE = 1<<4, - POSITION = 1<<5, - OFFSETPOSITION = 1<<6, - ROTATIONOFFSET = 1<<7, - ROTATIONALVELOCITY = 1<<8, - ACCELERATION = 1<<9, - ANGULARVELOCITY = 1<<10, - VELOCITY = 1<<11, - OBJECTOWNER = 1<<12, - PERMISSIONS = 1<<13, - DESCRIPTION = 1<<14, - NAME = 1<<15, - SCRIPT = 1<<16, - CLICKACTION = 1<<17, - PARTICLESYSTEM = 1<<18, - GLOW = 1<<19, - SALEPRICE = 1<<20, - SITNAME = 1<<21, - SITTARGETORIENTATION = 1<<22, - SITTARGETPOSITION = 1<<23, - TEXT = 1<<24, - TOUCHNAME = 1<<25 - } - - #endregion Enumerations - - public static class Difference - { - #region Static Fields - - static float TimeToDiff = 0; -// private static readonly ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - - #endregion Static Fields - - #region Private Methods - - private static bool AreQuaternionsEquivalent(Quaternion first, Quaternion second) - { - Vector3 firstVector = llRot2Euler(first); - Vector3 secondVector = llRot2Euler(second); - return AreVectorsEquivalent(firstVector, secondVector); - } - - private static bool AreVectorsEquivalent(Vector3 first, Vector3 second) - { - if (TruncateSignificant(first.X, 2) == TruncateSignificant(second.X, 2) - && TruncateSignificant(first.Y, 2) == TruncateSignificant(second.Y, 2) - && TruncateSignificant(first.Z, 2) == TruncateSignificant(second.Z, 2) - ) - return true; - else - return false; - } - - // Taken from Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs - private static double NormalizeAngle(double angle) - { - angle = angle % (Math.PI * 2); - if (angle < 0) angle = angle + Math.PI * 2; - return angle; - } - - private static int TruncateSignificant(float num, int digits) - { - return (int) Math.Ceiling((Math.Truncate(num * 10 * digits)/10*digits)); - // return (int) ((num * (10*digits))/10*digits); - } - - // Taken from Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs - // Also changed the original function from LSL_Types to LL types - private static Vector3 llRot2Euler(Quaternion r) - { - Quaternion t = new Quaternion(r.X * r.X, r.Y * r.Y, r.Z * r.Z, r.W * r.W); - double m = (t.X + t.Y + t.Z + t.W); - if (m == 0) return new Vector3(); - double n = 2 * (r.Y * r.W + r.X * r.Z); - double p = m * m - n * n; - if (p > 0) - return new Vector3((float)NormalizeAngle(Math.Atan2(2.0 * (r.X * r.W - r.Y * r.Z), (-t.X - t.Y + t.Z + t.W))), - (float)NormalizeAngle(Math.Atan2(n, Math.Sqrt(p))), - (float)NormalizeAngle(Math.Atan2(2.0 * (r.Z * r.W - r.X * r.Y), (t.X - t.Y - t.Z + t.W)))); - else if (n > 0) - return new Vector3(0.0f, (float)(Math.PI / 2), (float)NormalizeAngle(Math.Atan2((r.Z * r.W + r.X * r.Y), 0.5 - t.X - t.Z))); - else - return new Vector3(0.0f, (float)(-Math.PI / 2), (float)NormalizeAngle(Math.Atan2((r.Z * r.W + r.X * r.Y), 0.5 - t.X - t.Z))); - } - - #endregion Private Methods - - #region Public Methods - - /// - /// Compares the attributes (Vectors, Quaternions, Strings, etc.) between two scene object parts - /// and returns a Diff bitmask which details what the differences are. - /// - public static Diff FindDifferences(SceneObjectPart first, SceneObjectPart second) - { - Stopwatch x = new Stopwatch(); - x.Start(); - - Diff result = 0; - - // VECTOR COMPARISONS - if (!AreVectorsEquivalent(first.Acceleration, second.Acceleration)) - result |= Diff.ACCELERATION; - if (!AreVectorsEquivalent(first.AbsolutePosition, second.AbsolutePosition)) - result |= Diff.POSITION; - if (!AreVectorsEquivalent(first.AngularVelocity, second.AngularVelocity)) - result |= Diff.ANGULARVELOCITY; - if (!AreVectorsEquivalent(first.OffsetPosition, second.OffsetPosition)) - result |= Diff.OFFSETPOSITION; - if (!AreVectorsEquivalent(first.Scale, second.Scale)) - result |= Diff.SCALE; - if (!AreVectorsEquivalent(first.Velocity, second.Velocity)) - result |= Diff.VELOCITY; - - - // QUATERNION COMPARISONS - if (!AreQuaternionsEquivalent(first.RotationOffset, second.RotationOffset)) - result |= Diff.ROTATIONOFFSET; - - - // MISC COMPARISONS (UUID, Byte) - if (first.ClickAction != second.ClickAction) - result |= Diff.CLICKACTION; - if (first.OwnerID != second.OwnerID) - result |= Diff.OBJECTOWNER; - - - // STRING COMPARISONS - if (first.Description != second.Description) - result |= Diff.DESCRIPTION; - if (first.Material != second.Material) - result |= Diff.MATERIAL; - if (first.Name != second.Name) - result |= Diff.NAME; - if (first.SitName != second.SitName) - result |= Diff.SITNAME; - if (first.Text != second.Text) - result |= Diff.TEXT; - if (first.TouchName != second.TouchName) - result |= Diff.TOUCHNAME; - - x.Stop(); - TimeToDiff += x.ElapsedMilliseconds; - //m_log.Info("[DIFFERENCES] Time spent diffing objects so far" + TimeToDiff); - - return result; - } - - #endregion Public Methods - } -} diff --git a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs index 122ad40719..eed64506ac 100644 --- a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs @@ -28,10 +28,14 @@ using System; using System.Collections.Generic; using System.Reflection; +using System.Net; +using System.IO; +using System.Text; using log4net; using Nini.Config; using OpenMetaverse; +using OpenMetaverse.StructuredData; using OpenSim.Framework; using OpenSim.Region.Framework.Interfaces; @@ -50,6 +54,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady private bool m_lastOarLoadedOk; private int m_channelNotify = -1000; private bool m_enabled = false; + private bool m_disable_logins = false; + private string m_uri = string.Empty; Scene m_scene = null; @@ -68,10 +74,13 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady if (m_config != null) { m_enabled = m_config.GetBoolean("enabled", false); + if (m_enabled) { m_channelNotify = m_config.GetInt("channel_notify", m_channelNotify); - } + m_disable_logins = m_config.GetBoolean("login_disable", false); + m_uri = m_config.GetString("alert_uri",string.Empty); + } } // if (!m_enabled) @@ -91,8 +100,21 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady m_scene.EventManager.OnEmptyScriptCompileQueue += OnEmptyScriptCompileQueue; m_scene.EventManager.OnOarFileLoaded += OnOarFileLoaded; + m_scene.EventManager.OnLoginsEnabled += OnLoginsEnabled; m_log.DebugFormat("[RegionReady]: Enabled for region {0}", scene.RegionInfo.RegionName); + + if(m_disable_logins == true) + { + scene.LoginLock = true; + scene.LoginsDisabled = true; + m_log.InfoFormat("[RegionReady]: Logins disabled for {0}",m_scene.RegionInfo.RegionName); + + if(m_uri != string.Empty) + { + RRAlert("disabled"); + } + } } public void RemoveRegion(Scene scene) @@ -150,7 +172,9 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady m_log.InfoFormat("[RegionReady]: Region \"{0}\" is ready: \"{1}\" on channel {2}", m_scene.RegionInfo.RegionName, c.Message, m_channelNotify); - m_scene.EventManager.TriggerOnChatBroadcast(this, c); + + m_scene.EventManager.TriggerOnChatBroadcast(this, c); + m_scene.EventManager.TriggerLoginsEnabled(m_scene.RegionInfo.RegionName); } } @@ -165,5 +189,69 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady m_lastOarLoadedOk = false; } } + + void OnLoginsEnabled(string regionName) + { + if (m_disable_logins == true) + { + if (m_scene.StartDisabled == false) + { + m_scene.LoginsDisabled = false; + m_scene.LoginLock = false; + m_log.InfoFormat("[RegionReady]: Logins enabled for {0}", m_scene.RegionInfo.RegionName); + if ( m_uri != string.Empty ) + { + RRAlert("enabled"); + } + } + } + } + + public void RRAlert(string status) + { + string request_method = "POST"; + string content_type = "application/json"; + OSDMap RRAlert = new OSDMap(); + + RRAlert["alert"] = "region_ready"; + RRAlert["login"] = status; + RRAlert["region_name"] = m_scene.RegionInfo.RegionName; + RRAlert["region_id"] = m_scene.RegionInfo.RegionID; + + string strBuffer = ""; + byte[] buffer = new byte[1]; + try + { + strBuffer = OSDParser.SerializeJsonString(RRAlert); + Encoding str = Util.UTF8; + buffer = str.GetBytes(strBuffer); + + } + catch (Exception e) + { + m_log.WarnFormat("[RegionReady]: Exception thrown on alert: {0}", e.Message); + } + + WebRequest request = WebRequest.Create(m_uri); + request.Method = request_method; + request.ContentType = content_type; + + Stream os = null; + try + { + request.ContentLength = buffer.Length; + os = request.GetRequestStream(); + os.Write(buffer, 0, strBuffer.Length); + } + catch(Exception e) + { + m_log.WarnFormat("[RegionReady]: Exception thrown sending alert: {0}", e.Message); + } + finally + { + if (os != null) + os.Close(); + } + } } } diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs index d89543824e..f07ad67a1c 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs @@ -631,7 +631,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC { } - public virtual void SendDialog(string objectname, UUID objectID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch, string[] buttonlabels) + public virtual void SendDialog(string objectname, UUID objectID, UUID ownerID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch, string[] buttonlabels) { } diff --git a/OpenSim/Region/Physics/Manager/PhysicsActor.cs b/OpenSim/Region/Physics/Manager/PhysicsActor.cs index 880c3ea3cb..1c36e55b95 100644 --- a/OpenSim/Region/Physics/Manager/PhysicsActor.cs +++ b/OpenSim/Region/Physics/Manager/PhysicsActor.cs @@ -142,7 +142,12 @@ namespace OpenSim.Region.Physics.Manager public abstract PrimitiveBaseShape Shape { set; } - public abstract uint LocalID { set; } + uint m_baseLocalID; + public virtual uint LocalID + { + set { m_baseLocalID = value; } + get { return m_baseLocalID; } + } public abstract bool Grabbed { set; } diff --git a/OpenSim/Region/Physics/Manager/PhysicsScene.cs b/OpenSim/Region/Physics/Manager/PhysicsScene.cs index 217d307443..54c50f8eda 100644 --- a/OpenSim/Region/Physics/Manager/PhysicsScene.cs +++ b/OpenSim/Region/Physics/Manager/PhysicsScene.cs @@ -66,6 +66,13 @@ namespace OpenSim.Region.Physics.Manager public abstract PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying); + public virtual PhysicsActor AddAvatar(uint localID, string avName, Vector3 position, Vector3 size, bool isFlying) + { + PhysicsActor ret = AddAvatar(avName, position, size, isFlying); + if (ret != null) ret.LocalID = localID; + return ret; + } + public abstract void RemoveAvatar(PhysicsActor actor); public abstract void RemovePrim(PhysicsActor prim); @@ -75,6 +82,14 @@ namespace OpenSim.Region.Physics.Manager public abstract PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, Vector3 size, Quaternion rotation, bool isPhysical); + public virtual PhysicsActor AddPrimShape(uint localID, string primName, PrimitiveBaseShape pbs, Vector3 position, + Vector3 size, Quaternion rotation, bool isPhysical) + { + PhysicsActor ret = AddPrimShape(primName, pbs, position, size, rotation, isPhysical); + if (ret != null) ret.LocalID = localID; + return ret; + } + public virtual float TimeDilation { get { return 1.0f; } diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs index f89b824614..99b2d8477a 100644 --- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs +++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs @@ -303,7 +303,11 @@ namespace OpenSim.Region.Physics.Meshing if (meshOsd is OSDMap) { OSDMap map = (OSDMap)meshOsd; - OSDMap physicsParms = (OSDMap)map["physics_shape"]; + OSDMap physicsParms = (OSDMap)map["physics_shape"]; // old asset format + + if (physicsParms.Count == 0) + physicsParms = (OSDMap)map["physics_mesh"]; // new asset format + int physOffset = physicsParms["offset"].AsInteger() + (int)start; int physSize = physicsParms["size"].AsInteger(); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs index 3afedc72f9..d695a0cb30 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs @@ -309,7 +309,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins // In attachments, the sensor cone always orients with the // avatar rotation. This may include a nonzero elevation if // in mouselook. - ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.RootPart.AttachedAvatar); fromRegionPos = avatar.AbsolutePosition; q = avatar.Rotation; @@ -424,6 +423,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins SceneObjectPart SensePoint = ts.host; Vector3 fromRegionPos = SensePoint.AbsolutePosition; + Quaternion q = SensePoint.RotationOffset; if (SensePoint.ParentGroup.RootPart.IsAttachment) { @@ -435,6 +435,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins fromRegionPos = avatar.AbsolutePosition; q = avatar.Rotation; } + LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W); LSL_Types.Vector3 forward_dir = (new LSL_Types.Vector3(1, 0, 0) * r); double mag_fwd = LSL_Types.Vector3.Mag(forward_dir); diff --git a/OpenSim/Server/Base/ServerUtils.cs b/OpenSim/Server/Base/ServerUtils.cs index f4472c7dc0..8effdd2d1b 100644 --- a/OpenSim/Server/Base/ServerUtils.cs +++ b/OpenSim/Server/Base/ServerUtils.cs @@ -65,6 +65,10 @@ namespace OpenSim.Server.Base /// public static T LoadPlugin(string dllName, Object[] args) where T:class { + // This is good to debug configuration problems + //if (dllName == string.Empty) + // Util.PrintCallStack(); + string[] parts = dllName.Split(new char[] {':'}); dllName = parts[0]; @@ -124,6 +128,13 @@ namespace OpenSim.Server.Base return null; } + catch (ReflectionTypeLoadException rtle) + { + m_log.Error(string.Format("Error loading plugin from {0}:\n{1}", dllName, + String.Join("\n", Array.ConvertAll(rtle.LoaderExceptions, e => e.ToString()))), + rtle); + return null; + } catch (Exception e) { m_log.Error(string.Format("Error loading plugin from {0}", dllName), e); diff --git a/OpenSim/Server/Handlers/Friends/FriendServerConnector.cs b/OpenSim/Server/Handlers/Friends/FriendServerConnector.cs index 074f8690a5..5784bdf652 100644 --- a/OpenSim/Server/Handlers/Friends/FriendServerConnector.cs +++ b/OpenSim/Server/Handlers/Friends/FriendServerConnector.cs @@ -46,14 +46,14 @@ namespace OpenSim.Server.Handlers.Friends if (serverConfig == null) throw new Exception(String.Format("No section {0} in config file", m_ConfigName)); - string gridService = serverConfig.GetString("LocalServiceModule", + string theService = serverConfig.GetString("LocalServiceModule", String.Empty); - if (gridService == String.Empty) + if (theService == String.Empty) throw new Exception("No LocalServiceModule in config file"); Object[] args = new Object[] { config }; - m_FriendsService = ServerUtils.LoadPlugin(gridService, args); + m_FriendsService = ServerUtils.LoadPlugin(theService, args); server.AddStreamHandler(new FriendsServerPostHandler(m_FriendsService)); } diff --git a/OpenSim/Server/Handlers/Friends/FriendsServerPostHandler.cs b/OpenSim/Server/Handlers/Friends/FriendsServerPostHandler.cs index b168bb35c9..fc97d8c221 100644 --- a/OpenSim/Server/Handlers/Friends/FriendsServerPostHandler.cs +++ b/OpenSim/Server/Handlers/Friends/FriendsServerPostHandler.cs @@ -82,12 +82,18 @@ namespace OpenSim.Server.Handlers.Friends case "getfriends": return GetFriends(request); + case "getfriends_string": + return GetFriendsString(request); + case "storefriend": return StoreFriend(request); case "deletefriend": return DeleteFriend(request); + case "deletefriend_string": + return DeleteFriendString(request); + } m_log.DebugFormat("[FRIENDS HANDLER]: unknown method {0} request {1}", method.Length, method); } @@ -111,7 +117,25 @@ namespace OpenSim.Server.Handlers.Friends m_log.WarnFormat("[FRIENDS HANDLER]: no principalID in request to get friends"); FriendInfo[] finfos = m_FriendsService.GetFriends(principalID); - //m_log.DebugFormat("[FRIENDS HANDLER]: neighbours for region {0}: {1}", regionID, rinfos.Count); + + return PackageFriends(finfos); + } + + byte[] GetFriendsString(Dictionary request) + { + string principalID = string.Empty; + if (request.ContainsKey("PRINCIPALID")) + principalID = request["PRINCIPALID"].ToString(); + else + m_log.WarnFormat("[FRIENDS HANDLER]: no principalID in request to get friends"); + + FriendInfo[] finfos = m_FriendsService.GetFriends(principalID); + + return PackageFriends(finfos); + } + + private byte[] PackageFriends(FriendInfo[] finfos) + { Dictionary result = new Dictionary(); if ((finfos == null) || ((finfos != null) && (finfos.Length == 0))) @@ -136,9 +160,9 @@ namespace OpenSim.Server.Handlers.Friends byte[] StoreFriend(Dictionary request) { - FriendInfo friend = new FriendInfo(request); - - bool success = m_FriendsService.StoreFriend(friend.PrincipalID, friend.Friend, friend.MyFlags); + string principalID = string.Empty, friend = string.Empty; int flags = 0; + FromKeyValuePairs(request, out principalID, out friend, out flags); + bool success = m_FriendsService.StoreFriend(principalID, friend, flags); if (success) return SuccessResult(); @@ -163,7 +187,25 @@ namespace OpenSim.Server.Handlers.Friends else return FailureResult(); } - + + byte[] DeleteFriendString(Dictionary request) + { + string principalID = string.Empty; + if (request.ContainsKey("PRINCIPALID")) + principalID = request["PRINCIPALID"].ToString(); + else + m_log.WarnFormat("[FRIENDS HANDLER]: no principalID in request to delete friend"); + string friend = string.Empty; + if (request.ContainsKey("FRIEND")) + friend = request["FRIEND"].ToString(); + + bool success = m_FriendsService.Delete(principalID, friend); + if (success) + return SuccessResult(); + else + return FailureResult(); + } + #endregion #region Misc @@ -233,6 +275,19 @@ namespace OpenSim.Server.Handlers.Friends return ms.ToArray(); } + void FromKeyValuePairs(Dictionary kvp, out string principalID, out string friend, out int flags) + { + principalID = string.Empty; + if (kvp.ContainsKey("PrincipalID") && kvp["PrincipalID"] != null) + principalID = kvp["PrincipalID"].ToString(); + friend = string.Empty; + if (kvp.ContainsKey("Friend") && kvp["Friend"] != null) + friend = kvp["Friend"].ToString(); + flags = 0; + if (kvp.ContainsKey("MyFlags") && kvp["MyFlags"] != null) + Int32.TryParse(kvp["MyFlags"].ToString(), out flags); + } + #endregion } } diff --git a/OpenSim/Server/Handlers/Hypergrid/HGFriendServerConnector.cs b/OpenSim/Server/Handlers/Hypergrid/HGFriendServerConnector.cs new file mode 100644 index 0000000000..82a72206d3 --- /dev/null +++ b/OpenSim/Server/Handlers/Hypergrid/HGFriendServerConnector.cs @@ -0,0 +1,71 @@ +/* + * 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 Nini.Config; +using OpenSim.Server.Base; +using OpenSim.Services.Interfaces; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Server.Handlers.Base; + +namespace OpenSim.Server.Handlers.Hypergrid +{ + public class HGFriendsServerConnector : ServiceConnector + { + private IFriendsService m_FriendsService; + private IUserAgentService m_UserAgentService; + private string m_ConfigName = "HGFriendsService"; + + public HGFriendsServerConnector(IConfigSource config, IHttpServer server, string configName) : + base(config, server, configName) + { + if (configName != string.Empty) + m_ConfigName = configName; + + IConfig serverConfig = config.Configs[m_ConfigName]; + if (serverConfig == null) + throw new Exception(String.Format("No section {0} in config file", m_ConfigName)); + + string theService = serverConfig.GetString("LocalServiceModule", + String.Empty); + + if (theService == String.Empty) + throw new Exception("No LocalServiceModule in config file"); + + Object[] args = new Object[] { config }; + m_FriendsService = ServerUtils.LoadPlugin(theService, args); + + theService = serverConfig.GetString("UserAgentService", string.Empty); + if (theService == String.Empty) + throw new Exception("No UserAgentService in " + m_ConfigName); + + m_UserAgentService = ServerUtils.LoadPlugin(theService, args); + + server.AddStreamHandler(new HGFriendsServerPostHandler(m_FriendsService, m_UserAgentService)); + } + } +} diff --git a/OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs b/OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs new file mode 100644 index 0000000000..5c89d0fd75 --- /dev/null +++ b/OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs @@ -0,0 +1,320 @@ +/* + * 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 Nini.Config; +using log4net; +using System; +using System.Reflection; +using System.IO; +using System.Net; +using System.Text; +using System.Text.RegularExpressions; +using System.Xml; +using System.Xml.Serialization; +using System.Collections.Generic; +using OpenSim.Server.Base; +using OpenSim.Services.Interfaces; +using FriendInfo = OpenSim.Services.Interfaces.FriendInfo; +using OpenSim.Framework; +using OpenSim.Framework.Servers.HttpServer; +using OpenMetaverse; + +namespace OpenSim.Server.Handlers.Hypergrid +{ + public class HGFriendsServerPostHandler : BaseStreamHandler + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private IFriendsService m_FriendsService; + private IUserAgentService m_UserAgentService; + + public HGFriendsServerPostHandler(IFriendsService service, IUserAgentService uservice) : + base("POST", "/hgfriends") + { + m_FriendsService = service; + m_UserAgentService = uservice; + m_log.DebugFormat("[HGFRIENDS HANDLER]: HGFriendsServerPostHandler is On"); + } + + public override byte[] Handle(string path, Stream requestData, + OSHttpRequest httpRequest, OSHttpResponse httpResponse) + { + StreamReader sr = new StreamReader(requestData); + string body = sr.ReadToEnd(); + sr.Close(); + body = body.Trim(); + + //m_log.DebugFormat("[XXX]: query String: {0}", body); + + try + { + Dictionary request = + ServerUtils.ParseQueryString(body); + + if (!request.ContainsKey("METHOD")) + return FailureResult(); + + string method = request["METHOD"].ToString(); + + switch (method) + { + case "getfriendperms": + return GetFriendPerms(request); + + case "newfriendship": + return NewFriendship(request); + + case "deletefriendship": + return DeleteFriendship(request); + } + m_log.DebugFormat("[HGFRIENDS HANDLER]: unknown method {0} request {1}", method.Length, method); + } + catch (Exception e) + { + m_log.DebugFormat("[HGFRIENDS HANDLER]: Exception {0}", e); + } + + return FailureResult(); + + } + + #region Method-specific handlers + + byte[] GetFriendPerms(Dictionary request) + { + if (!VerifyServiceKey(request)) + return FailureResult(); + + UUID principalID = UUID.Zero; + if (request.ContainsKey("PRINCIPALID")) + UUID.TryParse(request["PRINCIPALID"].ToString(), out principalID); + else + { + m_log.WarnFormat("[HGFRIENDS HANDLER]: no principalID in request to get friend perms"); + return FailureResult(); + } + + UUID friendID = UUID.Zero; + if (request.ContainsKey("FRIENDID")) + UUID.TryParse(request["FRIENDID"].ToString(), out friendID); + else + { + m_log.WarnFormat("[HGFRIENDS HANDLER]: no friendID in request to get friend perms"); + return FailureResult(); + } + + string perms = "0"; + FriendInfo[] friendsInfo = m_FriendsService.GetFriends(principalID); + foreach (FriendInfo finfo in friendsInfo) + { + if (finfo.Friend.StartsWith(friendID.ToString())) + return SuccessResult(finfo.TheirFlags.ToString()); + } + + return FailureResult("Friend not found"); + } + + byte[] NewFriendship(Dictionary request) + { + if (!VerifyServiceKey(request)) + return FailureResult(); + + // OK, can proceed + FriendInfo friend = new FriendInfo(request); + UUID friendID; + string tmp = string.Empty; + if (!Util.ParseUniversalUserIdentifier(friend.Friend, out friendID, out tmp, out tmp, out tmp, out tmp)) + return FailureResult(); + + + m_log.DebugFormat("[HGFRIENDS HANDLER]: New friendship {0} {1}", friend.PrincipalID, friend.Friend); + + // If the friendship already exists, return fail + FriendInfo[] finfos = m_FriendsService.GetFriends(friend.PrincipalID); + foreach (FriendInfo finfo in finfos) + if (finfo.Friend.StartsWith(friendID.ToString())) + return FailureResult(); + + // the user needs to confirm when he gets home + bool success = m_FriendsService.StoreFriend(friend.PrincipalID.ToString(), friend.Friend, 0); + + if (success) + return SuccessResult(); + else + return FailureResult(); + } + + byte[] DeleteFriendship(Dictionary request) + { + FriendInfo friend = new FriendInfo(request); + string secret = string.Empty; + if (request.ContainsKey("SECRET")) + secret = request["SECRET"].ToString(); + + if (secret == string.Empty) + return FailureResult(); + + FriendInfo[] finfos = m_FriendsService.GetFriends(friend.PrincipalID); + foreach (FriendInfo finfo in finfos) + { + // We check the secret here + if (finfo.Friend.StartsWith(friend.Friend) && finfo.Friend.EndsWith(secret)) + { + m_log.DebugFormat("[HGFRIENDS HANDLER]: Delete friendship {0} {1}", friend.PrincipalID, friend.Friend); + m_FriendsService.Delete(friend.PrincipalID, finfo.Friend); + m_FriendsService.Delete(finfo.Friend, friend.PrincipalID.ToString()); + + return SuccessResult(); + } + } + + return FailureResult(); + } + + #endregion + + #region Misc + + private bool VerifyServiceKey(Dictionary request) + { + if (!request.ContainsKey("KEY") || !request.ContainsKey("SESSIONID")) + { + m_log.WarnFormat("[HGFRIENDS HANDLER]: ignoring request without Key or SessionID"); + return false; + } + + string serviceKey = request["KEY"].ToString(); + string sessionStr = request["SESSIONID"].ToString(); + UUID sessionID; + UUID.TryParse(sessionStr, out sessionID); + + if (!m_UserAgentService.VerifyAgent(sessionID, serviceKey)) + { + m_log.WarnFormat("[HGFRIENDS HANDLER]: Key {0} for session {1} did not match existing key. Ignoring request", serviceKey, sessionID); + return false; + } + + m_log.DebugFormat("[HGFRIENDS HANDLER]: Verification ok"); + return true; + } + + private byte[] SuccessResult() + { + XmlDocument doc = new XmlDocument(); + + XmlNode xmlnode = doc.CreateNode(XmlNodeType.XmlDeclaration, + "", ""); + + doc.AppendChild(xmlnode); + + XmlElement rootElement = doc.CreateElement("", "ServerResponse", + ""); + + doc.AppendChild(rootElement); + + XmlElement result = doc.CreateElement("", "Result", ""); + result.AppendChild(doc.CreateTextNode("Success")); + + rootElement.AppendChild(result); + + return DocToBytes(doc); + } + + private byte[] SuccessResult(string value) + { + XmlDocument doc = new XmlDocument(); + + XmlNode xmlnode = doc.CreateNode(XmlNodeType.XmlDeclaration, + "", ""); + + doc.AppendChild(xmlnode); + + XmlElement rootElement = doc.CreateElement("", "ServerResponse", + ""); + + doc.AppendChild(rootElement); + + XmlElement result = doc.CreateElement("", "Result", ""); + result.AppendChild(doc.CreateTextNode("Success")); + + rootElement.AppendChild(result); + + XmlElement message = doc.CreateElement("", "Value", ""); + message.AppendChild(doc.CreateTextNode(value)); + + rootElement.AppendChild(message); + + return DocToBytes(doc); + } + + + private byte[] FailureResult() + { + return FailureResult(String.Empty); + } + + private byte[] FailureResult(string msg) + { + XmlDocument doc = new XmlDocument(); + + XmlNode xmlnode = doc.CreateNode(XmlNodeType.XmlDeclaration, + "", ""); + + doc.AppendChild(xmlnode); + + XmlElement rootElement = doc.CreateElement("", "ServerResponse", + ""); + + doc.AppendChild(rootElement); + + XmlElement result = doc.CreateElement("", "Result", ""); + result.AppendChild(doc.CreateTextNode("Failure")); + + rootElement.AppendChild(result); + + XmlElement message = doc.CreateElement("", "Message", ""); + message.AppendChild(doc.CreateTextNode(msg)); + + rootElement.AppendChild(message); + + return DocToBytes(doc); + } + + private byte[] DocToBytes(XmlDocument doc) + { + MemoryStream ms = new MemoryStream(); + XmlTextWriter xw = new XmlTextWriter(ms, null); + xw.Formatting = Formatting.Indented; + doc.WriteTo(xw); + xw.Flush(); + + return ms.ToArray(); + } + + #endregion + } +} diff --git a/OpenSim/Server/Handlers/Hypergrid/InstantMessageServerConnector.cs b/OpenSim/Server/Handlers/Hypergrid/InstantMessageServerConnector.cs new file mode 100644 index 0000000000..80eb5d2faf --- /dev/null +++ b/OpenSim/Server/Handlers/Hypergrid/InstantMessageServerConnector.cs @@ -0,0 +1,243 @@ +/* + * 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.Net; +using System.Reflection; + +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Server.Base; +using OpenSim.Services.Interfaces; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Server.Handlers.Base; +using GridRegion = OpenSim.Services.Interfaces.GridRegion; + +using log4net; +using Nwc.XmlRpc; +using OpenMetaverse; + +namespace OpenSim.Server.Handlers.Hypergrid +{ + public class InstantMessageServerConnector : ServiceConnector + { + private static readonly ILog m_log = + LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + + private IInstantMessage m_IMService; + + public InstantMessageServerConnector(IConfigSource config, IHttpServer server) : + this(config, server, null) + { + } + + public InstantMessageServerConnector(IConfigSource config, IHttpServer server, IInstantMessageSimConnector simConnector) : + base(config, server, String.Empty) + { + IConfig gridConfig = config.Configs["HGInstantMessageService"]; + if (gridConfig != null) + { + string serviceDll = gridConfig.GetString("LocalServiceModule", string.Empty); + + Object[] args = new Object[] { config, simConnector }; + m_IMService = ServerUtils.LoadPlugin(serviceDll, args); + } + if (m_IMService == null) + throw new Exception("InstantMessage server connector cannot proceed because of missing service"); + + server.AddXmlRPCHandler("grid_instant_message", ProcessInstantMessage, false); + + } + + public IInstantMessage GetService() + { + return m_IMService; + } + + protected virtual XmlRpcResponse ProcessInstantMessage(XmlRpcRequest request, IPEndPoint remoteClient) + { + bool successful = false; + + try + { + // various rational defaults + UUID fromAgentID = UUID.Zero; + UUID toAgentID = UUID.Zero; + UUID imSessionID = UUID.Zero; + uint timestamp = 0; + string fromAgentName = ""; + string message = ""; + byte dialog = (byte)0; + bool fromGroup = false; + byte offline = (byte)0; + uint ParentEstateID = 0; + Vector3 Position = Vector3.Zero; + UUID RegionID = UUID.Zero; + byte[] binaryBucket = new byte[0]; + + float pos_x = 0; + float pos_y = 0; + float pos_z = 0; + //m_log.Info("Processing IM"); + + + Hashtable requestData = (Hashtable)request.Params[0]; + // Check if it's got all the data + if (requestData.ContainsKey("from_agent_id") + && requestData.ContainsKey("to_agent_id") && requestData.ContainsKey("im_session_id") + && requestData.ContainsKey("timestamp") && requestData.ContainsKey("from_agent_name") + && requestData.ContainsKey("message") && requestData.ContainsKey("dialog") + && requestData.ContainsKey("from_group") + && requestData.ContainsKey("offline") && requestData.ContainsKey("parent_estate_id") + && requestData.ContainsKey("position_x") && requestData.ContainsKey("position_y") + && requestData.ContainsKey("position_z") && requestData.ContainsKey("region_id") + && requestData.ContainsKey("binary_bucket")) + { + // Do the easy way of validating the UUIDs + UUID.TryParse((string)requestData["from_agent_id"], out fromAgentID); + UUID.TryParse((string)requestData["to_agent_id"], out toAgentID); + UUID.TryParse((string)requestData["im_session_id"], out imSessionID); + UUID.TryParse((string)requestData["region_id"], out RegionID); + try + { + timestamp = (uint)Convert.ToInt32((string)requestData["timestamp"]); + } + catch (ArgumentException) + { + } + catch (FormatException) + { + } + catch (OverflowException) + { + } + + fromAgentName = (string)requestData["from_agent_name"]; + message = (string)requestData["message"]; + if (message == null) + message = string.Empty; + + // Bytes don't transfer well over XMLRPC, so, we Base64 Encode them. + string requestData1 = (string)requestData["dialog"]; + if (string.IsNullOrEmpty(requestData1)) + { + dialog = 0; + } + else + { + byte[] dialogdata = Convert.FromBase64String(requestData1); + dialog = dialogdata[0]; + } + + if ((string)requestData["from_group"] == "TRUE") + fromGroup = true; + + string requestData2 = (string)requestData["offline"]; + if (String.IsNullOrEmpty(requestData2)) + { + offline = 0; + } + else + { + byte[] offlinedata = Convert.FromBase64String(requestData2); + offline = offlinedata[0]; + } + + try + { + ParentEstateID = (uint)Convert.ToInt32((string)requestData["parent_estate_id"]); + } + catch (ArgumentException) + { + } + catch (FormatException) + { + } + catch (OverflowException) + { + } + + float.TryParse((string)requestData["position_x"], out pos_x); + float.TryParse((string)requestData["position_y"], out pos_y); + float.TryParse((string)requestData["position_z"], out pos_z); + + Position = new Vector3(pos_x, pos_y, pos_z); + + string requestData3 = (string)requestData["binary_bucket"]; + if (string.IsNullOrEmpty(requestData3)) + { + binaryBucket = new byte[0]; + } + else + { + binaryBucket = Convert.FromBase64String(requestData3); + } + + // Create a New GridInstantMessageObject the the data + GridInstantMessage gim = new GridInstantMessage(); + gim.fromAgentID = fromAgentID.Guid; + gim.fromAgentName = fromAgentName; + gim.fromGroup = fromGroup; + gim.imSessionID = imSessionID.Guid; + gim.RegionID = RegionID.Guid; + gim.timestamp = timestamp; + gim.toAgentID = toAgentID.Guid; + gim.message = message; + gim.dialog = dialog; + gim.offline = offline; + gim.ParentEstateID = ParentEstateID; + gim.Position = Position; + gim.binaryBucket = binaryBucket; + + successful = m_IMService.IncomingInstantMessage(gim); + + } + } + catch (Exception e) + { + m_log.Error("[INSTANT MESSAGE]: Caught unexpected exception:", e); + successful = false; + } + + //Send response back to region calling if it was successful + // calling region uses this to know when to look up a user's location again. + XmlRpcResponse resp = new XmlRpcResponse(); + Hashtable respdata = new Hashtable(); + if (successful) + respdata["success"] = "TRUE"; + else + respdata["success"] = "FALSE"; + resp.Value = respdata; + + return resp; + } + + } +} diff --git a/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs b/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs index 0e8ce800a7..72a4aeaa62 100644 --- a/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs +++ b/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs @@ -52,15 +52,24 @@ namespace OpenSim.Server.Handlers.Hypergrid // MethodBase.GetCurrentMethod().DeclaringType); private IUserAgentService m_HomeUsersService; + private string[] m_AuthorizedCallers; + + private bool m_VerifyCallers = false; public UserAgentServerConnector(IConfigSource config, IHttpServer server) : + this(config, server, null) + { + } + + public UserAgentServerConnector(IConfigSource config, IHttpServer server, IFriendsSimConnector friendsConnector) : base(config, server, String.Empty) { IConfig gridConfig = config.Configs["UserAgentService"]; if (gridConfig != null) { string serviceDll = gridConfig.GetString("LocalServiceModule", string.Empty); - Object[] args = new Object[] { config }; + + Object[] args = new Object[] { config, friendsConnector }; m_HomeUsersService = ServerUtils.LoadPlugin(serviceDll, args); } if (m_HomeUsersService == null) @@ -69,12 +78,24 @@ namespace OpenSim.Server.Handlers.Hypergrid string loginServerIP = gridConfig.GetString("LoginServerIP", "127.0.0.1"); bool proxy = gridConfig.GetBoolean("HasProxy", false); + m_VerifyCallers = gridConfig.GetBoolean("VerifyCallers", false); + string csv = gridConfig.GetString("AuthorizedCallers", "127.0.0.1"); + csv = csv.Replace(" ", ""); + m_AuthorizedCallers = csv.Split(','); + server.AddXmlRPCHandler("agent_is_coming_home", AgentIsComingHome, false); server.AddXmlRPCHandler("get_home_region", GetHomeRegion, false); server.AddXmlRPCHandler("verify_agent", VerifyAgent, false); server.AddXmlRPCHandler("verify_client", VerifyClient, false); server.AddXmlRPCHandler("logout_agent", LogoutAgent, false); + server.AddXmlRPCHandler("status_notification", StatusNotification, false); + server.AddXmlRPCHandler("get_online_friends", GetOnlineFriends, false); + server.AddXmlRPCHandler("get_server_urls", GetServerURLs, false); + + server.AddXmlRPCHandler("locate_user", LocateUser, false); + server.AddXmlRPCHandler("get_uui", GetUUI, false); + server.AddHTTPHandler("/homeagent/", new HomeAgentHandler(m_HomeUsersService, loginServerIP, proxy).Handler); } @@ -194,5 +215,201 @@ namespace OpenSim.Server.Handlers.Hypergrid } + public XmlRpcResponse StatusNotification(XmlRpcRequest request, IPEndPoint remoteClient) + { + Hashtable hash = new Hashtable(); + hash["result"] = "false"; + + Hashtable requestData = (Hashtable)request.Params[0]; + //string host = (string)requestData["host"]; + //string portstr = (string)requestData["port"]; + if (requestData.ContainsKey("userID") && requestData.ContainsKey("online")) + { + string userID_str = (string)requestData["userID"]; + UUID userID = UUID.Zero; + UUID.TryParse(userID_str, out userID); + List ids = new List(); + foreach (object key in requestData.Keys) + { + if (key is string && ((string)key).StartsWith("friend_") && requestData[key] != null) + ids.Add(requestData[key].ToString()); + } + bool online = false; + bool.TryParse(requestData["online"].ToString(), out online); + + // let's spawn a thread for this, because it may take a long time... + List friendsOnline = m_HomeUsersService.StatusNotification(ids, userID, online); + if (friendsOnline.Count > 0) + { + int i = 0; + foreach (UUID id in friendsOnline) + { + hash["friend_" + i.ToString()] = id.ToString(); + i++; + } + } + else + hash["result"] = "No Friends Online"; + + } + + XmlRpcResponse response = new XmlRpcResponse(); + response.Value = hash; + return response; + + } + + public XmlRpcResponse GetOnlineFriends(XmlRpcRequest request, IPEndPoint remoteClient) + { + Hashtable hash = new Hashtable(); + + Hashtable requestData = (Hashtable)request.Params[0]; + //string host = (string)requestData["host"]; + //string portstr = (string)requestData["port"]; + if (requestData.ContainsKey("userID")) + { + string userID_str = (string)requestData["userID"]; + UUID userID = UUID.Zero; + UUID.TryParse(userID_str, out userID); + List ids = new List(); + foreach (object key in requestData.Keys) + { + if (key is string && ((string)key).StartsWith("friend_") && requestData[key] != null) + ids.Add(requestData[key].ToString()); + } + + //List online = m_HomeUsersService.GetOnlineFriends(userID, ids); + //if (online.Count > 0) + //{ + // int i = 0; + // foreach (UUID id in online) + // { + // hash["friend_" + i.ToString()] = id.ToString(); + // i++; + // } + //} + //else + // hash["result"] = "No Friends Online"; + } + + XmlRpcResponse response = new XmlRpcResponse(); + response.Value = hash; + return response; + + } + + public XmlRpcResponse GetServerURLs(XmlRpcRequest request, IPEndPoint remoteClient) + { + Hashtable hash = new Hashtable(); + + Hashtable requestData = (Hashtable)request.Params[0]; + //string host = (string)requestData["host"]; + //string portstr = (string)requestData["port"]; + if (requestData.ContainsKey("userID")) + { + string userID_str = (string)requestData["userID"]; + UUID userID = UUID.Zero; + UUID.TryParse(userID_str, out userID); + + Dictionary serverURLs = m_HomeUsersService.GetServerURLs(userID); + if (serverURLs.Count > 0) + { + foreach (KeyValuePair kvp in serverURLs) + hash["SRV_" + kvp.Key] = kvp.Value.ToString(); + } + else + hash["result"] = "No Service URLs"; + } + + XmlRpcResponse response = new XmlRpcResponse(); + response.Value = hash; + return response; + + } + + /// + /// Locates the user. + /// This is a sensitive operation, only authorized IP addresses can perform it. + /// + /// + /// + /// + public XmlRpcResponse LocateUser(XmlRpcRequest request, IPEndPoint remoteClient) + { + Hashtable hash = new Hashtable(); + + bool authorized = true; + if (m_VerifyCallers) + { + authorized = false; + foreach (string s in m_AuthorizedCallers) + if (s == remoteClient.Address.ToString()) + { + authorized = true; + break; + } + } + + if (authorized) + { + Hashtable requestData = (Hashtable)request.Params[0]; + //string host = (string)requestData["host"]; + //string portstr = (string)requestData["port"]; + if (requestData.ContainsKey("userID")) + { + string userID_str = (string)requestData["userID"]; + UUID userID = UUID.Zero; + UUID.TryParse(userID_str, out userID); + + string url = m_HomeUsersService.LocateUser(userID); + if (url != string.Empty) + hash["URL"] = url; + else + hash["result"] = "Unable to locate user"; + } + } + + XmlRpcResponse response = new XmlRpcResponse(); + response.Value = hash; + return response; + + } + + /// + /// Locates the user. + /// This is a sensitive operation, only authorized IP addresses can perform it. + /// + /// + /// + /// + public XmlRpcResponse GetUUI(XmlRpcRequest request, IPEndPoint remoteClient) + { + Hashtable hash = new Hashtable(); + + Hashtable requestData = (Hashtable)request.Params[0]; + //string host = (string)requestData["host"]; + //string portstr = (string)requestData["port"]; + if (requestData.ContainsKey("userID") && requestData.ContainsKey("targetUserID")) + { + string userID_str = (string)requestData["userID"]; + UUID userID = UUID.Zero; + UUID.TryParse(userID_str, out userID); + + string tuserID_str = (string)requestData["targetUserID"]; + UUID targetUserID = UUID.Zero; + UUID.TryParse(tuserID_str, out targetUserID); + string uui = m_HomeUsersService.GetUUI(userID, targetUserID); + if (uui != string.Empty) + hash["UUI"] = uui; + else + hash["result"] = "User unknown"; + } + + XmlRpcResponse response = new XmlRpcResponse(); + response.Value = hash; + return response; + + } + } } diff --git a/OpenSim/Server/Handlers/Map/MapAddServerConnector.cs b/OpenSim/Server/Handlers/Map/MapAddServerConnector.cs new file mode 100644 index 0000000000..99f98b60d7 --- /dev/null +++ b/OpenSim/Server/Handlers/Map/MapAddServerConnector.cs @@ -0,0 +1,183 @@ +/* + * 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.Generic; +using System.IO; +using System.Reflection; +using System.Xml; + +using Nini.Config; +using log4net; + +using OpenSim.Server.Base; +using OpenSim.Services.Interfaces; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Server.Handlers.Base; + +namespace OpenSim.Server.Handlers.MapImage +{ + public class MapAddServiceConnector : ServiceConnector + { + private IMapImageService m_MapService; + private string m_ConfigName = "MapImageService"; + + public MapAddServiceConnector(IConfigSource config, IHttpServer server, string configName) : + base(config, server, configName) + { + IConfig serverConfig = config.Configs[m_ConfigName]; + if (serverConfig == null) + throw new Exception(String.Format("No section {0} in config file", m_ConfigName)); + + string gridService = serverConfig.GetString("LocalServiceModule", + String.Empty); + + if (gridService == String.Empty) + throw new Exception("No LocalServiceModule in config file"); + + Object[] args = new Object[] { config }; + m_MapService = ServerUtils.LoadPlugin(gridService, args); + + server.AddStreamHandler(new MapServerPostHandler(m_MapService)); + } + } + + class MapServerPostHandler : BaseStreamHandler + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private IMapImageService m_MapService; + + public MapServerPostHandler(IMapImageService service) : + base("POST", "/map") + { + m_MapService = service; + } + + public override byte[] Handle(string path, Stream requestData, OSHttpRequest httpRequest, OSHttpResponse httpResponse) + { + m_log.DebugFormat("[MAP SERVICE IMAGE HANDLER]: Received {0}", path); + StreamReader sr = new StreamReader(requestData); + string body = sr.ReadToEnd(); + sr.Close(); + body = body.Trim(); + + try + { + Dictionary request = ServerUtils.ParseQueryString(body); + + if (!request.ContainsKey("X") || !request.ContainsKey("Y") || !request.ContainsKey("DATA")) + { + httpResponse.StatusCode = (int)OSHttpStatusCode.ClientErrorBadRequest; + return FailureResult("Bad request."); + } + int x = 0, y = 0; + Int32.TryParse(request["X"].ToString(), out x); + Int32.TryParse(request["Y"].ToString(), out y); + string type = "image/jpeg"; + if (request.ContainsKey("TYPE")) + type = request["TYPE"].ToString(); + byte[] data = Convert.FromBase64String(request["DATA"].ToString()); + + string reason = string.Empty; + bool result = m_MapService.AddMapTile(x, y, data, out reason); + + if (result) + return SuccessResult(); + else + return FailureResult(reason); + + } + catch (Exception e) + { + m_log.ErrorFormat("[MAP SERVICE IMAGE HANDLER]: Exception {0} {1}", e.Message, e.StackTrace); + } + + return FailureResult("Unexpected server error"); + + } + + private byte[] SuccessResult() + { + XmlDocument doc = new XmlDocument(); + + XmlNode xmlnode = doc.CreateNode(XmlNodeType.XmlDeclaration, + "", ""); + + doc.AppendChild(xmlnode); + + XmlElement rootElement = doc.CreateElement("", "ServerResponse", + ""); + + doc.AppendChild(rootElement); + + XmlElement result = doc.CreateElement("", "Result", ""); + result.AppendChild(doc.CreateTextNode("Success")); + + rootElement.AppendChild(result); + + return DocToBytes(doc); + } + + private byte[] FailureResult(string msg) + { + XmlDocument doc = new XmlDocument(); + + XmlNode xmlnode = doc.CreateNode(XmlNodeType.XmlDeclaration, + "", ""); + + doc.AppendChild(xmlnode); + + XmlElement rootElement = doc.CreateElement("", "ServerResponse", + ""); + + doc.AppendChild(rootElement); + + XmlElement result = doc.CreateElement("", "Result", ""); + result.AppendChild(doc.CreateTextNode("Failure")); + + rootElement.AppendChild(result); + + XmlElement message = doc.CreateElement("", "Message", ""); + message.AppendChild(doc.CreateTextNode(msg)); + + rootElement.AppendChild(message); + + return DocToBytes(doc); + } + + private byte[] DocToBytes(XmlDocument doc) + { + MemoryStream ms = new MemoryStream(); + XmlTextWriter xw = new XmlTextWriter(ms, null); + xw.Formatting = Formatting.Indented; + doc.WriteTo(xw); + xw.Flush(); + + return ms.ToArray(); + } + } +} diff --git a/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs b/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs new file mode 100644 index 0000000000..e8a424f513 --- /dev/null +++ b/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs @@ -0,0 +1,105 @@ +/* + * 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.Net; +using System.Reflection; + +using Nini.Config; +using log4net; + +using OpenSim.Server.Base; +using OpenSim.Services.Interfaces; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Server.Handlers.Base; + +namespace OpenSim.Server.Handlers.MapImage +{ + public class MapGetServiceConnector : ServiceConnector + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private IMapImageService m_MapService; + + private string m_ConfigName = "MapImageService"; + + public MapGetServiceConnector(IConfigSource config, IHttpServer server, string configName) : + base(config, server, configName) + { + IConfig serverConfig = config.Configs[m_ConfigName]; + if (serverConfig == null) + throw new Exception(String.Format("No section {0} in config file", m_ConfigName)); + + string gridService = serverConfig.GetString("LocalServiceModule", + String.Empty); + + if (gridService == String.Empty) + throw new Exception("No LocalServiceModule in config file"); + + Object[] args = new Object[] { config }; + m_MapService = ServerUtils.LoadPlugin(gridService, args); + + server.AddStreamHandler(new MapServerGetHandler(m_MapService)); + } + } + + class MapServerGetHandler : BaseStreamHandler + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private IMapImageService m_MapService; + + public MapServerGetHandler(IMapImageService service) : + base("GET", "/map") + { + m_MapService = service; + } + + public override byte[] Handle(string path, Stream request, OSHttpRequest httpRequest, OSHttpResponse httpResponse) + { + byte[] result = new byte[0]; + + string format = string.Empty; + result = m_MapService.GetMapTile(path.Trim('/'), out format); + if (result.Length > 0) + { + httpResponse.StatusCode = (int)HttpStatusCode.OK; + if (format.Equals(".png")) + httpResponse.ContentType = "image/png"; + else if (format.Equals(".jpg") || format.Equals(".jpeg")) + httpResponse.ContentType = "image/jpeg"; + } + else + { + httpResponse.StatusCode = (int)HttpStatusCode.NotFound; + httpResponse.ContentType = "text/plain"; + } + + return result; + } + + } +} diff --git a/OpenSim/Services/Connectors/Friends/FriendsServiceConnector.cs b/OpenSim/Services/Connectors/Friends/FriendsServiceConnector.cs index 861c4759a3..c5ae0c056e 100644 --- a/OpenSim/Services/Connectors/Friends/FriendsServiceConnector.cs +++ b/OpenSim/Services/Connectors/Friends/FriendsServiceConnector.cs @@ -38,7 +38,7 @@ using FriendInfo = OpenSim.Services.Interfaces.FriendInfo; using OpenSim.Server.Base; using OpenMetaverse; -namespace OpenSim.Services.Connectors +namespace OpenSim.Services.Connectors.Friends { public class FriendsServicesConnector : IFriendsService { @@ -84,7 +84,7 @@ namespace OpenSim.Services.Connectors #region IFriendsService - + public FriendInfo[] GetFriends(UUID PrincipalID) { Dictionary sendData = new Dictionary(); @@ -92,6 +92,21 @@ namespace OpenSim.Services.Connectors sendData["PRINCIPALID"] = PrincipalID.ToString(); sendData["METHOD"] = "getfriends"; + return GetFriends(sendData, PrincipalID.ToString()); + } + + public FriendInfo[] GetFriends(string PrincipalID) + { + Dictionary sendData = new Dictionary(); + + sendData["PRINCIPALID"] = PrincipalID; + sendData["METHOD"] = "getfriends_string"; + + return GetFriends(sendData, PrincipalID); + } + + protected FriendInfo[] GetFriends(Dictionary sendData, string PrincipalID) + { string reqString = ServerUtils.BuildQueryString(sendData); try @@ -144,14 +159,10 @@ namespace OpenSim.Services.Connectors } - public bool StoreFriend(UUID PrincipalID, string Friend, int flags) + public bool StoreFriend(string PrincipalID, string Friend, int flags) { - FriendInfo finfo = new FriendInfo(); - finfo.PrincipalID = PrincipalID; - finfo.Friend = Friend; - finfo.MyFlags = flags; - Dictionary sendData = finfo.ToKeyValuePairs(); + Dictionary sendData = ToKeyValuePairs(PrincipalID, Friend, flags); sendData["METHOD"] = "storefriend"; @@ -189,6 +200,16 @@ namespace OpenSim.Services.Connectors } + public bool Delete(string PrincipalID, string Friend) + { + Dictionary sendData = new Dictionary(); + sendData["PRINCIPALID"] = PrincipalID.ToString(); + sendData["FRIEND"] = Friend; + sendData["METHOD"] = "deletefriend_string"; + + return Delete(sendData, PrincipalID, Friend); + } + public bool Delete(UUID PrincipalID, string Friend) { Dictionary sendData = new Dictionary(); @@ -196,6 +217,11 @@ namespace OpenSim.Services.Connectors sendData["FRIEND"] = Friend; sendData["METHOD"] = "deletefriend"; + return Delete(sendData, PrincipalID.ToString(), Friend); + } + + public bool Delete(Dictionary sendData, string PrincipalID, string Friend) + { string reply = string.Empty; try { @@ -230,5 +256,16 @@ namespace OpenSim.Services.Connectors } #endregion + + public Dictionary ToKeyValuePairs(string principalID, string friend, int flags) + { + Dictionary result = new Dictionary(); + result["PrincipalID"] = principalID; + result["Friend"] = friend; + result["MyFlags"] = flags; + + return result; + } + } } \ No newline at end of file diff --git a/OpenSim/Services/Connectors/Hypergrid/HGFriendsServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/HGFriendsServiceConnector.cs new file mode 100644 index 0000000000..d699f596a2 --- /dev/null +++ b/OpenSim/Services/Connectors/Hypergrid/HGFriendsServiceConnector.cs @@ -0,0 +1,206 @@ +/* + * 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 System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Services.Interfaces; +using OpenSim.Services.Connectors.Friends; +using FriendInfo = OpenSim.Services.Interfaces.FriendInfo; +using OpenSim.Server.Base; +using OpenMetaverse; + +namespace OpenSim.Services.Connectors.Hypergrid +{ + public class HGFriendsServicesConnector + { + private static readonly ILog m_log = + LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + + private string m_ServerURI = String.Empty; + private string m_ServiceKey = String.Empty; + private UUID m_SessionID; + + public HGFriendsServicesConnector() + { + } + + public HGFriendsServicesConnector(string serverURI) + { + m_ServerURI = serverURI.TrimEnd('/'); + } + + public HGFriendsServicesConnector(string serverURI, UUID sessionID, string serviceKey) + { + m_ServerURI = serverURI.TrimEnd('/'); + m_ServiceKey = serviceKey; + m_SessionID = sessionID; + } + + #region IFriendsService + + public uint GetFriendPerms(UUID PrincipalID, UUID friendID) + { + Dictionary sendData = new Dictionary(); + + sendData["PRINCIPALID"] = PrincipalID.ToString(); + sendData["FRIENDID"] = friendID.ToString(); + sendData["METHOD"] = "getfriendperms"; + sendData["KEY"] = m_ServiceKey; + sendData["SESSIONID"] = m_SessionID.ToString(); + + string reqString = ServerUtils.BuildQueryString(sendData); + + try + { + string reply = SynchronousRestFormsRequester.MakeRequest("POST", + m_ServerURI + "/hgfriends", + reqString); + if (reply != string.Empty) + { + Dictionary replyData = ServerUtils.ParseXmlResponse(reply); + + if ((replyData != null) && replyData.ContainsKey("Value") && (replyData["Value"] != null)) + { + uint perms = 0; + uint.TryParse(replyData["Value"].ToString(), out perms); + return perms; + } + else + m_log.DebugFormat("[HGFRIENDS CONNECTOR]: GetFriendPerms {0} received null response", + PrincipalID); + + } + } + catch (Exception e) + { + m_log.DebugFormat("[HGFRIENDS CONNECTOR]: Exception when contacting friends server: {0}", e.Message); + } + + return 0; + + } + + public bool NewFriendship(UUID PrincipalID, string Friend) + { + FriendInfo finfo = new FriendInfo(); + finfo.PrincipalID = PrincipalID; + finfo.Friend = Friend; + + Dictionary sendData = finfo.ToKeyValuePairs(); + + sendData["METHOD"] = "newfriendship"; + sendData["KEY"] = m_ServiceKey; + sendData["SESSIONID"] = m_SessionID.ToString(); + + string reply = string.Empty; + try + { + reply = SynchronousRestFormsRequester.MakeRequest("POST", + m_ServerURI + "/hgfriends", + ServerUtils.BuildQueryString(sendData)); + } + catch (Exception e) + { + m_log.DebugFormat("[HGFRIENDS CONNECTOR]: Exception when contacting friends server: {0}", e.Message); + return false; + } + + if (reply != string.Empty) + { + Dictionary replyData = ServerUtils.ParseXmlResponse(reply); + + if ((replyData != null) && replyData.ContainsKey("Result") && (replyData["Result"] != null)) + { + bool success = false; + Boolean.TryParse(replyData["Result"].ToString(), out success); + return success; + } + else + m_log.DebugFormat("[HGFRIENDS CONNECTOR]: StoreFriend {0} {1} received null response", + PrincipalID, Friend); + } + else + m_log.DebugFormat("[HGFRIENDS CONNECTOR]: StoreFriend received null reply"); + + return false; + + } + + public bool DeleteFriendship(UUID PrincipalID, UUID Friend, string secret) + { + FriendInfo finfo = new FriendInfo(); + finfo.PrincipalID = PrincipalID; + finfo.Friend = Friend.ToString(); + + Dictionary sendData = finfo.ToKeyValuePairs(); + + sendData["METHOD"] = "deletefriendship"; + sendData["SECRET"] = secret; + + string reply = string.Empty; + try + { + reply = SynchronousRestFormsRequester.MakeRequest("POST", + m_ServerURI + "/hgfriends", + ServerUtils.BuildQueryString(sendData)); + } + catch (Exception e) + { + m_log.DebugFormat("[HGFRIENDS CONNECTOR]: Exception when contacting friends server: {0}", e.Message); + return false; + } + + if (reply != string.Empty) + { + Dictionary replyData = ServerUtils.ParseXmlResponse(reply); + + if ((replyData != null) && replyData.ContainsKey("Result") && (replyData["Result"] != null)) + { + bool success = false; + Boolean.TryParse(replyData["Result"].ToString(), out success); + return success; + } + else + m_log.DebugFormat("[HGFRIENDS CONNECTOR]: Delete {0} {1} received null response", + PrincipalID, Friend); + } + else + m_log.DebugFormat("[HGFRIENDS CONNECTOR]: DeleteFriend received null reply"); + + return false; + + } + + #endregion + } +} \ No newline at end of file diff --git a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs index 7ddcfa61ae..4ce406c3c3 100644 --- a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs +++ b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs @@ -51,20 +51,31 @@ namespace OpenSim.Services.Connectors.Hypergrid MethodBase.GetCurrentMethod().DeclaringType); string m_ServerURL; - public UserAgentServiceConnector(string url) + + public UserAgentServiceConnector(string url) : this(url, true) + { + } + + public UserAgentServiceConnector(string url, bool dnsLookup) { m_ServerURL = url; - // Doing this here, because XML-RPC or mono have some strong ideas about - // caching DNS translations. - try + + if (dnsLookup) { - Uri m_Uri = new Uri(m_ServerURL); - IPAddress ip = Util.GetHostFromDNS(m_Uri.Host); - m_ServerURL = m_ServerURL.Replace(m_Uri.Host, ip.ToString()); ; - } - catch (Exception e) - { - m_log.DebugFormat("[USER AGENT CONNECTOR]: Malformed Uri {0}: {1}", m_ServerURL, e.Message); + // Doing this here, because XML-RPC or mono have some strong ideas about + // caching DNS translations. + try + { + Uri m_Uri = new Uri(m_ServerURL); + IPAddress ip = Util.GetHostFromDNS(m_Uri.Host); + m_ServerURL = m_ServerURL.Replace(m_Uri.Host, ip.ToString()); + if (!m_ServerURL.EndsWith("/")) + m_ServerURL += "/"; + } + catch (Exception e) + { + m_log.DebugFormat("[USER AGENT CONNECTOR]: Malformed Uri {0}: {1}", m_ServerURL, e.Message); + } } m_log.DebugFormat("[USER AGENT CONNECTOR]: new connector to {0} ({1})", url, m_ServerURL); } @@ -400,6 +411,329 @@ namespace OpenSim.Services.Connectors.Hypergrid GetBoolResponse(request, out reason); } + public List StatusNotification(List friends, UUID userID, bool online) + { + Hashtable hash = new Hashtable(); + hash["userID"] = userID.ToString(); + hash["online"] = online.ToString(); + int i = 0; + foreach (string s in friends) + { + hash["friend_" + i.ToString()] = s; + i++; + } + + IList paramList = new ArrayList(); + paramList.Add(hash); + + XmlRpcRequest request = new XmlRpcRequest("status_notification", paramList); + string reason = string.Empty; + + // Send and get reply + List friendsOnline = new List(); + XmlRpcResponse response = null; + try + { + response = request.Send(m_ServerURL, 6000); + } + catch (Exception e) + { + m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0}", m_ServerURL); + reason = "Exception: " + e.Message; + return friendsOnline; + } + + if (response.IsFault) + { + m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} returned an error: {1}", m_ServerURL, response.FaultString); + reason = "XMLRPC Fault"; + return friendsOnline; + } + + hash = (Hashtable)response.Value; + //foreach (Object o in hash) + // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value); + try + { + if (hash == null) + { + m_log.ErrorFormat("[USER AGENT CONNECTOR]: GetOnlineFriends Got null response from {0}! THIS IS BAAAAD", m_ServerURL); + reason = "Internal error 1"; + return friendsOnline; + } + + // Here is the actual response + foreach (object key in hash.Keys) + { + if (key is string && ((string)key).StartsWith("friend_") && hash[key] != null) + { + UUID uuid; + if (UUID.TryParse(hash[key].ToString(), out uuid)) + friendsOnline.Add(uuid); + } + } + + } + catch (Exception e) + { + m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got exception on GetOnlineFriends response."); + reason = "Exception: " + e.Message; + } + + return friendsOnline; + } + + public List GetOnlineFriends(UUID userID, List friends) + { + Hashtable hash = new Hashtable(); + hash["userID"] = userID.ToString(); + int i = 0; + foreach (string s in friends) + { + hash["friend_" + i.ToString()] = s; + i++; + } + + IList paramList = new ArrayList(); + paramList.Add(hash); + + XmlRpcRequest request = new XmlRpcRequest("get_online_friends", paramList); + string reason = string.Empty; + + // Send and get reply + List online = new List(); + XmlRpcResponse response = null; + try + { + response = request.Send(m_ServerURL, 10000); + } + catch (Exception e) + { + m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0}", m_ServerURL); + reason = "Exception: " + e.Message; + return online; + } + + if (response.IsFault) + { + m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} returned an error: {1}", m_ServerURL, response.FaultString); + reason = "XMLRPC Fault"; + return online; + } + + hash = (Hashtable)response.Value; + //foreach (Object o in hash) + // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value); + try + { + if (hash == null) + { + m_log.ErrorFormat("[USER AGENT CONNECTOR]: GetOnlineFriends Got null response from {0}! THIS IS BAAAAD", m_ServerURL); + reason = "Internal error 1"; + return online; + } + + // Here is the actual response + foreach (object key in hash.Keys) + { + if (key is string && ((string)key).StartsWith("friend_") && hash[key] != null) + { + UUID uuid; + if (UUID.TryParse(hash[key].ToString(), out uuid)) + online.Add(uuid); + } + } + + } + catch (Exception e) + { + m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got exception on GetOnlineFriends response."); + reason = "Exception: " + e.Message; + } + + return online; + } + + public Dictionary GetServerURLs(UUID userID) + { + Hashtable hash = new Hashtable(); + hash["userID"] = userID.ToString(); + + IList paramList = new ArrayList(); + paramList.Add(hash); + + XmlRpcRequest request = new XmlRpcRequest("get_server_urls", paramList); + string reason = string.Empty; + + // Send and get reply + Dictionary serverURLs = new Dictionary(); + XmlRpcResponse response = null; + try + { + response = request.Send(m_ServerURL, 10000); + } + catch (Exception e) + { + m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0}", m_ServerURL); + reason = "Exception: " + e.Message; + return serverURLs; + } + + if (response.IsFault) + { + m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} returned an error: {1}", m_ServerURL, response.FaultString); + reason = "XMLRPC Fault"; + return serverURLs; + } + + hash = (Hashtable)response.Value; + //foreach (Object o in hash) + // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value); + try + { + if (hash == null) + { + m_log.ErrorFormat("[USER AGENT CONNECTOR]: GetServerURLs Got null response from {0}! THIS IS BAAAAD", m_ServerURL); + reason = "Internal error 1"; + return serverURLs; + } + + // Here is the actual response + foreach (object key in hash.Keys) + { + if (key is string && ((string)key).StartsWith("SRV_") && hash[key] != null) + { + string serverType = key.ToString().Substring(4); // remove "SRV_" + serverURLs.Add(serverType, hash[key].ToString()); + } + } + + } + catch (Exception e) + { + m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got exception on GetOnlineFriends response."); + reason = "Exception: " + e.Message; + } + + return serverURLs; + } + + public string LocateUser(UUID userID) + { + Hashtable hash = new Hashtable(); + hash["userID"] = userID.ToString(); + + IList paramList = new ArrayList(); + paramList.Add(hash); + + XmlRpcRequest request = new XmlRpcRequest("locate_user", paramList); + string reason = string.Empty; + + // Send and get reply + string url = string.Empty; + XmlRpcResponse response = null; + try + { + response = request.Send(m_ServerURL, 10000); + } + catch (Exception e) + { + m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0}", m_ServerURL); + reason = "Exception: " + e.Message; + return url; + } + + if (response.IsFault) + { + m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} returned an error: {1}", m_ServerURL, response.FaultString); + reason = "XMLRPC Fault"; + return url; + } + + hash = (Hashtable)response.Value; + //foreach (Object o in hash) + // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value); + try + { + if (hash == null) + { + m_log.ErrorFormat("[USER AGENT CONNECTOR]: LocateUser Got null response from {0}! THIS IS BAAAAD", m_ServerURL); + reason = "Internal error 1"; + return url; + } + + // Here's the actual response + if (hash.ContainsKey("URL")) + url = hash["URL"].ToString(); + + } + catch (Exception e) + { + m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got exception on LocateUser response."); + reason = "Exception: " + e.Message; + } + + return url; + } + + public string GetUUI(UUID userID, UUID targetUserID) + { + Hashtable hash = new Hashtable(); + hash["userID"] = userID.ToString(); + hash["targetUserID"] = targetUserID.ToString(); + + IList paramList = new ArrayList(); + paramList.Add(hash); + + XmlRpcRequest request = new XmlRpcRequest("get_uui", paramList); + string reason = string.Empty; + + // Send and get reply + string uui = string.Empty; + XmlRpcResponse response = null; + try + { + response = request.Send(m_ServerURL, 10000); + } + catch (Exception e) + { + m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0}", m_ServerURL); + reason = "Exception: " + e.Message; + return uui; + } + + if (response.IsFault) + { + m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} returned an error: {1}", m_ServerURL, response.FaultString); + reason = "XMLRPC Fault"; + return uui; + } + + hash = (Hashtable)response.Value; + //foreach (Object o in hash) + // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value); + try + { + if (hash == null) + { + m_log.ErrorFormat("[USER AGENT CONNECTOR]: GetUUI Got null response from {0}! THIS IS BAAAAD", m_ServerURL); + reason = "Internal error 1"; + return uui; + } + + // Here's the actual response + if (hash.ContainsKey("UUI")) + uui = hash["UUI"].ToString(); + + } + catch (Exception e) + { + m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got exception on LocateUser response."); + reason = "Exception: " + e.Message; + } + + return uui; + } private bool GetBoolResponse(XmlRpcRequest request, out string reason) { diff --git a/OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs b/OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs new file mode 100644 index 0000000000..dbce9f613c --- /dev/null +++ b/OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs @@ -0,0 +1,131 @@ +/* + * 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.Net; +using System.Reflection; + +using OpenMetaverse; +using Nwc.XmlRpc; +using log4net; + +using OpenSim.Framework; + +namespace OpenSim.Services.Connectors.InstantMessage +{ + public class InstantMessageServiceConnector + { + private static readonly ILog m_log = + LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// This actually does the XMLRPC Request + /// + /// URL we pull the data out of to send the request to + /// The Instant Message + /// Bool if the message was successfully delivered at the other side. + public static bool SendInstantMessage(string url, GridInstantMessage im) + { + Hashtable xmlrpcdata = ConvertGridInstantMessageToXMLRPC(im); + xmlrpcdata["region_handle"] = 0; + + ArrayList SendParams = new ArrayList(); + SendParams.Add(xmlrpcdata); + XmlRpcRequest GridReq = new XmlRpcRequest("grid_instant_message", SendParams); + try + { + + XmlRpcResponse GridResp = GridReq.Send(url, 10000); + + Hashtable responseData = (Hashtable)GridResp.Value; + + if (responseData.ContainsKey("success")) + { + if ((string)responseData["success"] == "TRUE") + { + //m_log.DebugFormat("[XXX] Success"); + return true; + } + else + { + //m_log.DebugFormat("[XXX] Fail"); + return false; + } + } + else + { + m_log.DebugFormat("[GRID INSTANT MESSAGE]: No response from {0}", url); + return false; + } + } + catch (WebException e) + { + m_log.ErrorFormat("[GRID INSTANT MESSAGE]: Error sending message to {0} the host didn't respond " + e.ToString(), url); + } + + return false; + } + + /// + /// Takes a GridInstantMessage and converts it into a Hashtable for XMLRPC + /// + /// The GridInstantMessage object + /// Hashtable containing the XMLRPC request + protected static Hashtable ConvertGridInstantMessageToXMLRPC(GridInstantMessage msg) + { + Hashtable gim = new Hashtable(); + gim["from_agent_id"] = msg.fromAgentID.ToString(); + // Kept for compatibility + gim["from_agent_session"] = UUID.Zero.ToString(); + gim["to_agent_id"] = msg.toAgentID.ToString(); + gim["im_session_id"] = msg.imSessionID.ToString(); + gim["timestamp"] = msg.timestamp.ToString(); + gim["from_agent_name"] = msg.fromAgentName; + gim["message"] = msg.message; + byte[] dialogdata = new byte[1]; dialogdata[0] = msg.dialog; + gim["dialog"] = Convert.ToBase64String(dialogdata, Base64FormattingOptions.None); + + if (msg.fromGroup) + gim["from_group"] = "TRUE"; + else + gim["from_group"] = "FALSE"; + byte[] offlinedata = new byte[1]; offlinedata[0] = msg.offline; + gim["offline"] = Convert.ToBase64String(offlinedata, Base64FormattingOptions.None); + gim["parent_estate_id"] = msg.ParentEstateID.ToString(); + gim["position_x"] = msg.Position.X.ToString(); + gim["position_y"] = msg.Position.Y.ToString(); + gim["position_z"] = msg.Position.Z.ToString(); + gim["region_id"] = msg.RegionID.ToString(); + gim["binary_bucket"] = Convert.ToBase64String(msg.binaryBucket, Base64FormattingOptions.None); + + return gim; + } + + } +} diff --git a/OpenSim/Services/Connectors/MapImage/MapImageServiceConnector.cs b/OpenSim/Services/Connectors/MapImage/MapImageServiceConnector.cs new file mode 100644 index 0000000000..520d639ccf --- /dev/null +++ b/OpenSim/Services/Connectors/MapImage/MapImageServiceConnector.cs @@ -0,0 +1,157 @@ +/* + * 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 System; +using System.Collections.Generic; +using System.IO; +using System.Net; +using System.Reflection; + +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Framework.Communications; +using OpenSim.Server.Base; +using OpenSim.Services.Interfaces; +using OpenMetaverse; +using OpenMetaverse.StructuredData; + +namespace OpenSim.Services.Connectors +{ + public class MapImageServicesConnector : IMapImageService + { + private static readonly ILog m_log = + LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + + private string m_ServerURI = String.Empty; + private IImprovedAssetCache m_Cache = null; + + public MapImageServicesConnector() + { + } + + public MapImageServicesConnector(string serverURI) + { + m_ServerURI = serverURI.TrimEnd('/'); + } + + public MapImageServicesConnector(IConfigSource source) + { + Initialise(source); + } + + public virtual void Initialise(IConfigSource source) + { + IConfig config = source.Configs["MapImageService"]; + if (config == null) + { + m_log.Error("[MAP IMAGE CONNECTOR]: MapImageService missing"); + throw new Exception("MapImage connector init error"); + } + + string serviceURI = config.GetString("MapImageServerURI", + String.Empty); + + if (serviceURI == String.Empty) + { + m_log.Error("[MAP IMAGE CONNECTOR]: No Server URI named in section MapImageService"); + throw new Exception("MapImage connector init error"); + } + m_ServerURI = serviceURI; + m_ServerURI = serviceURI.TrimEnd('/'); + } + + public bool AddMapTile(int x, int y, byte[] jpgData, out string reason) + { + reason = string.Empty; + int tickstart = Util.EnvironmentTickCount(); + Dictionary sendData = new Dictionary(); + sendData["X"] = x.ToString(); + sendData["Y"] = y.ToString(); + sendData["TYPE"] = "image/jpeg"; + sendData["DATA"] = Convert.ToBase64String(jpgData); + + string reqString = ServerUtils.BuildQueryString(sendData); + + try + { + string reply = SynchronousRestFormsRequester.MakeRequest("POST", + m_ServerURI + "/map", + reqString); + if (reply != string.Empty) + { + Dictionary replyData = ServerUtils.ParseXmlResponse(reply); + + if (replyData.ContainsKey("Result") && (replyData["Result"].ToString().ToLower() == "success")) + { + return true; + } + else if (replyData.ContainsKey("Result") && (replyData["Result"].ToString().ToLower() == "failure")) + { + m_log.DebugFormat("[MAP IMAGE CONNECTOR]: Registration failed: {0}", replyData["Message"].ToString()); + reason = replyData["Message"].ToString(); + return false; + } + else if (!replyData.ContainsKey("Result")) + { + m_log.DebugFormat("[MAP IMAGE CONNECTOR]: reply data does not contain result field"); + } + else + { + m_log.DebugFormat("[MAP IMAGE CONNECTOR]: unexpected result {0}", replyData["Result"].ToString()); + reason = "Unexpected result " + replyData["Result"].ToString(); + } + + } + else + m_log.DebugFormat("[MAP IMAGE CONNECTOR]: RegisterRegion received null reply"); + } + catch (Exception e) + { + m_log.DebugFormat("[MAP IMAGE CONNECTOR]: Exception when contacting grid server: {0}", e.Message); + } + finally + { + // This just dumps a warning for any operation that takes more than 100 ms + int tickdiff = Util.EnvironmentTickCountSubtract(tickstart); + m_log.DebugFormat("[MAP IMAGE CONNECTOR]: map tile uploaded in {0}ms", tickdiff); + } + + return false; + + } + + public byte[] GetMapTile(string fileName, out string format) + { + format = string.Empty; + new Exception("GetMapTile method not Implemented"); + return null; + } + } +} diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs index 6f2d73559b..7422d94b44 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs @@ -77,6 +77,11 @@ namespace OpenSim.Services.Connectors.SimianGrid #region IFriendsService public FriendInfo[] GetFriends(UUID principalID) + { + return GetFriends(principalID.ToString()); + } + + public FriendInfo[] GetFriends(string principalID) { if (String.IsNullOrEmpty(m_serverUrl)) return new FriendInfo[0]; @@ -95,7 +100,14 @@ namespace OpenSim.Services.Connectors.SimianGrid UUID friendID = friendEntry["Key"].AsUUID(); FriendInfo friend = new FriendInfo(); - friend.PrincipalID = principalID; + if (!UUID.TryParse(principalID, out friend.PrincipalID)) + { + string tmp = string.Empty; + if (!Util.ParseUniversalUserIdentifier(principalID, out friend.PrincipalID, out tmp, out tmp, out tmp, out tmp)) + // bad record. ignore this entry + continue; + } + friend.Friend = friendID.ToString(); friend.MyFlags = friendEntry["Value"].AsInteger(); friend.TheirFlags = -1; @@ -127,7 +139,7 @@ namespace OpenSim.Services.Connectors.SimianGrid return array; } - public bool StoreFriend(UUID principalID, string friend, int flags) + public bool StoreFriend(string principalID, string friend, int flags) { if (String.IsNullOrEmpty(m_serverUrl)) return true; @@ -151,6 +163,11 @@ namespace OpenSim.Services.Connectors.SimianGrid } public bool Delete(UUID principalID, string friend) + { + return Delete(principalID.ToString(), friend); + } + + public bool Delete(string principalID, string friend) { if (String.IsNullOrEmpty(m_serverUrl)) return true; @@ -174,7 +191,7 @@ namespace OpenSim.Services.Connectors.SimianGrid #endregion IFriendsService - private OSDArray GetFriended(UUID ownerID) + private OSDArray GetFriended(string ownerID) { NameValueCollection requestArgs = new NameValueCollection { @@ -195,7 +212,7 @@ namespace OpenSim.Services.Connectors.SimianGrid } } - private OSDArray GetFriendedBy(UUID ownerID) + private OSDArray GetFriendedBy(string ownerID) { NameValueCollection requestArgs = new NameValueCollection { diff --git a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs index 725c6df553..6fb583cbcc 100644 --- a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs +++ b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs @@ -103,16 +103,31 @@ namespace OpenSim.Services.Connectors.Simulation args["teleport_flags"] = OSD.FromString(flags.ToString()); OSDMap result = WebUtil.PostToServiceCompressed(uri, args, 30000); - if (result["Success"].AsBoolean()) - return true; - + bool success = result["success"].AsBoolean(); + if (success && result.ContainsKey("_Result")) + { + OSDMap data = (OSDMap)result["_Result"]; + + reason = data["reason"].AsString(); + success = data["success"].AsBoolean(); + return success; + } + + // Try the old version, uncompressed result = WebUtil.PostToService(uri, args, 30000); if (result["Success"].AsBoolean()) { - m_log.WarnFormat( - "[REMOTE SIMULATION CONNECTOR]: Remote simulator {0} did not accept compressed transfer, suggest updating it.", destination.RegionName); - return true; + if (result.ContainsKey("_Result")) + { + OSDMap data = (OSDMap)result["_Result"]; + + reason = data["reason"].AsString(); + success = data["success"].AsBoolean(); + m_log.WarnFormat( + "[REMOTE SIMULATION CONNECTOR]: Remote simulator {0} did not accept compressed transfer, suggest updating it.", destination.RegionName); + return success; + } } m_log.WarnFormat( diff --git a/OpenSim/Services/FreeswitchService/FreeswitchService.cs b/OpenSim/Services/FreeswitchService/FreeswitchService.cs index c3f10560d7..201e72f511 100644 --- a/OpenSim/Services/FreeswitchService/FreeswitchService.cs +++ b/OpenSim/Services/FreeswitchService/FreeswitchService.cs @@ -54,10 +54,10 @@ namespace OpenSim.Services.FreeswitchService Hashtable response = new Hashtable(); - foreach (DictionaryEntry item in request) - { -// m_log.InfoFormat("[FreeSwitchDirectory]: requestBody item {0} {1}",item.Key, item.Value); - } +// foreach (DictionaryEntry item in request) +// { +//// m_log.InfoFormat("[FreeSwitchDirectory]: requestBody item {0} {1}",item.Key, item.Value); +// } string requestcontext = (string) request["Hunt-Context"]; response["content_type"] = "text/xml"; diff --git a/OpenSim/Services/Friends/FriendsService.cs b/OpenSim/Services/Friends/FriendsService.cs index 3c64eccdf6..e2033ac93d 100644 --- a/OpenSim/Services/Friends/FriendsService.cs +++ b/OpenSim/Services/Friends/FriendsService.cs @@ -43,17 +43,16 @@ namespace OpenSim.Services.Friends { } - public FriendInfo[] GetFriends(UUID PrincipalID) + public virtual FriendInfo[] GetFriends(UUID PrincipalID) { FriendsData[] data = m_Database.GetFriends(PrincipalID); - List info = new List(); foreach (FriendsData d in data) { FriendInfo i = new FriendInfo(); - i.PrincipalID = d.PrincipalID; + i.PrincipalID = new UUID(d.PrincipalID); i.Friend = d.Friend; i.MyFlags = Convert.ToInt32(d.Data["Flags"]); i.TheirFlags = Convert.ToInt32(d.Data["TheirFlags"]); @@ -64,7 +63,33 @@ namespace OpenSim.Services.Friends return info.ToArray(); } - public bool StoreFriend(UUID PrincipalID, string Friend, int flags) + public virtual FriendInfo[] GetFriends(string PrincipalID) + { + FriendsData[] data = m_Database.GetFriends(PrincipalID); + List info = new List(); + + foreach (FriendsData d in data) + { + FriendInfo i = new FriendInfo(); + + if (!UUID.TryParse(d.PrincipalID, out i.PrincipalID)) + { + string tmp = string.Empty; + if (!Util.ParseUniversalUserIdentifier(d.PrincipalID, out i.PrincipalID, out tmp, out tmp, out tmp, out tmp)) + // bad record. ignore this entry + continue; + } + i.Friend = d.Friend; + i.MyFlags = Convert.ToInt32(d.Data["Flags"]); + i.TheirFlags = Convert.ToInt32(d.Data["TheirFlags"]); + + info.Add(i); + } + + return info.ToArray(); + } + + public virtual bool StoreFriend(string PrincipalID, string Friend, int flags) { FriendsData d = new FriendsData(); @@ -76,7 +101,12 @@ namespace OpenSim.Services.Friends return m_Database.Store(d); } - public bool Delete(UUID PrincipalID, string Friend) + public bool Delete(string principalID, string friend) + { + return m_Database.Delete(principalID, friend); + } + + public virtual bool Delete(UUID PrincipalID, string Friend) { return m_Database.Delete(PrincipalID, Friend); } diff --git a/OpenSim/Services/GridService/HypergridLinker.cs b/OpenSim/Services/GridService/HypergridLinker.cs index b226971950..6d63748e87 100644 --- a/OpenSim/Services/GridService/HypergridLinker.cs +++ b/OpenSim/Services/GridService/HypergridLinker.cs @@ -327,10 +327,13 @@ namespace OpenSim.Services.GridService else regInfo.RegionName = externalName; - m_log.Debug("[HYPERGRID LINKER]: naming linked region " + regInfo.RegionName); + m_log.DebugFormat("[HYPERGRID LINKER]: naming linked region {0}, handle {1}", regInfo.RegionName, handle.ToString()); // Get the map image - regInfo.TerrainImage = m_GatekeeperConnector.GetMapImage(regionID, imageURL, m_MapTileDirectory); + regInfo.TerrainImage = GetMapImage(regionID, imageURL); + + // Store the origin's coordinates somewhere + regInfo.RegionSecret = handle.ToString(); AddHyperlinkRegion(regInfo, handle); m_log.Info("[HYPERGRID LINKER]: Successfully linked to region_uuid " + regInfo.RegionID); @@ -427,6 +430,10 @@ namespace OpenSim.Services.GridService m_Database.Delete(regionID); } + public UUID GetMapImage(UUID regionID, string imageURL) + { + return m_GatekeeperConnector.GetMapImage(regionID, imageURL, m_MapTileDirectory); + } #endregion diff --git a/OpenSim/Services/HypergridService/HGInstantMessageService.cs b/OpenSim/Services/HypergridService/HGInstantMessageService.cs new file mode 100644 index 0000000000..ded589de2d --- /dev/null +++ b/OpenSim/Services/HypergridService/HGInstantMessageService.cs @@ -0,0 +1,349 @@ +/* + * 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.Generic; +using System.Net; +using System.Reflection; + +using OpenSim.Framework; +using OpenSim.Services.Connectors.Friends; +using OpenSim.Services.Connectors.Hypergrid; +using OpenSim.Services.Interfaces; +using OpenSim.Services.Connectors.InstantMessage; +using GridRegion = OpenSim.Services.Interfaces.GridRegion; +using OpenSim.Server.Base; +using FriendInfo = OpenSim.Services.Interfaces.FriendInfo; + +using OpenMetaverse; +using log4net; +using Nini.Config; + +namespace OpenSim.Services.HypergridService +{ + /// + /// Inter-grid IM + /// + public class HGInstantMessageService : IInstantMessage + { + private static readonly ILog m_log = + LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + + private const double CACHE_EXPIRATION_SECONDS = 120000.0; // 33 hours + + static bool m_Initialized = false; + + protected static IGridService m_GridService; + protected static IPresenceService m_PresenceService; + protected static IUserAgentService m_UserAgentService; + + protected static IInstantMessageSimConnector m_IMSimConnector; + + protected static Dictionary m_UserLocationMap = new Dictionary(); + private static ExpiringCache m_RegionCache; + + private static string m_RestURL; + private static bool m_ForwardOfflineGroupMessages; + private static bool m_InGatekeeper; + + public HGInstantMessageService(IConfigSource config) + : this(config, null) + { + } + + public HGInstantMessageService(IConfigSource config, IInstantMessageSimConnector imConnector) + { + if (imConnector != null) + m_IMSimConnector = imConnector; + + if (!m_Initialized) + { + m_Initialized = true; + + IConfig serverConfig = config.Configs["HGInstantMessageService"]; + if (serverConfig == null) + throw new Exception(String.Format("No section HGInstantMessageService in config file")); + + string gridService = serverConfig.GetString("GridService", String.Empty); + string presenceService = serverConfig.GetString("PresenceService", String.Empty); + string userAgentService = serverConfig.GetString("UserAgentService", String.Empty); + m_InGatekeeper = serverConfig.GetBoolean("InGatekeeper", false); + m_log.DebugFormat("[HG IM SERVICE]: Starting... InRobust? {0}", m_InGatekeeper); + + + if (gridService == string.Empty || presenceService == string.Empty) + throw new Exception(String.Format("Incomplete specifications, InstantMessage Service cannot function.")); + + Object[] args = new Object[] { config }; + m_GridService = ServerUtils.LoadPlugin(gridService, args); + m_PresenceService = ServerUtils.LoadPlugin(presenceService, args); + m_UserAgentService = ServerUtils.LoadPlugin(userAgentService, args); + + m_RegionCache = new ExpiringCache(); + + IConfig cnf = config.Configs["Messaging"]; + if (cnf == null) + { + return; + } + + m_RestURL = cnf.GetString("OfflineMessageURL", string.Empty); + m_ForwardOfflineGroupMessages = cnf.GetBoolean("ForwardOfflineGroupMessages", false); + + } + } + + public bool IncomingInstantMessage(GridInstantMessage im) + { + m_log.DebugFormat("[HG IM SERVICE]: Received message from {0} to {1}", im.fromAgentID, im.toAgentID); + UUID toAgentID = new UUID(im.toAgentID); + + bool success = false; + if (m_IMSimConnector != null) + { + //m_log.DebugFormat("[XXX] SendIMToRegion local im connector"); + success = m_IMSimConnector.SendInstantMessage(im); + } + else + { + success = TrySendInstantMessage(im, "", true, false); + } + + if (!success && m_InGatekeeper) // we do this only in the Gatekeeper IM service + UndeliveredMessage(im); + + return success; + } + + public bool OutgoingInstantMessage(GridInstantMessage im, string url, bool foreigner) + { + m_log.DebugFormat("[HG IM SERVICE]: Sending message from {0} to {1}@{2}", im.fromAgentID, im.toAgentID, url); + if (url != string.Empty) + return TrySendInstantMessage(im, url, true, foreigner); + else + { + PresenceInfo upd = new PresenceInfo(); + upd.RegionID = UUID.Zero; + return TrySendInstantMessage(im, upd, true, foreigner); + } + + } + + protected bool TrySendInstantMessage(GridInstantMessage im, object previousLocation, bool firstTime, bool foreigner) + { + UUID toAgentID = new UUID(im.toAgentID); + + PresenceInfo upd = null; + string url = string.Empty; + + bool lookupAgent = false; + + lock (m_UserLocationMap) + { + if (m_UserLocationMap.ContainsKey(toAgentID)) + { + object o = m_UserLocationMap[toAgentID]; + if (o is PresenceInfo) + upd = (PresenceInfo)o; + else if (o is string) + url = (string)o; + + // We need to compare the current location with the previous + // or the recursive loop will never end because it will never try to lookup the agent again + if (!firstTime) + { + lookupAgent = true; + upd = null; + } + } + else + { + lookupAgent = true; + } + } + + //m_log.DebugFormat("[XXX] Neeed lookup ? {0}", (lookupAgent ? "yes" : "no")); + + // Are we needing to look-up an agent? + if (lookupAgent) + { + // Non-cached user agent lookup. + PresenceInfo[] presences = m_PresenceService.GetAgents(new string[] { toAgentID.ToString() }); + if (presences != null && presences.Length > 0) + { + foreach (PresenceInfo p in presences) + { + if (p.RegionID != UUID.Zero) + { + //m_log.DebugFormat("[XXX]: Found presence in {0}", p.RegionID); + upd = p; + break; + } + } + } + + if (upd == null && !foreigner) + { + // Let's check with the UAS if the user is elsewhere + m_log.DebugFormat("[HG IM SERVICE]: User is not present. Checking location with User Agent service"); + url = m_UserAgentService.LocateUser(toAgentID); + } + + // check if we've tried this before.. + // This is one way to end the recursive loop + // + if (!firstTime && ((previousLocation is PresenceInfo && upd != null && upd.RegionID == ((PresenceInfo)previousLocation).RegionID) || + (previousLocation is string && upd == null && previousLocation.Equals(url)))) + { + // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); + m_log.DebugFormat("[HG IM SERVICE]: Fail 2 {0} {1}", previousLocation, url); + + return false; + } + } + + if (upd != null) + { + // ok, the user is around somewhere. Let's send back the reply with "success" + // even though the IM may still fail. Just don't keep the caller waiting for + // the entire time we're trying to deliver the IM + return SendIMToRegion(upd, im, toAgentID, foreigner); + } + else if (url != string.Empty) + { + // ok, the user is around somewhere. Let's send back the reply with "success" + // even though the IM may still fail. Just don't keep the caller waiting for + // the entire time we're trying to deliver the IM + return ForwardIMToGrid(url, im, toAgentID, foreigner); + } + else if (firstTime && previousLocation is string && (string)previousLocation != string.Empty) + { + return ForwardIMToGrid((string)previousLocation, im, toAgentID, foreigner); + } + else + m_log.DebugFormat("[HG IM SERVICE]: Unable to locate user {0}", toAgentID); + return false; + } + + bool SendIMToRegion(PresenceInfo upd, GridInstantMessage im, UUID toAgentID, bool foreigner) + { + bool imresult = false; + GridRegion reginfo = null; + if (!m_RegionCache.TryGetValue(upd.RegionID, out reginfo)) + { + reginfo = m_GridService.GetRegionByUUID(UUID.Zero /*!!!*/, upd.RegionID); + if (reginfo != null) + m_RegionCache.AddOrUpdate(upd.RegionID, reginfo, CACHE_EXPIRATION_SECONDS); + } + + if (reginfo != null) + { + imresult = InstantMessageServiceConnector.SendInstantMessage(reginfo.ServerURI, im); + } + else + { + m_log.DebugFormat("[HG IM SERVICE]: Failed to deliver message to {0}", reginfo.ServerURI); + return false; + } + + if (imresult) + { + // IM delivery successful, so store the Agent's location in our local cache. + lock (m_UserLocationMap) + { + if (m_UserLocationMap.ContainsKey(toAgentID)) + { + m_UserLocationMap[toAgentID] = upd; + } + else + { + m_UserLocationMap.Add(toAgentID, upd); + } + } + return true; + } + else + { + // try again, but lookup user this time. + // Warning, this must call the Async version + // of this method or we'll be making thousands of threads + // The version within the spawned thread is SendGridInstantMessageViaXMLRPCAsync + // The version that spawns the thread is SendGridInstantMessageViaXMLRPC + + // This is recursive!!!!! + return TrySendInstantMessage(im, upd, false, foreigner); + } + } + + bool ForwardIMToGrid(string url, GridInstantMessage im, UUID toAgentID, bool foreigner) + { + if (InstantMessageServiceConnector.SendInstantMessage(url, im)) + { + // IM delivery successful, so store the Agent's location in our local cache. + lock (m_UserLocationMap) + { + if (m_UserLocationMap.ContainsKey(toAgentID)) + { + m_UserLocationMap[toAgentID] = url; + } + else + { + m_UserLocationMap.Add(toAgentID, url); + } + } + + return true; + } + else + { + // try again, but lookup user this time. + + // This is recursive!!!!! + return TrySendInstantMessage(im, url, false, foreigner); + } + + } + + private bool UndeliveredMessage(GridInstantMessage im) + { + if (m_RestURL != string.Empty && (im.offline != 0) + && (!im.fromGroup || (im.fromGroup && m_ForwardOfflineGroupMessages))) + { + m_log.DebugFormat("[HG IM SERVICE]: Message saved"); + return SynchronousRestObjectPoster.BeginPostObject( + "POST", m_RestURL + "/SaveMessage/", im); + + } + + else + { + return false; + } + } + } +} diff --git a/OpenSim/Services/HypergridService/HGInventoryService.cs b/OpenSim/Services/HypergridService/HGInventoryService.cs index 9ee1ae4c5f..4eb61ba6b9 100644 --- a/OpenSim/Services/HypergridService/HGInventoryService.cs +++ b/OpenSim/Services/HypergridService/HGInventoryService.cs @@ -134,6 +134,7 @@ namespace OpenSim.Services.HypergridService public override InventoryFolderBase GetRootFolder(UUID principalID) { + //m_log.DebugFormat("[HG INVENTORY SERVICE]: GetRootFolder for {0}", principalID); // Warp! Root folder for travelers XInventoryFolder[] folders = m_Database.GetFolders( new string[] { "agentID", "folderName"}, @@ -171,6 +172,7 @@ namespace OpenSim.Services.HypergridService public override InventoryFolderBase GetFolderForType(UUID principalID, AssetType type) { + //m_log.DebugFormat("[HG INVENTORY SERVICE]: GetFolderForType for {0} {0}", principalID, type); return GetRootFolder(principalID); } diff --git a/OpenSim/Services/HypergridService/UserAgentService.cs b/OpenSim/Services/HypergridService/UserAgentService.cs index 09e785fd39..ac535837cc 100644 --- a/OpenSim/Services/HypergridService/UserAgentService.cs +++ b/OpenSim/Services/HypergridService/UserAgentService.cs @@ -31,10 +31,12 @@ using System.Net; using System.Reflection; using OpenSim.Framework; +using OpenSim.Services.Connectors.Friends; using OpenSim.Services.Connectors.Hypergrid; using OpenSim.Services.Interfaces; using GridRegion = OpenSim.Services.Interfaces.GridRegion; using OpenSim.Server.Base; +using FriendInfo = OpenSim.Services.Interfaces.FriendInfo; using OpenMetaverse; using log4net; @@ -63,19 +65,35 @@ namespace OpenSim.Services.HypergridService protected static IGridService m_GridService; protected static GatekeeperServiceConnector m_GatekeeperConnector; protected static IGatekeeperService m_GatekeeperService; + protected static IFriendsService m_FriendsService; + protected static IPresenceService m_PresenceService; + protected static IUserAccountService m_UserAccountService; + protected static IFriendsSimConnector m_FriendsLocalSimConnector; // standalone, points to HGFriendsModule + protected static FriendsSimConnector m_FriendsSimConnector; // grid protected static string m_GridName; protected static bool m_BypassClientVerification; - public UserAgentService(IConfigSource config) + public UserAgentService(IConfigSource config) : this(config, null) { + } + + public UserAgentService(IConfigSource config, IFriendsSimConnector friendsConnector) + { + // Let's set this always, because we don't know the sequence + // of instantiations + if (friendsConnector != null) + m_FriendsLocalSimConnector = friendsConnector; + if (!m_Initialized) { m_Initialized = true; m_log.DebugFormat("[HOME USERS SECURITY]: Starting..."); - + + m_FriendsSimConnector = new FriendsSimConnector(); + IConfig serverConfig = config.Configs["UserAgentService"]; if (serverConfig == null) throw new Exception(String.Format("No section UserAgentService in config file")); @@ -83,6 +101,9 @@ namespace OpenSim.Services.HypergridService string gridService = serverConfig.GetString("GridService", String.Empty); string gridUserService = serverConfig.GetString("GridUserService", String.Empty); string gatekeeperService = serverConfig.GetString("GatekeeperService", String.Empty); + string friendsService = serverConfig.GetString("FriendsService", String.Empty); + string presenceService = serverConfig.GetString("PresenceService", String.Empty); + string userAccountService = serverConfig.GetString("UserAccountService", String.Empty); m_BypassClientVerification = serverConfig.GetBoolean("BypassClientVerification", false); @@ -94,6 +115,9 @@ namespace OpenSim.Services.HypergridService m_GridUserService = ServerUtils.LoadPlugin(gridUserService, args); m_GatekeeperConnector = new GatekeeperServiceConnector(); m_GatekeeperService = ServerUtils.LoadPlugin(gatekeeperService, args); + m_FriendsService = ServerUtils.LoadPlugin(friendsService, args); + m_PresenceService = ServerUtils.LoadPlugin(presenceService, args); + m_UserAccountService = ServerUtils.LoadPlugin(userAccountService, args); m_GridName = serverConfig.GetString("ExternalName", string.Empty); if (m_GridName == string.Empty) @@ -155,12 +179,17 @@ namespace OpenSim.Services.HypergridService string myExternalIP = string.Empty; string gridName = gatekeeper.ServerURI; - m_log.DebugFormat("[USER AGENT SERVICE]: m_grid - {0}, gn - {1}", m_GridName, gridName); - + m_log.DebugFormat("[USER AGENT SERVICE]: this grid: {0}, desired grid: {1}", m_GridName, gridName); + if (m_GridName == gridName) success = m_GatekeeperService.LoginAgent(agentCircuit, finalDestination, out reason); else + { success = m_GatekeeperConnector.CreateAgent(region, agentCircuit, (uint)Constants.TeleportFlags.ViaLogin, out myExternalIP, out reason); + if (success) + // Report them as nowhere + m_PresenceService.ReportAgent(agentCircuit.SessionID, UUID.Zero); + } if (!success) { @@ -169,7 +198,12 @@ namespace OpenSim.Services.HypergridService // restore the old travel info lock (m_TravelingAgents) - m_TravelingAgents[agentCircuit.SessionID] = old; + { + if (old == null) + m_TravelingAgents.Remove(agentCircuit.SessionID); + else + m_TravelingAgents[agentCircuit.SessionID] = old; + } return false; } @@ -179,6 +213,7 @@ namespace OpenSim.Services.HypergridService if (clientIP != null) m_TravelingAgents[agentCircuit.SessionID].ClientIPAddress = clientIP.Address.ToString(); m_TravelingAgents[agentCircuit.SessionID].MyIpAddress = myExternalIP; + return true; } @@ -289,6 +324,213 @@ namespace OpenSim.Services.HypergridService return false; } + public List StatusNotification(List friends, UUID foreignUserID, bool online) + { + if (m_FriendsService == null || m_PresenceService == null) + { + m_log.WarnFormat("[USER AGENT SERVICE]: Unable to perform status notifications because friends or presence services are missing"); + return new List(); + } + + List localFriendsOnline = new List(); + + m_log.DebugFormat("[USER AGENT SERVICE]: Status notification: foreign user {0} wants to notify {1} local friends", foreignUserID, friends.Count); + + // First, let's double check that the reported friends are, indeed, friends of that user + // And let's check that the secret matches + List usersToBeNotified = new List(); + foreach (string uui in friends) + { + UUID localUserID; + string secret = string.Empty, tmp = string.Empty; + if (Util.ParseUniversalUserIdentifier(uui, out localUserID, out tmp, out tmp, out tmp, out secret)) + { + FriendInfo[] friendInfos = m_FriendsService.GetFriends(localUserID); + foreach (FriendInfo finfo in friendInfos) + { + if (finfo.Friend.StartsWith(foreignUserID.ToString()) && finfo.Friend.EndsWith(secret)) + { + // great! + usersToBeNotified.Add(localUserID.ToString()); + } + } + } + } + + // Now, let's send the notifications + m_log.DebugFormat("[USER AGENT SERVICE]: Status notification: user has {0} local friends", usersToBeNotified.Count); + + // First, let's send notifications to local users who are online in the home grid + PresenceInfo[] friendSessions = m_PresenceService.GetAgents(usersToBeNotified.ToArray()); + if (friendSessions != null && friendSessions.Length > 0) + { + PresenceInfo friendSession = null; + foreach (PresenceInfo pinfo in friendSessions) + if (pinfo.RegionID != UUID.Zero) // let's guard against traveling agents + { + friendSession = pinfo; + break; + } + + if (friendSession != null) + { + ForwardStatusNotificationToSim(friendSession.RegionID, foreignUserID, friendSession.UserID, online); + usersToBeNotified.Remove(friendSession.UserID.ToString()); + UUID id; + if (UUID.TryParse(friendSession.UserID, out id)) + localFriendsOnline.Add(id); + + } + } + + // Lastly, let's notify the rest who may be online somewhere else + foreach (string user in usersToBeNotified) + { + UUID id = new UUID(user); + if (m_TravelingAgents.ContainsKey(id) && m_TravelingAgents[id].GridExternalName != m_GridName) + { + string url = m_TravelingAgents[id].GridExternalName; + // forward + m_log.WarnFormat("[USER AGENT SERVICE]: User {0} is visiting {1}. HG Status notifications still not implemented.", user, url); + } + } + + // and finally, let's send the online friends + if (online) + { + return localFriendsOnline; + } + else + return new List(); + } + + protected void ForwardStatusNotificationToSim(UUID regionID, UUID foreignUserID, string user, bool online) + { + UUID userID; + if (UUID.TryParse(user, out userID)) + { + if (m_FriendsLocalSimConnector != null) + { + m_log.DebugFormat("[USER AGENT SERVICE]: Local Notify, user {0} is {1}", foreignUserID, (online ? "online" : "offline")); + m_FriendsLocalSimConnector.StatusNotify(foreignUserID, userID, online); + } + else + { + GridRegion region = m_GridService.GetRegionByUUID(UUID.Zero /* !!! */, regionID); + if (region != null) + { + m_log.DebugFormat("[USER AGENT SERVICE]: Remote Notify to region {0}, user {1} is {2}", region.RegionName, foreignUserID, (online ? "online" : "offline")); + m_FriendsSimConnector.StatusNotify(region, foreignUserID, userID, online); + } + } + } + } + + public List GetOnlineFriends(UUID foreignUserID, List friends) + { + List online = new List(); + + if (m_FriendsService == null || m_PresenceService == null) + { + m_log.WarnFormat("[USER AGENT SERVICE]: Unable to get online friends because friends or presence services are missing"); + return online; + } + + m_log.DebugFormat("[USER AGENT SERVICE]: Foreign user {0} wants to know status of {1} local friends", foreignUserID, friends.Count); + + // First, let's double check that the reported friends are, indeed, friends of that user + // And let's check that the secret matches and the rights + List usersToBeNotified = new List(); + foreach (string uui in friends) + { + UUID localUserID; + string secret = string.Empty, tmp = string.Empty; + if (Util.ParseUniversalUserIdentifier(uui, out localUserID, out tmp, out tmp, out tmp, out secret)) + { + FriendInfo[] friendInfos = m_FriendsService.GetFriends(localUserID); + foreach (FriendInfo finfo in friendInfos) + { + if (finfo.Friend.StartsWith(foreignUserID.ToString()) && finfo.Friend.EndsWith(secret) && + (finfo.TheirFlags & (int)FriendRights.CanSeeOnline) != 0 && (finfo.TheirFlags != -1)) + { + // great! + usersToBeNotified.Add(localUserID.ToString()); + } + } + } + } + + // Now, let's find out their status + m_log.DebugFormat("[USER AGENT SERVICE]: GetOnlineFriends: user has {0} local friends with status rights", usersToBeNotified.Count); + + // First, let's send notifications to local users who are online in the home grid + PresenceInfo[] friendSessions = m_PresenceService.GetAgents(usersToBeNotified.ToArray()); + if (friendSessions != null && friendSessions.Length > 0) + { + foreach (PresenceInfo pi in friendSessions) + { + UUID presenceID; + if (UUID.TryParse(pi.UserID, out presenceID)) + online.Add(presenceID); + } + } + + return online; + } + + public Dictionary GetServerURLs(UUID userID) + { + if (m_UserAccountService == null) + { + m_log.WarnFormat("[USER AGENT SERVICE]: Unable to get server URLs because user account service is missing"); + return new Dictionary(); + } + UserAccount account = m_UserAccountService.GetUserAccount(UUID.Zero /*!!!*/, userID); + if (account != null) + return account.ServiceURLs; + + return new Dictionary(); + } + + public string LocateUser(UUID userID) + { + foreach (TravelingAgentInfo t in m_TravelingAgents.Values) + { + if (t == null) + { + m_log.ErrorFormat("[USER AGENT SERVICE]: Oops! Null TravelingAgentInfo. Please report this on mantis"); + continue; + } + if (t.UserID == userID && !m_GridName.Equals(t.GridExternalName)) + return t.GridExternalName; + } + + return string.Empty; + } + + public string GetUUI(UUID userID, UUID targetUserID) + { + // Let's see if it's a local user + UserAccount account = m_UserAccountService.GetUserAccount(UUID.Zero, targetUserID); + if (account != null) + return targetUserID.ToString() + ";" + m_GridName + ";" + account.FirstName + " " + account.LastName ; + + // Let's try the list of friends + FriendInfo[] friends = m_FriendsService.GetFriends(userID); + if (friends != null && friends.Length > 0) + { + foreach (FriendInfo f in friends) + if (f.Friend.StartsWith(targetUserID.ToString())) + { + // Let's remove the secret + UUID id; string tmp = string.Empty, secret = string.Empty; + if (Util.ParseUniversalUserIdentifier(f.Friend, out id, out tmp, out tmp, out tmp, out secret)) + return f.Friend.Replace(secret, "0"); + } + } + + return string.Empty; + } } class TravelingAgentInfo diff --git a/OpenSim/Services/Interfaces/IFriendsService.cs b/OpenSim/Services/Interfaces/IFriendsService.cs index 0ddd5e53a9..1664f3b3e1 100644 --- a/OpenSim/Services/Interfaces/IFriendsService.cs +++ b/OpenSim/Services/Interfaces/IFriendsService.cs @@ -74,7 +74,9 @@ namespace OpenSim.Services.Interfaces public interface IFriendsService { FriendInfo[] GetFriends(UUID PrincipalID); - bool StoreFriend(UUID PrincipalID, string Friend, int flags); + FriendInfo[] GetFriends(string PrincipalID); + bool StoreFriend(string PrincipalID, string Friend, int flags); bool Delete(UUID PrincipalID, string Friend); + bool Delete(string PrincipalID, string Friend); } } diff --git a/OpenSim/Services/Interfaces/IGatekeeperService.cs b/OpenSim/Services/Interfaces/IHypergridServices.cs similarity index 76% rename from OpenSim/Services/Interfaces/IGatekeeperService.cs rename to OpenSim/Services/Interfaces/IHypergridServices.cs index aac82936b0..220caef007 100644 --- a/OpenSim/Services/Interfaces/IGatekeeperService.cs +++ b/OpenSim/Services/Interfaces/IHypergridServices.cs @@ -54,9 +54,34 @@ namespace OpenSim.Services.Interfaces bool LoginAgentToGrid(AgentCircuitData agent, GridRegion gatekeeper, GridRegion finalDestination, out string reason); void LogoutAgent(UUID userID, UUID sessionID); GridRegion GetHomeRegion(UUID userID, out Vector3 position, out Vector3 lookAt); + Dictionary GetServerURLs(UUID userID); + + string LocateUser(UUID userID); + // Tries to get the universal user identifier for the targetUserId + // on behalf of the userID + string GetUUI(UUID userID, UUID targetUserID); + + // Returns the local friends online + List StatusNotification(List friends, UUID userID, bool online); + //List GetOnlineFriends(UUID userID, List friends); bool AgentIsComingHome(UUID sessionID, string thisGridExternalName); bool VerifyAgent(UUID sessionID, string token); bool VerifyClient(UUID sessionID, string reportedIP); } + + public interface IInstantMessage + { + bool IncomingInstantMessage(GridInstantMessage im); + bool OutgoingInstantMessage(GridInstantMessage im, string url, bool foreigner); + } + public interface IFriendsSimConnector + { + bool StatusNotify(UUID userID, UUID friendID, bool online); + } + + public interface IInstantMessageSimConnector + { + bool SendInstantMessage(GridInstantMessage im); + } } diff --git a/OpenSim/Services/Interfaces/IMapService.cs b/OpenSim/Services/Interfaces/IMapImageService.cs similarity index 86% rename from OpenSim/Services/Interfaces/IMapService.cs rename to OpenSim/Services/Interfaces/IMapImageService.cs index c70f484f08..a7b2cf1dfd 100644 --- a/OpenSim/Services/Interfaces/IMapService.cs +++ b/OpenSim/Services/Interfaces/IMapImageService.cs @@ -31,8 +31,10 @@ using OpenMetaverse; namespace OpenSim.Services.Interfaces { - public interface IMapService + public interface IMapImageService { - List GetMapBlocks(UUID scopeID, int minX, int minY, int maxX, int maxY); + //List GetMapBlocks(UUID scopeID, int minX, int minY, int maxX, int maxY); + bool AddMapTile(int x, int y, byte[] imageData, out string reason); + byte[] GetMapTile(string fileName, out string format); } } diff --git a/OpenSim/Services/InventoryService/InventoryService.cs b/OpenSim/Services/InventoryService/InventoryService.cs index e543337c71..73dd06ac3a 100644 --- a/OpenSim/Services/InventoryService/InventoryService.cs +++ b/OpenSim/Services/InventoryService/InventoryService.cs @@ -340,6 +340,9 @@ namespace OpenSim.Services.InventoryService List itemsList = new List(); itemsList.AddRange(m_Database.getInventoryInFolder(folderID)); + +// m_log.DebugFormat( +// "[INVENTORY SERVICE]: Found {0} items in folder {1} for {2}", itemsList.Count, folderID, userID); return itemsList; } @@ -385,8 +388,9 @@ namespace OpenSim.Services.InventoryService // See IInventoryServices public virtual bool AddItem(InventoryItemBase item) { - m_log.DebugFormat( - "[INVENTORY SERVICE]: Adding item {0} {1} to folder {2}", item.Name, item.ID, item.Folder); +// m_log.DebugFormat( +// "[INVENTORY SERVICE]: Adding item {0} {1} to folder {2} for {3}", +// item.Name, item.ID, item.Folder, item.Owner); m_Database.addInventoryItem(item); diff --git a/OpenSim/Services/InventoryService/XInventoryService.cs b/OpenSim/Services/InventoryService/XInventoryService.cs index 58c59ebb93..eeab67a666 100644 --- a/OpenSim/Services/InventoryService/XInventoryService.cs +++ b/OpenSim/Services/InventoryService/XInventoryService.cs @@ -40,9 +40,9 @@ namespace OpenSim.Services.InventoryService { public class XInventoryService : ServiceBase, IInventoryService { -// private static readonly ILog m_log = -// LogManager.GetLogger( -// MethodBase.GetCurrentMethod().DeclaringType); + //private static readonly ILog m_log = + // LogManager.GetLogger( + // MethodBase.GetCurrentMethod().DeclaringType); protected IXInventoryData m_Database; protected bool m_AllowDelete = true; @@ -385,8 +385,8 @@ namespace OpenSim.Services.InventoryService public virtual bool AddItem(InventoryItemBase item) { -// m_log.DebugFormat( -// "[XINVENTORY SERVICE]: Adding item {0} to folder {1} for {2}", item.ID, item.Folder, item.Owner); + //m_log.DebugFormat( + // "[XINVENTORY SERVICE]: Adding item {0} to folder {1} for {2}", item.ID, item.Folder, item.Owner); return m_Database.StoreItem(ConvertFromOpenSim(item)); } diff --git a/OpenSim/Services/LLLoginService/LLLoginResponse.cs b/OpenSim/Services/LLLoginService/LLLoginResponse.cs index f8868f5cf7..82acfbcb05 100644 --- a/OpenSim/Services/LLLoginService/LLLoginResponse.cs +++ b/OpenSim/Services/LLLoginService/LLLoginResponse.cs @@ -627,7 +627,19 @@ namespace OpenSim.Services.LLLoginService if (finfo.TheirFlags == -1) continue; LLLoginResponse.BuddyList.BuddyInfo buddyitem = new LLLoginResponse.BuddyList.BuddyInfo(finfo.Friend); - buddyitem.BuddyID = finfo.Friend; + // finfo.Friend may not be a simple uuid + UUID friendID = UUID.Zero; + if (UUID.TryParse(finfo.Friend, out friendID)) + buddyitem.BuddyID = finfo.Friend; + else + { + string tmp; + if (Util.ParseUniversalUserIdentifier(finfo.Friend, out friendID, out tmp, out tmp, out tmp, out tmp)) + buddyitem.BuddyID = friendID.ToString(); + else + // junk entry + continue; + } buddyitem.BuddyRightsHave = (int)finfo.TheirFlags; buddyitem.BuddyRightsGiven = (int)finfo.MyFlags; buddylistreturn.AddNewBuddy(buddyitem); diff --git a/OpenSim/Services/LLLoginService/LLLoginService.cs b/OpenSim/Services/LLLoginService/LLLoginService.cs index ffed15eb5d..e7dd15ebfb 100644 --- a/OpenSim/Services/LLLoginService/LLLoginService.cs +++ b/OpenSim/Services/LLLoginService/LLLoginService.cs @@ -112,6 +112,14 @@ namespace OpenSim.Services.LLLoginService m_AllowedClients = m_LoginServerConfig.GetString("AllowedClients", string.Empty); m_DeniedClients = m_LoginServerConfig.GetString("DeniedClients", string.Empty); + // Clean up some of these vars + if (m_MapTileURL != String.Empty) + { + m_MapTileURL = m_MapTileURL.Trim(); + if (!m_MapTileURL.EndsWith("/")) + m_MapTileURL = m_MapTileURL + "/"; + } + // These are required; the others aren't if (accountService == string.Empty || authService == string.Empty) throw new Exception("LoginService is missing service specifications"); @@ -523,6 +531,7 @@ namespace OpenSim.Services.LLLoginService // free uri form // e.g. New Moon&135&46 New Moon@osgrid.org:8002&153&34 where = "url"; + GridRegion region = null; Regex reURI = new Regex(@"^uri:(?[^&]+)&(?\d+)&(?\d+)&(?\d+)$"); Match uriMatch = reURI.Match(startLocation); if (uriMatch == null) @@ -553,8 +562,18 @@ namespace OpenSim.Services.LLLoginService } else { - m_log.InfoFormat("[LLLOGIN SERVICE]: Got Custom Login URI {0}, Grid does not provide default regions.", startLocation); - return null; + m_log.Info("[LLOGIN SERVICE]: Last Region Not Found Attempting to find random region"); + region = FindAlternativeRegion(scopeID); + if (region != null) + { + where = "safe"; + return region; + } + else + { + m_log.InfoFormat("[LLLOGIN SERVICE]: Got Custom Login URI {0}, Grid does not provide default regions and no alternative found.", startLocation); + return null; + } } } return regions[0]; @@ -582,7 +601,8 @@ namespace OpenSim.Services.LLLoginService if (parts.Length > 1) UInt32.TryParse(parts[1], out port); - GridRegion region = FindForeignRegion(domainName, port, regionName, out gatekeeper); +// GridRegion region = FindForeignRegion(domainName, port, regionName, out gatekeeper); + region = FindForeignRegion(domainName, port, regionName, out gatekeeper); return region; } } @@ -811,16 +831,13 @@ namespace OpenSim.Services.LLLoginService // Old style: get the service keys from the DB foreach (KeyValuePair kvp in account.ServiceURLs) { - if (kvp.Value == null || (kvp.Value != null && kvp.Value.ToString() == string.Empty)) - { - aCircuit.ServiceURLs[kvp.Key] = m_LoginServerConfig.GetString(kvp.Key, string.Empty); - } - else + if (kvp.Value != null) { aCircuit.ServiceURLs[kvp.Key] = kvp.Value; + + if (!aCircuit.ServiceURLs[kvp.Key].ToString().EndsWith("/")) + aCircuit.ServiceURLs[kvp.Key] = aCircuit.ServiceURLs[kvp.Key] + "/"; } - if (!aCircuit.ServiceURLs[kvp.Key].ToString().EndsWith("/")) - aCircuit.ServiceURLs[kvp.Key] = aCircuit.ServiceURLs[kvp.Key] + "/"; } // New style: service keys start with SRV_; override the previous @@ -828,16 +845,29 @@ namespace OpenSim.Services.LLLoginService if (keys.Length > 0) { + bool newUrls = false; IEnumerable serviceKeys = keys.Where(value => value.StartsWith("SRV_")); foreach (string serviceKey in serviceKeys) { string keyName = serviceKey.Replace("SRV_", ""); - aCircuit.ServiceURLs[keyName] = m_LoginServerConfig.GetString(serviceKey, string.Empty); - if (!aCircuit.ServiceURLs[keyName].ToString().EndsWith("/")) - aCircuit.ServiceURLs[keyName] = aCircuit.ServiceURLs[keyName] + "/"; + string keyValue = m_LoginServerConfig.GetString(serviceKey, string.Empty); + if (!keyValue.EndsWith("/")) + keyValue = keyValue + "/"; + + if (!account.ServiceURLs.ContainsKey(keyName) || (account.ServiceURLs.ContainsKey(keyName) && account.ServiceURLs[keyName] != keyValue)) + { + account.ServiceURLs[keyName] = keyValue; + newUrls = true; + } + aCircuit.ServiceURLs[keyName] = keyValue; m_log.DebugFormat("[LLLOGIN SERVICE]: found new key {0} {1}", keyName, aCircuit.ServiceURLs[keyName]); } + + // The grid operator decided to override the defaults in the + // [LoginService] configuration. Let's store the correct ones. + if (newUrls) + m_UserAccountService.StoreUserAccount(account); } } diff --git a/OpenSim/Services/MapImageService/MapImageService.cs b/OpenSim/Services/MapImageService/MapImageService.cs new file mode 100644 index 0000000000..7e7391c988 --- /dev/null +++ b/OpenSim/Services/MapImageService/MapImageService.cs @@ -0,0 +1,298 @@ +/* + * 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. + * + * The design of this map service is based on SimianGrid's PHP-based + * map service. See this URL for the original PHP version: + * https://github.com/openmetaversefoundation/simiangrid/ + */ + +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Net; +using System.Reflection; + +using Nini.Config; +using log4net; +using OpenMetaverse; + +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Services.Interfaces; + + +namespace OpenSim.Services.MapImageService +{ + public class MapImageService : IMapImageService + { + private static readonly ILog m_log = + LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + + private const int ZOOM_LEVELS = 8; + private const int IMAGE_WIDTH = 256; + private const int HALF_WIDTH = 128; + private const int JPEG_QUALITY = 80; + + private static string m_TilesStoragePath = "maptiles"; + + private static object m_Sync = new object(); + private static bool m_Initialized = false; + private static string m_WaterTileFile = string.Empty; + private static Color m_Watercolor = Color.FromArgb(29, 71, 95); + + public MapImageService(IConfigSource config) + { + if (!m_Initialized) + { + m_Initialized = true; + m_log.Debug("[MAP IMAGE SERVICE]: Starting MapImage service"); + + IConfig serviceConfig = config.Configs["MapImageService"]; + if (serviceConfig != null) + { + m_TilesStoragePath = serviceConfig.GetString("TilesStoragePath", m_TilesStoragePath); + if (!Directory.Exists(m_TilesStoragePath)) + Directory.CreateDirectory(m_TilesStoragePath); + + + m_WaterTileFile = Path.Combine(m_TilesStoragePath, "water.jpg"); + if (!File.Exists(m_WaterTileFile)) + { + Bitmap waterTile = new Bitmap(IMAGE_WIDTH, IMAGE_WIDTH); + FillImage(waterTile, m_Watercolor); + waterTile.Save(m_WaterTileFile); + } + } + } + } + + #region IMapImageService + + public bool AddMapTile(int x, int y, byte[] imageData, out string reason) + { + reason = string.Empty; + string fileName = GetFileName(1, x, y); + + lock (m_Sync) + { + try + { + using (FileStream f = File.Open(fileName, FileMode.OpenOrCreate, FileAccess.Write)) + f.Write(imageData, 0, imageData.Length); + } + catch (Exception e) + { + m_log.WarnFormat("[MAP IMAGE SERVICE]: Unable to save image file {0}: {1}", fileName, e); + reason = e.Message; + return false; + } + + // Also save in png format? + + // Stitch seven more aggregate tiles together + for (uint zoomLevel = 2; zoomLevel <= ZOOM_LEVELS; zoomLevel++) + { + // Calculate the width (in full resolution tiles) and bottom-left + // corner of the current zoom level + int width = (int)Math.Pow(2, (double)(zoomLevel - 1)); + int x1 = x - (x % width); + int y1 = y - (y % width); + + if (!CreateTile(zoomLevel, x1, y1)) + { + m_log.WarnFormat("[MAP IMAGE SERVICE]: Unable to create tile for {0} at zoom level {1}", fileName, zoomLevel); + reason = string.Format("Map tile at zoom level {0} failed", zoomLevel); + return false; + } + } + } + + return true; + } + + public byte[] GetMapTile(string fileName, out string format) + { + format = ".jpg"; + string fullName = Path.Combine(m_TilesStoragePath, fileName); + if (File.Exists(fullName)) + { + format = Path.GetExtension(fileName).ToLower(); + //m_log.DebugFormat("[MAP IMAGE SERVICE]: Found file {0}, extension {1}", fileName, format); + return File.ReadAllBytes(fullName); + } + else if (File.Exists(m_WaterTileFile)) + { + return File.ReadAllBytes(m_WaterTileFile); + } + else + { + m_log.DebugFormat("[MAP IMAGE SERVICE]: unable to get file {0}", fileName); + return new byte[0]; + } + } + + #endregion + + + private string GetFileName(uint zoomLevel, int x, int y) + { + string extension = "jpg"; + return Path.Combine(m_TilesStoragePath, string.Format("map-{0}-{1}-{2}-objects.{3}", zoomLevel, x, y, extension)); + } + + private Bitmap GetInputTileImage(string fileName) + { + try + { + if (File.Exists(fileName)) + return new Bitmap(fileName); + } + catch (Exception e) + { + m_log.WarnFormat("[MAP IMAGE SERVICE]: Unable to read image data from {0}: {1}", fileName, e); + } + + return null; + } + + private Bitmap GetOutputTileImage(string fileName) + { + try + { + if (File.Exists(fileName)) + return new Bitmap(fileName); + + else + { + // Create a new output tile with a transparent background + Bitmap bm = new Bitmap(IMAGE_WIDTH, IMAGE_WIDTH, PixelFormat.Format24bppRgb); + bm.MakeTransparent(); + return bm; + } + } + catch (Exception e) + { + m_log.WarnFormat("[MAP IMAGE SERVICE]: Unable to read image data from {0}: {1}", fileName, e); + } + + return null; + } + + private bool CreateTile(uint zoomLevel, int x, int y) + { + m_log.DebugFormat("[MAP IMAGE SERVICE]: Create tile for {0} {1}, zoom {2}", x, y, zoomLevel); + int prevWidth = (int)Math.Pow(2, (double)zoomLevel - 2); + int thisWidth = (int)Math.Pow(2, (double)zoomLevel - 1); + + // Convert x and y to the bottom left tile for this zoom level + int xIn = x - (x % prevWidth); + int yIn = y - (y % prevWidth); + + // Convert x and y to the bottom left tile for the next zoom level + int xOut = x - (x % thisWidth); + int yOut = y - (y % thisWidth); + + // Try to open the four input tiles from the previous zoom level + Bitmap inputBL = GetInputTileImage(GetFileName(zoomLevel - 1, xIn, yIn)); + Bitmap inputBR = GetInputTileImage(GetFileName(zoomLevel - 1, xIn + prevWidth, yIn)); + Bitmap inputTL = GetInputTileImage(GetFileName(zoomLevel - 1, xIn, yIn + prevWidth)); + Bitmap inputTR = GetInputTileImage(GetFileName(zoomLevel - 1, xIn + prevWidth, yIn + prevWidth)); + + // Open the output tile (current zoom level) + string outputFile = GetFileName(zoomLevel, xOut, yOut); + Bitmap output = GetOutputTileImage(outputFile); + if (output == null) + return false; + FillImage(output, m_Watercolor); + + if (inputBL != null) + { + ImageCopyResampled(output, inputBL, 0, HALF_WIDTH, 0, 0); + inputBL.Dispose(); + } + if (inputBR != null) + { + ImageCopyResampled(output, inputBR, HALF_WIDTH, HALF_WIDTH, 0, 0); + inputBR.Dispose(); + } + if (inputTL != null) + { + ImageCopyResampled(output, inputTL, 0, 0, 0, 0); + inputTL.Dispose(); + } + if (inputTR != null) + { + ImageCopyResampled(output, inputTR, HALF_WIDTH, 0, 0, 0); + inputTR.Dispose(); + } + + // Write the modified output + try + { + using (Bitmap final = new Bitmap(output)) + { + output.Dispose(); + final.Save(outputFile, ImageFormat.Jpeg); + } + } + catch (Exception e) + { + m_log.WarnFormat("[MAP IMAGE SERVICE]: Oops on saving {0} {1}", outputFile, e); + } + + // Save also as png? + + return true; + } + + #region Image utilities + + private void FillImage(Bitmap bm, Color c) + { + for (int x = 0; x < bm.Width; x++) + for (int y = 0; y < bm.Height; y++) + bm.SetPixel(x, y, c); + } + + private void ImageCopyResampled(Bitmap output, Bitmap input, int destX, int destY, int srcX, int srcY) + { + int resamplingRateX = 2; // (input.Width - srcX) / (output.Width - destX); + int resamplingRateY = 2; // (input.Height - srcY) / (output.Height - destY); + + for (int x = destX; x < destX + HALF_WIDTH; x++) + for (int y = destY; y < destY + HALF_WIDTH; y++) + { + Color p = input.GetPixel(srcX + (x - destX) * resamplingRateX, srcY + (y - destY) * resamplingRateY); + output.SetPixel(x, y, p); + } + } + + #endregion + } +} diff --git a/OpenSim/Tests/Clients/InstantMessage/IMClient.cs b/OpenSim/Tests/Clients/InstantMessage/IMClient.cs new file mode 100644 index 0000000000..e7304a24dc --- /dev/null +++ b/OpenSim/Tests/Clients/InstantMessage/IMClient.cs @@ -0,0 +1,75 @@ +/* + * 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.Generic; +using System.Text; +using System.Reflection; + +using OpenMetaverse; +using log4net; +using log4net.Appender; +using log4net.Layout; + +using OpenSim.Framework; +using OpenSim.Services.Interfaces; +using OpenSim.Services.Connectors.InstantMessage; + +namespace OpenSim.Tests.Clients.InstantMessage +{ + public class IMClient + { + private static readonly ILog m_log = + LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + + public static void Main(string[] args) + { + ConsoleAppender consoleAppender = new ConsoleAppender(); + consoleAppender.Layout = + new PatternLayout("%date [%thread] %-5level %logger [%property{NDC}] - %message%newline"); + log4net.Config.BasicConfigurator.Configure(consoleAppender); + + string serverURI = "http://127.0.0.1:8002"; + GridInstantMessage im = new GridInstantMessage(); + im.fromAgentID = new Guid(); + im.toAgentID = new Guid(); + im.message = "Hello"; + im.imSessionID = new Guid(); + + bool success = InstantMessageServiceConnector.SendInstantMessage(serverURI, im); + + if (success) + m_log.InfoFormat("[IM CLIENT]: Successfully IMed {0}", serverURI); + else + m_log.InfoFormat("[IM CLIENT]: failed to IM {0}", serverURI); + + System.Console.WriteLine("\n"); + } + + } +} diff --git a/OpenSim/Tests/Clients/Presence/OpenSim.Server.ini b/OpenSim/Tests/Clients/Presence/OpenSim.Server.ini index 47e73f9887..8610c78a63 100644 --- a/OpenSim/Tests/Clients/Presence/OpenSim.Server.ini +++ b/OpenSim/Tests/Clients/Presence/OpenSim.Server.ini @@ -29,5 +29,5 @@ port = 8003 [PresenceService] LocalServiceModule = "OpenSim.Services.PresenceService.dll:PresenceService" StorageProvider = "OpenSim.Data.MySQL.dll" - ConnectionString = "Data Source=localhost;Database=opensim;User ID=opensim;Password=opensim123;" + ConnectionString = "Data Source=localhost;Database=opensim;User ID=opensim;Password=opensim123;Old Guids=true;" diff --git a/OpenSim/Tests/Clients/UserAccounts/OpenSim.Server.ini b/OpenSim/Tests/Clients/UserAccounts/OpenSim.Server.ini index eb1f47346a..453e17e65c 100644 --- a/OpenSim/Tests/Clients/UserAccounts/OpenSim.Server.ini +++ b/OpenSim/Tests/Clients/UserAccounts/OpenSim.Server.ini @@ -29,5 +29,5 @@ port = 8003 [UserAccountService] LocalServiceModule = "OpenSim.Services.UserAccountService.dll:UserAccountService" StorageProvider = "OpenSim.Data.MySQL.dll" - ConnectionString = "Data Source=localhost;Database=opensim;User ID=opensim;Password=opensim123;" + ConnectionString = "Data Source=localhost;Database=opensim;User ID=opensim;Password=opensim123;Old Guids=true;" diff --git a/OpenSim/Tests/Common/Helpers/UserAccountHelpers.cs b/OpenSim/Tests/Common/Helpers/UserAccountHelpers.cs index 8cfad79f28..d924ecd5c8 100644 --- a/OpenSim/Tests/Common/Helpers/UserAccountHelpers.cs +++ b/OpenSim/Tests/Common/Helpers/UserAccountHelpers.cs @@ -117,17 +117,20 @@ namespace OpenSim.Tests.Common // } public static UserAccount CreateUserWithInventory(Scene scene) + { + return CreateUserWithInventory(scene, 99); + } + + public static UserAccount CreateUserWithInventory(Scene scene, int uuidTail) { return CreateUserWithInventory( - scene, "Bill", "Bailey", UUID.Parse("00000000-0000-0000-0000-000000000099"), "troll"); + scene, "Bill", "Bailey", new UUID(string.Format("00000000-0000-0000-0000-{0:X12}", uuidTail)), "troll"); } public static UserAccount CreateUserWithInventory( Scene scene, string firstName, string lastName, UUID userId, string pw) { - UserAccount ua - = new UserAccount(userId) - { FirstName = firstName, LastName = lastName }; + UserAccount ua = new UserAccount(userId) { FirstName = firstName, LastName = lastName }; CreateUserWithInventory(scene, ua, pw); return ua; } diff --git a/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs b/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs index 04191349e3..1703597549 100644 --- a/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs +++ b/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs @@ -26,8 +26,10 @@ */ using System; +using System.Collections.Generic; using OpenMetaverse; using OpenSim.Framework; +using OpenSim.Region.CoreModules.Avatar.Inventory.Archiver; using OpenSim.Region.Framework.Scenes; using OpenSim.Services.Interfaces; @@ -40,18 +42,41 @@ namespace OpenSim.Tests.Common { public static readonly string PATH_DELIMITER = "/"; - public static InventoryItemBase CreateInventoryItem( - Scene scene, string itemName, UUID itemId, string folderPath, UUID userId) + /// + /// Creates a notecard in the objects folder and specify an item id. + /// + /// + /// + /// + /// + /// + public static InventoryItemBase CreateInventoryItem(Scene scene, string itemName, UUID userId) { + return CreateInventoryItem(scene, itemName, UUID.Random(), userId); + } + + /// + /// Creates a notecard in the objects folder and specify an item id. + /// + /// + /// + /// + /// + /// + public static InventoryItemBase CreateInventoryItem(Scene scene, string itemName, UUID itemId, UUID userId) + { + AssetBase asset = AssetHelpers.CreateAsset(scene, userId); InventoryItemBase item = new InventoryItemBase(); item.Name = itemName; - item.AssetID = AssetHelpers.CreateAsset(scene, userId).FullID; + item.AssetID = asset.FullID; item.ID = itemId; + item.Owner = userId; + item.AssetType = asset.Type; + item.InvType = (int)InventoryType.Notecard; + + InventoryFolderBase folder = scene.InventoryService.GetFolderForType(userId, AssetType.Notecard); - // Really quite bad since the objs folder could be moved in the future and confuse the tests - InventoryFolderBase objsFolder = scene.InventoryService.GetFolderForType(userId, AssetType.Object); - - item.Folder = objsFolder.ID; + item.Folder = folder.ID; scene.AddInventoryItem(item); return item; @@ -111,5 +136,60 @@ namespace OpenSim.Tests.Common else return newFolder; } + + /// + /// Get the inventory folder that matches the path name. If there are multiple folders then only the first + /// is returned. + /// + /// + /// + /// + /// null if no folder matching the path was found + public static InventoryFolderBase GetInventoryFolder(IInventoryService inventoryService, UUID userId, string path) + { + List folders = GetInventoryFolders(inventoryService, userId, path); + + if (folders.Count != 0) + return folders[0]; + else + return null; + } + + /// + /// Get the inventory folders that match the path name. + /// + /// + /// + /// + /// An empty list if no matching folders were found + public static List GetInventoryFolders(IInventoryService inventoryService, UUID userId, string path) + { + return InventoryArchiveUtils.FindFolderByPath(inventoryService, userId, path); + } + + /// + /// Get the inventory item that matches the path name. If there are multiple items then only the first + /// is returned. + /// + /// + /// + /// + /// null if no item matching the path was found + public static InventoryItemBase GetInventoryItem(IInventoryService inventoryService, UUID userId, string path) + { + return InventoryArchiveUtils.FindItemByPath(inventoryService, userId, path); + } + + /// + /// Get the inventory items that match the path name. + /// + /// + /// + /// + /// An empty list if no matching items were found. + public static List GetInventoryItems(IInventoryService inventoryService, UUID userId, string path) + { + return InventoryArchiveUtils.FindItemsByPath(inventoryService, userId, path); + } } } \ No newline at end of file diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs index 7f0eaa7659..bacd773f8c 100644 --- a/OpenSim/Tests/Common/Mock/TestClient.cs +++ b/OpenSim/Tests/Common/Mock/TestClient.cs @@ -637,7 +637,7 @@ namespace OpenSim.Tests.Common.Mock { } - public virtual void SendDialog(string objectname, UUID objectID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch, string[] buttonlabels) + public virtual void SendDialog(string objectname, UUID objectID, UUID ownerID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch, string[] buttonlabels) { } diff --git a/bin/OpenMetaverse.Rendering.Meshmerizer.dll b/bin/OpenMetaverse.Rendering.Meshmerizer.dll index 6139a9d5d9..a6dec04461 100755 Binary files a/bin/OpenMetaverse.Rendering.Meshmerizer.dll and b/bin/OpenMetaverse.Rendering.Meshmerizer.dll differ diff --git a/bin/OpenMetaverse.StructuredData.dll b/bin/OpenMetaverse.StructuredData.dll index e3b729c6ee..ed0a2d6446 100755 Binary files a/bin/OpenMetaverse.StructuredData.dll and b/bin/OpenMetaverse.StructuredData.dll differ diff --git a/bin/OpenMetaverse.dll b/bin/OpenMetaverse.dll index 69c4e9b9df..37ec47a7a8 100755 Binary files a/bin/OpenMetaverse.dll and b/bin/OpenMetaverse.dll differ diff --git a/bin/OpenMetaverseTypes.dll b/bin/OpenMetaverseTypes.dll index cab014d534..6f7fbacb5a 100755 Binary files a/bin/OpenMetaverseTypes.dll and b/bin/OpenMetaverseTypes.dll differ diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index c5df0dba58..bab118fd63 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -307,6 +307,14 @@ ; serving this cap from the simulators may lead to poor performace. Cap_WebFetchInventoryDescendents = "" +[SimulatorFeatures] + ; Experimental new information sent in SimulatorFeatures cap for Kokua viewers + ; meant to override the MapImage and search server url given at login, and varying + ; on a sim-basis. + ; Viewers that don't understand it, will ignore it + ;MapImageServerURI = "http://127.0.0.1:9000/ + ;SearchServerURI = "http://127.0.0.1:9000/ + [Chat] ;# {whisper_distance} {} {Distance at which a whisper is heard, in meters?} {} 10 ;; Distance in meters that whispers should travel. @@ -635,50 +643,13 @@ ;; You need to load a local service for a standalone, and a remote service ;; for a grid region. Use one of the lines below, as appropriate - ;; If you're using Freeswitch on a standalone then you will also need to configure the [FreeswitchService] section + ;; If you're using Freeswitch on a standalone then you will also need to configure the [FreeswitchService] section in config-include/StandaloneCommon.ini ; LocalServiceModule = OpenSim.Services.FreeswitchService.dll:FreeswitchService ; LocalServiceModule = OpenSim.Services.Connectors.dll:RemoteFreeswitchConnector ;; If using a remote connector, specify the server URL ; FreeswitchServiceURL = http://my.grid.server:8004/fsapi - -[FreeswitchService] - ;; !!!!!!!!!!!!!!!!!!!!!!!!!!! - ;; !!!!!!STANDALONE ONLY!!!!!! - ;; !!!!!!!!!!!!!!!!!!!!!!!!!!! - ;; The IP address of your FreeSWITCH server. The common case is for this to be the same as the server running the OpenSim standalone - ;; This has to be set for the FreeSWITCH service to work - ;ServerAddress = 127.0.0.1 - - ;; The following configuration parameters are optional - - ;; By default, this is the same as the ServerAddress - ; Realm = 127.0.0.1 - - ;; By default, this is the same as the ServerAddress on port 5060 - ; SIPProxy = 127.0.0.1:5060 - - ;; Default is 5000ms - ; DefaultTimeout = 5000 - - ;; The dial plan context. Default is "default" - ; Context = default - - ;; Currently unused - ; UserName = freeswitch - - ;; Currently unused - ; Password = password - - ;; The following parameters are for STUN = Simple Traversal of UDP through NATs - ;; See http://wiki.freeswitch.org/wiki/NAT_Traversal - ;; stun.freeswitch.org is not guaranteed to be running so use it in - ;; production at your own risk - ; EchoServer = 127.0.0.1 - ; EchoPort = 50505 - ; AttemptSTUN = false - [Groups] ;# {Enabled} {} {Enable groups?} {true false} false ;; Enables the groups module diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini index 53eac02a68..860e7583e7 100644 --- a/bin/OpenSimDefaults.ini +++ b/bin/OpenSimDefaults.ini @@ -1174,6 +1174,10 @@ ; - the third field is a number indicating how many scripts failed to compile ; - "oar error" if supplied, provides the error message from the OAR load channel_notify = -800 + ; - disallow logins while scripts are loading + login_disable = false + ; - send an alert as json to a service + ; alert_uri = "http://myappserver.net/my_handler/" [MRM] diff --git a/bin/Robust.HG.ini.example b/bin/Robust.HG.ini.example index 0d79e77b7a..ea271b864a 100644 --- a/bin/Robust.HG.ini.example +++ b/bin/Robust.HG.ini.example @@ -21,7 +21,7 @@ ; * [[@]/][:] ; * [Startup] -ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003/OpenSim.Server.Handlers.dll:XInventoryInConnector,8004/OpenSim.Server.Handlers.dll:FreeswitchServerConnector,8003/OpenSim.Server.Handlers.dll:GridServiceConnector,8002/OpenSim.Server.Handlers.dll:GridInfoServerInConnector,8003/OpenSim.Server.Handlers.dll:AuthenticationServiceConnector,8002/OpenSim.Server.Handlers.dll:OpenIdServerConnector,8003/OpenSim.Server.Handlers.dll:AvatarServiceConnector,8002/OpenSim.Server.Handlers.dll:LLLoginServiceInConnector,8003/OpenSim.Server.Handlers.dll:PresenceServiceConnector,8003/OpenSim.Server.Handlers.dll:UserAccountServiceConnector,8003/OpenSim.Server.Handlers.dll:GridUserServiceConnector,8003/OpenSim.Server.Handlers.dll:FriendsServiceConnector,8002/OpenSim.Server.Handlers.dll:GatekeeperServiceInConnector,8002/OpenSim.Server.Handlers.dll:UserAgentServerConnector,HGInventoryService@8002/OpenSim.Server.Handlers.dll:XInventoryInConnector,HGAssetService@8002/OpenSim.Server.Handlers.dll:AssetServiceConnector,8002/OpenSim.Server.Handlers.dll:HeloServiceInConnector" +ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003/OpenSim.Server.Handlers.dll:XInventoryInConnector,8004/OpenSim.Server.Handlers.dll:FreeswitchServerConnector,8003/OpenSim.Server.Handlers.dll:GridServiceConnector,8002/OpenSim.Server.Handlers.dll:GridInfoServerInConnector,8003/OpenSim.Server.Handlers.dll:AuthenticationServiceConnector,8002/OpenSim.Server.Handlers.dll:OpenIdServerConnector,8003/OpenSim.Server.Handlers.dll:AvatarServiceConnector,8002/OpenSim.Server.Handlers.dll:LLLoginServiceInConnector,8003/OpenSim.Server.Handlers.dll:PresenceServiceConnector,8003/OpenSim.Server.Handlers.dll:UserAccountServiceConnector,8003/OpenSim.Server.Handlers.dll:GridUserServiceConnector,8003/OpenSim.Server.Handlers.dll:FriendsServiceConnector,8002/OpenSim.Server.Handlers.dll:GatekeeperServiceInConnector,8002/OpenSim.Server.Handlers.dll:UserAgentServerConnector,HGInventoryService@8002/OpenSim.Server.Handlers.dll:XInventoryInConnector,HGAssetService@8002/OpenSim.Server.Handlers.dll:AssetServiceConnector,8002/OpenSim.Server.Handlers.dll:HeloServiceInConnector,8002/OpenSim.Server.Handlers.dll:HGFriendsServerConnector,8002/OpenSim.Server.Handlers.dll:InstantMessageServerConnector,8003/OpenSim.Server.Handlers.dll:MapAddServiceConnector,8002/OpenSim.Server.Handlers.dll:MapGetServiceConnector" ; * This is common for all services, it's the network setup for the entire ; * server instance, if none is specified above @@ -107,6 +107,7 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 LocalServiceModule = "OpenSim.Services.FreeswitchService.dll:FreeswitchService" ;; The IP address of your FreeSWITCH server. + ;; This address must be reachable by viewers. ; ServerAddress = 127.0.0.1 ;; The following configuration parameters are optional @@ -205,6 +206,9 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 WelcomeMessage = "Welcome, Avatar!" AllowRemoteSetLoginLevel = "false" + ; For V2 map + ; MapTileURL = "http://127.0.0.1:8002"; + ; If you run this login server behind a proxy, set this to true ; HasProxy = false @@ -216,6 +220,8 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 SRV_InventoryServerURI = "http://127.0.0.1:8002" SRV_AssetServerURI = "http://127.0.0.1:8002" SRV_ProfileServerURI = "http://127.0.0.1:8002/user" + SRV_FriendsServerURI = "http://127.0.0.1:8002" + SRV_IMServerURI = "http://127.0.0.1:8002" ;; Regular expressions for controlling which client versions are accepted/denied. ;; An empty string means nothing is checked. @@ -234,6 +240,11 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 ;AllowedClients = "" ;DeniedClients = "" +[MapImageService] + LocalServiceModule = "OpenSim.Services.MapImageService.dll:MapImageService" + ; Set this if you want to change the default + ; TilesStoragePath = "maptiles" + [GridInfoService] ; These settings are used to return information on a get_grid_info call. ; Client launcher scripts and third-party clients make use of this to @@ -316,7 +327,10 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 GridUserService = "OpenSim.Services.UserAccountService.dll:GridUserService" GridService = "OpenSim.Services.GridService.dll:GridService" GatekeeperService = "OpenSim.Services.HypergridService.dll:GatekeeperService" - + PresenceService = "OpenSim.Services.PresenceService.dll:PresenceService" + FriendsService = "OpenSim.Services.FriendsService.dll:FriendsService" + UserAccountService = "OpenSim.Services.UserAccountService.dll:UserAccountService" + ; If you run this user agent server behind a proxy, set this to true ; HasProxy = false @@ -344,3 +358,29 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 LocalServiceModule = "OpenSim.Services.HypergridService.dll:HGAssetService" UserAccountsService = "OpenSim.Services.UserAccountService.dll:UserAccountService" ProfileServerURI = "http://127.0.0.1:8002/user" + +[HGFriendsService] + LocalServiceModule = "OpenSim.Services.FriendsService.dll:FriendsService" + UserAgentService = "OpenSim.Services.HypergridService.dll:UserAgentService" + +[HGInstantMessageService] + LocalServiceModule = "OpenSim.Services.HypergridService.dll:HGInstantMessageService" + GridService = "OpenSim.Services.GridService.dll:GridService" + PresenceService = "OpenSim.Services.PresenceService.dll:PresenceService" + UserAgentService = "OpenSim.Services.HypergridService.dll:UserAgentService" + ; This should always be true in the Robust config + InGatekeeper = True + +[Messaging] + ; If you have an Offline IM server, set the vars in this section, so that + ; incomming IMs to local users from foreign grids can be saved + ; + ;# {OfflineMessageURL} {OfflineMessageModule:OfflineMessageModule} {URL of offline messaging service} {} + ;; URL of web service for offline message storage + ; OfflineMessageURL = http://yourserver/Offline.php + + ;; Control whether group messages are forwarded to offline users. + ;; Default is true. + ;; This applies to the core groups module (Flotsam) only. + ; ForwardOfflineGroupMessages = true + diff --git a/bin/Robust.ini.example b/bin/Robust.ini.example index cc018f8867..14f79aac14 100644 --- a/bin/Robust.ini.example +++ b/bin/Robust.ini.example @@ -13,7 +13,7 @@ ; * [[@]/][:] ; * [Startup] -ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003/OpenSim.Server.Handlers.dll:XInventoryInConnector,8004/OpenSim.Server.Handlers.dll:FreeswitchServerConnector,8003/OpenSim.Server.Handlers.dll:GridServiceConnector,8002/OpenSim.Server.Handlers.dll:GridInfoServerInConnector,8003/OpenSim.Server.Handlers.dll:AuthenticationServiceConnector,8002/OpenSim.Server.Handlers.dll:OpenIdServerConnector,8003/OpenSim.Server.Handlers.dll:AvatarServiceConnector,8002/OpenSim.Server.Handlers.dll:LLLoginServiceInConnector,8003/OpenSim.Server.Handlers.dll:PresenceServiceConnector,8003/OpenSim.Server.Handlers.dll:UserAccountServiceConnector,8003/OpenSim.Server.Handlers.dll:GridUserServiceConnector,8003/OpenSim.Server.Handlers.dll:FriendsServiceConnector" +ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003/OpenSim.Server.Handlers.dll:XInventoryInConnector,8004/OpenSim.Server.Handlers.dll:FreeswitchServerConnector,8003/OpenSim.Server.Handlers.dll:GridServiceConnector,8002/OpenSim.Server.Handlers.dll:GridInfoServerInConnector,8003/OpenSim.Server.Handlers.dll:AuthenticationServiceConnector,8002/OpenSim.Server.Handlers.dll:OpenIdServerConnector,8003/OpenSim.Server.Handlers.dll:AvatarServiceConnector,8002/OpenSim.Server.Handlers.dll:LLLoginServiceInConnector,8003/OpenSim.Server.Handlers.dll:PresenceServiceConnector,8003/OpenSim.Server.Handlers.dll:UserAccountServiceConnector,8003/OpenSim.Server.Handlers.dll:GridUserServiceConnector,8003/OpenSim.Server.Handlers.dll:FriendsServiceConnector,8003/OpenSim.Server.Handlers.dll:MapAddServiceConnector,8002/OpenSim.Server.Handlers.dll:MapGetServiceConnector" ; * This is common for all services, it's the network setup for the entire ; * server instance, if none is specified above @@ -21,7 +21,6 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 [Network] port = 8003 - ; HTTPS for "Out of band" management applications such as the remote admin ; module. May specify https_main = True to make the main http server ; use https or "False" to make the main server HTTP @@ -92,6 +91,7 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 LocalServiceModule = "OpenSim.Services.FreeswitchService.dll:FreeswitchService" ;; The IP address of your FreeSWITCH server. + ;; This address must be reachable by viewers. ; ServerAddress = 127.0.0.1 ;; The following configuration parameters are optional @@ -191,8 +191,8 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 WelcomeMessage = "Welcome, Avatar!" AllowRemoteSetLoginLevel = "false" - ; For snowglobe's web map - ; MapTileURL = ""; + ; For V2 map + ; MapTileURL = "http://127.0.0.1:8002"; ; If you run this login server behind a proxy, set this to true ; HasProxy = false @@ -214,6 +214,12 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 ;AllowedClients = "" ;DeniedClients = "" +[MapImageService] + LocalServiceModule = "OpenSim.Services.MapImageService.dll:MapImageService" + ; Set this if you want to change the default + ; TilesStoragePath = "maptiles" + + [GridInfoService] ; These settings are used to return information on a get_grid_info call. ; Client launcher scripts and third-party clients make use of this to diff --git a/bin/config-include/CenomeCache.ini.example b/bin/config-include/CenomeCache.ini.example index 8ef4e03bdc..4340493355 100644 --- a/bin/config-include/CenomeCache.ini.example +++ b/bin/config-include/CenomeCache.ini.example @@ -1,13 +1,14 @@ [AssetCache] ;; - ;; Options for CenmoeAssetCache + ;; Options for CenomeAssetCache ;; - ; 256 MB (default: 134217728) - MaxSize = 268435456 + ; Max size of the cache in bytes + ; 134217728 = 128 MB, 26843556 = 256 MB, etc (default: 134217728) + MaxSize = 134217728 - ; How many assets it is possible to store cache (default: 4096) - MaxCount = 16384 + ; How many assets it is possible to store in the cache (default: 4096) + MaxCount = 4096 - ; Expiration time - 1 hour (default: 30 minutes) - ExpirationTime = 60 + ; Expiration time in minutes (default: 30) + ExpirationTime = 30 diff --git a/bin/config-include/FlotsamCache.ini.example b/bin/config-include/FlotsamCache.ini.example index 026dee718d..ad38ad15b5 100644 --- a/bin/config-include/FlotsamCache.ini.example +++ b/bin/config-include/FlotsamCache.ini.example @@ -29,7 +29,7 @@ ; How long {in hours} to keep assets cached on disk, .5 == 30 minutes ; Specify 0 if you do not want your disk cache to expire - FileCacheTimeout = 0 + FileCacheTimeout = 48 ; How often {in hours} should the disk be checked for expired filed ; Specify 0 to disable expiration checking @@ -38,6 +38,7 @@ ; If WAIT_ON_INPROGRESS_REQUESTS has been defined then this specifies how ; long (in miliseconds) to block a request thread while trying to complete ; an existing write to disk. + ; NOTE: THIS PARAMETER IS NOT CURRENTLY USED BY THE CACHE ; WaitOnInprogressTimeout = 3000 ; Number of tiers to use for cache directories (current valid diff --git a/bin/config-include/Grid.ini b/bin/config-include/Grid.ini index ce5588eb1b..da860c6859 100644 --- a/bin/config-include/Grid.ini +++ b/bin/config-include/Grid.ini @@ -21,12 +21,16 @@ EntityTransferModule = "BasicEntityTransferModule" InventoryAccessModule = "BasicInventoryAccessModule" LandServices = "RemoteLandServicesConnector" + MapImageService = "MapImageServiceModule" LandServiceInConnector = true NeighbourServiceInConnector = true SimulationServiceInConnector = true LibraryModule = true +[Profile] + Module = "BasicProfileModule" + [SimulationDataStore] LocalServiceModule = "OpenSim.Services.Connectors.dll:SimulationDataService" @@ -47,3 +51,8 @@ [Friends] Connector = "OpenSim.Services.Connectors.dll:FriendsServicesConnector" + +[MapImageService] + LocalServiceModule = "OpenSim.Services.Connectors.dll:MapImageServicesConnector" + ; in minutes + RefreshTime = 60 diff --git a/bin/config-include/GridCommon.ini.example b/bin/config-include/GridCommon.ini.example index bc8bc0fdab..4eb6fcf333 100644 --- a/bin/config-include/GridCommon.ini.example +++ b/bin/config-include/GridCommon.ini.example @@ -10,9 +10,17 @@ ; Uncomment these lines if you want to use mysql storage ; Change the connection string to your db details ;StorageProvider = "OpenSim.Data.MySQL.dll" - ;ConnectionString = "Data Source=localhost;Database=opensim;User ID=opensim;Password=***;" + ;ConnectionString = "Data Source=localhost;Database=opensim;User ID=opensim;Password=***;Old Guids=true;" ; Uncomment this line if you are using MySQL and want to use a different database for estates - ;EstateConnectionString = "Data Source=localhost;Database=opensim;User ID=opensim;Password=***;" + ;EstateConnectionString = "Data Source=localhost;Database=opensim;User ID=opensim;Password=***;Old Guids=true;" + + ; MSSQL + ; Uncomment these lines if you want to use MSSQL storage + ; Change the connection string to your db details + ; The value for server property is shown in your SQL Server Management Studio login dialog. + ; (This sample is the default of express edition) + ;StorageProvider = "OpenSim.Data.MSSQL.dll" + ;ConnectionString = "Server=localhost\SQLEXPRESS;Database=opensim;User Id=opensim; password=***;" [AssetService] @@ -46,6 +54,13 @@ ;; Robust server in port 8002, but not always) Gatekeeper="http://mygridserver.com:8002" +[Messaging] + ; === HG ONLY === + ;; change this to the address of your Gatekeeper service + ;; (usually bundled with the rest of the services in one + ;; Robust server in port 8002, but not always) + Gatekeeper = "http://mygridserver.com:8002" + [AvatarService] ; ; change this to your grid-wide grid server @@ -85,14 +100,24 @@ [HGInventoryAccessModule] ; ; === HG ONLY === - ; Change this to your profile server + ; Change this to your server ; accessible from other grids ; ProfileServerURI = "http://mygridserver.com:8002/user" + Gatekeeper = "http://mygridserver.com:8002" ;; If you want to protect your assets from being copied by foreign visitors ;; uncomment the next line. You may want to do this on sims that have licensed content. ; OutboundPermission = False +[UserAgentService] + ; + ; === HG ONLY === + ; Change this to your user agent server (HG robust) + ; + UserAgentServerURI = "http://mygridserver.com:8002" + +[MapImageService] + MapImageServerURI = "http://mygridserver.com:8003" [Modules] ;; Choose 0 or 1 cache modules, and the corresponding config file, if it exists. diff --git a/bin/config-include/GridHypergrid.ini b/bin/config-include/GridHypergrid.ini index 5142d90eda..60a3c625f2 100644 --- a/bin/config-include/GridHypergrid.ini +++ b/bin/config-include/GridHypergrid.ini @@ -24,12 +24,17 @@ EntityTransferModule = "HGEntityTransferModule" InventoryAccessModule = "HGInventoryAccessModule" LandServices = "RemoteLandServicesConnector" + FriendsModule = "HGFriendsModule" + MapImageService = "MapImageServiceModule" LandServiceInConnector = true NeighbourServiceInConnector = true SimulationServiceInConnector = true LibraryModule = true +[Profile] + Module = "BasicProfileModule" + [SimulationDataStore] LocalServiceModule = "OpenSim.Services.Connectors.dll:SimulationDataService" @@ -63,3 +68,18 @@ [Friends] Connector = "OpenSim.Services.Connectors.dll:FriendsServicesConnector" + +[Messaging] + MessageTransferModule = HGMessageTransferModule + LureModule = HGLureModule + +[HGInstantMessageService] + LocalServiceModule = "OpenSim.Services.HypergridService.dll:HGInstantMessageService" + GridService = "OpenSim.Services.Connectors.dll:GridServicesConnector" + PresenceService = "OpenSim.Services.Connectors.dll:PresenceServicesConnector" + UserAgentService = "OpenSim.Services.Connectors.dll:UserAgentServiceConnector" + +[MapImageService] + LocalServiceModule = "OpenSim.Services.Connectors.dll:MapImageServicesConnector" + ; in minutes + RefreshTime = 60 diff --git a/bin/config-include/Standalone.ini b/bin/config-include/Standalone.ini index 6355d09041..bf89d0bb9c 100644 --- a/bin/config-include/Standalone.ini +++ b/bin/config-include/Standalone.ini @@ -17,10 +17,15 @@ AvatarServices = "LocalAvatarServicesConnector" EntityTransferModule = "BasicEntityTransferModule" InventoryAccessModule = "BasicInventoryAccessModule" + MapImageService = "MapImageServiceModule" LibraryModule = true LLLoginServiceInConnector = true GridInfoServiceInConnector = true + MapImageServiceInConnector = true + +[Profile] + Module = "BasicProfileModule" [SimulationDataStore] LocalServiceModule = "OpenSim.Services.Connectors.dll:SimulationDataService" @@ -88,6 +93,11 @@ WelcomeMessage = "Welcome, Avatar!" +[MapImageService] + LocalServiceModule = "OpenSim.Services.MapImageService.dll:MapImageService" + ; in minutes + RefreshTime = 60 + ;; This should always be the very last thing on this file [Includes] Include-Common = "config-include/StandaloneCommon.ini" diff --git a/bin/config-include/StandaloneCommon.ini.example b/bin/config-include/StandaloneCommon.ini.example index 67efa11564..cbe3fa0aef 100644 --- a/bin/config-include/StandaloneCommon.ini.example +++ b/bin/config-include/StandaloneCommon.ini.example @@ -16,6 +16,14 @@ ; Uncomment this line if you are using MySQL and want to use a different database for estates ;EstateConnectionString = "Data Source=localhost;Database=opensim;User ID=opensim;Password=***;Old Guids=true;" + ; MSSQL + ; Uncomment these lines if you want to use MSSQL storage + ; Change the connection string to your db details + ; The value for server property is shown in your SQL Server Management Studio login dialog. + ; (This sample is the default of express edition) + ;StorageProvider = "OpenSim.Data.MSSQL.dll" + ;ConnectionString = "Server=localhost\SQLEXPRESS;Database=opensim;User Id=opensim; password=***;" + [AssetService] DefaultAssetLoader = "OpenSim.Framework.AssetLoader.Filesystem.dll" AssetLoaderArgs = "assets/AssetSets.xml" @@ -28,6 +36,7 @@ [HGInventoryAccessModule] ProfileServerURI = "http://127.0.0.1:9000/profiles" + Gatekeeper = "http://127.0.0.1:9000" ;; If you want to protect your assets from being copied by foreign visitors ;; uncomment the next line. You may want to do this on sims that have licensed content. @@ -70,6 +79,11 @@ ;; change this to the address of your simulator Gatekeeper="http://127.0.0.1:9000" +[Messaging] + ; === HG ONLY === + ;; change this to the address of your simulator + Gatekeeper = "http://127.0.0.1:9000" + [LibraryModule] ; Set this if you want to change the name of the OpenSim Library ;LibraryName = "My World's Library" @@ -82,6 +96,11 @@ SRV_InventoryServerURI = "http://127.0.0.1:9000" SRV_AssetServerURI = "http://127.0.0.1:9000" SRV_ProfileServerURI = "http://127.0.0.1:9000" + SRV_FriendsServerURI = "http://127.0.0.1:9000" + SRV_IMServerURI = "http://127.0.0.1:9000" + + ;; For Viewer 2 + MapTileURL = "http://127.0.0.1:9000/" ;; Regular expressions for controlling which client versions are accepted/denied. ;; An empty string means nothing is checked. @@ -124,6 +143,42 @@ ;AllowedClients = "" ;DeniedClients = "" +[FreeswitchService] + ;; If FreeSWITCH is not being used then you don't need to set any of these parameters + ;; + ;; The IP address of your FreeSWITCH server. The common case is for this to be the same as the server running the OpenSim standalone + ;; This has to be set for the FreeSWITCH service to work + ;; This address must be reachable by viewers. + ;ServerAddress = 127.0.0.1 + + ;; The following configuration parameters are optional + + ;; By default, this is the same as the ServerAddress + ; Realm = 127.0.0.1 + + ;; By default, this is the same as the ServerAddress on port 5060 + ; SIPProxy = 127.0.0.1:5060 + + ;; Default is 5000ms + ; DefaultTimeout = 5000 + + ;; The dial plan context. Default is "default" + ; Context = default + + ;; Currently unused + ; UserName = freeswitch + + ;; Currently unused + ; Password = password + + ;; The following parameters are for STUN = Simple Traversal of UDP through NATs + ;; See http://wiki.freeswitch.org/wiki/NAT_Traversal + ;; stun.freeswitch.org is not guaranteed to be running so use it in + ;; production at your own risk + ; EchoServer = 127.0.0.1 + ; EchoPort = 50505 + ; AttemptSTUN = false + [GridInfoService] ; These settings are used to return information on a get_grid_info call. ; Client launcher scripts and third-party clients make use of this to @@ -168,3 +223,7 @@ ; password help: optional: page providing password assistance for users of your grid ; currently unused ;password = http://127.0.0.1/password + +[MapImageService] + ; Set this if you want to change the default + ; TilesStoragePath = "maptiles" diff --git a/bin/config-include/StandaloneHypergrid.ini b/bin/config-include/StandaloneHypergrid.ini index 486f22e698..719df5c5c3 100644 --- a/bin/config-include/StandaloneHypergrid.ini +++ b/bin/config-include/StandaloneHypergrid.ini @@ -18,8 +18,10 @@ GridUserServices = "LocalGridUserServicesConnector" SimulationServices = "RemoteSimulationConnectorModule" AvatarServices = "LocalAvatarServicesConnector" + MapImageService = "MapImageServiceModule" EntityTransferModule = "HGEntityTransferModule" InventoryAccessModule = "HGInventoryAccessModule" + FriendsModule = "HGFriendsModule" InventoryServiceInConnector = true AssetServiceInConnector = true @@ -30,6 +32,14 @@ GridInfoServiceInConnector = true AuthenticationServiceInConnector = true SimulationServiceInConnector = true + MapImageServiceInConnector = true + +[Profile] + Module = "BasicProfileModule" + +[Messaging] + MessageTransferModule = HGMessageTransferModule + LureModule = HGLureModule [SimulationDataStore] LocalServiceModule = "OpenSim.Services.Connectors.dll:SimulationDataService" @@ -108,7 +118,12 @@ GridService = "OpenSim.Services.GridService.dll:GridService" AvatarService = "OpenSim.Services.AvatarService.dll:AvatarService" FriendsService = "OpenSim.Services.FriendsService.dll:FriendsService" - + +[MapImageService] + LocalServiceModule = "OpenSim.Services.MapImageService.dll:MapImageService" + ; in minutes + RefreshTime = 60 + [GatekeeperService] LocalServiceModule = "OpenSim.Services.HypergridService.dll:GatekeeperService" ;; for the service @@ -125,6 +140,9 @@ GridUserService = "OpenSim.Services.UserAccountService.dll:GridUserService" GridService = "OpenSim.Services.GridService.dll:GridService" GatekeeperService = "OpenSim.Services.HypergridService.dll:GatekeeperService" + PresenceService = "OpenSim.Services.PresenceService.dll:PresenceService" + FriendsService = "OpenSim.Services.FriendsService.dll:FriendsService" + UserAccountService = "OpenSim.Services.UserAccountService.dll:UserAccountService" ;; The interface that local users get when they are in other grids @@ -140,6 +158,18 @@ LocalServiceModule = "OpenSim.Services.HypergridService.dll:HGAssetService" UserAccountsService = "OpenSim.Services.UserAccountService.dll:UserAccountService" +[HGFriendsService] + LocalServiceModule = "OpenSim.Services.FriendsService.dll:FriendsService" + UserAgentService = "OpenSim.Services.HypergridService.dll:UserAgentService" + +[HGInstantMessageService] + LocalServiceModule = "OpenSim.Services.HypergridService.dll:HGInstantMessageService" + GridService = "OpenSim.Services.GridService.dll:GridService" + PresenceService = "OpenSim.Services.PresenceService.dll:PresenceService" + 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/bin/mssql_connection.ini.example b/bin/mssql_connection.ini.example deleted file mode 100644 index e0ae7bace9..0000000000 --- a/bin/mssql_connection.ini.example +++ /dev/null @@ -1,18 +0,0 @@ -; The IniConfig.cs that parses this file by just finding the first key={value} in the whole text so comments aren't really honoured. -; Also, this algorithm can probably lead to 'amusing' results in unfortunate cases. - -[mssqlconnection] -data_source=\SQLEXPRESS -initial_catalog=database -persist_security_info=True -user_id=username -password=password - -; These entries are only for if you, for some reason, wish to customize your user server table names. -; Do note that if you change the table names, you might have to change the sql resources too manually -; If ommitted, default values will be used. - -userstablename=users -userfriendstablename=userfriends -agentstablename=agents -regionstablename=regions diff --git a/prebuild.xml b/prebuild.xml index a97d34fd6e..0e96176883 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -1287,6 +1287,7 @@ + @@ -1299,6 +1300,36 @@ + + + + ../../../bin/ + + + + + ../../../bin/ + + + + ../../../bin/ + + + + + + + + + + + + + + + + + @@ -1612,7 +1643,6 @@ - @@ -2676,6 +2706,32 @@ + + + + ../../../../bin/ + + + + + ../../../../bin/ + + + + ../../../../bin/ + + + + + + + + + + + + +