/**
* @author Ma Bingyao(andot@ujn.edu.cn)
* @copyright CoolCode.CN
* @package DOTNET_PHPRPC_CLIENT
* @version 2.1
* @last_update 2006-08-09
* @link http://www.coolcode.cn/?p=198
*
* Example usage:
*
using System;
using PHPRPC;
public class AddTest
{
public static void Main(string[] args) {
Client rpc = new Client();
rpc.UseService("http://test.coolcode.cn/phprpc_2.1/sample/server.php", true);
rpc.Encrypt = 2;
Console.WriteLine(rpc.Invoke("add", Int32.Parse(args[0]), Int32.Parse(args[1])).ToString());
}
}
*
*/
using System;
using System.IO;
using System.Collections;
using System.Text;
using System.Text.RegularExpressions;
using System.Net;
using Mono.Math;
namespace PHPRPC
{
public class Error
{
private int __errno;
private string __errstr;
internal Error(int errno, string errstr)
{
this.__errno = errno;
this.__errstr = errstr;
}
public int Number
{
get
{
return this.__errno;
}
}
public string Message
{
get
{
return this.__errstr;
}
}
public override string ToString()
{
return this.Message;
}
}
public class Client
{
private string __uri;
private Encoding __encoding;
private CookieCollection __cookies;
private string __output;
private byte __encrypt;
private Error __warning;
private byte[] __key;
private WebProxy __proxy;
private ICredentials __credentials;
public string Output
{
get
{
return __output;
}
}
public byte Encrypt
{
get
{
return __encrypt;
}
set
{
__encrypt = value;
}
}
public Error Warning
{
get
{
return __warning;
}
}
public WebProxy Proxy
{
get
{
return __proxy;
}
set
{
__proxy = value;
}
}
public ICredentials Credentials
{
get
{
return __credentials;
}
set
{
__credentials = value;
}
}
public Client()
{
__uri = null;
__cookies = null;
__proxy = null;
__key = null;
__encoding = null;
__output = "";
__encrypt = 0;
__warning = null;
}
public void SetProxy(string Address)
{
__proxy = new WebProxy(Address);
}
public void SetProxy(string Host, int Port)
{
__proxy = new WebProxy(Host, Port);
}
public bool UseService(string requestUriString)
{
return UseService(requestUriString, false);
}
public bool UseService(string requestUriString, bool encrypt)
{
this.__uri = requestUriString;
this.__warning = null;
this.__output = "";
this.__cookies = null;
this.__key = null;
if (encrypt)
{
return __SwitchKey();
}
else
{
HttpWebResponse response = this.__GET("");
this.__encoding = this.__GetEncoding(response);
response.Close();
return true;
}
}
private Encoding __GetEncoding(HttpWebResponse response)
{
string charset = response.GetResponseHeader("Content-Type");
if (charset.StartsWith("text/plain; charset="))
{
charset = charset.Substring(20, charset.Length - 20);
return Encoding.GetEncoding(charset);
}
return Encoding.UTF8;
}
private HttpWebResponse __GET(string requestString)
{
Uri uri = new Uri(String.Concat(this.__uri, "?", requestString));
HttpWebRequest request = HttpWebRequest.Create(uri) as HttpWebRequest;
request.UserAgent = "PHPRPC Client/2.1 for .NET";
request.CookieContainer = new CookieContainer();
if (this.__cookies != null)
{
request.CookieContainer.Add(this.__cookies);
}
if (this.__proxy != null)
{
request.Proxy = (IWebProxy)this.__proxy;
}
else
{
request.Proxy = GlobalProxySelection.GetEmptyWebProxy();
}
request.Credentials = this.__credentials;
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
if (response.GetResponseHeader("X-Powered-By").IndexOf("PHPRPC Server") < 0)
{
response.Close();
throw new Exception("Wrong PHPRPC Server!");
}
return response;
}
private HttpWebResponse __POST(string requestString)
{
HttpWebRequest request = HttpWebRequest.Create(new Uri(this.__uri)) as HttpWebRequest;
request.Method = "POST";
request.UserAgent = "PHPRPC Client/2.1 for .NET";
request.ContentType = String.Concat("application/x-www-form-urlencoded; charset=", this.__encoding.WebName);
request.CookieContainer = new CookieContainer();
if (this.__cookies != null)
{
request.CookieContainer.Add(this.__cookies);
}
if (this.__proxy != null)
{
request.Proxy = (IWebProxy)this.__proxy;
}
else
{
request.Proxy = GlobalProxySelection.GetEmptyWebProxy();
}
request.Credentials = this.__credentials;
Stream rs = request.GetRequestStream();
byte[] buf = this.__encoding.GetBytes(requestString);
rs.Write(buf, 0, buf.Length);
rs.Close();
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
if (response.GetResponseHeader("X-Powered-By").IndexOf("PHPRPC Server") < 0)
{
response.Close();
throw new Exception("Wrong PHPRPC Server!");
}
return response;
}
private bool __SwitchKey()
{
HttpWebResponse response = this.__GET("phprpc_encrypt=true");
this.__encoding = this.__GetEncoding(response);
this.__cookies = response.Cookies;
Stream s = response.GetResponseStream();
StreamReader sr = new StreamReader(s);
string[] body = Regex.Split(sr.ReadToEnd(), "\r\n");
response.Close();
if (body[0].StartsWith("phprpc_encrypt"))
{
Hashtable kp = (Hashtable)PHPSerializer.UnSerialize(Convert.FromBase64String(body[0].Substring(16, body[0].Length - 18)));
BigInteger p = BigInteger.Parse(kp["p"] as string);
BigInteger g = BigInteger.Parse(kp["g"] as string);
BigInteger y = BigInteger.Parse(kp["y"] as string);
BigInteger x = BigInteger.GenerateRandom(127);
this.__key = new byte[16];
byte[] key = y.ModPow(x, p).GetBytes();
for (int i = 1, n = key.Length; i <= n; i++)
{
this.__key[16 - i] = key[n - i];
}
this.__GET(String.Concat("phprpc_encrypt=", (g.ModPow(x, p)).ToString())).Close();
return true;
}
else
{
this.__warning = new Error(2, "PHPRPC Server can't support encrypt");
return false;
}
}
private void __SetWarning(string errno, string errstr)
{
int number = Int32.Parse(errno.Substring(14, errno.Length - 16));
if (number != 0)
{
this.__warning = new Error(number, this.__encoding.GetString(Convert.FromBase64String(errstr.Substring(15, errstr.Length - 17))));
}
}
private void __SetOutput(string output)
{
this.__output = this.__encoding.GetString(Convert.FromBase64String(output.Substring(15, output.Length - 17)));
}
public object Invoke(string function, params object[] args)
{
return this.Invoke(false, function, ref args);
}
public object Invoke(string function, ref object[] args)
{
return this.Invoke(true, function, ref args);
}
protected object Invoke(bool byref, string function, ref object[] args)
{
StringBuilder sb = new StringBuilder();
sb.Append("phprpc_func=");
sb.Append(function);
if (args.Length > 0)
{
byte[] arguments = PHPSerializer.Serialize(args);
if (this.__key != null && this.__encrypt > 0)
{
arguments = XXTEA.Encrypt(arguments, this.__key);
}
sb.Append("&phprpc_args=");
sb.Append(Convert.ToBase64String(arguments).Replace("+", "%2B"));
if (!byref)
{
sb.Append("&phprpc_ref=false");
}
}
if (this.__key != null)
{
sb.Append("&phprpc_encrypt=");
sb.Append(this.__encrypt);
}
HttpWebResponse response = this.__POST(sb.ToString());
Stream s = response.GetResponseStream();
StreamReader sr = new StreamReader(s);
string[] body = Regex.Split(sr.ReadToEnd(), "\r\n");
response.Close();
this.__warning = null;
if (body[0].StartsWith("phprpc_errno"))
{
throw new Exception(this.__encoding.GetString(Convert.FromBase64String(body[1].Substring(15, body[1].Length - 17))));
}
if (body[0].StartsWith("phprpc_result"))
{
byte[] result = Convert.FromBase64String(body[0].Substring(15, body[0].Length - 17));
byte[] arguments = null;
bool has_args = body[1].StartsWith("phprpc_args");
if (has_args)
{
arguments = Convert.FromBase64String(body[1].Substring(13, body[1].Length - 15));
this.__SetWarning(body[2], body[3]);
this.__SetOutput(body[4]);
}
else
{
this.__SetWarning(body[1], body[2]);
this.__SetOutput(body[3]);
}
if ((this.__key != null) && (this.__encrypt > 0))
{
if (this.__encrypt > 1)
{
result = XXTEA.Decrypt(result, this.__key);
}
if (has_args)
{
arguments = XXTEA.Decrypt(arguments, this.__key);
}
}
if (has_args)
{
args = (object[])PHPSerializer.UnSerialize(arguments, typeof(object[]));
}
return PHPSerializer.UnSerialize(result);
}
else
{
throw new Exception("Wrong PHPRPC Server!");
}
}
}
}