diff --git a/OpenSim/Data/IXInventoryData.cs b/OpenSim/Data/IXInventoryData.cs
index d85a7efb8f..85a5c08d37 100644
--- a/OpenSim/Data/IXInventoryData.cs
+++ b/OpenSim/Data/IXInventoryData.cs
@@ -74,9 +74,38 @@ namespace OpenSim.Data
bool StoreFolder(XInventoryFolder folder);
bool StoreItem(XInventoryItem item);
+ ///
+ /// Delete folders where field == val
+ ///
+ ///
+ ///
+ /// true if the delete was successful, false if it was not
bool DeleteFolders(string field, string val);
+
+ ///
+ /// Delete folders where field1 == val1, field2 == val2...
+ ///
+ ///
+ ///
+ /// true if the delete was successful, false if it was not
+ bool DeleteFolders(string[] fields, string[] vals);
+
+ ///
+ /// Delete items where field == val
+ ///
+ ///
+ ///
+ /// true if the delete was successful, false if it was not
bool DeleteItems(string field, string val);
+ ///
+ /// Delete items where field1 == val1, field2 == val2...
+ ///
+ ///
+ ///
+ /// true if the delete was successful, false if it was not
+ bool DeleteItems(string[] fields, string[] vals);
+
bool MoveItem(string id, string newParent);
XInventoryItem[] GetActiveGestures(UUID principalID);
int GetAssetPermissions(UUID principalID, UUID assetID);
diff --git a/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs b/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs
index 19e8fa63fa..6e695cecc3 100644
--- a/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs
+++ b/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs
@@ -335,24 +335,35 @@ namespace OpenSim.Data.MSSQL
}
}
- public virtual bool Delete(string field, string val)
+ public virtual bool Delete(string field, string key)
{
+ return Delete(new string[] { field }, new string[] { key });
+ }
+
+ public virtual bool Delete(string[] fields, string[] keys)
+ {
+ if (fields.Length != keys.Length)
+ return false;
+
+ List terms = new List();
+
using (SqlConnection conn = new SqlConnection(m_ConnectionString))
using (SqlCommand cmd = new SqlCommand())
{
- string deleteCommand = String.Format("DELETE FROM {0} WHERE [{1}] = @{1}", m_Realm, field);
- cmd.CommandText = deleteCommand;
-
- cmd.Parameters.Add(m_database.CreateParameter(field, val));
- cmd.Connection = conn;
- conn.Open();
-
- if (cmd.ExecuteNonQuery() > 0)
+ for (int i = 0; i < fields.Length; i++)
{
- //m_log.Warn("[MSSQLGenericTable]: " + deleteCommand);
- return true;
+ cmd.Parameters.Add(m_database.CreateParameter(fields[i], keys[i]));
+ terms.Add("[" + fields[i] + "] = @" + fields[i]);
}
- return false;
+
+ string where = String.Join(" AND ", terms.ToArray());
+
+ string query = String.Format("DELETE * FROM {0} WHERE {1}", m_Realm, where);
+
+ cmd.Connection = conn;
+ cmd.CommandText = query;
+ conn.Open();
+ return cmd.ExecuteNonQuery() > 0;
}
}
}
diff --git a/OpenSim/Data/MSSQL/MSSQLXInventoryData.cs b/OpenSim/Data/MSSQL/MSSQLXInventoryData.cs
index 739eb55ad4..dc35a2e0c0 100644
--- a/OpenSim/Data/MSSQL/MSSQLXInventoryData.cs
+++ b/OpenSim/Data/MSSQL/MSSQLXInventoryData.cs
@@ -79,11 +79,21 @@ namespace OpenSim.Data.MSSQL
return m_Folders.Delete(field, val);
}
+ public bool DeleteFolders(string[] fields, string[] vals)
+ {
+ return m_Folders.Delete(fields, vals);
+ }
+
public bool DeleteItems(string field, string val)
{
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);
diff --git a/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs b/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs
index cfffbd8739..754cf725f0 100644
--- a/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs
+++ b/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs
@@ -264,18 +264,33 @@ namespace OpenSim.Data.MySQL
}
}
- public virtual bool Delete(string field, string val)
+ public virtual bool Delete(string field, string key)
{
+ return Delete(new string[] { field }, new string[] { key });
+ }
+
+ public virtual bool Delete(string[] fields, string[] keys)
+ {
+ if (fields.Length != keys.Length)
+ return false;
+
+ List terms = new List();
+
using (MySqlCommand cmd = new MySqlCommand())
{
+ for (int i = 0 ; i < fields.Length ; i++)
+ {
+ cmd.Parameters.AddWithValue(fields[i], keys[i]);
+ terms.Add("`" + fields[i] + "` = ?" + fields[i]);
+ }
- cmd.CommandText = String.Format("delete from {0} where `{1}` = ?{1}", m_Realm, field);
- cmd.Parameters.AddWithValue(field, val);
+ string where = String.Join(" and ", terms.ToArray());
- if (ExecuteNonQuery(cmd) > 0)
- return true;
+ string query = String.Format("delete from {0} where {1}", m_Realm, where);
- return false;
+ cmd.CommandText = query;
+
+ return ExecuteNonQuery(cmd) > 0;
}
}
}
diff --git a/OpenSim/Data/MySQL/MySQLXInventoryData.cs b/OpenSim/Data/MySQL/MySQLXInventoryData.cs
index 481da493a3..caf18a4780 100644
--- a/OpenSim/Data/MySQL/MySQLXInventoryData.cs
+++ b/OpenSim/Data/MySQL/MySQLXInventoryData.cs
@@ -85,11 +85,21 @@ namespace OpenSim.Data.MySQL
return m_Folders.Delete(field, val);
}
+ public bool DeleteFolders(string[] fields, string[] vals)
+ {
+ return m_Folders.Delete(fields, vals);
+ }
+
public bool DeleteItems(string field, string val)
{
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);
diff --git a/OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs b/OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs
index 0d7b001e3f..3fb2d3facb 100644
--- a/OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs
+++ b/OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs
@@ -258,17 +258,33 @@ namespace OpenSim.Data.SQLite
return false;
}
- public bool Delete(string field, string val)
+ public virtual bool Delete(string field, string key)
{
+ return Delete(new string[] { field }, new string[] { key });
+ }
+
+ public bool Delete(string[] fields, string[] keys)
+ {
+ if (fields.Length != keys.Length)
+ return false;
+
+ List terms = new List();
+
SqliteCommand cmd = new SqliteCommand();
- cmd.CommandText = String.Format("delete from {0} where `{1}` = :{1}", m_Realm, field);
- cmd.Parameters.Add(new SqliteParameter(field, val));
+ for (int i = 0 ; i < fields.Length ; i++)
+ {
+ cmd.Parameters.Add(new SqliteParameter(":" + fields[i], keys[i]));
+ terms.Add("`" + fields[i] + "` = :" + fields[i]);
+ }
- if (ExecuteNonQuery(cmd, m_Connection) > 0)
- return true;
+ string where = String.Join(" and ", terms.ToArray());
- return false;
+ string query = String.Format("delete * from {0} where {1}", m_Realm, where);
+
+ cmd.CommandText = query;
+
+ return ExecuteNonQuery(cmd, m_Connection) > 0;
}
}
}
diff --git a/OpenSim/Data/SQLite/SQLiteXInventoryData.cs b/OpenSim/Data/SQLite/SQLiteXInventoryData.cs
index ccbd86e119..02edc30707 100644
--- a/OpenSim/Data/SQLite/SQLiteXInventoryData.cs
+++ b/OpenSim/Data/SQLite/SQLiteXInventoryData.cs
@@ -91,11 +91,21 @@ namespace OpenSim.Data.SQLite
return m_Folders.Delete(field, val);
}
+ public bool DeleteFolders(string[] fields, string[] vals)
+ {
+ return m_Folders.Delete(fields, vals);
+ }
+
public bool DeleteItems(string field, string val)
{
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);
diff --git a/OpenSim/Framework/WebUtil.cs b/OpenSim/Framework/WebUtil.cs
index f8691dc859..f176485bd5 100644
--- a/OpenSim/Framework/WebUtil.cs
+++ b/OpenSim/Framework/WebUtil.cs
@@ -974,7 +974,7 @@ namespace OpenSim.Framework
}
catch (Exception e)
{
- m_log.WarnFormat("[SynchronousRestObjectRequester]: exception in sending data to {0}: {1}", requestUrl, e);
+ m_log.DebugFormat("[SynchronousRestObjectRequester]: exception in sending data to {0}: {1}", requestUrl, e);
return deserial;
}
finally
@@ -999,18 +999,18 @@ namespace OpenSim.Framework
respStream.Close();
}
else
- m_log.WarnFormat("[SynchronousRestObjectRequester]: Oops! no content found in response stream from {0} {1}", requestUrl, verb);
+ m_log.DebugFormat("[SynchronousRestObjectRequester]: Oops! no content found in response stream from {0} {1}", requestUrl, verb);
}
}
catch (System.InvalidOperationException)
{
// This is what happens when there is invalid XML
- m_log.WarnFormat("[SynchronousRestObjectRequester]: Invalid XML {0} {1}", requestUrl, typeof(TResponse).ToString());
+ m_log.DebugFormat("[SynchronousRestObjectRequester]: Invalid XML {0} {1}", requestUrl, typeof(TResponse).ToString());
}
catch (Exception e)
{
- m_log.WarnFormat("[SynchronousRestObjectRequester]: Exception on response from {0} {1}", requestUrl, e);
+ m_log.DebugFormat("[SynchronousRestObjectRequester]: Exception on response from {0} {1}", requestUrl, e);
}
return deserial;
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 17242dcc15..431f3dc745 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -1423,7 +1423,10 @@ namespace OpenSim.Region.Framework.Scenes
if (item.AssetType == (int)AssetType.Link)
{
InventoryItemBase linkedItem = InventoryService.GetItem(new InventoryItemBase(item.AssetID));
- linkedItemFolderIdsToSend.Add(linkedItem.Folder);
+
+ // Take care of genuinely broken links where the target doesn't exist
+ if (linkedItem != null)
+ linkedItemFolderIdsToSend.Add(linkedItem.Folder);
}
}
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index bac66cbb61..313a46906c 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -620,7 +620,7 @@ namespace OpenSim.Region.Framework.Scenes
"delete object uuid ",
"Delete object by uuid", HandleDeleteObject);
MainConsole.Instance.Commands.AddCommand("region", false, "delete object name",
- "delete object name ",
+ "delete object name ",
"Delete object by name", HandleDeleteObject);
//Bind Storage Manager functions to some land manager functions for this scene
diff --git a/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs b/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs
index ce9a4481ea..b74d6e7c7d 100644
--- a/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs
+++ b/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs
@@ -58,12 +58,9 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
///
///
/// Config Settings Documentation.
- /// At the TOP LEVEL, e.g. in OpenSim.ini, we have the following options:
- /// EACH REGION, in OpenSim.ini, can have the following settings under the [AutoBackupModule] section.
- /// IMPORTANT: You may optionally specify the key name as follows for a per-region key: [Region Name].[Key Name]
- /// Example: My region is named Foo.
- /// If I wanted to specify the "AutoBackupInterval" key just for this region, I would name my key "Foo.AutoBackupInterval", under the [AutoBackupModule] section of OpenSim.ini.
- /// Instead of specifying them on a per-region basis, you can also omit the region name to specify the default setting for all regions.
+ /// Each configuration setting can be specified in two places: OpenSim.ini or Regions.ini.
+ /// If specified in Regions.ini, the settings should be within the region's section name.
+ /// If specified in OpenSim.ini, the settings should be within the [AutoBackupModule] section.
/// Region-specific settings take precedence.
///
/// AutoBackupModuleEnabled: True/False. Default: False. If True, use the auto backup module. This setting does not support per-region basis.
@@ -71,7 +68,7 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
/// AutoBackup: True/False. Default: False. If True, activate auto backup functionality.
/// This is the only required option for enabling auto-backup; the other options have sane defaults.
/// If False for a particular region, the auto-backup module becomes a no-op for the region, and all other AutoBackup* settings are ignored.
- /// If False globally (the default), only regions that specifically override this with "FooRegion.AutoBackup = true" will get AutoBackup functionality.
+ /// If False globally (the default), only regions that specifically override it in Regions.ini will get AutoBackup functionality.
/// AutoBackupInterval: Double, non-negative value. Default: 720 (12 hours).
/// The number of minutes between each backup attempt.
/// If a negative or zero value is given, it is equivalent to setting AutoBackup = False.
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 48a79537fd..c240edff27 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -4887,6 +4887,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return result;
}
+ public LSL_Integer llGetLinkNumberOfSides(int link)
+ {
+ m_host.AddScriptLPS(1);
+
+ SceneObjectPart linkedPart;
+
+ if (link == ScriptBaseClass.LINK_ROOT)
+ linkedPart = m_host.ParentGroup.RootPart;
+ else if (link == ScriptBaseClass.LINK_THIS)
+ linkedPart = m_host;
+ else
+ linkedPart = m_host.ParentGroup.GetLinkNumPart(link);
+
+ return GetNumberOfSides(linkedPart);
+ }
+
public LSL_Integer llGetNumberOfSides()
{
m_host.AddScriptLPS(1);
diff --git a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
index 665f4a677c..6bfee9156f 100644
--- a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
@@ -1530,6 +1530,7 @@ namespace OpenSim.Region.ScriptEngine.Shared
public struct LSLInteger
{
public int value;
+ private static readonly Regex castRegex = new Regex(@"(^[ ]*0[xX][0-9A-Fa-f][0-9A-Fa-f]*)|(^[ ]*(-?|\+?)[0-9][0-9]*)");
#region Constructors
public LSLInteger(int i)
@@ -1549,9 +1550,10 @@ namespace OpenSim.Region.ScriptEngine.Shared
public LSLInteger(string s)
{
- Regex r = new Regex("(^[ ]*0[xX][0-9A-Fa-f][0-9A-Fa-f]*)|(^[ ]*-?[0-9][0-9]*)");
- Match m = r.Match(s);
+ Match m = castRegex.Match(s);
string v = m.Groups[0].Value;
+ // Leading plus sign is allowed, but ignored
+ v = v.Replace("+", "");
if (v == String.Empty)
{
diff --git a/OpenSim/Services/InventoryService/XInventoryService.cs b/OpenSim/Services/InventoryService/XInventoryService.cs
index 0af35c84ac..2282ee85bc 100644
--- a/OpenSim/Services/InventoryService/XInventoryService.cs
+++ b/OpenSim/Services/InventoryService/XInventoryService.cs
@@ -393,6 +393,10 @@ namespace OpenSim.Services.InventoryService
public virtual bool UpdateItem(InventoryItemBase item)
{
+ if (!m_AllowDelete)
+ if (item.AssetType == (sbyte)AssetType.Link || item.AssetType == (sbyte)AssetType.LinkFolder)
+ return false;
+
return m_Database.StoreItem(ConvertFromOpenSim(item));
}
@@ -411,12 +415,30 @@ namespace OpenSim.Services.InventoryService
public virtual bool DeleteItems(UUID principalID, List itemIDs)
{
if (!m_AllowDelete)
- return false;
-
- // Just use the ID... *facepalms*
- //
- foreach (UUID id in itemIDs)
- m_Database.DeleteItems("inventoryID", id.ToString());
+ {
+ // We must still allow links and links to folders to be deleted, otherwise they will build up
+ // in the player's inventory until they can no longer log in. Deletions of links due to code bugs or
+ // similar is inconvenient but on a par with accidental movement of items. The original item is never
+ // touched.
+ foreach (UUID id in itemIDs)
+ {
+ if (!m_Database.DeleteItems(
+ new string[] { "inventoryID", "assetType" },
+ new string[] { id.ToString(), ((sbyte)AssetType.Link).ToString() }));
+ {
+ m_Database.DeleteItems(
+ new string[] { "inventoryID", "assetType" },
+ new string[] { id.ToString(), ((sbyte)AssetType.LinkFolder).ToString() });
+ }
+ }
+ }
+ else
+ {
+ // Just use the ID... *facepalms*
+ //
+ foreach (UUID id in itemIDs)
+ m_Database.DeleteItems("inventoryID", id.ToString());
+ }
return true;
}