本文給出了 PHPRPC 2.1 協議的 AJax 客戶端實現。該客戶端的使用方式與 2.0 版本的使用方式基本上相同。不同點在於如果要調用的遠程函數是引用參數傳遞的話,需要在調用前設置該函數的 ref 屬性為 true。該屬性表示是否是引用參數傳遞。該屬性默認為 false。推薦在客戶端對象的 onready 事件中進行設置。
下面為該客戶端的實現代碼:
下載:
PHPrpc_AJax_clIEnt.JS
- /* phprpc_ajax_clIEnt.JS - AJax PHPRPC ClIEnt
- *
- * Copyright Ma Bingyao <andot@ujn.edu.cn>
- * Version: 2.1
- * LastModifIEd: 2006-03-12
- * This library is free. You can redistribute it and/or modify it.
- * http://www.coolcode.cn/?p=146
- */
-
- /*
- * 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.async = true;
- this.ready = false;
- this.args = null;
- this.output = "";
- this.use_service = function (url, encrypt) {
- if (typeof(encrypt) == "undefined") {
- encrypt = this.__encrypt;
- }
- if (typeof(this.__name) == "undefined") {
- return false;
- }
- this.__url = url;
- var xmlhttp = this.__create_XMLhttp();
- var __rpc = this;
- if (encrypt === true) {
- XMLhttp.onreadystatechange = function () {
- if (XMLhttp.readyState == 4) {
- if (XMLhttp.responseText) {
- eval(XMLhttp.responseText);
- if (typeof(PHPrpc_encrypt) == "undefined") {
- __rpc.__encrypt = false;
- __rpc.use_service(__rpc.__url);
- }
- else {
- __rpc.__encrypt = __rpc.__php.unserialize(PHPrpc_encrypt);
- __rpc.__encrypt['p'] = dec2num(__rpc.__encrypt['p']);
- __rpc.__encrypt['g'] = dec2num(__rpc.__encrypt['g']);
- __rpc.__encrypt['y'] = dec2num(__rpc.__encrypt['y']);
- __rpc.__encrypt['x'] = rand(127, 1);
- var key = pow_mod(__rpc.__encrypt['y'],
- __rpc.__encrypt['x'],
- __rpc.__encrypt['p']);
- key = num2str(key);
- for (var i = 0; i < 16 - key.length; i++) {
- key = '\0' + key;
- }
- __rpc.__encrypt['k'] = key;
- var encrypt = pow_mod(__rpc.__encrypt['g'],
- __rpc.__encrypt['x'],
- __rpc.__encrypt['p']);
- __rpc.use_service(__rpc.__url, num2dec(encrypt).replace(/\+/g, '%2B'));
- }
- }
- delete(XMLhttp);
- }
- }
- }
- else {
- XMLhttp.onreadystatechange = function () {
- if (XMLhttp.readyState == 4) {
- if (XMLhttp.responseText) {
- eval(XMLhttp.responseText);
- var functions = __rpc.__php.unserialize(PHPrpc_functions);
- var func;
- for (var i = 0; i < functions.length; i++) {
- func = __rpc.__name + "." + functions[i] + " = function () {\r\n";
- func += " this.__call('" + functions[i] + "', this.__args_to_array(arguments));\r\n";
- func += "}\r\n";
- func += __rpc.__name + "." + functions[i] + ".ref = false;\r\n";
- eval(func);
- }
- __rpc.ready = true;
- if (typeof(__rpc.onready) == "function") {
- __rpc.onready();
- }
- }
- delete(XMLhttp);
- }
- }
- }
- XMLhttp.open("get", this.__url + '?phprpc_encrypt=' + encrypt + '&PHPrpc_encode=false', true);
- XMLhttp.send(null);
- };
- 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 request = 'PHPrpc_func=' + func
- + '&PHPrpc_args=' + __args
- + '&PHPrpc_encode=false'
- + '&PHPrpc_encrypt=' + this.encrypt;
- var ref = eval(this.__name + "." + func + ".ref");
- if (!ref) {
- request += '&PHPrpc_ref=false';
- }
- var xmlhttp = this.__create_XMLhttp();
- var session = {'args': args, 'ref': ref, 'encrypt': this.encrypt};
- if (this.async) {
- var __rpc = this;
- XMLhttp.onreadystatechange = function () {
- if (XMLhttp.readyState == 4) {
- if (XMLhttp.responseText) {
- __rpc.__get_result(XMLhttp, session);
- if (typeof(eval(__rpc.__name + "." + func + "_callback")) == "function") {
- eval(__rpc.__name + "." + func + "_callback(phprpc_result, phprpc_args, PHPrpc_output);");
- }
- }
- delete(XMLhttp);
- }
- }
- }
- XMLhttp.open("post", this.__url, this.async);
- XMLhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
- XMLhttp.send(request.replace(/\+/g, '%2B'));
- if (!this.async) {
- if (XMLhttp.responseText) {
- this.__get_result(XMLhttp, session);
- this.output = PHPrpc_output;
- this.args = PHPrpc_args;
- return PHPrpc_result;
- }
- else {
- return new PHPrpc_error(1, "No data received from server");
- }
- delete(XMLhttp);
- }
- };
- this.__get_result = function (XMLhttp, session) {
- eval(XMLhttp.responseText);
- if (PHPrpc_errno == 0) {
- if ((this.__encrypt !== false) && (session.encrypt > 0)) {
- if (session.encrypt > 1) {
- phprpc_result = xxtea_decrypt(PHPrpc_result, this.__encrypt['k']);
- }
- if (session.ref) {
- phprpc_args = xxtea_decrypt(PHPrpc_args, this.__encrypt['k']);
- }
- }
- phprpc_result = this.__php.unserialize(PHPrpc_result);
- if (session.ref) {
- phprpc_args = this.__php.unserialize(PHPrpc_args);
- }
- else {
- PHPrpc_args = this.args;
- }
- }
- else {
- phprpc_result = new phprpc_error(phprpc_errno, PHPrpc_errstr);
- PHPrpc_args = null;
- }
- }
- // the function __create_XMLhttp modifIEd from
- // http://webfx.eae.Net/DHtml/xmlextras/XMLextras.Html and
- // http://www.ugia.cn/?p=85
- this.__create_XMLhttp = function() {
- if (window.XMLHttpRequest) {
- var objXMLHttp = new XMLHttpRequest();
-
- // some older versions of Moz did not support the readyState property
- // and the onreadystate event so we patch it!
- if (objXMLHttp.readyState == null) {
- objXMLHttp.readyState = 0;
- objXMLHttp.addEventListener(
- "load",
- function () {
- objXMLHttp.readyState = 4;
- if (typeof(objXMLHttp.onreadystatechange) == "function") {
- objXMLHttp.onreadystatechange();
- }
- },
- false
- );
- }
- return objXMLHttp;
- }
- else {
- var MSXML = ['MSXML2.XMLHTTP.5.0', 'MSXML2.XMLHTTP.4.0', 'MSXML2.XMLHTTP.3.0', 'MSXML2.XMLHTTP', 'Microsoft.XMLHTTP'];
- for(var n = 0; n < MSXML.length; n ++) {
- try {
- return objXMLHttp = new ActiveXObject(MSXML[n]);
- }
- catch(e) {}
- }
- throw new Error("Your browser does not support XMLhttp objects");
- }
- };
- this.__args_to_array = function (args) {
- argArray = [];
- for (i = 0; i < args.length; i++) {
- argArray[i] = args[i];
- }
- return argArray;
- }
- }
-
- PHPrpc_clIEnt.create = function (name, encrypt) {
- eval(name + ' = new PHPrpc_clIEnt();');
- eval(name + '.__name = "' + name + '";');
- if (encrypt) {
- encrypt = true;
- eval(name + '.__encrypt = ' + encrypt + ';');
- }
- }