ajax|用戶端
本文給出了 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 + ';');
- }
- }
作者 andot
<