Moved programs into the Programs folder
git-svn-id: http://libopenmetaverse.googlecode.com/svn/trunk@1958 52acb1d6-8a22-11de-b505-999d5b087335
This commit is contained in:
46
Programs/SLProxy/XmlRpcCS/Logger.cs
Normal file
46
Programs/SLProxy/XmlRpcCS/Logger.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
namespace Nwc.XmlRpc
|
||||
{
|
||||
using System;
|
||||
|
||||
/// <summary>Define levels of logging.</summary><remarks> This duplicates
|
||||
/// similar enumerations in System.Diagnostics.EventLogEntryType. The
|
||||
/// duplication was merited because .NET Compact Framework lacked the EventLogEntryType enum.</remarks>
|
||||
public enum LogLevel
|
||||
{
|
||||
/// <summary>Information level, log entry for informational reasons only.</summary>
|
||||
Information,
|
||||
/// <summary>Warning level, indicates a possible problem.</summary>
|
||||
Warning,
|
||||
/// <summary>Error level, implies a significant problem.</summary>
|
||||
Error
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///Logging singleton with swappable output delegate.
|
||||
///</summary>
|
||||
///<remarks>
|
||||
///This singleton provides a centralized log. The actual WriteEntry calls are passed
|
||||
///off to a delegate however. Having a delegate do the actual logginh allows you to
|
||||
///implement different logging mechanism and have them take effect throughout the system.
|
||||
///</remarks>
|
||||
public class Logger
|
||||
{
|
||||
///<summary>Delegate definition for logging.</summary>
|
||||
///<param name="message">The message <c>String</c> to log.</param>
|
||||
///<param name="level">The <c>LogLevel</c> of your message.</param>
|
||||
public delegate void LoggerDelegate(String message, LogLevel level);
|
||||
///<summary>The LoggerDelegate that will recieve WriteEntry requests.</summary>
|
||||
static public LoggerDelegate Delegate = null;
|
||||
|
||||
///<summary>
|
||||
///Method logging events are sent to.
|
||||
///</summary>
|
||||
///<param name="message">The message <c>String</c> to log.</param>
|
||||
///<param name="level">The <c>LogLevel</c> of your message.</param>
|
||||
static public void WriteEntry(String message, LogLevel level)
|
||||
{
|
||||
if (Delegate != null)
|
||||
Delegate(message, level);
|
||||
}
|
||||
}
|
||||
}
|
||||
204
Programs/SLProxy/XmlRpcCS/SimpleHttpRequest.cs
Normal file
204
Programs/SLProxy/XmlRpcCS/SimpleHttpRequest.cs
Normal file
@@ -0,0 +1,204 @@
|
||||
namespace Nwc.XmlRpc
|
||||
{
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net.Sockets;
|
||||
using System.Collections;
|
||||
|
||||
///<summary>Very basic HTTP request handler.</summary>
|
||||
///<remarks>This class is designed to accept a TcpClient and treat it as an HTTP request.
|
||||
/// It will do some basic header parsing and manage the input and output streams associated
|
||||
/// with the request.</remarks>
|
||||
public class SimpleHttpRequest
|
||||
{
|
||||
private String _httpMethod = null;
|
||||
private String _protocol;
|
||||
private String _filePathFile = null;
|
||||
private String _filePathDir = null;
|
||||
private String __filePath;
|
||||
private TcpClient _client;
|
||||
private StreamReader _input;
|
||||
private StreamWriter _output;
|
||||
private Hashtable _headers;
|
||||
|
||||
/// <summary>A constructor which accepts the TcpClient.</summary>
|
||||
/// <remarks>It creates the associated input and output streams, determines the request type,
|
||||
/// and parses the remaining HTTP header.</remarks>
|
||||
/// <param name="client">The <c>TcpClient</c> associated with the HTTP connection.</param>
|
||||
public SimpleHttpRequest(TcpClient client)
|
||||
{
|
||||
_client = client;
|
||||
_output = new StreamWriter(client.GetStream());
|
||||
_input = new StreamReader(client.GetStream());
|
||||
GetRequestMethod();
|
||||
GetRequestHeaders();
|
||||
}
|
||||
|
||||
/// <summary>The output <c>StreamWriter</c> associated with the request.</summary>
|
||||
public StreamWriter Output
|
||||
{
|
||||
get { return _output; }
|
||||
}
|
||||
|
||||
/// <summary>The input <c>StreamReader</c> associated with the request.</summary>
|
||||
public StreamReader Input
|
||||
{
|
||||
get { return _input; }
|
||||
}
|
||||
|
||||
/// <summary>The <c>TcpClient</c> with the request.</summary>
|
||||
public TcpClient Client
|
||||
{
|
||||
get { return _client; }
|
||||
}
|
||||
|
||||
private String _filePath
|
||||
{
|
||||
get { return __filePath; }
|
||||
set
|
||||
{
|
||||
__filePath = value;
|
||||
_filePathDir = null;
|
||||
_filePathFile = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>The type of HTTP request (i.e. PUT, GET, etc.).</summary>
|
||||
public String HttpMethod
|
||||
{
|
||||
get { return _httpMethod; }
|
||||
}
|
||||
|
||||
/// <summary>The level of the HTTP protocol.</summary>
|
||||
public String Protocol
|
||||
{
|
||||
get { return _protocol; }
|
||||
}
|
||||
|
||||
/// <summary>The "path" which is part of any HTTP request.</summary>
|
||||
public String FilePath
|
||||
{
|
||||
get { return _filePath; }
|
||||
}
|
||||
|
||||
/// <summary>The file portion of the "path" which is part of any HTTP request.</summary>
|
||||
public String FilePathFile
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_filePathFile != null)
|
||||
return _filePathFile;
|
||||
|
||||
int i = FilePath.LastIndexOf("/");
|
||||
|
||||
if (i == -1)
|
||||
return "";
|
||||
|
||||
i++;
|
||||
_filePathFile = FilePath.Substring(i, FilePath.Length - i);
|
||||
return _filePathFile;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>The directory portion of the "path" which is part of any HTTP request.</summary>
|
||||
public String FilePathDir
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_filePathDir != null)
|
||||
return _filePathDir;
|
||||
|
||||
int i = FilePath.LastIndexOf("/");
|
||||
|
||||
if (i == -1)
|
||||
return "";
|
||||
|
||||
i++;
|
||||
_filePathDir = FilePath.Substring(0, i);
|
||||
return _filePathDir;
|
||||
}
|
||||
}
|
||||
|
||||
private void GetRequestMethod()
|
||||
{
|
||||
string req = _input.ReadLine();
|
||||
if (req == null)
|
||||
throw new ApplicationException("Void request.");
|
||||
|
||||
if (0 == String.Compare("GET ", req.Substring(0, 4), true))
|
||||
_httpMethod = "GET";
|
||||
else if (0 == String.Compare("POST ", req.Substring(0, 5), true))
|
||||
_httpMethod = "POST";
|
||||
else
|
||||
throw new InvalidOperationException("Unrecognized method in query: " + req);
|
||||
|
||||
req = req.TrimEnd();
|
||||
int idx = req.IndexOf(' ') + 1;
|
||||
if (idx >= req.Length)
|
||||
throw new ApplicationException("What do you want?");
|
||||
|
||||
string page_protocol = req.Substring(idx);
|
||||
int idx2 = page_protocol.IndexOf(' ');
|
||||
if (idx2 == -1)
|
||||
idx2 = page_protocol.Length;
|
||||
|
||||
_filePath = page_protocol.Substring(0, idx2).Trim();
|
||||
_protocol = page_protocol.Substring(idx2).Trim();
|
||||
}
|
||||
|
||||
private void GetRequestHeaders()
|
||||
{
|
||||
String line;
|
||||
int idx;
|
||||
|
||||
_headers = new Hashtable();
|
||||
|
||||
while ((line = _input.ReadLine()) != "")
|
||||
{
|
||||
if (line == null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
idx = line.IndexOf(':');
|
||||
if (idx == -1 || idx == line.Length - 1)
|
||||
{
|
||||
Logger.WriteEntry("Malformed header line: " + line, LogLevel.Information);
|
||||
continue;
|
||||
}
|
||||
|
||||
String key = line.Substring(0, idx);
|
||||
String value = line.Substring(idx + 1);
|
||||
|
||||
try
|
||||
{
|
||||
_headers.Add(key, value);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Logger.WriteEntry("Duplicate header key in line: " + line, LogLevel.Information);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Format the object contents into a useful string representation.
|
||||
/// </summary>
|
||||
///<returns><c>String</c> representation of the <c>SimpleHttpRequest</c> as the <i>HttpMethod FilePath Protocol</i>.</returns>
|
||||
override public String ToString()
|
||||
{
|
||||
return HttpMethod + " " + FilePath + " " + Protocol;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Close the <c>SimpleHttpRequest</c>. This flushes and closes all associated io streams.
|
||||
/// </summary>
|
||||
public void Close()
|
||||
{
|
||||
_output.Flush();
|
||||
_output.Close();
|
||||
_input.Close();
|
||||
_client.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
51
Programs/SLProxy/XmlRpcCS/XmlRpcBoxcarRequest.cs
Normal file
51
Programs/SLProxy/XmlRpcCS/XmlRpcBoxcarRequest.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
namespace Nwc.XmlRpc
|
||||
{
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using System.Xml;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Reflection;
|
||||
|
||||
/// <summary>Class that collects individual <c>XmlRpcRequest</c> objects and submits them as a <i>boxcarred</i> request.</summary>
|
||||
/// <remarks>A boxcared request is when a number of request are collected before being sent via XML-RPC, and then are sent via
|
||||
/// a single HTTP connection. This results in a speed up from reduced connection time. The results are then retuned collectively
|
||||
/// as well.
|
||||
///</remarks>
|
||||
/// <seealso cref="XmlRpcRequest"/>
|
||||
public class XmlRpcBoxcarRequest : XmlRpcRequest
|
||||
{
|
||||
/// <summary>ArrayList to collect the requests to boxcar.</summary>
|
||||
public IList Requests = new ArrayList();
|
||||
|
||||
/// <summary>Basic constructor.</summary>
|
||||
public XmlRpcBoxcarRequest()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>Returns the <c>String</c> "system.multiCall" which is the server method that handles boxcars.</summary>
|
||||
public override String MethodName
|
||||
{
|
||||
get { return "system.multiCall"; }
|
||||
}
|
||||
|
||||
/// <summary>The <c>ArrayList</c> of boxcarred <paramref>Requests</paramref> as properly formed parameters.</summary>
|
||||
public override IList Params
|
||||
{
|
||||
get {
|
||||
_params.Clear();
|
||||
ArrayList reqArray = new ArrayList();
|
||||
foreach (XmlRpcRequest request in Requests)
|
||||
{
|
||||
Hashtable requestEntry = new Hashtable();
|
||||
requestEntry.Add(XmlRpcXmlTokens.METHOD_NAME, request.MethodName);
|
||||
requestEntry.Add(XmlRpcXmlTokens.PARAMS, request.Params);
|
||||
reqArray.Add(requestEntry);
|
||||
}
|
||||
_params.Add(reqArray);
|
||||
return _params;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
61
Programs/SLProxy/XmlRpcCS/XmlRpcClientProxy.cs
Normal file
61
Programs/SLProxy/XmlRpcCS/XmlRpcClientProxy.cs
Normal file
@@ -0,0 +1,61 @@
|
||||
namespace Nwc.XmlRpc
|
||||
{
|
||||
using System;
|
||||
using System.Runtime.Remoting.Proxies;
|
||||
using System.Runtime.Remoting.Messaging;
|
||||
|
||||
/// <summary>This class provides support for creating local proxies of XML-RPC remote objects</summary>
|
||||
/// <remarks>
|
||||
/// To create a local proxy you need to create a local C# interface and then, via <i>createProxy</i>
|
||||
/// associate that interface with a remote object at a given URL.
|
||||
/// </remarks>
|
||||
public class XmlRpcClientProxy : RealProxy
|
||||
{
|
||||
private String _remoteObjectName;
|
||||
private String _url;
|
||||
private XmlRpcRequest _client = new XmlRpcRequest();
|
||||
|
||||
/// <summary>Factory method to create proxies.</summary>
|
||||
/// <remarks>
|
||||
/// To create a local proxy you need to create a local C# interface with methods that mirror those of the server object.
|
||||
/// Next, pass that interface into <c>createProxy</c> along with the object name and URL of the remote object and
|
||||
/// cast the resulting object to the specifice interface.
|
||||
/// </remarks>
|
||||
/// <param name="remoteObjectName"><c>String</c> The name of the remote object.</param>
|
||||
/// <param name="url"><c>String</c> The URL of the remote object.</param>
|
||||
/// <param name="anInterface"><c>Type</c> The typeof() of a C# interface.</param>
|
||||
/// <returns><c>Object</c> A proxy for your specified interface. Cast to appropriate type.</returns>
|
||||
public static Object createProxy(String remoteObjectName, String url, Type anInterface)
|
||||
{
|
||||
return new XmlRpcClientProxy(remoteObjectName, url, anInterface).GetTransparentProxy();
|
||||
}
|
||||
|
||||
private XmlRpcClientProxy(String remoteObjectName, String url, Type t) : base(t)
|
||||
{
|
||||
_remoteObjectName = remoteObjectName;
|
||||
_url = url;
|
||||
}
|
||||
|
||||
/// <summary>The local method dispatcher - do not invoke.</summary>
|
||||
override public IMessage Invoke(IMessage msg)
|
||||
{
|
||||
IMethodCallMessage methodMessage = (IMethodCallMessage)msg;
|
||||
|
||||
_client.MethodName = _remoteObjectName + "." + methodMessage.MethodName;
|
||||
_client.Params.Clear();
|
||||
foreach (Object o in methodMessage.Args)
|
||||
_client.Params.Add(o);
|
||||
|
||||
try
|
||||
{
|
||||
Object ret = _client.Invoke(_url);
|
||||
return new ReturnMessage(ret,null,0,
|
||||
methodMessage.LogicalCallContext, methodMessage);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return new ReturnMessage(e, methodMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
195
Programs/SLProxy/XmlRpcCS/XmlRpcDeserializer.cs
Normal file
195
Programs/SLProxy/XmlRpcCS/XmlRpcDeserializer.cs
Normal file
@@ -0,0 +1,195 @@
|
||||
namespace Nwc.XmlRpc
|
||||
{
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using System.Xml;
|
||||
using System.Globalization;
|
||||
|
||||
/// <summary>Parser context, we maintain contexts in a stack to avoiding recursion. </summary>
|
||||
struct Context
|
||||
{
|
||||
public String Name;
|
||||
public Object Container;
|
||||
}
|
||||
|
||||
/// <summary>Basic XML-RPC data deserializer.</summary>
|
||||
/// <remarks>Uses <c>XmlTextReader</c> to parse the XML data. This level of the class
|
||||
/// only handles the tokens common to both Requests and Responses. This class is not useful in and of itself
|
||||
/// but is designed to be subclassed.</remarks>
|
||||
public class XmlRpcDeserializer : XmlRpcXmlTokens
|
||||
{
|
||||
private static DateTimeFormatInfo _dateFormat = new DateTimeFormatInfo();
|
||||
|
||||
private Object _container;
|
||||
private Stack _containerStack;
|
||||
|
||||
/// <summary>Protected reference to last text.</summary>
|
||||
protected String _text;
|
||||
/// <summary>Protected reference to last deserialized value.</summary>
|
||||
protected Object _value;
|
||||
/// <summary>Protected reference to last name field.</summary>
|
||||
protected String _name;
|
||||
|
||||
|
||||
/// <summary>Basic constructor.</summary>
|
||||
public XmlRpcDeserializer()
|
||||
{
|
||||
Reset();
|
||||
_dateFormat.FullDateTimePattern = ISO_DATETIME;
|
||||
}
|
||||
|
||||
/// <summary>Static method that parses XML data into a response using the Singleton.</summary>
|
||||
/// <param name="xmlData"><c>StreamReader</c> containing an XML-RPC response.</param>
|
||||
/// <returns><c>Object</c> object resulting from the deserialization.</returns>
|
||||
virtual public Object Deserialize(TextReader xmlData)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>Protected method to parse a node in an XML-RPC XML stream.</summary>
|
||||
/// <remarks>Method deals with elements common to all XML-RPC data, subclasses of
|
||||
/// this object deal with request/response spefic elements.</remarks>
|
||||
/// <param name="reader"><c>XmlTextReader</c> of the in progress parsing data stream.</param>
|
||||
protected void DeserializeNode(XmlTextReader reader)
|
||||
{
|
||||
switch (reader.NodeType)
|
||||
{
|
||||
case XmlNodeType.Element:
|
||||
if (Logger.Delegate != null)
|
||||
Logger.WriteEntry("START " + reader.Name, LogLevel.Information);
|
||||
switch (reader.Name)
|
||||
{
|
||||
case VALUE:
|
||||
_value = null;
|
||||
_text = null;
|
||||
break;
|
||||
case STRUCT:
|
||||
PushContext();
|
||||
_container = new Hashtable();
|
||||
break;
|
||||
case ARRAY:
|
||||
PushContext();
|
||||
_container = new ArrayList();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case XmlNodeType.EndElement:
|
||||
if (Logger.Delegate != null)
|
||||
Logger.WriteEntry("END " + reader.Name, LogLevel.Information);
|
||||
switch (reader.Name)
|
||||
{
|
||||
case BASE64:
|
||||
_value = Convert.FromBase64String(_text);
|
||||
break;
|
||||
case BOOLEAN:
|
||||
int val = Int16.Parse(_text);
|
||||
if (val == 0)
|
||||
_value = false;
|
||||
else if (val == 1)
|
||||
_value = true;
|
||||
break;
|
||||
case STRING:
|
||||
_value = _text;
|
||||
break;
|
||||
case DOUBLE:
|
||||
_value = Double.Parse(_text);
|
||||
break;
|
||||
case INT:
|
||||
case ALT_INT:
|
||||
_value = Int32.Parse(_text);
|
||||
break;
|
||||
case DATETIME:
|
||||
#if __MONO__
|
||||
_value = DateParse(_text);
|
||||
#else
|
||||
_value = DateTime.ParseExact(_text, "F", _dateFormat);
|
||||
#endif
|
||||
break;
|
||||
case NAME:
|
||||
_name = _text;
|
||||
break;
|
||||
case VALUE:
|
||||
if (_value == null)
|
||||
_value = _text; // some kits don't use <string> tag, they just do <value>
|
||||
|
||||
if ((_container != null) && (_container is IList)) // in an array? If so add value to it.
|
||||
((IList)_container).Add(_value);
|
||||
break;
|
||||
case MEMBER:
|
||||
if ((_container != null) && (_container is IDictionary)) // in an struct? If so add value to it.
|
||||
((IDictionary)_container).Add(_name, _value);
|
||||
break;
|
||||
case ARRAY:
|
||||
case STRUCT:
|
||||
_value = _container;
|
||||
PopContext();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case XmlNodeType.Text:
|
||||
if (Logger.Delegate != null)
|
||||
Logger.WriteEntry("Text " + reader.Value, LogLevel.Information);
|
||||
_text = reader.Value;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Static method that parses XML in a <c>String</c> into a
|
||||
/// request using the Singleton.</summary>
|
||||
/// <param name="xmlData"><c>String</c> containing an XML-RPC request.</param>
|
||||
/// <returns><c>XmlRpcRequest</c> object resulting from the parse.</returns>
|
||||
public Object Deserialize(String xmlData)
|
||||
{
|
||||
StringReader sr = new StringReader(xmlData);
|
||||
return Deserialize(sr);
|
||||
}
|
||||
|
||||
/// <summary>Pop a Context of the stack, an Array or Struct has closed.</summary>
|
||||
private void PopContext()
|
||||
{
|
||||
Context c = (Context)_containerStack.Pop();
|
||||
_container = c.Container;
|
||||
_name = c.Name;
|
||||
}
|
||||
|
||||
/// <summary>Push a Context on the stack, an Array or Struct has opened.</summary>
|
||||
private void PushContext()
|
||||
{
|
||||
Context context;
|
||||
|
||||
context.Container = _container;
|
||||
context.Name = _name;
|
||||
|
||||
_containerStack.Push(context);
|
||||
}
|
||||
|
||||
/// <summary>Reset the internal state of the deserializer.</summary>
|
||||
protected void Reset()
|
||||
{
|
||||
_text = null;
|
||||
_value = null;
|
||||
_name = null;
|
||||
_container = null;
|
||||
_containerStack = new Stack();
|
||||
}
|
||||
|
||||
#if __MONO__
|
||||
private DateTime DateParse(String str)
|
||||
{
|
||||
int year = Int32.Parse(str.Substring(0,4));
|
||||
int month = Int32.Parse(str.Substring(4,2));
|
||||
int day = Int32.Parse(str.Substring(6,2));
|
||||
int hour = Int32.Parse(str.Substring(9,2));
|
||||
int min = Int32.Parse(str.Substring(12,2));
|
||||
int sec = Int32.Parse(str.Substring(15,2));
|
||||
return new DateTime(year,month,day,hour,min,sec);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
51
Programs/SLProxy/XmlRpcCS/XmlRpcErrorCodes.cs
Normal file
51
Programs/SLProxy/XmlRpcCS/XmlRpcErrorCodes.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
namespace Nwc.XmlRpc
|
||||
{
|
||||
using System;
|
||||
|
||||
/// <summary>Standard XML-RPC error codes.</summary>
|
||||
public class XmlRpcErrorCodes
|
||||
{
|
||||
/// <summary></summary>
|
||||
public const int PARSE_ERROR_MALFORMED = -32700;
|
||||
/// <summary></summary>
|
||||
public const String PARSE_ERROR_MALFORMED_MSG = "Parse Error, not well formed";
|
||||
|
||||
/// <summary></summary>
|
||||
public const int PARSE_ERROR_ENCODING = -32701;
|
||||
/// <summary></summary>
|
||||
public const String PARSE_ERROR_ENCODING_MSG = "Parse Error, unsupported encoding";
|
||||
|
||||
//
|
||||
// -32702 ---> parse error. invalid character for encoding
|
||||
// -32600 ---> server error. invalid xml-rpc. not conforming to spec.
|
||||
//
|
||||
|
||||
/// <summary></summary>
|
||||
public const int SERVER_ERROR_METHOD = -32601;
|
||||
/// <summary></summary>
|
||||
public const String SERVER_ERROR_METHOD_MSG = "Server Error, requested method not found";
|
||||
|
||||
/// <summary></summary>
|
||||
public const int SERVER_ERROR_PARAMS = -32602;
|
||||
/// <summary></summary>
|
||||
public const String SERVER_ERROR_PARAMS_MSG = "Server Error, invalid method parameters";
|
||||
|
||||
//
|
||||
// -32603 ---> server error. internal xml-rpc error
|
||||
//
|
||||
|
||||
/// <summary></summary>
|
||||
public const int APPLICATION_ERROR = -32500;
|
||||
/// <summary></summary>
|
||||
public const String APPLICATION_ERROR_MSG = "Application Error";
|
||||
|
||||
//
|
||||
// -32400 ---> system error
|
||||
//
|
||||
|
||||
/// <summary></summary>
|
||||
public const int TRANSPORT_ERROR = -32300;
|
||||
/// <summary></summary>
|
||||
public const String TRANSPORT_ERROR_MSG = "Transport Layer Error";
|
||||
}
|
||||
}
|
||||
39
Programs/SLProxy/XmlRpcCS/XmlRpcException.cs
Normal file
39
Programs/SLProxy/XmlRpcCS/XmlRpcException.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
namespace Nwc.XmlRpc
|
||||
{
|
||||
using System;
|
||||
|
||||
/// <summary>An XML-RPC Exception.</summary>
|
||||
/// <remarks>Maps a C# exception to an XML-RPC fault. Normal exceptions
|
||||
/// include a message so this adds the code needed by XML-RPC.</remarks>
|
||||
public class XmlRpcException : Exception
|
||||
{
|
||||
private int _code;
|
||||
|
||||
/// <summary>Instantiate an <c>XmlRpcException</c> with a code and message.</summary>
|
||||
/// <param name="code"><c>Int</c> faultCode associated with this exception.</param>
|
||||
/// <param name="message"><c>String</c> faultMessage associated with this exception.</param>
|
||||
public XmlRpcException(int code, String message)
|
||||
: base(message)
|
||||
{
|
||||
_code = code;
|
||||
}
|
||||
|
||||
/// <summary>The value of the faults message, i.e. the faultString.</summary>
|
||||
public String FaultString
|
||||
{
|
||||
get { return Message; }
|
||||
}
|
||||
|
||||
/// <summary>The value of the faults code, i.e. the faultCode.</summary>
|
||||
public int FaultCode
|
||||
{
|
||||
get { return _code; }
|
||||
}
|
||||
|
||||
/// <summary>Format the message to include the code.</summary>
|
||||
override public String ToString()
|
||||
{
|
||||
return "Code: " + FaultCode + " Message: " + base.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
60
Programs/SLProxy/XmlRpcCS/XmlRpcExposedAttribute.cs
Normal file
60
Programs/SLProxy/XmlRpcCS/XmlRpcExposedAttribute.cs
Normal file
@@ -0,0 +1,60 @@
|
||||
namespace Nwc.XmlRpc
|
||||
{
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
/// <summary>
|
||||
/// Simple tagging attribute to indicate participation is XML-RPC exposure.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If present at the class level it indicates that this class does explicitly
|
||||
/// expose methods. If present at the method level it denotes that the method
|
||||
/// is exposed.
|
||||
/// </remarks>
|
||||
[AttributeUsage(
|
||||
AttributeTargets.Class | AttributeTargets.Method,
|
||||
AllowMultiple = false,
|
||||
Inherited = true
|
||||
)]
|
||||
public class XmlRpcExposedAttribute : Attribute
|
||||
{
|
||||
/// <summary>Check if <paramref>obj</paramref> is an object utilizing the XML-RPC exposed Attribute.</summary>
|
||||
/// <param name="obj"><c>Object</c> of a class or method to check for attribute.</param>
|
||||
/// <returns><c>Boolean</c> true if attribute present.</returns>
|
||||
public static Boolean ExposedObject(Object obj)
|
||||
{
|
||||
return IsExposed(obj.GetType());
|
||||
}
|
||||
|
||||
/// <summary>Check if <paramref>obj</paramref>.<paramref>methodName</paramref> is an XML-RPC exposed method.</summary>
|
||||
/// <remarks>A method is considered to be exposed if it exists and, either, the object does not use the XmlRpcExposed attribute,
|
||||
/// or the object does use the XmlRpcExposed attribute and the method has the XmlRpcExposed attribute as well.</remarks>
|
||||
/// <returns><c>Boolean</c> true if the method is exposed.</returns>
|
||||
public static Boolean ExposedMethod(Object obj, String methodName)
|
||||
{
|
||||
Type type = obj.GetType();
|
||||
MethodInfo method = type.GetMethod(methodName);
|
||||
|
||||
if (method == null)
|
||||
throw new MissingMethodException("Method " + methodName + " not found.");
|
||||
|
||||
if (!IsExposed(type))
|
||||
return true;
|
||||
|
||||
return IsExposed(method);
|
||||
}
|
||||
|
||||
/// <summary>Check if <paramref>mi</paramref> is XML-RPC exposed.</summary>
|
||||
/// <param name="mi"><c>MemberInfo</c> of a class or method to check for attribute.</param>
|
||||
/// <returns><c>Boolean</c> true if attribute present.</returns>
|
||||
public static Boolean IsExposed(MemberInfo mi)
|
||||
{
|
||||
foreach (Attribute attr in mi.GetCustomAttributes(true))
|
||||
{
|
||||
if (attr is XmlRpcExposedAttribute)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
150
Programs/SLProxy/XmlRpcCS/XmlRpcRequest.cs
Normal file
150
Programs/SLProxy/XmlRpcCS/XmlRpcRequest.cs
Normal file
@@ -0,0 +1,150 @@
|
||||
namespace Nwc.XmlRpc
|
||||
{
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using System.Xml;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Reflection;
|
||||
using System.Net.Security;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
|
||||
internal class AcceptAllCertificatePolicy : ICertificatePolicy
|
||||
{
|
||||
public AcceptAllCertificatePolicy()
|
||||
{
|
||||
}
|
||||
|
||||
public bool CheckValidationResult(ServicePoint sPoint,
|
||||
System.Security.Cryptography.X509Certificates.X509Certificate cert,
|
||||
WebRequest wRequest, int certProb)
|
||||
{
|
||||
// Always accept
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Class supporting the request side of an XML-RPC transaction.</summary>
|
||||
public class XmlRpcRequest
|
||||
{
|
||||
private String _methodName = null;
|
||||
private Encoding _encoding = new ASCIIEncoding();
|
||||
private XmlRpcRequestSerializer _serializer = new XmlRpcRequestSerializer();
|
||||
private XmlRpcResponseDeserializer _deserializer = new XmlRpcResponseDeserializer();
|
||||
|
||||
/// <summary><c>ArrayList</c> containing the parameters.</summary>
|
||||
protected IList _params = null;
|
||||
|
||||
/// <summary>Instantiate an <c>XmlRpcRequest</c></summary>
|
||||
public XmlRpcRequest()
|
||||
{
|
||||
_params = new ArrayList();
|
||||
}
|
||||
|
||||
/// <summary>Instantiate an <c>XmlRpcRequest</c> for a specified method and parameters.</summary>
|
||||
/// <param name="methodName"><c>String</c> designating the <i>object.method</i> on the server the request
|
||||
/// should be directed to.</param>
|
||||
/// <param name="parameters"><c>ArrayList</c> of XML-RPC type parameters to invoke the request with.</param>
|
||||
public XmlRpcRequest(String methodName, IList parameters)
|
||||
{
|
||||
MethodName = methodName;
|
||||
_params = parameters;
|
||||
}
|
||||
|
||||
/// <summary><c>ArrayList</c> conntaining the parameters for the request.</summary>
|
||||
public virtual IList Params
|
||||
{
|
||||
get { return _params; }
|
||||
}
|
||||
|
||||
/// <summary><c>String</c> conntaining the method name, both object and method, that the request will be sent to.</summary>
|
||||
public virtual String MethodName
|
||||
{
|
||||
get { return _methodName; }
|
||||
set { _methodName = value; }
|
||||
}
|
||||
|
||||
/// <summary><c>String</c> object name portion of the method name.</summary>
|
||||
public String MethodNameObject
|
||||
{
|
||||
get
|
||||
{
|
||||
int index = MethodName.IndexOf(".");
|
||||
|
||||
if (index == -1)
|
||||
return MethodName;
|
||||
|
||||
return MethodName.Substring(0, index);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary><c>String</c> method name portion of the object.method name.</summary>
|
||||
public String MethodNameMethod
|
||||
{
|
||||
get
|
||||
{
|
||||
int index = MethodName.IndexOf(".");
|
||||
|
||||
if (index == -1)
|
||||
return MethodName;
|
||||
|
||||
return MethodName.Substring(index + 1, MethodName.Length - index - 1);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Invoke this request on the server.</summary>
|
||||
/// <param name="url"><c>String</c> The url of the XML-RPC server.</param>
|
||||
/// <returns><c>Object</c> The value returned from the method invocation on the server.</returns>
|
||||
/// <exception cref="XmlRpcException">If an exception generated on the server side.</exception>
|
||||
public Object Invoke(String url)
|
||||
{
|
||||
XmlRpcResponse res = Send(url, 10000);
|
||||
|
||||
if (res.IsFault)
|
||||
throw new XmlRpcException(res.FaultCode, res.FaultString);
|
||||
|
||||
return res.Value;
|
||||
}
|
||||
|
||||
/// <summary>Send the request to the server.</summary>
|
||||
/// <param name="url"><c>String</c> The url of the XML-RPC server.</param>
|
||||
/// <param name="timeout">Milliseconds before the connection times out.</param>
|
||||
/// <returns><c>XmlRpcResponse</c> The response generated.</returns>
|
||||
public XmlRpcResponse Send(String url, int timeout)
|
||||
{
|
||||
// Override SSL authentication mechanisms
|
||||
ServicePointManager.CertificatePolicy = new AcceptAllCertificatePolicy();
|
||||
|
||||
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
|
||||
if (request == null)
|
||||
throw new XmlRpcException(XmlRpcErrorCodes.TRANSPORT_ERROR,
|
||||
XmlRpcErrorCodes.TRANSPORT_ERROR_MSG + ": Could not create request with " + url);
|
||||
request.Method = "POST";
|
||||
request.ContentType = "text/xml";
|
||||
request.AllowWriteStreamBuffering = true;
|
||||
request.Timeout = timeout;
|
||||
|
||||
Stream stream = request.GetRequestStream();
|
||||
XmlTextWriter xml = new XmlTextWriter(stream, _encoding);
|
||||
_serializer.Serialize(xml, this);
|
||||
xml.Flush();
|
||||
xml.Close();
|
||||
|
||||
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
|
||||
StreamReader input = new StreamReader(response.GetResponseStream());
|
||||
|
||||
XmlRpcResponse resp = (XmlRpcResponse)_deserializer.Deserialize(input);
|
||||
input.Close();
|
||||
response.Close();
|
||||
return resp;
|
||||
}
|
||||
|
||||
/// <summary>Produce <c>String</c> representation of the object.</summary>
|
||||
/// <returns><c>String</c> representation of the object.</returns>
|
||||
override public String ToString()
|
||||
{
|
||||
return _serializer.Serialize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
64
Programs/SLProxy/XmlRpcCS/XmlRpcRequestDeserializer.cs
Normal file
64
Programs/SLProxy/XmlRpcCS/XmlRpcRequestDeserializer.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
namespace Nwc.XmlRpc
|
||||
{
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Xml;
|
||||
|
||||
/// <summary>Class to deserialize XML data representing a request.</summary>
|
||||
public class XmlRpcRequestDeserializer : XmlRpcDeserializer
|
||||
{
|
||||
static private XmlRpcRequestDeserializer _singleton;
|
||||
/// <summary>A static singleton instance of this deserializer.</summary>
|
||||
[Obsolete("This object is now thread safe, just use an instance.", false)]
|
||||
static public XmlRpcRequestDeserializer Singleton
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_singleton == null)
|
||||
_singleton = new XmlRpcRequestDeserializer();
|
||||
|
||||
return _singleton;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Static method that parses XML data into a request using the Singleton.</summary>
|
||||
/// <param name="xmlData"><c>StreamReader</c> containing an XML-RPC request.</param>
|
||||
/// <returns><c>XmlRpcRequest</c> object resulting from the parse.</returns>
|
||||
override public Object Deserialize(TextReader xmlData)
|
||||
{
|
||||
XmlTextReader reader = new XmlTextReader(xmlData);
|
||||
XmlRpcRequest request = new XmlRpcRequest();
|
||||
bool done = false;
|
||||
|
||||
lock (this)
|
||||
{
|
||||
Reset();
|
||||
while (!done && reader.Read())
|
||||
{
|
||||
DeserializeNode(reader); // Parent parse...
|
||||
switch (reader.NodeType)
|
||||
{
|
||||
case XmlNodeType.EndElement:
|
||||
switch (reader.Name)
|
||||
{
|
||||
case METHOD_NAME:
|
||||
request.MethodName = _text;
|
||||
break;
|
||||
case METHOD_CALL:
|
||||
done = true;
|
||||
break;
|
||||
case PARAM:
|
||||
request.Params.Add(_value);
|
||||
_text = null;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return request;
|
||||
}
|
||||
}
|
||||
}
|
||||
51
Programs/SLProxy/XmlRpcCS/XmlRpcRequestSerializer.cs
Normal file
51
Programs/SLProxy/XmlRpcCS/XmlRpcRequestSerializer.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
namespace Nwc.XmlRpc
|
||||
{
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Xml;
|
||||
using System.IO;
|
||||
|
||||
/// <summary>Class responsible for serializing an XML-RPC request.</summary>
|
||||
/// <remarks>This class handles the request envelope, depending on <c>XmlRpcSerializer</c>
|
||||
/// to serialize the payload.</remarks>
|
||||
/// <seealso cref="XmlRpcSerializer"/>
|
||||
public class XmlRpcRequestSerializer : XmlRpcSerializer
|
||||
{
|
||||
static private XmlRpcRequestSerializer _singleton;
|
||||
/// <summary>A static singleton instance of this deserializer.</summary>
|
||||
static public XmlRpcRequestSerializer Singleton
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_singleton == null)
|
||||
_singleton = new XmlRpcRequestSerializer();
|
||||
|
||||
return _singleton;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Serialize the <c>XmlRpcRequest</c> to the output stream.</summary>
|
||||
/// <param name="output">An <c>XmlTextWriter</c> stream to write data to.</param>
|
||||
/// <param name="obj">An <c>XmlRpcRequest</c> to serialize.</param>
|
||||
/// <seealso cref="XmlRpcRequest"/>
|
||||
override public void Serialize(XmlTextWriter output, Object obj)
|
||||
{
|
||||
XmlRpcRequest request = (XmlRpcRequest)obj;
|
||||
output.WriteStartDocument();
|
||||
output.WriteStartElement(METHOD_CALL);
|
||||
output.WriteElementString(METHOD_NAME, request.MethodName);
|
||||
output.WriteStartElement(PARAMS);
|
||||
foreach (Object param in request.Params)
|
||||
{
|
||||
output.WriteStartElement(PARAM);
|
||||
output.WriteStartElement(VALUE);
|
||||
SerializeObject(output, param);
|
||||
output.WriteEndElement();
|
||||
output.WriteEndElement();
|
||||
}
|
||||
|
||||
output.WriteEndElement();
|
||||
output.WriteEndElement();
|
||||
}
|
||||
}
|
||||
}
|
||||
98
Programs/SLProxy/XmlRpcCS/XmlRpcResponder.cs
Normal file
98
Programs/SLProxy/XmlRpcCS/XmlRpcResponder.cs
Normal file
@@ -0,0 +1,98 @@
|
||||
namespace Nwc.XmlRpc
|
||||
{
|
||||
using System;
|
||||
using System.Xml;
|
||||
using System.Net.Sockets;
|
||||
|
||||
/// <summary>The class is a container of the context of an XML-RPC dialog on the server side.</summary>
|
||||
/// <remarks>Instances of this class maintain the context for an individual XML-RPC server
|
||||
/// side dialog. Namely they manage an inbound deserializer and an outbound serializer. </remarks>
|
||||
public class XmlRpcResponder
|
||||
{
|
||||
private XmlRpcRequestDeserializer _deserializer = new XmlRpcRequestDeserializer();
|
||||
private XmlRpcResponseSerializer _serializer = new XmlRpcResponseSerializer();
|
||||
private XmlRpcServer _server;
|
||||
private TcpClient _client;
|
||||
private SimpleHttpRequest _httpReq;
|
||||
|
||||
/// <summary>The SimpleHttpRequest based on the TcpClient.</summary>
|
||||
public SimpleHttpRequest HttpReq
|
||||
{
|
||||
get { return _httpReq; }
|
||||
}
|
||||
|
||||
/// <summary>Basic constructor.</summary>
|
||||
/// <param name="server">XmlRpcServer that this XmlRpcResponder services.</param>
|
||||
/// <param name="client">TcpClient with the connection.</param>
|
||||
public XmlRpcResponder(XmlRpcServer server, TcpClient client)
|
||||
{
|
||||
_server = server;
|
||||
_client = client;
|
||||
_httpReq = new SimpleHttpRequest(_client);
|
||||
}
|
||||
|
||||
/// <summary>Call close to insure proper shutdown.</summary>
|
||||
~XmlRpcResponder()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
///<summary>Respond using this responders HttpReq.</summary>
|
||||
public void Respond()
|
||||
{
|
||||
Respond(HttpReq);
|
||||
}
|
||||
|
||||
/// <summary>Handle an HTTP request containing an XML-RPC request.</summary>
|
||||
/// <remarks>This method deserializes the XML-RPC request, invokes the
|
||||
/// described method, serializes the response (or fault) and sends the XML-RPC response
|
||||
/// back as a valid HTTP page.
|
||||
/// </remarks>
|
||||
/// <param name="httpReq"><c>SimpleHttpRequest</c> containing the request.</param>
|
||||
public void Respond(SimpleHttpRequest httpReq)
|
||||
{
|
||||
XmlRpcRequest xmlRpcReq = (XmlRpcRequest)_deserializer.Deserialize(httpReq.Input);
|
||||
XmlRpcResponse xmlRpcResp = new XmlRpcResponse();
|
||||
|
||||
try
|
||||
{
|
||||
xmlRpcResp.Value = _server.Invoke(xmlRpcReq);
|
||||
}
|
||||
catch (XmlRpcException e)
|
||||
{
|
||||
xmlRpcResp.SetFault(e.FaultCode, e.FaultString);
|
||||
}
|
||||
catch (Exception e2)
|
||||
{
|
||||
xmlRpcResp.SetFault(XmlRpcErrorCodes.APPLICATION_ERROR,
|
||||
XmlRpcErrorCodes.APPLICATION_ERROR_MSG + ": " + e2.Message);
|
||||
}
|
||||
|
||||
if (Logger.Delegate != null)
|
||||
Logger.WriteEntry(xmlRpcResp.ToString(), LogLevel.Information);
|
||||
|
||||
XmlRpcServer.HttpHeader(httpReq.Protocol, "text/xml", 0, " 200 OK", httpReq.Output);
|
||||
httpReq.Output.Flush();
|
||||
XmlTextWriter xml = new XmlTextWriter(httpReq.Output);
|
||||
_serializer.Serialize(xml, xmlRpcResp);
|
||||
xml.Flush();
|
||||
httpReq.Output.Flush();
|
||||
}
|
||||
|
||||
///<summary>Close all contained resources, both the HttpReq and client.</summary>
|
||||
public void Close()
|
||||
{
|
||||
if (_httpReq != null)
|
||||
{
|
||||
_httpReq.Close();
|
||||
_httpReq = null;
|
||||
}
|
||||
|
||||
if (_client != null)
|
||||
{
|
||||
_client.Close();
|
||||
_client = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
85
Programs/SLProxy/XmlRpcCS/XmlRpcResponse.cs
Normal file
85
Programs/SLProxy/XmlRpcCS/XmlRpcResponse.cs
Normal file
@@ -0,0 +1,85 @@
|
||||
namespace Nwc.XmlRpc
|
||||
{
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using System.Xml;
|
||||
|
||||
/// <summary>Class designed to represent an XML-RPC response.</summary>
|
||||
public class XmlRpcResponse
|
||||
{
|
||||
private Object _value;
|
||||
/// <summary><c>bool</c> indicating if this response represents a fault.</summary>
|
||||
public bool IsFault;
|
||||
|
||||
/// <summary>Basic constructor</summary>
|
||||
public XmlRpcResponse()
|
||||
{
|
||||
Value = null;
|
||||
IsFault = false;
|
||||
}
|
||||
|
||||
/// <summary>Constructor for a fault.</summary>
|
||||
/// <param name="code"><c>int</c> the numeric faultCode value.</param>
|
||||
/// <param name="message"><c>String</c> the faultString value.</param>
|
||||
public XmlRpcResponse(int code, String message)
|
||||
: this()
|
||||
{
|
||||
SetFault(code, message);
|
||||
}
|
||||
|
||||
/// <summary>The data value of the response, may be fault data.</summary>
|
||||
public Object Value
|
||||
{
|
||||
get { return _value; }
|
||||
set
|
||||
{
|
||||
IsFault = false;
|
||||
_value = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>The faultCode if this is a fault.</summary>
|
||||
public int FaultCode
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!IsFault)
|
||||
return 0;
|
||||
else
|
||||
return (int)((Hashtable)_value)[XmlRpcXmlTokens.FAULT_CODE];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>The faultString if this is a fault.</summary>
|
||||
public String FaultString
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!IsFault)
|
||||
return "";
|
||||
else
|
||||
return (String)((Hashtable)_value)[XmlRpcXmlTokens.FAULT_STRING];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Set this response to be a fault.</summary>
|
||||
/// <param name="code"><c>int</c> the numeric faultCode value.</param>
|
||||
/// <param name="message"><c>String</c> the faultString value.</param>
|
||||
public void SetFault(int code, String message)
|
||||
{
|
||||
Hashtable fault = new Hashtable();
|
||||
fault.Add("faultCode", code);
|
||||
fault.Add("faultString", message);
|
||||
Value = fault;
|
||||
IsFault = true;
|
||||
}
|
||||
|
||||
/// <summary>Form a useful string representation of the object, in this case the XML response.</summary>
|
||||
/// <returns><c>String</c> The XML serialized XML-RPC response.</returns>
|
||||
override public String ToString()
|
||||
{
|
||||
return XmlRpcResponseSerializer.Singleton.Serialize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
65
Programs/SLProxy/XmlRpcCS/XmlRpcResponseDeserializer.cs
Normal file
65
Programs/SLProxy/XmlRpcCS/XmlRpcResponseDeserializer.cs
Normal file
@@ -0,0 +1,65 @@
|
||||
namespace Nwc.XmlRpc
|
||||
{
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using System.Xml;
|
||||
|
||||
/// <summary>Class to deserialize XML data representing a response.</summary>
|
||||
public class XmlRpcResponseDeserializer : XmlRpcDeserializer
|
||||
{
|
||||
static private XmlRpcResponseDeserializer _singleton;
|
||||
/// <summary>A static singleton instance of this deserializer.</summary>
|
||||
[Obsolete("This object is now thread safe, just use an instance.", false)]
|
||||
static public XmlRpcResponseDeserializer Singleton
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_singleton == null)
|
||||
_singleton = new XmlRpcResponseDeserializer();
|
||||
|
||||
return _singleton;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Static method that parses XML data into a response using the Singleton.</summary>
|
||||
/// <param name="xmlData"><c>StreamReader</c> containing an XML-RPC response.</param>
|
||||
/// <returns><c>XmlRpcResponse</c> object resulting from the parse.</returns>
|
||||
override public Object Deserialize(TextReader xmlData)
|
||||
{
|
||||
XmlTextReader reader = new XmlTextReader(xmlData);
|
||||
XmlRpcResponse response = new XmlRpcResponse();
|
||||
bool done = false;
|
||||
|
||||
lock (this)
|
||||
{
|
||||
Reset();
|
||||
|
||||
while (!done && reader.Read())
|
||||
{
|
||||
DeserializeNode(reader); // Parent parse...
|
||||
switch (reader.NodeType)
|
||||
{
|
||||
case XmlNodeType.EndElement:
|
||||
switch (reader.Name)
|
||||
{
|
||||
case FAULT:
|
||||
response.Value = _value;
|
||||
response.IsFault = true;
|
||||
break;
|
||||
case PARAM:
|
||||
response.Value = _value;
|
||||
_value = null;
|
||||
_text = null;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return response;
|
||||
}
|
||||
}
|
||||
}
|
||||
57
Programs/SLProxy/XmlRpcCS/XmlRpcResponseSerializer.cs
Normal file
57
Programs/SLProxy/XmlRpcCS/XmlRpcResponseSerializer.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
namespace Nwc.XmlRpc
|
||||
{
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Xml;
|
||||
|
||||
/// <summary>Class responsible for serializing an XML-RPC response.</summary>
|
||||
/// <remarks>This class handles the response envelope, depending on XmlRpcSerializer
|
||||
/// to serialize the payload.</remarks>
|
||||
/// <seealso cref="XmlRpcSerializer"/>
|
||||
public class XmlRpcResponseSerializer : XmlRpcSerializer
|
||||
{
|
||||
static private XmlRpcResponseSerializer _singleton;
|
||||
/// <summary>A static singleton instance of this deserializer.</summary>
|
||||
static public XmlRpcResponseSerializer Singleton
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_singleton == null)
|
||||
_singleton = new XmlRpcResponseSerializer();
|
||||
|
||||
return _singleton;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Serialize the <c>XmlRpcResponse</c> to the output stream.</summary>
|
||||
/// <param name="output">An <c>XmlTextWriter</c> stream to write data to.</param>
|
||||
/// <param name="obj">An <c>Object</c> to serialize.</param>
|
||||
/// <seealso cref="XmlRpcResponse"/>
|
||||
override public void Serialize(XmlTextWriter output, Object obj)
|
||||
{
|
||||
XmlRpcResponse response = (XmlRpcResponse)obj;
|
||||
|
||||
output.WriteStartDocument();
|
||||
output.WriteStartElement(METHOD_RESPONSE);
|
||||
|
||||
if (response.IsFault)
|
||||
output.WriteStartElement(FAULT);
|
||||
else
|
||||
{
|
||||
output.WriteStartElement(PARAMS);
|
||||
output.WriteStartElement(PARAM);
|
||||
}
|
||||
|
||||
output.WriteStartElement(VALUE);
|
||||
|
||||
SerializeObject(output, response.Value);
|
||||
|
||||
output.WriteEndElement();
|
||||
|
||||
output.WriteEndElement();
|
||||
if (!response.IsFault)
|
||||
output.WriteEndElement();
|
||||
output.WriteEndElement();
|
||||
}
|
||||
}
|
||||
}
|
||||
109
Programs/SLProxy/XmlRpcCS/XmlRpcSerializer.cs
Normal file
109
Programs/SLProxy/XmlRpcCS/XmlRpcSerializer.cs
Normal file
@@ -0,0 +1,109 @@
|
||||
namespace Nwc.XmlRpc
|
||||
{
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using System.Xml;
|
||||
|
||||
/// <summary>Base class of classes serializing data to XML-RPC's XML format.</summary>
|
||||
/// <remarks>This class handles the basic type conversions like Integer to <i4>. </remarks>
|
||||
/// <seealso cref="XmlRpcXmlTokens"/>
|
||||
public class XmlRpcSerializer : XmlRpcXmlTokens
|
||||
{
|
||||
|
||||
/// <summary>Serialize the <c>XmlRpcRequest</c> to the output stream.</summary>
|
||||
/// <param name="output">An <c>XmlTextWriter</c> stream to write data to.</param>
|
||||
/// <param name="obj">An <c>Object</c> to serialize.</param>
|
||||
/// <seealso cref="XmlRpcRequest"/>
|
||||
virtual public void Serialize(XmlTextWriter output, Object obj)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>Serialize the <c>XmlRpcRequest</c> to a String.</summary>
|
||||
/// <remarks>Note this may represent a real memory hog for a large request.</remarks>
|
||||
/// <param name="obj">An <c>Object</c> to serialize.</param>
|
||||
/// <returns><c>String</c> containing XML-RPC representation of the request.</returns>
|
||||
/// <seealso cref="XmlRpcRequest"/>
|
||||
public String Serialize(Object obj)
|
||||
{
|
||||
StringWriter strBuf = new StringWriter();
|
||||
XmlTextWriter xml = new XmlTextWriter(strBuf);
|
||||
xml.Formatting = Formatting.Indented;
|
||||
xml.Indentation = 4;
|
||||
Serialize(xml, obj);
|
||||
xml.Flush();
|
||||
String returns = strBuf.ToString();
|
||||
xml.Close();
|
||||
return returns;
|
||||
}
|
||||
|
||||
/// <remarks>Serialize the object to the output stream.</remarks>
|
||||
/// <param name="output">An <c>XmlTextWriter</c> stream to write data to.</param>
|
||||
/// <param name="obj">An <c>Object</c> to serialize.</param>
|
||||
public void SerializeObject(XmlTextWriter output, Object obj)
|
||||
{
|
||||
if (obj == null)
|
||||
return;
|
||||
|
||||
if (obj is byte[])
|
||||
{
|
||||
byte[] ba = (byte[])obj;
|
||||
output.WriteStartElement(BASE64);
|
||||
output.WriteBase64(ba, 0, ba.Length);
|
||||
output.WriteEndElement();
|
||||
}
|
||||
else if (obj is String)
|
||||
{
|
||||
output.WriteElementString(STRING, obj.ToString());
|
||||
}
|
||||
else if (obj is Int32)
|
||||
{
|
||||
output.WriteElementString(INT, obj.ToString());
|
||||
}
|
||||
else if (obj is DateTime)
|
||||
{
|
||||
output.WriteElementString(DATETIME, ((DateTime)obj).ToString(ISO_DATETIME));
|
||||
}
|
||||
else if (obj is Double)
|
||||
{
|
||||
output.WriteElementString(DOUBLE, obj.ToString());
|
||||
}
|
||||
else if (obj is Boolean)
|
||||
{
|
||||
output.WriteElementString(BOOLEAN, ((((Boolean)obj) == true) ? "1" : "0"));
|
||||
}
|
||||
else if (obj is IList)
|
||||
{
|
||||
output.WriteStartElement(ARRAY);
|
||||
output.WriteStartElement(DATA);
|
||||
if (((ArrayList)obj).Count > 0)
|
||||
{
|
||||
foreach (Object member in ((IList)obj))
|
||||
{
|
||||
output.WriteStartElement(VALUE);
|
||||
SerializeObject(output, member);
|
||||
output.WriteEndElement();
|
||||
}
|
||||
}
|
||||
output.WriteEndElement();
|
||||
output.WriteEndElement();
|
||||
}
|
||||
else if (obj is IDictionary)
|
||||
{
|
||||
IDictionary h = (IDictionary)obj;
|
||||
output.WriteStartElement(STRUCT);
|
||||
foreach (String key in h.Keys)
|
||||
{
|
||||
output.WriteStartElement(MEMBER);
|
||||
output.WriteElementString(NAME, key);
|
||||
output.WriteStartElement(VALUE);
|
||||
SerializeObject(output, h[key]);
|
||||
output.WriteEndElement();
|
||||
output.WriteEndElement();
|
||||
}
|
||||
output.WriteEndElement();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
239
Programs/SLProxy/XmlRpcCS/XmlRpcServer.cs
Normal file
239
Programs/SLProxy/XmlRpcCS/XmlRpcServer.cs
Normal file
@@ -0,0 +1,239 @@
|
||||
namespace Nwc.XmlRpc
|
||||
{
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Xml;
|
||||
|
||||
/// <summary>A restricted HTTP server for use with XML-RPC.</summary>
|
||||
/// <remarks>It only handles POST requests, and only POSTs representing XML-RPC calls.
|
||||
/// In addition to dispatching requests it also provides a registry for request handlers.
|
||||
/// </remarks>
|
||||
public class XmlRpcServer : IEnumerable
|
||||
{
|
||||
#pragma warning disable 0414 // disable "private field assigned but not used"
|
||||
const int RESPONDER_COUNT = 10;
|
||||
private TcpListener _myListener;
|
||||
private int _port;
|
||||
private IPAddress _address;
|
||||
private IDictionary _handlers;
|
||||
private XmlRpcSystemObject _system;
|
||||
private WaitCallback _wc;
|
||||
#pragma warning restore 0414
|
||||
|
||||
///<summary>Constructor with port and address.</summary>
|
||||
///<remarks>This constructor sets up a TcpListener listening on the
|
||||
///given port and address. It also calls a Thread on the method StartListen().</remarks>
|
||||
///<param name="address"><c>IPAddress</c> value of the address to listen on.</param>
|
||||
///<param name="port"><c>Int</c> value of the port to listen on.</param>
|
||||
public XmlRpcServer(IPAddress address, int port)
|
||||
{
|
||||
_port = port;
|
||||
_address = address;
|
||||
_handlers = new Hashtable();
|
||||
_system = new XmlRpcSystemObject(this);
|
||||
_wc = new WaitCallback(WaitCallback);
|
||||
}
|
||||
|
||||
///<summary>Basic constructor.</summary>
|
||||
///<remarks>This constructor sets up a TcpListener listening on the
|
||||
///given port. It also calls a Thread on the method StartListen(). IPAddress.Any
|
||||
///is assumed as the address here.</remarks>
|
||||
///<param name="port"><c>Int</c> value of the port to listen on.</param>
|
||||
public XmlRpcServer(int port) : this(IPAddress.Any, port) { }
|
||||
|
||||
/// <summary>Start the server.</summary>
|
||||
public void Start()
|
||||
{
|
||||
try
|
||||
{
|
||||
Stop();
|
||||
//start listing on the given port
|
||||
// IPAddress addr = IPAddress.Parse("127.0.0.1");
|
||||
lock (this)
|
||||
{
|
||||
_myListener = new TcpListener(IPAddress.Any, _port);
|
||||
_myListener.Start();
|
||||
//start the thread which calls the method 'StartListen'
|
||||
Thread th = new Thread(new ThreadStart(StartListen));
|
||||
th.Start();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.WriteEntry("An Exception Occurred while Listening :" + e.ToString(), LogLevel.Error);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Stop the server.</summary>
|
||||
public void Stop()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_myListener != null)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
_myListener.Stop();
|
||||
_myListener = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.WriteEntry("An Exception Occurred while stopping :" +
|
||||
e.ToString(), LogLevel.Error);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Get an enumeration of my XML-RPC handlers.</summary>
|
||||
/// <returns><c>IEnumerable</c> the handler enumeration.</returns>
|
||||
public IEnumerator GetEnumerator()
|
||||
{
|
||||
return _handlers.GetEnumerator();
|
||||
}
|
||||
|
||||
/// <summary>Retrieve a handler by name.</summary>
|
||||
/// <param name="name"><c>String</c> naming a handler</param>
|
||||
/// <returns><c>Object</c> that is the handler.</returns>
|
||||
public Object this[String name]
|
||||
{
|
||||
get { return _handlers[name]; }
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///This method Accepts new connections and dispatches them when appropriate.
|
||||
///</summary>
|
||||
public void StartListen()
|
||||
{
|
||||
while (true && _myListener != null)
|
||||
{
|
||||
//Accept a new connection
|
||||
XmlRpcResponder responder = new XmlRpcResponder(this, _myListener.AcceptTcpClient());
|
||||
ThreadPool.QueueUserWorkItem(_wc, responder);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///<summary>
|
||||
///Add an XML-RPC handler object by name.
|
||||
///</summary>
|
||||
///<param name="name"><c>String</c> XML-RPC dispatch name of this object.</param>
|
||||
///<param name="obj"><c>Object</c> The object that is the XML-RPC handler.</param>
|
||||
public void Add(String name, Object obj)
|
||||
{
|
||||
_handlers.Add(name, obj);
|
||||
}
|
||||
|
||||
///<summary>Return a C# object.method name for and XML-RPC object.method name pair.</summary>
|
||||
///<param name="methodName">The XML-RPC object.method.</param>
|
||||
///<returns><c>String</c> of form object.method for the underlying C# method.</returns>
|
||||
public String MethodName(String methodName)
|
||||
{
|
||||
int dotAt = methodName.LastIndexOf('.');
|
||||
|
||||
if (dotAt == -1)
|
||||
{
|
||||
throw new XmlRpcException(XmlRpcErrorCodes.SERVER_ERROR_METHOD,
|
||||
XmlRpcErrorCodes.SERVER_ERROR_METHOD_MSG + ": Bad method name " + methodName);
|
||||
}
|
||||
|
||||
String objectName = methodName.Substring(0, dotAt);
|
||||
Object target = _handlers[objectName];
|
||||
|
||||
if (target == null)
|
||||
{
|
||||
throw new XmlRpcException(XmlRpcErrorCodes.SERVER_ERROR_METHOD,
|
||||
XmlRpcErrorCodes.SERVER_ERROR_METHOD_MSG + ": Object " + objectName + " not found");
|
||||
}
|
||||
|
||||
return target.GetType().FullName + "." + methodName.Substring(dotAt + 1);
|
||||
}
|
||||
|
||||
///<summary>Invoke a method described in a request.</summary>
|
||||
///<param name="req"><c>XmlRpcRequest</c> containing a method descriptions.</param>
|
||||
/// <seealso cref="XmlRpcSystemObject.Invoke"/>
|
||||
/// <seealso cref="XmlRpcServer.Invoke(String,String,IList)"/>
|
||||
public Object Invoke(XmlRpcRequest req)
|
||||
{
|
||||
return Invoke(req.MethodNameObject, req.MethodNameMethod, req.Params);
|
||||
}
|
||||
|
||||
///<summary>Invoke a method on a named handler.</summary>
|
||||
///<param name="objectName"><c>String</c> The name of the handler.</param>
|
||||
///<param name="methodName"><c>String</c> The name of the method to invoke on the handler.</param>
|
||||
///<param name="parameters"><c>IList</c> The parameters to invoke the method with.</param>
|
||||
/// <seealso cref="XmlRpcSystemObject.Invoke"/>
|
||||
public Object Invoke(String objectName, String methodName, IList parameters)
|
||||
{
|
||||
Object target = _handlers[objectName];
|
||||
|
||||
if (target == null)
|
||||
{
|
||||
throw new XmlRpcException(XmlRpcErrorCodes.SERVER_ERROR_METHOD,
|
||||
XmlRpcErrorCodes.SERVER_ERROR_METHOD_MSG + ": Object " + objectName + " not found");
|
||||
}
|
||||
|
||||
return XmlRpcSystemObject.Invoke(target, methodName, parameters);
|
||||
}
|
||||
|
||||
/// <summary>The method the thread pool invokes when a thread is available to handle an HTTP request.</summary>
|
||||
/// <param name="responder">TcpClient from the socket accept.</param>
|
||||
public void WaitCallback(object responder)
|
||||
{
|
||||
XmlRpcResponder resp = (XmlRpcResponder)responder;
|
||||
|
||||
if (resp.HttpReq.HttpMethod == "POST")
|
||||
{
|
||||
try
|
||||
{
|
||||
resp.Respond();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.WriteEntry("Failed on post: " + e, LogLevel.Error);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.WriteEntry("Only POST methods are supported: " + resp.HttpReq.HttpMethod +
|
||||
" ignored", LogLevel.Error);
|
||||
}
|
||||
|
||||
resp.Close();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function send the Header Information to the client (Browser)
|
||||
/// </summary>
|
||||
/// <param name="sHttpVersion">HTTP Version</param>
|
||||
/// <param name="sMIMEHeader">Mime Type</param>
|
||||
/// <param name="iTotBytes">Total Bytes to be sent in the body</param>
|
||||
/// <param name="sStatusCode"></param>
|
||||
/// <param name="output">Socket reference</param>
|
||||
static public void HttpHeader(string sHttpVersion, string sMIMEHeader, long iTotBytes, string sStatusCode, TextWriter output)
|
||||
{
|
||||
String sBuffer = "";
|
||||
|
||||
// if Mime type is not provided set default to text/html
|
||||
if (sMIMEHeader.Length == 0)
|
||||
{
|
||||
sMIMEHeader = "text/html"; // Default Mime Type is text/html
|
||||
}
|
||||
|
||||
sBuffer += sHttpVersion + sStatusCode + "\r\n";
|
||||
sBuffer += "Connection: close\r\n";
|
||||
if (iTotBytes > 0)
|
||||
sBuffer += "Content-Length: " + iTotBytes + "\r\n";
|
||||
sBuffer += "Server: XmlRpcServer \r\n";
|
||||
sBuffer += "Content-Type: " + sMIMEHeader + "\r\n";
|
||||
sBuffer += "\r\n";
|
||||
|
||||
output.Write(sBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
252
Programs/SLProxy/XmlRpcCS/XmlRpcSystemObject.cs
Normal file
252
Programs/SLProxy/XmlRpcCS/XmlRpcSystemObject.cs
Normal file
@@ -0,0 +1,252 @@
|
||||
namespace Nwc.XmlRpc
|
||||
{
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
|
||||
/// <summary> XML-RPC System object implementation of extended specifications.</summary>
|
||||
[XmlRpcExposed]
|
||||
public class XmlRpcSystemObject
|
||||
{
|
||||
private XmlRpcServer _server;
|
||||
static private IDictionary _methodHelp = new Hashtable();
|
||||
|
||||
/// <summary>Static <c>IDictionary</c> to hold mappings of method name to associated documentation String</summary>
|
||||
static public IDictionary MethodHelp
|
||||
{
|
||||
get { return _methodHelp; }
|
||||
}
|
||||
|
||||
/// <summary>Constructor.</summary>
|
||||
/// <param name="server"><c>XmlRpcServer</c> server to be the system object for.</param>
|
||||
public XmlRpcSystemObject(XmlRpcServer server)
|
||||
{
|
||||
_server = server;
|
||||
server.Add("system", this);
|
||||
_methodHelp.Add(this.GetType().FullName + ".methodHelp", "Return a string description.");
|
||||
}
|
||||
|
||||
/// <summary>Invoke a method on a given object.</summary>
|
||||
/// <remarks>Using reflection, and respecting the <c>XmlRpcExposed</c> attribute,
|
||||
/// invoke the <paramref>methodName</paramref> method on the <paramref>target</paramref>
|
||||
/// instance with the <paramref>parameters</paramref> provided. All this packages other <c>Invoke</c> methods
|
||||
/// end up calling this.</remarks>
|
||||
/// <returns><c>Object</c> the value the invoked method returns.</returns>
|
||||
/// <exception cref="XmlRpcException">If method does not exist, is not exposed, parameters invalid, or invocation
|
||||
/// results in an exception. Note, the <c>XmlRpcException.Code</c> will indicate cause.</exception>
|
||||
static public Object Invoke(Object target, String methodName, IList parameters)
|
||||
{
|
||||
if (target == null)
|
||||
throw new XmlRpcException(XmlRpcErrorCodes.SERVER_ERROR_METHOD,
|
||||
XmlRpcErrorCodes.SERVER_ERROR_METHOD_MSG + ": Invalid target object.");
|
||||
|
||||
Type type = target.GetType();
|
||||
MethodInfo method = type.GetMethod(methodName);
|
||||
|
||||
try
|
||||
{
|
||||
if (!XmlRpcExposedAttribute.ExposedMethod(target, methodName))
|
||||
throw new XmlRpcException(XmlRpcErrorCodes.SERVER_ERROR_METHOD,
|
||||
XmlRpcErrorCodes.SERVER_ERROR_METHOD_MSG + ": Method " + methodName + " is not exposed.");
|
||||
}
|
||||
catch (MissingMethodException me)
|
||||
{
|
||||
throw new XmlRpcException(XmlRpcErrorCodes.SERVER_ERROR_METHOD,
|
||||
XmlRpcErrorCodes.SERVER_ERROR_METHOD_MSG + ": " + me.Message);
|
||||
}
|
||||
|
||||
Object[] args = new Object[parameters.Count];
|
||||
|
||||
int index = 0;
|
||||
foreach (Object arg in parameters)
|
||||
{
|
||||
args[index] = arg;
|
||||
index++;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Object retValue = method.Invoke(target, args);
|
||||
if (retValue == null)
|
||||
throw new XmlRpcException(XmlRpcErrorCodes.APPLICATION_ERROR,
|
||||
XmlRpcErrorCodes.APPLICATION_ERROR_MSG + ": Method returned NULL.");
|
||||
return retValue;
|
||||
}
|
||||
catch (XmlRpcException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch (ArgumentException ae)
|
||||
{
|
||||
Logger.WriteEntry(XmlRpcErrorCodes.SERVER_ERROR_PARAMS_MSG + ": " + ae.Message,
|
||||
LogLevel.Information);
|
||||
String call = methodName + "( ";
|
||||
foreach (Object o in args)
|
||||
{
|
||||
call += o.GetType().Name;
|
||||
call += " ";
|
||||
}
|
||||
call += ")";
|
||||
throw new XmlRpcException(XmlRpcErrorCodes.SERVER_ERROR_PARAMS,
|
||||
XmlRpcErrorCodes.SERVER_ERROR_PARAMS_MSG + ": Arguement type mismatch invoking " + call);
|
||||
}
|
||||
catch (TargetParameterCountException tpce)
|
||||
{
|
||||
Logger.WriteEntry(XmlRpcErrorCodes.SERVER_ERROR_PARAMS_MSG + ": " + tpce.Message,
|
||||
LogLevel.Information);
|
||||
throw new XmlRpcException(XmlRpcErrorCodes.SERVER_ERROR_PARAMS,
|
||||
XmlRpcErrorCodes.SERVER_ERROR_PARAMS_MSG + ": Arguement count mismatch invoking " + methodName);
|
||||
}
|
||||
catch (TargetInvocationException tie)
|
||||
{
|
||||
throw new XmlRpcException(XmlRpcErrorCodes.APPLICATION_ERROR,
|
||||
XmlRpcErrorCodes.APPLICATION_ERROR_MSG + " Invoked method " + methodName + ": " + tie.Message);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>List methods available on all handlers of this server.</summary>
|
||||
/// <returns><c>IList</c> An array of <c>Strings</c>, each <c>String</c> will have form "object.method".</returns>
|
||||
[XmlRpcExposed]
|
||||
public IList listMethods()
|
||||
{
|
||||
IList methods = new ArrayList();
|
||||
Boolean considerExposure;
|
||||
|
||||
foreach (DictionaryEntry handlerEntry in _server)
|
||||
{
|
||||
considerExposure = XmlRpcExposedAttribute.IsExposed(handlerEntry.Value.GetType());
|
||||
|
||||
foreach (MemberInfo mi in handlerEntry.Value.GetType().GetMembers())
|
||||
{
|
||||
if (mi.MemberType != MemberTypes.Method)
|
||||
continue;
|
||||
|
||||
if (!((MethodInfo)mi).IsPublic)
|
||||
continue;
|
||||
|
||||
if (considerExposure && !XmlRpcExposedAttribute.IsExposed(mi))
|
||||
continue;
|
||||
|
||||
methods.Add(handlerEntry.Key + "." + mi.Name);
|
||||
}
|
||||
}
|
||||
|
||||
return methods;
|
||||
}
|
||||
|
||||
/// <summary>Given a method name return the possible signatures for it.</summary>
|
||||
/// <param name="name"><c>String</c> The object.method name to look up.</param>
|
||||
/// <returns><c>IList</c> Of arrays of signatures.</returns>
|
||||
[XmlRpcExposed]
|
||||
public IList methodSignature(String name)
|
||||
{
|
||||
IList signatures = new ArrayList();
|
||||
int index = name.IndexOf('.');
|
||||
|
||||
if (index < 0)
|
||||
return signatures;
|
||||
|
||||
String oName = name.Substring(0, index);
|
||||
Object obj = _server[oName];
|
||||
|
||||
if (obj == null)
|
||||
return signatures;
|
||||
|
||||
MemberInfo[] mi = obj.GetType().GetMember(name.Substring(index + 1));
|
||||
|
||||
if (mi == null || mi.Length != 1) // for now we want a single signature
|
||||
return signatures;
|
||||
|
||||
MethodInfo method;
|
||||
|
||||
try
|
||||
{
|
||||
method = (MethodInfo)mi[0];
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.WriteEntry("Attempted methodSignature call on " + mi[0] + " caused: " + e,
|
||||
LogLevel.Information);
|
||||
return signatures;
|
||||
}
|
||||
|
||||
if (!method.IsPublic)
|
||||
return signatures;
|
||||
|
||||
IList signature = new ArrayList();
|
||||
signature.Add(method.ReturnType.Name);
|
||||
|
||||
foreach (ParameterInfo param in method.GetParameters())
|
||||
{
|
||||
signature.Add(param.ParameterType.Name);
|
||||
}
|
||||
|
||||
|
||||
signatures.Add(signature);
|
||||
|
||||
return signatures;
|
||||
}
|
||||
|
||||
/// <summary>Help for given method signature. Not implemented yet.</summary>
|
||||
/// <param name="name"><c>String</c> The object.method name to look up.</param>
|
||||
/// <returns><c>String</c> help text. Rich HTML text.</returns>
|
||||
[XmlRpcExposed]
|
||||
public String methodHelp(String name)
|
||||
{
|
||||
String help = null;
|
||||
|
||||
try
|
||||
{
|
||||
help = (String)_methodHelp[_server.MethodName(name)];
|
||||
}
|
||||
catch (XmlRpcException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch (Exception) { /* ignored */ };
|
||||
|
||||
if (help == null)
|
||||
help = "No help available for: " + name;
|
||||
|
||||
return help;
|
||||
}
|
||||
|
||||
/// <summary>Boxcarring support method.</summary>
|
||||
/// <param name="calls"><c>IList</c> of calls</param>
|
||||
/// <returns><c>ArrayList</c> of results/faults.</returns>
|
||||
[XmlRpcExposed]
|
||||
public IList multiCall(IList calls)
|
||||
{
|
||||
IList responses = new ArrayList();
|
||||
XmlRpcResponse fault = new XmlRpcResponse();
|
||||
|
||||
foreach (IDictionary call in calls)
|
||||
{
|
||||
try
|
||||
{
|
||||
XmlRpcRequest req = new XmlRpcRequest((String)call[XmlRpcXmlTokens.METHOD_NAME],
|
||||
(ArrayList)call[XmlRpcXmlTokens.PARAMS]);
|
||||
Object results = _server.Invoke(req);
|
||||
IList response = new ArrayList();
|
||||
response.Add(results);
|
||||
responses.Add(response);
|
||||
}
|
||||
catch (XmlRpcException e)
|
||||
{
|
||||
fault.SetFault(e.FaultCode, e.FaultString);
|
||||
responses.Add(fault.Value);
|
||||
}
|
||||
catch (Exception e2)
|
||||
{
|
||||
fault.SetFault(XmlRpcErrorCodes.APPLICATION_ERROR,
|
||||
XmlRpcErrorCodes.APPLICATION_ERROR_MSG + ": " + e2.Message);
|
||||
responses.Add(fault.Value);
|
||||
}
|
||||
}
|
||||
|
||||
return responses;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
76
Programs/SLProxy/XmlRpcCS/XmlRpcXmlTokens.cs
Normal file
76
Programs/SLProxy/XmlRpcCS/XmlRpcXmlTokens.cs
Normal file
@@ -0,0 +1,76 @@
|
||||
namespace Nwc.XmlRpc
|
||||
{
|
||||
using System;
|
||||
|
||||
/// <summary>Class collecting <c>String</c> tokens that are part of XML-RPC files.</summary>
|
||||
public class XmlRpcXmlTokens
|
||||
{
|
||||
/// <summary>C# formatting string to describe an ISO 8601 date.</summary>
|
||||
public const String ISO_DATETIME = "yyyyMMdd\\THH\\:mm\\:ss";
|
||||
/// <summary>Base64 field indicator.</summary>
|
||||
/// <remarks>Corresponds to the <base64> tag.</remarks>
|
||||
public const String BASE64 = "base64";
|
||||
/// <summary>String field indicator.</summary>
|
||||
/// <remarks>Corresponds to the <string> tag.</remarks>
|
||||
public const String STRING = "string";
|
||||
/// <summary>Integer field integer.</summary>
|
||||
/// <remarks>Corresponds to the <i4> tag.</remarks>
|
||||
public const String INT = "i4";
|
||||
/// <summary>Alternate integer field indicator.</summary>
|
||||
/// <remarks>Corresponds to the <int> tag.</remarks>
|
||||
public const String ALT_INT = "int";
|
||||
/// <summary>Date field indicator.</summary>
|
||||
/// <remarks>Corresponds to the <dateTime.iso8601> tag.</remarks>
|
||||
public const String DATETIME = "dateTime.iso8601";
|
||||
/// <summary>Boolean field indicator.</summary>
|
||||
/// <remarks>Corresponds to the <boolean> tag.</remarks>
|
||||
public const String BOOLEAN = "boolean";
|
||||
/// <summary>Value token.</summary>
|
||||
/// <remarks>Corresponds to the <value> tag.</remarks>
|
||||
public const String VALUE = "value";
|
||||
/// <summary>Name token.</summary>
|
||||
/// <remarks>Corresponds to the <name> tag.</remarks>
|
||||
public const String NAME = "name";
|
||||
/// <summary>Array field indicator..</summary>
|
||||
/// <remarks>Corresponds to the <array> tag.</remarks>
|
||||
public const String ARRAY = "array";
|
||||
/// <summary>Data token.</summary>
|
||||
/// <remarks>Corresponds to the <data> tag.</remarks>
|
||||
public const String DATA = "data";
|
||||
/// <summary>Member token.</summary>
|
||||
/// <remarks>Corresponds to the <member> tag.</remarks>
|
||||
public const String MEMBER = "member";
|
||||
/// <summary>Stuct field indicator.</summary>
|
||||
/// <remarks>Corresponds to the <struct> tag.</remarks>
|
||||
public const String STRUCT = "struct";
|
||||
/// <summary>Double field indicator.</summary>
|
||||
/// <remarks>Corresponds to the <double> tag.</remarks>
|
||||
public const String DOUBLE = "double";
|
||||
/// <summary>Param token.</summary>
|
||||
/// <remarks>Corresponds to the <param> tag.</remarks>
|
||||
public const String PARAM = "param";
|
||||
/// <summary>Params token.</summary>
|
||||
/// <remarks>Corresponds to the <params> tag.</remarks>
|
||||
public const String PARAMS = "params";
|
||||
/// <summary>MethodCall token.</summary>
|
||||
/// <remarks>Corresponds to the <methodCall> tag.</remarks>
|
||||
public const String METHOD_CALL = "methodCall";
|
||||
/// <summary>MethodName token.</summary>
|
||||
/// <remarks>Corresponds to the <methodName> tag.</remarks>
|
||||
public const String METHOD_NAME = "methodName";
|
||||
/// <summary>MethodResponse token</summary>
|
||||
/// <remarks>Corresponds to the <methodResponse> tag.</remarks>
|
||||
public const String METHOD_RESPONSE = "methodResponse";
|
||||
/// <summary>Fault response token.</summary>
|
||||
/// <remarks>Corresponds to the <fault> tag.</remarks>
|
||||
public const String FAULT = "fault";
|
||||
/// <summary>FaultCode token.</summary>
|
||||
/// <remarks>Corresponds to the <faultCode> tag.</remarks>
|
||||
public const String FAULT_CODE = "faultCode";
|
||||
/// <summary>FaultString token.</summary>
|
||||
/// <remarks>Corresponds to the <faultString> tag.</remarks>
|
||||
public const String FAULT_STRING = "faultString";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user