adding ability for listeners to be filtered by regular expressions and a general-purpose function to see if a given string matches a given regex
parent
18b1ee6f37
commit
e977761071
|
@ -28,6 +28,7 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
using Nini.Config;
|
||||
using OpenMetaverse;
|
||||
using OpenSim.Framework;
|
||||
|
@ -170,12 +171,42 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
|
|||
/// <param name="hostID">UUID of the SceneObjectPart</param>
|
||||
/// <param name="channel">channel to listen on</param>
|
||||
/// <param name="name">name to filter on</param>
|
||||
/// <param name="id">key to filter on (user given, could be totally faked)</param>
|
||||
/// <param name="id">
|
||||
/// key to filter on (user given, could be totally faked)
|
||||
/// </param>
|
||||
/// <param name="msg">msg to filter on</param>
|
||||
/// <returns>number of the scripts handle</returns>
|
||||
public int Listen(uint localID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg)
|
||||
public int Listen(uint localID, UUID itemID, UUID hostID, int channel,
|
||||
string name, UUID id, string msg)
|
||||
{
|
||||
return m_listenerManager.AddListener(localID, itemID, hostID, channel, name, id, msg);
|
||||
return m_listenerManager.AddListener(localID, itemID, hostID,
|
||||
channel, name, id, msg);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a listen event callback with the specified filters.
|
||||
/// The parameters localID,itemID are needed to uniquely identify
|
||||
/// the script during 'peek' time. Parameter hostID is needed to
|
||||
/// determine the position of the script.
|
||||
/// </summary>
|
||||
/// <param name="localID">localID of the script engine</param>
|
||||
/// <param name="itemID">UUID of the script engine</param>
|
||||
/// <param name="hostID">UUID of the SceneObjectPart</param>
|
||||
/// <param name="channel">channel to listen on</param>
|
||||
/// <param name="name">name to filter on</param>
|
||||
/// <param name="id">
|
||||
/// key to filter on (user given, could be totally faked)
|
||||
/// </param>
|
||||
/// <param name="msg">msg to filter on</param>
|
||||
/// <param name="regexBitfield">
|
||||
/// Bitfield indicating which strings should be processed as regex.
|
||||
/// </param>
|
||||
/// <returns>number of the scripts handle</returns>
|
||||
public int Listen(uint localID, UUID itemID, UUID hostID, int channel,
|
||||
string name, UUID id, string msg, int regexBitfield)
|
||||
{
|
||||
return m_listenerManager.AddListener(localID, itemID, hostID,
|
||||
channel, name, id, msg, regexBitfield);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -465,10 +496,20 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
|
|||
m_curlisteners = 0;
|
||||
}
|
||||
|
||||
public int AddListener(uint localID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg)
|
||||
public int AddListener(uint localID, UUID itemID, UUID hostID,
|
||||
int channel, string name, UUID id, string msg)
|
||||
{
|
||||
return AddListener(localID, itemID, hostID, channel, name, id,
|
||||
msg, 0);
|
||||
}
|
||||
|
||||
public int AddListener(uint localID, UUID itemID, UUID hostID,
|
||||
int channel, string name, UUID id, string msg,
|
||||
int regexBitfield)
|
||||
{
|
||||
// do we already have a match on this particular filter event?
|
||||
List<ListenerInfo> coll = GetListeners(itemID, channel, name, id, msg);
|
||||
List<ListenerInfo> coll = GetListeners(itemID, channel, name, id,
|
||||
msg);
|
||||
|
||||
if (coll.Count > 0)
|
||||
{
|
||||
|
@ -485,7 +526,9 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
|
|||
|
||||
if (newHandle > 0)
|
||||
{
|
||||
ListenerInfo li = new ListenerInfo(newHandle, localID, itemID, hostID, channel, name, id, msg);
|
||||
ListenerInfo li = new ListenerInfo(newHandle, localID,
|
||||
itemID, hostID, channel, name, id, msg,
|
||||
regexBitfield);
|
||||
|
||||
List<ListenerInfo> listeners;
|
||||
if (!m_listeners.TryGetValue(channel,out listeners))
|
||||
|
@ -626,6 +669,22 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
|
|||
return -1;
|
||||
}
|
||||
|
||||
/// These are duplicated from ScriptBaseClass
|
||||
/// http://opensimulator.org/mantis/view.php?id=6106#c21945
|
||||
#region Constants for the bitfield parameter of osListenRegex
|
||||
|
||||
/// <summary>
|
||||
/// process name parameter as regex
|
||||
/// </summary>
|
||||
public const int OS_LISTEN_REGEX_NAME = 0x1;
|
||||
|
||||
/// <summary>
|
||||
/// process message parameter as regex
|
||||
/// </summary>
|
||||
public const int OS_LISTEN_REGEX_MESSAGE = 0x2;
|
||||
|
||||
#endregion
|
||||
|
||||
// Theres probably a more clever and efficient way to
|
||||
// do this, maybe with regex.
|
||||
// PM2008: Ha, one could even be smart and define a specialized Enumerator.
|
||||
|
@ -651,7 +710,10 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
|
|||
{
|
||||
continue;
|
||||
}
|
||||
if (li.GetName().Length > 0 && !li.GetName().Equals(name))
|
||||
if (li.GetName().Length > 0 && (
|
||||
((li.GetRegexBitfield() & OS_LISTEN_REGEX_NAME) != OS_LISTEN_REGEX_NAME && !li.GetName().Equals(name)) ||
|
||||
((li.GetRegexBitfield() & OS_LISTEN_REGEX_NAME) == OS_LISTEN_REGEX_NAME && !Regex.IsMatch(name, li.GetName()))
|
||||
))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
@ -659,7 +721,10 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
|
|||
{
|
||||
continue;
|
||||
}
|
||||
if (li.GetMessage().Length > 0 && !li.GetMessage().Equals(msg))
|
||||
if (li.GetMessage().Length > 0 && (
|
||||
((li.GetRegexBitfield() & OS_LISTEN_REGEX_MESSAGE) != OS_LISTEN_REGEX_MESSAGE && !li.GetMessage().Equals(msg)) ||
|
||||
((li.GetRegexBitfield() & OS_LISTEN_REGEX_MESSAGE) == OS_LISTEN_REGEX_MESSAGE && !Regex.IsMatch(msg, li.GetMessage()))
|
||||
))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
@ -692,10 +757,13 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
|
|||
{
|
||||
int idx = 0;
|
||||
Object[] item = new Object[6];
|
||||
int dataItemLength = 6;
|
||||
|
||||
while (idx < data.Length)
|
||||
{
|
||||
Array.Copy(data, idx, item, 0, 6);
|
||||
dataItemLength = (idx + 7 == data.Length || (idx + 7 < data.Length && data[idx + 7] is bool)) ? 7 : 6;
|
||||
item = new Object[dataItemLength];
|
||||
Array.Copy(data, idx, item, 0, dataItemLength);
|
||||
|
||||
ListenerInfo info =
|
||||
ListenerInfo.FromData(localID, itemID, hostID, item);
|
||||
|
@ -707,7 +775,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
|
|||
m_listeners[(int)item[2]].Add(info);
|
||||
}
|
||||
|
||||
idx+=6;
|
||||
idx+=dataItemLength;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -723,19 +791,33 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
|
|||
private UUID m_id; // ID to filter messages from
|
||||
private string m_name; // Object name to filter messages from
|
||||
private string m_message; // The message
|
||||
private int m_regexBitfield; // The regex bitfield
|
||||
|
||||
public ListenerInfo(int handle, uint localID, UUID ItemID, UUID hostID, int channel, string name, UUID id, string message)
|
||||
{
|
||||
Initialise(handle, localID, ItemID, hostID, channel, name, id, message);
|
||||
Initialise(handle, localID, ItemID, hostID, channel, name, id,
|
||||
message, 0);
|
||||
}
|
||||
|
||||
public ListenerInfo(int handle, uint localID, UUID ItemID,
|
||||
UUID hostID, int channel, string name, UUID id,
|
||||
string message, int regexBitfield)
|
||||
{
|
||||
Initialise(handle, localID, ItemID, hostID, channel, name, id,
|
||||
message, regexBitfield);
|
||||
}
|
||||
|
||||
public ListenerInfo(ListenerInfo li, string name, UUID id, string message)
|
||||
{
|
||||
Initialise(li.m_handle, li.m_localID, li.m_itemID, li.m_hostID, li.m_channel, name, id, message);
|
||||
Initialise(li.m_handle, li.m_localID, li.m_itemID, li.m_hostID, li.m_channel, name, id, message, 0);
|
||||
}
|
||||
|
||||
private void Initialise(int handle, uint localID, UUID ItemID, UUID hostID, int channel, string name,
|
||||
UUID id, string message)
|
||||
public ListenerInfo(ListenerInfo li, string name, UUID id, string message, int regexBitfield)
|
||||
{
|
||||
Initialise(li.m_handle, li.m_localID, li.m_itemID, li.m_hostID, li.m_channel, name, id, message, regexBitfield);
|
||||
}
|
||||
|
||||
private void Initialise(int handle, uint localID, UUID ItemID, UUID hostID, int channel, string name, UUID id, string message, int regexBitfield)
|
||||
{
|
||||
m_active = true;
|
||||
m_handle = handle;
|
||||
|
@ -746,11 +828,12 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
|
|||
m_name = name;
|
||||
m_id = id;
|
||||
m_message = message;
|
||||
m_regexBitfield = regexBitfield;
|
||||
}
|
||||
|
||||
public Object[] GetSerializationData()
|
||||
{
|
||||
Object[] data = new Object[6];
|
||||
Object[] data = new Object[7];
|
||||
|
||||
data[0] = m_active;
|
||||
data[1] = m_handle;
|
||||
|
@ -758,16 +841,19 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
|
|||
data[3] = m_name;
|
||||
data[4] = m_id;
|
||||
data[5] = m_message;
|
||||
data[6] = m_regexBitfield;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
public static ListenerInfo FromData(uint localID, UUID ItemID, UUID hostID, Object[] data)
|
||||
{
|
||||
ListenerInfo linfo = new ListenerInfo((int)data[1], localID,
|
||||
ItemID, hostID, (int)data[2], (string)data[3],
|
||||
(UUID)data[4], (string)data[5]);
|
||||
ListenerInfo linfo = new ListenerInfo((int)data[1], localID, ItemID, hostID, (int)data[2], (string)data[3], (UUID)data[4], (string)data[5]);
|
||||
linfo.m_active = (bool)data[0];
|
||||
if (data.Length >= 7)
|
||||
{
|
||||
linfo.m_regexBitfield = (int)data[6];
|
||||
}
|
||||
|
||||
return linfo;
|
||||
}
|
||||
|
@ -826,5 +912,10 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
|
|||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
public int GetRegexBitfield()
|
||||
{
|
||||
return m_regexBitfield;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,6 +45,14 @@ namespace OpenSim.Region.Framework.Interfaces
|
|||
void Deactivate();
|
||||
void Activate();
|
||||
UUID GetID();
|
||||
|
||||
/// <summary>
|
||||
/// Bitfield indicating which strings should be processed as regex.
|
||||
/// 1 corresponds to IWorldCommListenerInfo::GetName()
|
||||
/// 2 corresponds to IWorldCommListenerInfo::GetMessage()
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
int GetRegexBitfield();
|
||||
}
|
||||
|
||||
public interface IWorldComm
|
||||
|
@ -70,6 +78,23 @@ namespace OpenSim.Region.Framework.Interfaces
|
|||
/// <returns>number of the scripts handle</returns>
|
||||
int Listen(uint LocalID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg);
|
||||
|
||||
/// <summary>
|
||||
/// Create a listen event callback with the specified filters.
|
||||
/// The parameters localID,itemID are needed to uniquely identify
|
||||
/// the script during 'peek' time. Parameter hostID is needed to
|
||||
/// determine the position of the script.
|
||||
/// </summary>
|
||||
/// <param name="LocalID">localID of the script engine</param>
|
||||
/// <param name="itemID">UUID of the script engine</param>
|
||||
/// <param name="hostID">UUID of the SceneObjectPart</param>
|
||||
/// <param name="channel">channel to listen on</param>
|
||||
/// <param name="name">name to filter on</param>
|
||||
/// <param name="id">key to filter on (user given, could be totally faked)</param>
|
||||
/// <param name="msg">msg to filter on</param>
|
||||
/// <param name="regexBitfield">Bitfield indicating which strings should be processed as regex.</param>
|
||||
/// <returns>number of the scripts handle</returns>
|
||||
int Listen(uint LocalID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg, int regexBitfield);
|
||||
|
||||
/// <summary>
|
||||
/// This method scans over the objects which registered an interest in listen callbacks.
|
||||
/// For everyone it finds, it checks if it fits the given filter. If it does, then
|
||||
|
|
|
@ -3647,5 +3647,68 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
|||
|
||||
DropAttachmentAt(false, pos, rot);
|
||||
}
|
||||
|
||||
public LSL_Integer osListenRegex(int channelID, string name, string ID, string msg, int regexBitfield)
|
||||
{
|
||||
CheckThreatLevel(ThreatLevel.Low, "osListenRegex");
|
||||
m_host.AddScriptLPS(1);
|
||||
UUID keyID;
|
||||
UUID.TryParse(ID, out keyID);
|
||||
|
||||
// if we want the name to be used as a regular expression, ensure it is valid first.
|
||||
if ((regexBitfield & ScriptBaseClass.OS_LISTEN_REGEX_NAME) == ScriptBaseClass.OS_LISTEN_REGEX_NAME)
|
||||
{
|
||||
try
|
||||
{
|
||||
Regex.IsMatch("", name);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
OSSLShoutError("Name regex is invalid.");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// if we want the msg to be used as a regular expression, ensure it is valid first.
|
||||
if ((regexBitfield & ScriptBaseClass.OS_LISTEN_REGEX_MESSAGE) == ScriptBaseClass.OS_LISTEN_REGEX_MESSAGE)
|
||||
{
|
||||
try
|
||||
{
|
||||
Regex.IsMatch("", msg);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
OSSLShoutError("Message regex is invalid.");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
|
||||
return (wComm == null) ? -1 : wComm.Listen(
|
||||
m_host.LocalId,
|
||||
m_item.ItemID,
|
||||
m_host.UUID,
|
||||
channelID,
|
||||
name,
|
||||
keyID,
|
||||
msg,
|
||||
regexBitfield
|
||||
);
|
||||
}
|
||||
|
||||
public LSL_Integer osRegexIsMatch(string input, string pattern)
|
||||
{
|
||||
CheckThreatLevel(ThreatLevel.Low, "osRegexIsMatch");
|
||||
m_host.AddScriptLPS(1);
|
||||
try
|
||||
{
|
||||
return Regex.IsMatch(input, pattern) ? 1 : 0;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
OSSLShoutError("Possible invalid regular expression detected.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -418,5 +418,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
|
|||
/// <param name="pos"></param>
|
||||
/// <param name="rot"></param>
|
||||
void osForceDropAttachmentAt(vector pos, rotation rot);
|
||||
|
||||
/// <summary>
|
||||
/// Identical to llListen except for a bitfield which indicates which
|
||||
/// string parameters should be parsed as regex patterns.
|
||||
/// </summary>
|
||||
/// <param name="channelID"></param>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="ID"></param>
|
||||
/// <param name="msg"></param>
|
||||
/// <param name="regexBitfield">
|
||||
/// OS_LISTEN_REGEX_NAME
|
||||
/// OS_LISTEN_REGEX_MESSAGE
|
||||
/// </param>
|
||||
/// <returns></returns>
|
||||
LSL_Integer osListenRegex(int channelID, string name, string ID,
|
||||
string msg, int regexBitfield);
|
||||
|
||||
/// <summary>
|
||||
/// Wraps to bool Regex.IsMatch(string input, string pattern)
|
||||
/// </summary>
|
||||
/// <param name="input">string to test for match</param>
|
||||
/// <param name="regex">string to use as pattern</param>
|
||||
/// <returns>boolean</returns>
|
||||
LSL_Integer osRegexIsMatch(string input, string pattern);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -716,5 +716,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
|
|||
public static readonly LSLInteger RCERR_UNKNOWN = -1;
|
||||
public static readonly LSLInteger RCERR_SIM_PERF_LOW = -2;
|
||||
public static readonly LSLInteger RCERR_CAST_TIME_EXCEEDED = 3;
|
||||
|
||||
/// <summary>
|
||||
/// process name parameter as regex
|
||||
/// </summary>
|
||||
public const int OS_LISTEN_REGEX_NAME = 0x1;
|
||||
|
||||
/// <summary>
|
||||
/// process message parameter as regex
|
||||
/// </summary>
|
||||
public const int OS_LISTEN_REGEX_MESSAGE = 0x2;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -992,5 +992,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
|
|||
{
|
||||
m_OSSL_Functions.osForceDropAttachmentAt(pos, rot);
|
||||
}
|
||||
|
||||
public LSL_Integer osListenRegex(int channelID, string name, string ID, string msg, int regexBitfield)
|
||||
{
|
||||
return m_OSSL_Functions.osListenRegex(channelID, name, ID, msg, regexBitfield);
|
||||
}
|
||||
|
||||
public LSL_Integer osRegexIsMatch(string input, string pattern)
|
||||
{
|
||||
return m_OSSL_Functions.osRegexIsMatch(input, pattern);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue