/**********************************************************\
| |
| The implementation of PHPRPC Protocol 3.0 |
| |
| phprpc_client.js |
| |
| Release 3.0.0 beta 10 |
| Copyright (c) 2005-2007 by Team-PHPRPC |
| |
| WebSite: http://www.phprpc.org/ |
| http://www.phprpc.com/ |
| http://sourceforge.net/projects/php-rpc/ |
| |
| Authors: Ma Bingyao <andot@ujn.edu.cn> |
| |
| This file may be distributed and/or modified under the |
| terms of the GNU Lesser General Public License (LGPL) |
| version 2.1 as published by the Free Software Foundation |
| and appearing in the included file LICENSE. |
| |
\**********************************************************/
/* PHPRPC Client for browser JavaScript
*
* Copyright (C) 2005-2008 Ma Bingyao <andot@ujn.edu.cn>
* Version: 3.0.0 beta 10
* LastModified: Mar 18, 2007
* This library is free. You can redistribute it and/or modify it.
*/
/*
* Interfaces:
* var rpc = new PHPRPC_Client();
* rpc.useService('http://domain.com/rpcserver.php');
* rpc.setKeyLength(96);
* rpc.setEncryptMode(3);
* rpc.onready = function () {
* rpc.remoteFunctionName(args1, args2, ..., function(result, args, output, warning) {
* if (result instanceof PHPRPC_Error) {
* alert(result.Number);
* alert(result.Message);
* alert(result.toString());
* }
* else {
* alert(result); // or do any other things.
* alert(args[1]);
* alert(output);
* alert(warning.Number);
* alert(warning.Message);
* alert(warning.toString());
* }
* }, true);
* }
*/
// Public objects, properties & methods
/*
* You never need to create PHPRPC_Error object by yourself,
* when an error occurred during invoking remote function,
* this object will be created automatically as the result of callback function.
*/
function PHPRPC_Error(errno, errstr) {
this.Number = errno;
this.Message = errstr;
}
PHPRPC_Error.prototype.toString = function() {
return this.Number + ":" + this.Message;
}
PHPRPC_Error.prototype.getNumber = function() {
return this.Number;
}
PHPRPC_Error.prototype.getMessage = function() {
return this.Message;
}
/* Create a PHPRPC Client object.
* The username and password can be contained in serverURL for HTTP Basic Authorization,
* but it is NOT recommended (see also useService method for the recommended usage).
* If you hope that the PHPRPC Client initialize remote functions without connecting to the PHPRPC Server,
* you can specify the functions parameter.
*/
function PHPRPC_Client(serverURL, functions) {
this.ready = false;
this.__id = PHPRPC_Client.__list.length;
this.__timeout = 30000;
PHPRPC_Client.__list[this.__id] = this;
this.__name = 'PHPRPC_Client.__list[' + this.__id + ']';
if (typeof(serverURL) != "undefined")
{
if (typeof(functions) == "undefined") {
functions = null;
}
this.useService(serverURL, null, null, functions);
}
}
/*
* This method is for VBScript to create PHPRPC Client object,
* because VBScript can't use new keyword to create a JavaScript Object.
* but you can use this method in JavaScript too.
*/
PHPRPC_Client.create = function(serverURL, functions) {
if (typeof(functions) == "undefined") {
functions = null;
}
return new PHPRPC_Client(serverURL, functions);
}
/*
* Abort all remoting functions and then kill itself.
*/
PHPRPC_Client.prototype.dispose = function() {
this.abort();
PHPRPC_Client.__list[this.__id] = null
delete PHPRPC_Client.__list[this.__id];
}
/*
* Set the URL of the PHPRPC Server.
* The username and password can be contained in serverURL for HTTP Basic Authorization,
* but it is NOT recommended. It is recommended to specify the username and password by parameters.
* If you hope that the PHPRPC Client initialize remote functions without connecting to the PHPRPC Server,
* you can specify the functions parameter.
*/
PHPRPC_Client.prototype.useService = function(serverURL, username, password, functions) {
this.__username = null;
this.__password = null;
if (typeof(serverURL) == "undefined") {
return new PHPRPC_Error(1, "You should set serverURL first!");
}
this.__url = serverURL;
if ((typeof(username) != "undefined") && (typeof(password) != "undefined")) {
this.__username = username;
this.__password = password;
}
this.__initService();
if ((typeof(functions) == "undefined") || (functions == null)) {
this.__useService();
}
else {
this.__setFunctions(functions);
}
return true;
}
/*
* Set the key length for the key exchange.
* This method will return false if the key exchange has already been completed.
*/
PHPRPC_Client.prototype.setKeyLength = function(keyLength) {
if (this.__key != null) {
return false;
}
else {
this.__keylen = keyLength;
return true;
}
}
/*
* Get the key length.
* This method will return the actual key length when the key exchange is completed.
* Otherwise, you will get the default length or the length you set.
*/
PHPRPC_Client.prototype.getKeyLength = function() {
return this.__keylen;
}
/*
* Set the encrypt mode.
* 0 indicates encrypting nothing.
* 1 indicates encrypting arguments.
* 2 indicates encrypting arguments and result.
* 3 indicates encrypting arguments, result and output of the server-side page.
* If any invalid value are set, it would return false.
*/
PHPRPC_Client.prototype.setEncryptMode = function(encryptMode) {
if (encryptMode >= 0 && encryptMode <= 3) {
this.__encryptMode = parseInt(encryptMode);
return true;
}
else {
this.__encryptMode = 0;
return false;
}
}
/*
* There are two ways to invoke the remote functions. One is:
*
* string remoteFunctionName(arg1, arg2, ..., argN);
* string remoteFunctionName(arg1, arg2, ..., argN, callbackFunction);
* string remoteFunctionName(arg1, arg2, ..., argN, callbackFunction, byRef);
*
* The other is:
*
* string invoke(remoteFunctionName, arg1, arg2, ..., argN);
* string invoke(remoteFunctionName, arg1, arg2, ..., argN, callbackFunction);
* string invoke(remoteFunctionName, arg1, arg2, ..., argN, callbackFunction, byRef);
*
* The invoke method is similar to use the remote function name directly to invoke the remote function.
* The difference is the invoke method is available before the getReady() becomes true,
* that is to say, the invoke method can be called after using useService method immediately.
* The return value is remote function id,
* you can use abort method to abort the remote function with this value.
* If you want to pass the arguments by reference, set byRef to be true.
* You can specify a callback function, when the remote function completed,
* this callback function will be call automatically. If you didn't specify a callback function,
* the default callback function is remoteFunctionName_callback(), You can define it separately.
* the callback function can be defined like this:
*
* callbackFunction = function (result, args, output, warning) {
* ...
* }
*
* The parameter result is the result of the remote function,
* when an error occurred during invoking remote function,
* this parameter is a PHPRPC_Error object.
* The parameter args is the remote function arguments,
* you can get the changed arguments with it when passing the arguments by reference.
* The parameter output is the output of the server console.
* The parameter warning is the warning of the remote function, it is a PHPRPC_Error object.
*/
PHPRPC_Client.prototype.invoke = function() {
var args = this.__argsToArray(arguments);
var func = args.shift();
return this.__invoke(func, args);
}
/*
* If you use this method with a specified remote function id parameter,
* it would abort the remote function you specified only,
* otherwise it would abort all of the remote functions.
*/
PHPRPC_Client.prototype.abort = function(id) {
if (typeof(id) == "undefined") {
for (id in this.__reqHeap) {
this.abort(id);
}
}
else if (typeof(this.__reqHeap[id]) != "undefined") {
if (this.__ajax) {
if ((this.__reqHeap[id] != null) && (typeof(this.__reqHeap[id].abort) == "function")) {
this.__reqHeap[id].onreadystatechange = function() {};
this.__reqHeap[id].abort();
}
this.__deleteReqHeap(id);
}
else {
this.__removeScript(id);
this.__deleteReqHeap(id);
}
}
}
/*
* Set the number of milliseconds a remote function is allowed to invoke.
* The default limit is 30 seconds.
* If the timeout parameter is set to zero or null, no time limit is imposed.
*/
PHPRPC_Client.prototype.setTimeout = function(timeout) {
this.__timeout = timeout;
}
/*
* Get the timeout in milliseconds for invoking a remote function.
*/
PHPRPC_Client.prototype.getTimeout = function() {
return this.__timeout;
}
/*
* When the useService method completes,
* this method return true, otherwise return false.
*/
PHPRPC_Client.prototype.getReady = function() {
return this.ready;
}
// Private objects, properties & methods
// to save all PHPRPC clients in one page.
PHPRPC_Client.__list = [];
PHPRPC_Client.__id = 0;
PHPRPC_Client.__timeout = function (cid, id) {
if (typeof(PHPRPC_Client.__list[cid]) != "undefined") {
PHPRPC_Client.__list[cid].abort(id);
}
}
// The XMLHttp ActiveX object name cache. Only IE use it.
PHPRPC_Client.__MSXML = null;
/*
* the function __createXMLHttp() modified from
* http://webfx.eae.net/dhtml/xmlextras/xmlextras.html and
* http://www.ugia.cn/?p=85
*/
PHPRPC_Client.__createXMLHttp = 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 if (PHPRPC_Client.__MSXML != null) {
// Use the cache name first.
return new ActiveXObject(PHPRPC_Client.__MSXML);
}
else {
var MSXML = ['MSXML2.XMLHTTP.6.0',
'MSXML2.XMLHTTP.5.0',
'MSXML2.XMLHTTP.4.0',
'MSXML2.XMLHTTP.3.0',
'MsXML2.XMLHTTP.2.6',
'MSXML2.XMLHTTP',
'Microsoft.XMLHTTP.1.0',
'Microsoft.XMLHTTP.1',
'Microsoft.XMLHTTP'];
var n = MSXML.length;
for(var i = 0; i < n; i++) {
try {
objXMLHttp = new ActiveXObject(MSXML[i]);
// Cache the XMLHttp ActiveX object name.
PHPRPC_Client.__MSXML = MSXML[i];
return objXMLHttp;
}
catch(e) {}
}
return null;
}
}
PHPRPC_Client.__createID = function() {
return PHPRPC_Client.__id++;
}
PHPRPC_Client.prototype.__initService = function() {
this.ready = false;
this.__key = null;
this.__keylen = 128;
this.__keyExchanging = false;
this.__encryptMode = 0;
this.__reqHeap = [];
this.__taskQueue = [];
this.__dataObject = [];
var url = this.__url;
var p = 0;
var protocol = null;
var host = null;
var path = null;
if (url.substr(0, 7).toLowerCase() == 'http://') {
protocol = 'http:';
p = 7;
}
else if (url.substr(0, 8).toLowerCase() == 'https://') {
protocol = 'https:';
p = 8;
}
if (p > 0) {
host = url.substring(p, url.indexOf('/', p));
var m = host.match(/^([^:]*):([^@]*)@(.*)$/);
if (m != null) {
if (this.__username == null) {
this.__username = decodeURIComponent(m[1]);
}
if (this.__password == null) {
this.__password = decodeURIComponent(m[2]);
}
host = m[3];
}
path = url.substr(url.indexOf('/', p));
}
if (((protocol == null) || (location.protocol == 'file:')
|| (protocol == location.protocol && host == location.host))
&& PHPRPC_Client.__createXMLHttp() != null) {
this.__ajax = true;
}
else {
this.__ajax = false;
}
if ((p > 0) && (this.__username != null) && (this.__password != null)) {
this.__url = protocol + '//';
if (!this.__ajax) {
this.__url += encodeURIComponent(this.__username) + ':' + encodeURIComponent(this.__password) + '@';
}
this.__url += host + path;
}
this.__url = this.__url.replace(/[\&\?]+$/g, '');
this.__url += (this.__url.indexOf('?', 0) == -1) ? '?' : '&';
this.__url += 'phprpc_id=' + this.__id + '&';
}
PHPRPC_Client.prototype.__useService = function() {
if (this.__ajax) {
var xmlhttp = PHPRPC_Client.__createXMLHttp();
var __rpc = this;
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4) {
if (xmlhttp.responseText) {
var id = PHPRPC_Client.__createID();
__rpc.__createDataObject(xmlhttp.responseText, id);
__rpc.__setFunctions(unserialize(__rpc.__dataObject[id].phprpc_functions));
__rpc.__deleteDataObject(id);
}
__rpc = null;
xmlhttp = null;
}
}
try {
xmlhttp.open('GET', this.__url + 'phprpc_encode=false', true);
if (this.__username !== null) {
xmlhttp.setRequestHeader('Authorization', 'Basic ' + base64encode(this.__username + ":" + this.__password));
}
xmlhttp.send(null);
}
catch (e) {
xmlhttp = null;
this.__ajax = false;
this.__useService();
}
}
else {
var id = PHPRPC_Client.__createID();
var callback = base64encode(utf16to8(this.__name + ".__getFunctions('" + id + "');"));
var request = 'phprpc_encode=false&phprpc_callback=' + callback;
this.__appendScript(id, request);
}
}
PHPRPC_Client.prototype.__appendScript = function(id, request, args, ref, encrypt, callback) {
var script = document.createElement('script');
script.id = 'script_' + id;
script.src = this.__url + request.replace(/\+/g, '%2B');
script.defer = true;
script.type = 'text/javascript';
script.args = args;
script.ref = ref;
script.encrypt = encrypt;
script.callback = callback;
var head = document.getElementsByTagName('head').item(0);
head.appendChild(script);
}
PHPRPC_Client.prototype.__removeScript = function(id) {
var script = document.getElementById('script_' + id);
if (script) {
var head = document.getElementsByTagName('head').item(0);
head.removeChild(script);
}
}
PHPRPC_Client.prototype.__argsToArray = function(args) {
var n = args.length;
var argArray = new Array(n);
for (var i = 0; i < n; i++) {
argArray[i] = args[i];
}
return argArray;
}
PHPRPC_Client.prototype.__createDataObject = function(str, id) {
var params = str.split(";\r\n");
var result = {};
var n = params.length;
for (var i = 0; i < n; i++) {
var p = params[i].indexOf('=');
if (p >= 0) {
var l = params[i].substr(0, p);
var r = params[i].substr(p + 1);
result[l] = eval(r);
}
}
this.__dataObject[id] = result;
}
PHPRPC_Client.prototype.__deleteDataObject = function(id) {
if (this.__dataObject[id]) {
delete(this.__dataObject[id]);
}
}
PHPRPC_Client.prototype.__deleteReqHeap = function(id) {
if (typeof(this.__reqHeap[id]) != 'undefined') {
this.__reqHeap[id] = null;
delete(this.__reqHeap[id]);
}
}
PHPRPC_Client.prototype.__invoke = function(func, args) {
var __rpc = this;
var id = PHPRPC_Client.__createID();
this.__reqHeap[id] = null;
var task = function() {
__rpc.__call(id, func, args);
if (__rpc.__timeout) {
setTimeout('PHPRPC_Client.__timeout(' + __rpc.__id + ', "' + id + '");', __rpc.__timeout);
}
__rpc = null;
};
this.__taskQueue.push(task);
this.__keyExchange();
return id;
}
PHPRPC_Client.prototype.__setFunctions = function(functions) {
for (var i = 0; i < functions.length; i++) {
PHPRPC_Client.__list[this.__id][functions[i]] = new Function("return this.__invoke('" + functions[i] + "', this.__argsToArray(arguments));");
}
this.ready = true;
if (typeof(this.onready) == 'function') {
/*
* This is a event. You can define it before you called useService method.
* When the useService method completes, this event will be fired.
* If you define it after you called useService method, this event may not be fired.
*/
this.onready();
}
}
PHPRPC_Client.prototype.__getFunctions = function(id) {
var functions = phprpc_functions;
delete(phprpc_functions);
this.__setFunctions(unserialize(functions));
this.__removeScript(id);
}
PHPRPC_Client.prototype.__keyExchange = function() {
if (this.__keyExchanging) return;
if (this.__key == null && this.__encryptMode > 0) {
this.__keyExchanging = true;
if (this.__ajax) {
var xmlhttp = PHPRPC_Client.__createXMLHttp();
var __rpc = this;
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4) {
if (xmlhttp.responseText) {
var id = PHPRPC_Client.__createID();
__rpc.__createDataObject(xmlhttp.responseText, id);
__rpc.__keyExchange2(id);
__rpc.__deleteDataObject(id);
}
__rpc = null;
xmlhttp = null;
}
}
xmlhttp.open('GET', this.__url + 'phprpc_encrypt=true&phprpc_encode=false&phprpc_keylen=' + this.__keylen, true);
if (this.__username !== null) {
xmlhttp.setRequestHeader('Authorization', 'Basic ' + base64encode(this.__username + ':' + this.__password));
}
xmlhttp.send(null);
}
else {
var id = PHPRPC_Client.__createID();
var callback = base64encode(utf16to8(this.__name + ".__keyExchange2('" + id + "');"));
var request = 'phprpc_encrypt=true&phprpc_encode=false&phprpc_keylen=' + this.__keylen + '&phprpc_callback=' + callback;
this.__appendScript(id, request);
}
}
else {
this.__keyExchanged();
}
}
PHPRPC_Client.prototype.__keyExchange2 = function(id) {
if (this.__ajax) {
var data = this.__dataObject[id];
if (typeof(data.phprpc_encrypt) == 'undefined') {
this.__key = null;
this.__encorytMode = 0;
this.__keyExchanging = false;
this.__keyExchanged();
}
else {
if (typeof(data.phprpc_keylen) != 'undefined') {
this.__keylen = parseInt(data.phprpc_keylen);
}
else {
this.__keylen = 128;
}
var encrypt = this.__getKey(unserialize(data.phprpc_encrypt));
var __rpc = this;
var xmlhttp = PHPRPC_Client.__createXMLHttp();
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4) {
if (xmlhttp.responseText) {
__rpc.__keyExchange3();
}
__rpc = null;
xmlhttp = null;
}
}
xmlhttp.open('GET', this.__url + 'phprpc_encode=false&phprpc_encrypt=' + encrypt, true);
if (this.__username !== null) {
xmlhttp.setRequestHeader('Authorization', 'Basic ' + base64encode(this.__username + ":" + this.__password));
}
xmlhttp.send(null);
}
}
else {
if (typeof(phprpc_encrypt) == 'undefined') {
this.__key = null;
this.__encorytMode = 0;
this.__keyExchanging = false;
this.__keyExchanged();
}
else {
if (typeof(phprpc_keylen) != 'undefined') {
this.__keylen = parseInt(phprpc_keylen);
delete(phprpc_keylen);
}
else {
this.__keylen = 128;
}
var encrypt = phprpc_encrypt;
delete(phprpc_encrypt);
this.__removeScript(id);
var callback = base64encode(utf16to8(this.__name + ".__keyExchange3('" + id + "');"));
var request = 'phprpc_encrypt=' + this.__getKey(unserialize(encrypt))
+ '&phprpc_encode=false&phprpc_callback=' + callback;
this.__appendScript(id, request);
}
}
}
PHPRPC_Client.prototype.__keyExchange3 = function(id) {
if (!this.__ajax) {
delete(phprpc_encrypt);
delete(phprpc_keylen);
delete(phprpc_functions);
this.__removeScript(id);
}
this.__keyExchanging = false;
this.__keyExchanged();
}
PHPRPC_Client.prototype.__getKey = function(encrypt) {
var p = dec2num(encrypt['p']);
var g = dec2num(encrypt['g']);
var y = dec2num(encrypt['y']);
var x = rand(this.__keylen - 1, 1);
var key = pow_mod(y, x, p);
if (this.__keylen == 128) {
key = num2str(key);
var n = 16 - key.length;
var k = [];
for (var i = 0; i < n; i++) {
k[i] = '\0';
}
k[n] = key;
this.__key = k.join('');
}
else {
this.__key = md5(num2dec(key));
}
return num2dec(pow_mod(g, x, p));
}
PHPRPC_Client.prototype.__keyExchanged = function() {
while (this.__taskQueue.length > 0) {
var task = this.__taskQueue.shift();
if (typeof(task) == 'function') {
task();
}
}
}
PHPRPC_Client.prototype.__call = function (id, func, args) {
if (typeof(this.__reqHeap[id]) == 'undefined') return;
var ref = false;
var encrypt = this.__encryptMode;
var callback = PHPRPC_Client.__list[this.__id][func + '_callback'];
if (typeof(callback) != 'function') {
callback = null;
}
if (typeof(args[args.length - 1]) == 'boolean' && typeof(args[args.length - 2]) == 'function') {
ref = args[args.length - 1];
callback = args[args.length - 2];
args.length -= 2;
}
if (typeof(args[args.length - 1]) == 'function') {
callback = args[args.length - 1];
args.length--;
}
var __args = base64encode(this.__encryptString(serialize(args), encrypt, 1));
var request = 'phprpc_func=' + func
+ '&phprpc_args=' + __args
+ '&phprpc_encode=false'
+ '&phprpc_encrypt=' + encrypt;
if (!ref) {
request += '&phprpc_ref=false';
}
if (this.__ajax) {
if (typeof(this.__reqHeap[id]) == 'undefined') return;
var xmlhttp = PHPRPC_Client.__createXMLHttp();
this.__reqHeap[id] = xmlhttp;
var __rpc = this;
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4) {
if (xmlhttp.responseText) {
__rpc.__createDataObject(xmlhttp.responseText, id);
__rpc.__getResult(id, args, ref, encrypt, callback);
__rpc.__deleteDataObject(id);
}
__rpc.__deleteReqHeap(id);
__rpc = null;
xmlhttp = null;
}
}
xmlhttp.open('POST', this.__url, true);
xmlhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
if (this.__username !== null) {
xmlhttp.setRequestHeader('Authorization', 'Basic ' + base64encode(this.__username + ":" + this.__password));
}
xmlhttp.send(request.replace(/\+/g, '%2B'));
}
else {
request += '&phprpc_callback=' + base64encode(utf16to8(this.__name + ".__callback('" + id + "');"));
if (typeof(this.__reqHeap[id]) == 'undefined') return;
this.__appendScript(id, request, args, ref, encrypt, callback);
}
}
PHPRPC_Client.prototype.__encryptString = function(str, encrypt, level) {
if ((this.__key != null) && (encrypt >= level)) {
str = xxtea_encrypt(str, this.__key);
}
return str;
}
PHPRPC_Client.prototype.__decryptString = function(str, encrypt, level) {
if ((this.__key != null) && (encrypt >= level)) {
str = xxtea_decrypt(str, this.__key);
}
return str;
}
PHPRPC_Client.prototype.__getResult = function(id, args, ref, encrypt, callback) {
if (typeof(callback) == 'function' && typeof(this.__reqHeap[id]) != 'undefined') {
var data = this.__dataObject[id];
var output = data.phprpc_output;
if ((this.__key !== null) && (encrypt > 2)) {
output = xxtea_decrypt(output, this.__key);
if (output === null) {
output = data.phprpc_output;
}
else {
output = utf8to16(output);
}
}
var result = new PHPRPC_Error(data.phprpc_errno, data.phprpc_errstr);
var warning = result;
if (typeof(data.phprpc_result) != 'undefined') {
result = unserialize(this.__decryptString(data.phprpc_result, encrypt, 2));
if (ref && (typeof(data.phprpc_args) != 'undefined')) {
args = unserialize(this.__decryptString(data.phprpc_args, encrypt, 1));
}
}
callback(result, args, output, warning);
}
}
PHPRPC_Client.prototype.__callback = function (id) {
if (typeof(this.__reqHeap[id]) == 'undefined') return;
var data = {};
data.phprpc_errno = phprpc_errno;
data.phprpc_errstr = phprpc_errstr;
data.phprpc_output = phprpc_output;
delete(phprpc_errno);
delete(phprpc_errstr);
delete(phprpc_output);
if (typeof(phprpc_result) != 'undefined') {
data.phprpc_result = phprpc_result;
delete(phprpc_result);
}
if (typeof(phprpc_args) != 'undefined') {
data.phprpc_args = phprpc_args;
delete(phprpc_args);
}
this.__dataObject[id] = data;
var script = document.getElementById('script_' + id);
this.__getResult(id, script.args, script.ref, script.encrypt, script.callback);
this.__deleteDataObject(id);
this.__deleteReqHeap(id);
this.__removeScript(id);
}