/* phprpc_client.js - JavaScript PHPRPC Client
*
* Copyright Ma Bingyao <andot@ujn.edu.cn>
* Version: 2.1
* LastModified: 2006-03-21
* This library is free. You can redistribute it and/or modify it.
* http://www.coolcode.cn/?p=145
*/
/*
* Interfaces:
* phprpc_client.create('rpc');
* rpc.use_service('http://domain.com/phprpc/server.php');
* rpc.method_callback = function(result, args, output) {
* if (result instanceof phprpc_error) {
* alert(result.errstr);
* }
* else {
* alert(result); // or do any other things.
* }
* }
* ....
* if (rpc.ready) rpc.method();
*/
function phprpc_error(errno, errstr) {
this.errno = errno;
this.errstr = errstr;
}
function phprpc_client() {
this.__php = new PHP_Serializer();
this.__url = '';
this.__encrypt = false;
this.encrypt = 0;
this.ready = false;
this.use_service = function (url, encrypt) {
if (encrypt) {
this.__encrypt = true;
}
if (typeof(this.__name) == "undefined") {
return false;
}
this.__url = url;
this.ready = false;
var id = this.__create_id();
var callback;
if (this.__encrypt) {
callback = base64encode(utf16to8([this.__name, ".__switch_key('", id, "');"].join('')));
}
else {
callback = base64encode(utf16to8([this.__name, ".__get_functions('", id, "');"].join('')));
}
this.__append_script(id, ['phprpc_encrypt=', this.__encrypt, '&phprpc_callback=', callback, '&phprpc_encode=false'].join(''));
return true;
}
this.__switch_key = function (id) {
if (typeof(phprpc_encrypt) == "undefined") {
this.__encrypt = false;
this.__get_functions(id);
}
else {
this.__encrypt = this.__php.unserialize(phprpc_encrypt);
this.__remove_script(id);
this.__encrypt['p'] = dec2num(this.__encrypt['p']);
this.__encrypt['g'] = dec2num(this.__encrypt['g']);
this.__encrypt['y'] = dec2num(this.__encrypt['y']);
this.__encrypt['x'] = rand(127, 1);
var key = pow_mod(this.__encrypt['y'],
this.__encrypt['x'],
this.__encrypt['p']);
key = num2str(key);
for (var i = 0; i < 16 - key.length; i++) {
key = '\0' + key;
}
this.__encrypt['k'] = key;
var encrypt = pow_mod(this.__encrypt['g'],
this.__encrypt['x'],
this.__encrypt['p']);
var callback = base64encode(utf16to8([this.__name, ".__get_functions('", id, "');"].join('')));
this.__append_script(id, ['phprpc_encrypt=', num2dec(encrypt), '&phprpc_callback=', callback, '&phprpc_encode=false'].join(''));
}
}
this.__get_functions = function (id) {
var functions = this.__php.unserialize(phprpc_functions);
var func = [];
for (var i = 0; i < functions.length; i++) {
func = [this.__name, ".", functions[i],
" = function () {\r\n this.__call('",
functions[i],
"', this.__args_to_array(arguments));\r\n}\r\n",
this.__name, ".", functions[i],
".ref = false;\r\n"].join('');
eval(func);
}
this.__remove_script(id);
this.ready = true;
if (typeof(this.onready) == "function") {
this.onready();
}
}
this.__call = function (func, args) {
var __args = this.__php.serialize(args);
if ((this.__encrypt !== false) && (this.encrypt > 0)) {
__args = xxtea_encrypt(__args, this.__encrypt['k']);
}
__args = base64encode(__args);
var id = this.__create_id();
var request = ['phprpc_func=', func,
'&phprpc_args=', __args,
'&phprpc_encode=false',
'&phprpc_encrypt=', this.encrypt];
var callback = [this.__name, ".", func, "_callback"].join('');
if (typeof(eval(callback)) == "function") {
request[request.length] = '&phprpc_callback=';
request[request.length] = base64encode(utf16to8([this.__name, ".__callback('", id, "', ", callback, ");"].join('')));
}
var ref = eval([this.__name, ".", func, ".ref"].join(''));
if (!ref) {
request[request.length] = '&phprpc_ref=false';
}
this.__append_script(id, request.join(''), args, ref);
}
this.__callback = function (id, callback) {
phprpc_warning = null;
if ((phprpc_errno != 1) && (phprpc_errno != 16) &&
(phprpc_errno != 64) && (phprpc_errno != 256)) {
var script = document.getElementById("script_" + id);
if ((this.__encrypt !== false) && (script.encrypt > 0)) {
if (script.encrypt > 1) {
phprpc_result = xxtea_decrypt(phprpc_result, this.__encrypt['k']);
}
if (script.ref) {
phprpc_args = xxtea_decrypt(phprpc_args, this.__encrypt['k']);
}
}
phprpc_result = this.__php.unserialize(phprpc_result);
if (script.ref) {
phprpc_args = this.__php.unserialize(phprpc_args);
}
else {
phprpc_args = script.args;
}
phprpc_warning = new phprpc_error(phprpc_errno, phprpc_errstr);
}
else {
phprpc_result = new phprpc_error(phprpc_errno, phprpc_errstr);
phprpc_args = null;
}
callback(phprpc_result, phprpc_args, phprpc_output, phprpc_warning);
this.__remove_script(id);
}
this.__create_id = function () {
return (new Date()).getTime().toString(36) + Math.floor(Math.random() * 100000000).toString(36);
}
this.__append_script = function (id, request, args, ref) {
var script = document.createElement("script");
script.id = "script_" + id;
script.src = [this.__url, "?", request.replace(/\+/g, '%2B')].join('');
script.defer = true;
script.type = "text/javascript";
script.args = args;
script.ref = ref;
script.encrypt = this.encrypt;
var head = document.getElementsByTagName("head").item(0);
head.appendChild(script);
}
this.__remove_script = function (id) {
var script = document.getElementById("script_" + id);
var head = document.getElementsByTagName("head").item(0);
head.removeChild(script);
}
this.__args_to_array = function (args) {
argArray = new Array();
for (i = 0; i < args.length; i++) {
argArray[i] = args[i];
}
return argArray;
}
}
phprpc_client.create = function (name, encrypt) {
eval([name, ' = new phprpc_client();', name, '.__name = "', name, '";'].join(''));
if (encrypt) {
encrypt = true;
eval([name, '.__encrypt = ', encrypt, ';'].join(''));
}
}