This commit is contained in:
2024-04-27 09:23:34 +02:00
commit 11e713ca6f
11884 changed files with 3263371 additions and 0 deletions

View File

@@ -0,0 +1,729 @@
/*
Copyright (c) 2003 Jan-Klaas Kollhof
This file is part of the JavaScript o lait library(jsolait).
jsolait is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This software is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this software; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/**
Evaluates script in a global scope.
@param [0] The code to evaluate.
*/
globalEval=function(){
return eval(arguments[0]);
}
/**
Creates a new class object which inherits from superClass.
@param className="anonymous" The name of the new class.
If the created class is a public member of a module then
the className is automatically set.
@param superClass=Object The class to inherit from (super class).
@param classScope A function which is executed for class construction.
As 1st parameter it will get the new class' protptype for
overrideing or extending the super class. As 2nd parameter it will get
the super class' wrapper for calling inherited methods.
*/
Class = function(className, superClass, classScope){
if(arguments.length == 2){
classScope = superClass;
if(typeof className != "string"){
superClass = className;
className = "anonymous";
}else{
superClass = Object;
}
}else if(arguments.length == 1){
classScope = className;
superClass = Object;
className = "anonymous";
}
//this is the constructor for the new objects created from the new class.
//if and only if it is NOT used for prototyping/subclassing the init method of the newly created object will be called.
var NewClass = function(calledBy){
if(calledBy !== Class){
return this.init.apply(this, arguments);
}
}
//This will create a new prototype object of the new class.
NewClass.createPrototype = function(){
return new NewClass(Class);
}
//setting class properties for the new class.
NewClass.superClass = superClass;
NewClass.className=className;
NewClass.toString = function(){
return "[class %s]".format(NewClass.className);
};
if(superClass.createPrototype!=null){//see if the super class can create prototypes. (creating an object without calling init())
NewClass.prototype = superClass.createPrototype();
}else{//just create an object of the super class
NewClass.prototype = new superClass();
}
//reset the constructor for new objects to the actual constructor.
NewClass.prototype.constructor = NewClass;
if(superClass == Object){//all other objects already have a nice toString method.
NewClass.prototype.toString = function(){
return "[object %s]".format(this.constructor.className);
};
}
if(NewClass.prototype.init==null){
NewClass.prototype.init=function(){
}
}
//create a supr function to be used to call methods of the super class
var supr = function(self){
//set up super class functionality so a call to super(this) will return an object with all super class methods
//the methods can be called like super(this).foo and the this object will be bound to that method
var wrapper = {};
var superProto = superClass.prototype;
for(var n in superProto){
if(typeof superProto[n] == "function"){
wrapper[n] = function(){
var f = arguments.callee;
return superProto[f._name].apply(self, arguments);
}
wrapper[n]._name = n;
}
}
return wrapper;
}
//execute the scope of the class
classScope(NewClass.prototype, supr);
return NewClass;
}
Class.toString = function(){
return "[object Class]";
}
Class.createPrototype=function(){
throw "Can't use Class as a super class.";
}
/**
Creates a new module and registers it.
@param name The name of the module.
@param version The version of a module.
@param moduleScope A function which is executed for module creation.
As 1st parameter it will get the module variable.
*/
Module = function(name, version, moduleScope){
var mod = new Object();
mod.version = version;
mod.name = name;
mod.toString=function(){
return "[module '%s' version: %s]".format(mod.name, mod.version);
}
/**
Base class for all module-Exceptions.
*/
mod.Exception=Class("Exception", function(publ){
/**
Initializes a new Exception.
@param msg The error message for the user.
@param trace=null The error causing this Exception if available.
*/
publ.init=function(msg, trace){
this.name = this.constructor.className;
this.message = msg;
this.trace = trace;
}
publ.toString=function(){
var s = "%s %s\n\n".format(this.name, this.module);
s += this.message;
return s;
}
/**
Returns the complete trace of the exception.
@return The error trace.
*/
publ.toTraceString=function(){
var s = "%s %s:\n ".format(this.name, this.module );
s+="%s\n\n".format(this.message);
if(this.trace){
if(this.trace.toTraceString){
s+= this.trace.toTraceString();
}else{
s+= this.trace;
}
}
return s;
}
///The name of the Exception(className).
publ.name;
///The error message.
publ.message;
///The module the Exception belongs to.
publ.module = mod;
///The error which caused the Exception or null.
publ.trace;
})
//execute the scope of the module
moduleScope(mod);
//todo: set classNames for anonymous classes.
for(var n in mod){
if(mod[n].className == "anonymous"){
mod[n].className = n;
}
}
if(name != "jsolait"){
jsolait.registerModule(mod);
}
return mod;
}
Module.toString = function(){
return "[object Module]";
}
Module.createPrototype=function(){
throw "Can't use Module as a super class.";
}
//docstart
/**
The root module for jsolait.
It provides some global functionality for loading modules,
some String enhancements.
*/
Module("jsolait", "0.1.0", function(mod){
///The global jsolait object.
jsolait=mod;
///base url for user modules.
mod.baseURL=".";
///The URL where jsolait is installed.
mod.libURL ="./jsolait";
///Collection of all loaded modules.(module cache)
mod.modules = new Array();
///The URLs of there the modules, part of jsolait.
mod.moduleURLs = {};
/*
mod.moduleURLs = {urllib:"%(libURL)s/lib/urllib.js",
xml:"%(libURL)s/lib/xml.js",
crypto:"%(libURL)s/lib/crypto.js",
codecs:"%(libURL)s/lib/codecs.js",
jsonrpc:"%(libURL)s/lib/jsonrpc.js",
lang:"%(libURL)s/lib/lang.js",
xmlrpc:"%(libURL)s/lib/xmlrpc.js"};
*/
mod.init=function(){
if(typeof(WScript) != 'undefined') {
initWS();
}
// //make jsolait work with WScript
// var ws = null;
// try{//see if WScript is available
// ws = WScript;
// }catch(e){
// }
// if(ws != null){
// initWS();
// }
}
///initializes jsolait for using it with WScript
var initWS = function(){
print=function(msg){
WScript.echo(msg);
}
alert=function(msg){
print(msg);
}
var args = WScript.arguments;
try{
//get script to execute
var url = args(0);
url = url.replace(/\\/g, "/");
url = url.split("/");
url = url.slice(0, url.length-1);
//set base for user module loading
mod.baseURL = url.join("/");
}catch(e){
throw new mod.Exception("Missing script filename to be run.", e);
}
//location of jsolait/init.js
url = WScript.ScriptFullName;
if(args(0).replace("file://","").toLowerCase() == url.toLowerCase()){
WScript.stderr.write("Can't run myself! exiting ... \n");
return;
}
url = url.replace(/\\/g, "/");
url = url.split("/");
url = url.slice(0, url.length-1);
mod.libURL = "file://" + url.join("/");
try{
mod.loadScript(args(0));
}catch(e){
WScript.stdErr.write("%s(1,1) jsolait runtime error:\n%s\n".format(args(0).replace("file://",""), e.toTraceString()));
}
}
/**
Imports a module given its name(someModule.someSubModule).
A module's file location is determined by treating each module name as a directory.
Only the last one points to a file.
If the module's URL is not known to jsolait then it will be searched for in jsolait.baseURL which is "." by default.
@param name The name of the module to load.
@return The module object.
*/
mod.importModule = function(name){
if (mod.modules[name]){ //module already loaded
return mod.modules[name];
}else{
var src,modURL;
//check if jsolait already knows the url of the module(moduleURLs contains urls to modules)
if(mod.moduleURLs[name]){
modURL = mod.moduleURLs[name].format(mod);
}else{
/*
assume it's a user module and located at baseURL
*/
modURL = "%s/%s.js".format(mod.baseURL, name.split(".").join("/"));
}
try{//to load module from location calculated above
src = getFile(modURL);
}catch(e){//module could not be found at the location.
throw new mod.ModuleImportFailed(name, modURL, e);
}
try{//interpret the script
globalEval(src);
}catch(e){
throw new mod.ModuleImportFailed(name, modURL, e);
}
//the module should have registered itself
return mod.modules[name];
}
}
//make it global
importModule = mod.importModule;
/**
Loads and interprets a script file.
@param url The url of the script to load.
*/
mod.loadScript=function(url){
var src = getFile(url);
try{//to interpret the source
globalEval(src);
}catch(e){
throw new mod.EvalFailed(url, e);
}
}
/**
Registers a new module.
Registered modules can be imported with importModule(...).
@param module The module to register.
*/
mod.registerModule = function(module){
this.modules[module.name] = module;
}
/**
Creates an HTTP request object for retreiving files.
@return HTTP request object.
*/
var getHTTP=function() {
var obj;
try{ //to get the mozilla httprequest object
obj = new XMLHttpRequest();
}catch(e){
try{ //to get MS HTTP request object
obj=new ActiveXObject("Msxml2.XMLHTTP.4.0");
}catch(e){
try{ //to get MS HTTP request object
obj=new ActiveXObject("Msxml2.XMLHTTP");
}catch(e){
try{// to get the old MS HTTP request object
obj = new ActiveXObject("microsoft.XMLHTTP");
}catch(e){
throw new mod.Exception("Unable to get an HTTP request object.");
}
}
}
}
return obj;
}
/**
Retrieves a file given its URL.
@param url The url to load.
@param headers=[] The headers to use.
@return The content of the file.
*/
var getFile=function(url, headers) {
//if callback is defined then the operation is done async
headers = (headers != null) ? headers : [];
//setup the request
try{
var xmlhttp= getHTTP();
xmlhttp.open("GET", url, false);
for(var i=0;i< headers.length;i++){
xmlhttp.setRequestHeader(headers[i][0], headers[i][1]);
}
xmlhttp.send("");
}catch(e){
throw new mod.Exception("Unable to load URL: '%s'.".format(url), e);
}
if(xmlhttp.status == 200 || xmlhttp.status == 0){
return xmlhttp.responseText;
}else{
throw new mod.Exception("File not loaded: '%s'.".format(url));
}
}
Error.prototype.toTraceString = function(){
if(this.message){
return "%s\n".format(this.message);
}
if (this.description){
return "%s\n".format(this.description);
}
return "unknown error\n";
}
/**
Thrown when a module could not be found.
*/
mod.ModuleImportFailed=Class(mod.Exception, function(publ, supr){
/**
Initializes a new ModuleImportFailed Exception.
@param name The name of the module.
@param url The url of the module.
@param trace The error cousing this Exception.
*/
publ.init=function(moduleName, url, trace){
supr(this).init("Failed to import module: '%s' from URL:'%s'".format(moduleName, url), trace);
this.moduleName = moduleName;
this.url = url;
}
///The name of the module that was not found.
publ.moduleName;
///The url the module was expected to be found at.
publ.url;
})
/**
Thrown when a source could not be loaded due to an interpretation error.
*/
mod.EvalFailed=Class(mod.Exception, function(publ, supr){
/**
Initializes a new EvalFailed exception.
@param url The url of the module.
@param trace The exception that was thrown while interpreting the module's source code.
*/
publ.init=function(url, trace){
supr(this).init("File '%s' Eval of script failed.".format(url), trace);
this.url = url;
}
///The url the module was expected to be found at.
publ.url;
})
/**
Displays an exception and it's trace.
This works better than alert(e) because traces are taken into account.
@param exception The exception to display.
*/
mod.reportException=function(exception){
if(exception.toTraceString){
var s= exception.toTraceString();
}else{
var s = exception.toString();
}
var ws = null;
try{//see if WScript is available
ws = WScript;
}catch(e){
}
if(ws != null){
WScript.stderr.write(s);
}else{
alert(s);
}
}
///The global exception report method;
reportException = mod.reportException;
})
//stringmod
/**
String formatting module.
It allows python like string formatting ("some text %s" % "something").
Also similar to sprintf from C.
*/
Module("stringformat", "0.1.0", function(mod){
/**
Creates a format specifier object.
*/
var FormatSpecifier=function(s){
var s = s.match(/%(\(\w+\)){0,1}([ 0-]){0,1}(\+){0,1}(\d+){0,1}(\.\d+){0,1}(.)/);
if(s[1]){
this.key=s[1].slice(1,-1);
}else{
this.key = null;
}
this.paddingFlag = s[2];
if(this.paddingFlag==""){
this.paddingFlag =" "
}
this.signed=(s[3] == "+");
this.minLength = parseInt(s[4]);
if(isNaN(this.minLength)){
this.minLength=0;
}
if(s[5]){
this.percision = parseInt(s[5].slice(1,s[5].length));
}else{
this.percision=-1;
}
this.type = s[6];
}
/**
Formats a string replacing formatting specifiers with values provided as arguments
which are formatted according to the specifier.
This is an implementation of python's % operator for strings and is similar to sprintf from C.
Usage:
resultString = formatString.format(value1, v2, ...);
Each formatString can contain any number of formatting specifiers which are
replaced with the formated values.
specifier([...]-items are optional):
"%(key)[flag][sign][min][percision]typeOfValue"
(key) If specified the 1st argument is treated as an object/associative array and the formating values
are retrieved from that object using the key.
flag:
0 Use 0s for padding.
- Left justify result, padding it with spaces.
Use spaces for padding.
sign:
+ Numeric values will contain a +|- infront of the number.
min:
l The string will be padded with the padding character until it has a minimum length of l.
percision:
.x Where x is the percision for floating point numbers and the lenght for 0 padding for integers.
typeOfValue:
d Signed integer decimal.
i Signed integer decimal.
b Unsigned binary. //This does not exist in python!
o Unsigned octal.
u Unsigned decimal.
x Unsigned hexidecimal (lowercase).
X Unsigned hexidecimal (uppercase).
e Floating point exponential format (lowercase).
E Floating point exponential format (uppercase).
f Floating point decimal format.
F Floating point decimal format.
c Single character (accepts byte or single character string).
s String (converts any object using object.toString()).
Examples:
"%02d".format(8) == "08"
"%05.2f".format(1.234) == "01.23"
"123 in binary is: %08b".format(123) == "123 in binary is: 01111011"
@param * Each parameter is treated as a formating value.
@return The formated String.
*/
String.prototype.format=function(){
var sf = this.match(/(%(\(\w+\)){0,1}[ 0-]{0,1}(\+){0,1}(\d+){0,1}(\.\d+){0,1}[dibouxXeEfFgGcrs%])|([^%]+)/g);
if(sf){
if(sf.join("") != this){
throw new mod.Exception("Unsupported formating string.");
}
}else{
throw new mod.Exception("Unsupported formating string.");
}
var rslt ="";
var s;
var obj;
var cnt=0;
var frmt;
var sign="";
for(var i=0;i<sf.length;i++){
s=sf[i];
if(s == "%%"){
s = "%";
}else if(s.slice(0,1) == "%"){
frmt = new FormatSpecifier(s);//get the formating object
if(frmt.key){//an object was given as formating value
if((typeof arguments[0]) == "object" && arguments.length == 1){
obj = arguments[0][frmt.key];
}else{
throw new mod.Exception("Object or associative array expected as formating value.");
}
}else{//get the current value
if(cnt>=arguments.length){
throw new mod.Exception("Not enough arguments for format string");
}else{
obj=arguments[cnt];
cnt++;
}
}
if(frmt.type == "s"){//String
if (obj == null){
obj = "null";
}
s=obj.toString().pad(frmt.paddingFlag, frmt.minLength);
}else if(frmt.type == "c"){//Character
if(frmt.paddingFlag == "0"){
frmt.paddingFlag=" ";//padding only spaces
}
if(typeof obj == "number"){//get the character code
s = String.fromCharCode(obj).pad(frmt.paddingFlag , frmt.minLength) ;
}else if(typeof obj == "string"){
if(obj.length == 1){
/*
make sure it's a single character
*/
s=obj.pad(frmt.paddingFlag, frmt.minLength);
}else{
throw new mod.Exception("Character of length 1 required.");
}
}else{
throw new mod.Exception("Character or Byte required.");
}
}else if(typeof obj == "number"){
//get sign of the number
if(obj < 0){
obj = -obj;
sign = "-"; //negative signs are always needed
}else if(frmt.signed){
sign = "+"; // if sign is always wanted add it
}else{
sign = "";
}
//do percision padding and number conversions
switch(frmt.type){
case "f": //floats
case "F":
if(frmt.percision > -1){
s = obj.toFixed(frmt.percision).toString();
}else{
s = obj.toString();
}
break;
case "E"://exponential
case "e":
if(frmt.percision > -1){
s = obj.toExponential(frmt.percision);
}else{
s = obj.toExponential();
}
s = s.replace("e", frmt.type);
break;
case "b"://binary
s = obj.toString(2);
s = s.pad("0", frmt.percision);
break;
case "o"://octal
s = obj.toString(8);
s = s.pad("0", frmt.percision);
break;
case "x"://hexadecimal
s = obj.toString(16).toLowerCase();
s = s.pad("0", frmt.percision);
break;
case "X"://hexadecimal
s = obj.toString(16).toUpperCase();
s = s.pad("0", frmt.percision);
break;
default://integers
s = parseInt(obj).toString();
s = s.pad("0", frmt.percision);
break;
}
if(frmt.paddingFlag == "0"){//do 0-padding
//make sure that the length of the possible sign is not ignored
s=s.pad("0", frmt.minLength - sign.length);
}
s=sign + s;//add sign
s=s.pad(frmt.paddingFlag, frmt.minLength);//do padding and justifiing
}else{
throw new mod.Exception("Number required.");
}
}
rslt += s;
}
return rslt;
}
/**
Padds a String with a character to have a minimum length.
@param flag "-": to padd with " " and left justify the string.
Other: the character to use for padding.
@param len The minimum length of the resulting string.
*/
String.prototype.pad = function(flag, len){
var s = "";
if(flag == "-"){
var c = " ";
}else{
var c = flag;
}
for(var i=0;i<len-this.length;i++){
s += c;
}
if(flag == "-"){
s = this + s;
}else{
s += this;
}
return s;
}
/**
Repeats a string.
@param c The count how often the string should be repeated.
*/
String.prototype.mul = function(c){
var a = new Array(this.length * c);
var s=""+ this;
for(var i=0;i<c;i++){
a[i] = s;
}
return a.join("");
}
})
//let jsolait do some startup initialization
jsolait.init();

View File

@@ -0,0 +1,168 @@
/*
Copyright (c) 2004 Jan-Klaas Kollhof
This file is part of the JavaScript o lait library(jsolait).
jsolait is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This software is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this software; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/**
Codecs for encoding decoding Strings.
To add new encoders simply create new String.prototype.encode_yourCodec methods.
To add new decoders simply create new String.prototype.decode_yourCodec methods.
*/
Module("codecs", "0.1.2", function(mod){
/**
Returns all all available encoders.
@return An array of encoder names.
*/
mod.listEncoders=function(){
var c=[];
for(var attr in String.prototype){
if(attr.slice(0, 7) == "encode_"){
c.push(attr.slice(7));
}
}
return c;
}
/**
Returns all all available decoders.
@return An array of decoder names.
*/
mod.listDecoders=function(){
var c=[];
for(var attr in String.prototype){
if(attr.slice(0, 7) == "decode_"){
c.push(attr.slice(7));
}
}
return c;
}
/**
Decodes an encoded string.
Parameters but the codec parameter are forwardet to the codec.
@param codec The codec to use.
*/
String.prototype.decode = function(codec){
var n ="decode_" + codec;
if(String.prototype[n]){
var args=[];
for(var i=1;i<arguments.length;i++){
args[i-1] = arguments[i];
}
return String.prototype[n].apply(this, args);
}else{
throw new mod.Exception("Decoder '%s' not found.".format(codec));
}
}
/**
Encodes a string.
Parameters but the codec parameter are forwardet to the codec.
@param codec The codec to use.
*/
String.prototype.encode = function(codec){
var n ="encode_" + codec;
if(String.prototype[n]){
var args=[];
for(var i=1;i<arguments.length;i++){
args[i-1] = arguments[i];
}
return String.prototype[n].apply(this, args);
}else{
throw new mod.Exception("Ecnoder '%s' not found.".format(codec));
}
}
/**
Decodes a Base64 encoded string to a byte string.
*/
String.prototype.decode_base64=function(){
if((this.length % 4) == 0){
if(typeof(atob) != "undefined"){//try using mozillas builtin codec
return atob(this);
}else{
var nBits;
//create a result buffer, this is much faster than having strings concatinated.
var sDecoded = new Array(this.length /4);
var base64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
for(var i=0; i < this.length; i+=4){
nBits = (base64.indexOf(this.charAt(i)) & 0xff) << 18 |
(base64.indexOf(this.charAt(i+1)) & 0xff) << 12 |
(base64.indexOf(this.charAt(i+2)) & 0xff) << 6 |
base64.indexOf(this.charAt(i+3)) & 0xff;
sDecoded[i] = String.fromCharCode((nBits & 0xff0000) >> 16, (nBits & 0xff00) >> 8, nBits & 0xff);
}
//make sure padding chars are left out.
sDecoded[sDecoded.length-1] = sDecoded[sDecoded.length-1].substring(0, 3 - ((this.charCodeAt(i - 2) == 61) ? 2 : (this.charCodeAt(i - 1) == 61 ? 1 : 0)));
return sDecoded.join("");
}
}else{
throw new mod.Exception("String length must be divisible by 4.");
}
}
/**
Encodes a string using Base64.
*/
String.prototype.encode_base64=function(){
if(typeof(btoa) != "undefined"){//try using mozillas builtin codec
return btoa(this);
}else{
var base64 = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
'0','1','2','3','4','5','6','7','8','9','+','/'];
var sbin;
var pad=0;
var s="" + this;
if((s.length % 3) == 1){
s+=String.fromCharCode(0);
s+=String.fromCharCode(0);
pad=2;
}else if((s.length % 3) == 2){
s+=String.fromCharCode(0);
pad=1;
}
//create a result buffer, this is much faster than having strings concatinated.
var rslt=new Array(s.length / 3);
var ri=0;
for(var i=0;i<s.length; i+=3){
sbin=((s.charCodeAt(i) & 0xff) << 16) | ((s.charCodeAt(i+1) & 0xff ) << 8) | (s.charCodeAt(i+2) & 0xff);
rslt[ri] = (base64[(sbin >> 18) & 0x3f] + base64[(sbin >> 12) & 0x3f] + base64[(sbin >>6) & 0x3f] + base64[sbin & 0x3f]);
ri++;
}
if(pad>0){
rslt[rslt.length-1] = rslt[rslt.length-1].substr(0, 4-pad) + ((pad==2) ? "==" : (pad==1) ? "=" : "");
}
return rslt.join("");
}
}
/**
Decodes a URI using decodeURI.
*/
String.prototype.decode_uri=function(){
return decodeURI(this);
}
/**
Encodes a URI using encodeURI.
*/
String.prototype.encode_uri=function(){
return encodeURI(this);
}
})

View File

@@ -0,0 +1,149 @@
/*
Copyright (c) 2003 Jan-Klaas Kollhof
This file is part of the JavaScript o lait library(jsolait).
jsolait is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This software is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this software; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/**
Cryptography module.
Provides String encryption/decryption and hashing.
*/
Module("crypto", "0.1.2", function(mod){
/**
Returns all all available encrypters.
@return An array of encrypters names.
*/
mod.listEncrypters=function(){
var c=[];
for(var attr in String.prototype){
if(attr.slice(0, 8) == "encrypt_"){
c.push(attr.slice(8));
}
}
return c;
}
/**
Returns all all available decrypters.
@return An array of decrypters names.
*/
mod.listDecrypters=function(){
var c=[];
for(var attr in String.prototype){
if(attr.slice(0, 8) == "decrypt_"){
c.push(attr.slice(8));
}
}
return c;
}
/**
Encrypts a string.
Parameters but the crypdec parameter are forwardet to the crypdec.
@param codec The codec to use.
*/
String.prototype.encrypt=function(crydec){
var n = "encrypt_" + crydec;
if(String.prototype[n]){
var args=[];
for(var i=1;i<arguments.length;i++){
args[i-1] = arguments[i];
}
return String.prototype[n].apply(this, args);
}else{
throw new mod.Exception("Decrypter '%s' not found.".format(crydec));
}
}
/**
Decrypts a string.
Parameters but the crypdec parameter are forwardet to the crypdec.
@param codec The codec to use.
*/
String.prototype.decrypt=function(crydec){
var n = "decrypt_" + crydec;
if(String.prototype[n]){
var args=[];
for(var i=1;i<arguments.length;i++){
args[i-1] = arguments[i];
}
return String.prototype[n].apply(this, args);
}else{
throw new mod.Exception("Encrypter '%s' not found.".format(crydec));
}
}
/**
Encrypts a string using XOR.
The whole String will be XORed with the key.
If the key is shorter than the String then it will be multiplied to fit the length of the String.
@param key The key to use for encryption.
*/
String.prototype.encrypt_xor=function(key){
var e=new Array(this.length);
var l=key.length;
for(var i=0;i<this.length;i++){
e[i] = String.fromCharCode(this.charCodeAt(i) ^ key.charCodeAt(i % l));
}
return e.join("");
}
/**
Decrypts a string using XOR.
Since XORing is symetric it is the same as the encrypter.
@param key The key to use for decryption.
*/
String.prototype.decrypt_xor=String.prototype.encrypt_xor;
/**
Encrypts a string using the ARC4 algorithm.
@param key The key to use for encryption.
*/
String.prototype.encrypt_rc4=function(key){
//generate substitution box
var sbox = new Array (256);
for (var i=0; i<256; i++){
sbox[i]=i;
}
//swap things around
var j=0;
for (var i=0; i < 256; i++) {
j = (j + sbox[i] + key.charCodeAt(i % key.length)) % 256;
var tmp = sbox[i];
sbox[i] = sbox[j];
sbox[j] = tmp;
}
//calculate the result
var i=256;
var j=256;
var rslt=new Array(this.length);
for (var k=0; k < this.length; k++) {
i = (i + 1) % 256;
j = (j + sbox[i]) % 256;
var tmp = sbox[i];
sbox[i] = sbox[j];
sbox[j] = tmp;
t = (sbox[i] + sbox[j]) % 256;
rslt[k] = String.fromCharCode(this.charCodeAt(k) ^ sbox[t]);
}
return rslt.join("");
}
/**
Decrypts a string using the ARC4 algorithm.
Since it is symetric it is the same as the encrypter.
@param key The key to use for decryption.
*/
String.prototype.decrypt_rc4=String.prototype.encrypt_rc4;
})

View File

@@ -0,0 +1,401 @@
/*
Copyright (c) 2003-2004 Jan-Klaas Kollhof
This file is part of the JavaScript o lait library(jsolait).
jsolait is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This software is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this software; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/**
Provides an JSON-RPC imlementation.
*/
Module("jsonrpc", "0.3.2", function(mod){
var lang = importModule("lang");
var tokens = lang.tokens;
var ObjectBuffer=Class("ObjectBuffer", function(publ, supr){
publ.init=function(){
this.data="";
}
publ.getObjects=function(data){
this.data += data;
var t = new lang.Tokenizer(this.data);
var brCnt= 0;
var objects = [];
var readCnt = 0
while(! t.finished()){
var n = t.next();
if(n.type != tokens.ERR){
if(n.value == "{"){
brCnt+=1;
}else if(n.value == "}"){
brCnt-=1;
if(brCnt==0){
var s = this.data.slice(readCnt, n.pos+1);
readCnt += s.length;
objects.push(s);
}
}
}else{
break;
}
}
this.data = this.data.slice(readCnt);
return objects;
}
})
var nameAllowed=function(name){
return name.match(/^[a-zA-Z]\w*$/) != null;
}
var getMethodByName=function(obj, name){
try{//to get a method by asking the service
obj = obj._getMethodByName(name)
}catch(e){
var names = name.split(".");
for(var i=0;i<names.length;i++){
name = names[i];
if(nameAllowed(name)){
obj = obj[name];
}
}
}
return obj;
}
var Response=Class("Response", function(publ, supr){
publ.init=function(id, result, error){
this.id=id;
this.result = result;
this.error = error;
}
publ._toJSON=function(){
var p = [lang.objToJson(this.id), lang.objToJson(this.result),lang.objToJson(this.error)];
return '{"id":' + p[0] + ', "result":' + p[1] + ', "error":' + p[2] + "}";
}
})
var Request=Class("Request", function(publ, supr){
publ.init=function(id, method, params){
this.id=id;
this.method = method;
this.params = params;
/*
var str = '';
for(hello in this.params)
{
str += "var:"+hello+":"+this.params[hello]+":\n";
}
alert(str);
*/
}
publ._toJSON=function(){
var p = [lang.objToJson(this.id), lang.objToJson(this.method),lang.objToJson(this.params)];
return '{"id":' + p[0] + ', "method":' + p[1] + ', "params":' + p[2] + "}";
}
})
var Notification=Class("Notification", function(publ, supr){
publ.init=function(method, params){
this.method = method;
this.params = params;
}
publ._toJSON=function(){
var p = [lang.objToJson(this.method),lang.objToJson(this.params)];
return '{"method":' + p[0] + ', "params":' + p[1] + "}";
}
})
var ResponseHandler=Class("ResponseHandler", function(publ, supr){
publ.init=function(callback){
this.callback=callback;
}
publ.handleResponse=function(resp){
this.callback(resp.result, resp.error);
}
})
var RPCLib = Class("RPCLib", function(publ, supr){
})
var BaseConnectionHandler = Class("BaseConnectionHandler", function(publ, supr){
publ.init=function(service){
this.service = service;
this.jsonParser = new lang.JSONParser();
this.jsonParser.addLib(new RPCLib(), "rpc", []);
this.respHandlers = [];
this.objBuffer = new ObjectBuffer();
}
publ.addResponseHandler=function(cb){
var id=1;
while(this.respHandlers[""+id] ){
id+=1;
}
id="" + id;
this.respHandlers[id] = new ResponseHandler(cb);
return id;
}
publ.send = function(data){
}
publ.sendNotify = function(name, args){
var n = new Notification(name, args);
n = this.jsonParser.objToJson(n);
this.send(n)
}
publ.sendRequest = function(name, args, callback){
var id = this.addResponseHandler(callback);
var r = new Request(id, name, args);
r = this.jsonParser.objToJson(r);
this.send(r);
}
publ.sendResponse = function(id, result, error){
var r = new Response(id, result, error);
r = this.jsonParser.objToJson(r);
this.send(r);
}
publ.handleRequest = function(req){
var name = req.method;
var params = req.params;
var id=req.id;
if(this.service[name]){
try{
var rslt = this.service[name].apply(this.service,params);
this.sendResponse(id, rslt, null)
}catch(e){
this.sendResponse(id, null, new ApplicationError("" + e))
}
}else{
this.sendResponse(id, null, new MethodNotFound());
}
}
publ.handleNotification = function(notif){
if(this.service[notif.method]){
try{
this.service[notif.method].apply(this.service, notif.params);
}catch(e){
}
}
}
publ.handleResponse = function(resp){
var id=resp.id;
var h = this.respHandlers[id];
h.handleResponse(resp)
delete this.respHandlers[id]
}
publ.handleData = function(data){
var objs = this.objBuffer.getObjects(data);
for(var i=0;i<objs.length;i++){
try{
var obj = this.jsonParser.jsonToObj(objs[i]);
}catch(e){
throw "Not well formed";
}
if(obj.method != null){
if(obj.id != null){
this.handleRequest(new Request(obj.id, obj.method, obj.params));
}else{
this.handleNotification(new Notification(obj.method, obj.params));
}
}else if(obj.id != null){
this.handleResponse(new Response(obj.id, obj.result, obj.error));
}else{
throw "Unknown Data";
}
}
}
})
var SocketConnectionHandler = Class("SocketConnectionHandler", BaseConnectionHandler, function(publ, supr){
publ.init=function(socket, localService){
this.socket = socket;
socket.addEventListener("connectionData", this, false);
supr(this).init( localService);
}
publ.handleEvent=function(evt){
this.handleData(evt.data);
}
publ.send=function(data){
this.socket.send(data);
}
publ.close=function(data){
this.socket.close();
}
})
var HTTPConnectionHandler = Class("HTTPConnectionHandler", BaseConnectionHandler, function(publ, supr){
var urllib;
publ.request_id = 1;
publ.init=function(url, localService){
urllib=importModule("urllib");
this.url = url;
supr(this).init( localService);
}
publ.handleData = function(data){
try{
var obj = JSON.parse(data);
}catch(e){;
throw " Not well formed\n\n" + e + "\n\nResponse from server:\n\n " + data;
}
if(obj.id != null){
return obj;
}else{
throw "Unknown Data (No id property found)";
}
}
publ.sendRequest = function(name, args, callback){
var sync = false;
if(typeof callback != "function"){//see if it is sync
args.push(callback);
sync=true;
}
var data = new Request(this.request_id++, name, args);
// cn: bug 12274 - defend against CSRF
data = JSON.stringify(data); // creates security envelope wrapped JSON object
if(sync){
var rsp = urllib.postURL(this.url, data, [["Content-Type", "text/plain"]]);
rsp = this.handleData(rsp.responseText);
if(rsp.error){
throw rsp.error;
}else{
return rsp.result;
}
}else{//async connection uses the respHandler to handle the repsonse
var self = this;
var request_id = this.request_id;
urllib.postURL(this.url, data, [["Content-Type", "text/plain"]], function(rsp){
try{
rsp = self.handleData(rsp.responseText);
}catch(e){
//callback(null,e);
callback(request_id,null,e);
return;
}
callback(request_id,rsp.result, rsp.error);
//callback(this.request_id,rsp.result, rsp.error);
//callback(rsp.result, rsp.error);
});
}
}
publ.sendNotify = function(name, args){
var data = new Notification(name, args);
data = this.jsonParser.objToJson(data);
urllib.postURL(this.url, data, [["Content-Type", "text/plain"]], function(rsp){});
}
})
var PeerObject=Class("PeerObject", function(publ, supr){
publ.init=function(name, conn){
var fn=function(){
var args=[];
for(var i=0;i<arguments.length;i++){
args[i] = arguments[i];
}
var cb=args.pop();
return conn.sendRequest(name, args, cb);
}
return fn;
}
})
var PeerNotifyObject=Class("PeerNotifyObject", function(publ, supr){
publ.init=function(name, conn){
var fn=function(){
var args=[];
for(var i=0;i<arguments.length;i++){
args[i] = arguments[i];
}
conn.sendNotify(name, args);
}
return fn;
}
})
var BasePeer = Class("BasePeer", function(publ, supr){
publ.init=function(conn, methodNames){
this._conn = conn;
this.notify = new PeerObject("notify", conn);
this._add(methodNames);
}
var setupPeerMethod=function(root, methodName, conn, MethClass){
var names = methodName.split(".");
var obj = root;
for(var n=0;n<names.length-1;n++){
var name = names[n];
if(obj[name]){
obj = obj[name];
}else{
obj[name] = new Object();
obj = obj[name];
}
}
var name = names[names.length-1];
if(obj[name]){
}else{
var mth = new MethClass(methodName, conn);
obj[name] = mth;
}
}
publ._add = function(methodNames){
for(var i=0;i<methodNames.length;i++){
setupPeerMethod(this, methodNames[i], this._conn, PeerObject);
setupPeerMethod(this.notify, methodNames[i], this._conn, PeerNotifyObject);
}
}
})
mod.ServiceProxy = Class("ServiceProxy", BasePeer, function(publ, supr){
publ.init = function(url, methodNames, localService){
var n = url.match(/^jsonrpc:\/\/(.*:\d*)$/);
if(n!=null){//is it json-rpc over TCP protocoll
var hostaddr = n[1];
try{
var socket = createConnection();
}catch(e){
throw "Can't create a socket connection."
}
socket.connect(hostaddr);
supr(this).init( new SocketConnectionHandler(socket, localService), methodNames);
}else{//or is it json-rpc over http
this.httpConn = new HTTPConnectionHandler(url, localService);
supr(this).init( this.httpConn, methodNames);
}
}
})
})

View File

@@ -0,0 +1,406 @@
/*
Copyright (c) 2003-2004 Jan-Klaas Kollhof
This file is part of the JavaScript o lait library(jsolait).
jsolait is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This software is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this software; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/**
// SUGARCRM:
// USES the langlite.php instead of lang.php
Provides an JSON-RPC imlementation.
*/
Module("jsonrpclite", "0.3.2", function(mod){
// SUGARCRM:
var lang = importModule("langlite");
// END SUGARCRM
var tokens = lang.tokens;
var ObjectBuffer=Class("ObjectBuffer", function(publ, supr){
publ.init=function(){
this.data="";
}
publ.getObjects=function(data){
this.data += data;
var t = new lang.Tokenizer(this.data);
var brCnt= 0;
var objects = [];
var readCnt = 0
while(! t.finished()){
var n = t.next();
if(n.type != tokens.ERR){
if(n.value == "{"){
brCnt+=1;
}else if(n.value == "}"){
brCnt-=1;
if(brCnt==0){
var s = this.data.slice(readCnt, n.pos+1);
readCnt += s.length;
objects.push(s);
}
}
}else{
break;
}
}
this.data = this.data.slice(readCnt);
return objects;
}
})
var nameAllowed=function(name){
return name.match(/^[a-zA-Z]\w*$/) != null;
}
var getMethodByName=function(obj, name){
try{//to get a method by asking the service
obj = obj._getMethodByName(name)
}catch(e){
var names = name.split(".");
for(var i=0;i<names.length;i++){
name = names[i];
if(nameAllowed(name)){
obj = obj[name];
}
}
}
return obj;
}
var Response=Class("Response", function(publ, supr){
publ.init=function(id, result, error){
this.id=id;
this.result = result;
this.error = error;
}
publ._toJSON=function(){
var p = [lang.objToJson(this.id), lang.objToJson(this.result),lang.objToJson(this.error)];
return '{"id":' + p[0] + ', "result":' + p[1] + ', "error":' + p[2] + "}";
}
})
var Request=Class("Request", function(publ, supr){
publ.init=function(id, method, params){
this.id=id;
this.method = method;
this.params = params;
/*
var str = '';
for(hello in this.params)
{
str += "var:"+hello+":"+this.params[hello]+":\n";
}
alert(str);
*/
}
publ._toJSON=function(){
var p = [lang.objToJson(this.id), lang.objToJson(this.method),lang.objToJson(this.params)];
return '{"id":' + p[0] + ', "method":' + p[1] + ', "params":' + p[2] + "}";
}
})
var Notification=Class("Notification", function(publ, supr){
publ.init=function(method, params){
this.method = method;
this.params = params;
}
publ._toJSON=function(){
var p = [lang.objToJson(this.method),lang.objToJson(this.params)];
return '{"method":' + p[0] + ', "params":' + p[1] + "}";
}
})
var ResponseHandler=Class("ResponseHandler", function(publ, supr){
publ.init=function(callback){
this.callback=callback;
}
publ.handleResponse=function(resp){
this.callback(resp.result, resp.error);
}
})
var RPCLib = Class("RPCLib", function(publ, supr){
})
var BaseConnectionHandler = Class("BaseConnectionHandler", function(publ, supr){
publ.init=function(service){
this.service = service;
this.jsonParser = new lang.JSONParser();
this.jsonParser.addLib(new RPCLib(), "rpc", []);
this.respHandlers = [];
this.objBuffer = new ObjectBuffer();
}
publ.addResponseHandler=function(cb){
var id=1;
while(this.respHandlers[""+id] ){
id+=1;
}
id="" + id;
this.respHandlers[id] = new ResponseHandler(cb);
return id;
}
publ.send = function(data){
}
publ.sendNotify = function(name, args){
var n = new Notification(name, args);
n = this.jsonParser.objToJson(n);
this.send(n)
}
publ.sendRequest = function(name, args, callback){
var id = this.addResponseHandler(callback);
var r = new Request(id, name, args);
r = this.jsonParser.objToJson(r);
this.send(r);
}
publ.sendResponse = function(id, result, error){
var r = new Response(id, result, error);
r = this.jsonParser.objToJson(r);
this.send(r);
}
publ.handleRequest = function(req){
var name = req.method;
var params = req.params;
var id=req.id;
if(this.service[name]){
try{
var rslt = this.service[name].apply(this.service,params);
this.sendResponse(id, rslt, null)
}catch(e){
this.sendResponse(id, null, new ApplicationError("" + e))
}
}else{
this.sendResponse(id, null, new MethodNotFound());
}
}
publ.handleNotification = function(notif){
if(this.service[notif.method]){
try{
this.service[notif.method].apply(this.service, notif.params);
}catch(e){
}
}
}
publ.handleResponse = function(resp){
var id=resp.id;
var h = this.respHandlers[id];
h.handleResponse(resp)
delete this.respHandlers[id]
}
publ.handleData = function(data){
var objs = this.objBuffer.getObjects(data);
for(var i=0;i<objs.length;i++){
try{
var obj = this.jsonParser.jsonToObj(objs[i]);
}catch(e){
throw "Not well formed";
}
if(obj.method != null){
if(obj.id != null){
this.handleRequest(new Request(obj.id, obj.method, obj.params));
}else{
this.handleNotification(new Notification(obj.method, obj.params));
}
}else if(obj.id != null){
this.handleResponse(new Response(obj.id, obj.result, obj.error));
}else{
throw "Unknown Data";
}
}
}
})
var SocketConnectionHandler = Class("SocketConnectionHandler", BaseConnectionHandler, function(publ, supr){
publ.init=function(socket, localService){
this.socket = socket;
socket.addEventListener("connectionData", this, false);
supr(this).init( localService);
}
publ.handleEvent=function(evt){
this.handleData(evt.data);
}
publ.send=function(data){
this.socket.send(data);
}
publ.close=function(data){
this.socket.close();
}
})
var HTTPConnectionHandler = Class("HTTPConnectionHandler", BaseConnectionHandler, function(publ, supr){
var urllib;
publ.request_id = 1;
publ.init=function(url, localService){
urllib=importModule("urllib");
this.url = url;
supr(this).init( localService);
}
publ.handleData = function(data){
try{
var obj = JSON.parse(data);
}catch(e){;
throw " Not well formed\n\n" + e + "\n\nResponse from server:\n\n " + data;
}
if(obj.id != null){
return obj;
}else{
throw "Unknown Data (No id property found)";
}
}
publ.sendRequest = function(name, args, callback){
var sync = false;
if(typeof callback != "function"){//see if it is sync
args.push(callback);
sync=true;
}
var data = new Request(this.request_id++, name, args);
// cn: bug 12274 - defend against CSRF
data = JSON.stringify(data); // creates security envelope wrapped JSON object
if(sync){
var rsp = urllib.postURL(this.url, data, [["Content-Type", "text/plain"]]);
rsp = this.handleData(rsp.responseText);
if(rsp.error){
throw rsp.error;
}else{
return rsp.result;
}
}else{//async connection uses the respHandler to handle the repsonse
var self = this;
var request_id = this.request_id;
urllib.postURL(this.url, data, [["Content-Type", "text/plain"]], function(rsp){
try{
rsp = self.handleData(rsp.responseText);
}catch(e){
//callback(null,e);
callback(request_id,null,e);
return;
}
callback(request_id,rsp.result, rsp.error);
//callback(this.request_id,rsp.result, rsp.error);
//callback(rsp.result, rsp.error);
});
}
}
publ.sendNotify = function(name, args){
var data = new Notification(name, args);
data = this.jsonParser.objToJson(data);
urllib.postURL(this.url, data, [["Content-Type", "text/plain"]], function(rsp){});
}
})
var PeerObject=Class("PeerObject", function(publ, supr){
publ.init=function(name, conn){
var fn=function(){
var args=[];
for(var i=0;i<arguments.length;i++){
args[i] = arguments[i];
}
var cb=args.pop();
return conn.sendRequest(name, args, cb);
}
return fn;
}
})
var PeerNotifyObject=Class("PeerNotifyObject", function(publ, supr){
publ.init=function(name, conn){
var fn=function(){
var args=[];
for(var i=0;i<arguments.length;i++){
args[i] = arguments[i];
}
conn.sendNotify(name, args);
}
return fn;
}
})
var BasePeer = Class("BasePeer", function(publ, supr){
publ.init=function(conn, methodNames){
this._conn = conn;
this.notify = new PeerObject("notify", conn);
this._add(methodNames);
}
var setupPeerMethod=function(root, methodName, conn, MethClass){
var names = methodName.split(".");
var obj = root;
for(var n=0;n<names.length-1;n++){
var name = names[n];
if(obj[name]){
obj = obj[name];
}else{
obj[name] = new Object();
obj = obj[name];
}
}
var name = names[names.length-1];
if(obj[name]){
}else{
var mth = new MethClass(methodName, conn);
obj[name] = mth;
}
}
publ._add = function(methodNames){
for(var i=0;i<methodNames.length;i++){
setupPeerMethod(this, methodNames[i], this._conn, PeerObject);
setupPeerMethod(this.notify, methodNames[i], this._conn, PeerNotifyObject);
}
}
})
mod.ServiceProxy = Class("ServiceProxy", BasePeer, function(publ, supr){
publ.init = function(url, methodNames, localService){
var n = url.match(/^jsonrpc:\/\/(.*:\d*)$/);
if(n!=null){//is it json-rpc over TCP protocoll
var hostaddr = n[1];
try{
var socket = createConnection();
}catch(e){
throw "Can't create a socket connection."
}
socket.connect(hostaddr);
supr(this).init( new SocketConnectionHandler(socket, localService), methodNames);
}else{//or is it json-rpc over http
this.httpConn = new HTTPConnectionHandler(url, localService);
supr(this).init( this.httpConn, methodNames);
}
}
})
})

View File

@@ -0,0 +1,485 @@
/*
Copyright (c) 2004 Jan-Klaas Kollhof
This file is part of the JavaScript o lait library(jsolait).
jsolait is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This software is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this software; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/**
Module providing language services like tokenizing JavaScript code
or converting JavaScript objects to and from JSON (see json.org).
To customize JSON serialization of Objects just overwrite the toJSON method in your class.
*/
Module("lang", "0.3.7", function(mod){
var ISODate = function(d){
if(/^(\d{4})(\d{2})(\d{2})T(\d{2}):(\d{2}):(\d{2})/.test(d)){
return new Date(Date.UTC(RegExp.$1, RegExp.$2-1, RegExp.$3, RegExp.$4, RegExp.$5, RegExp.$6));
}else{ //todo error message
throw new mod.Exception("Not an ISO date: " + d);
}
}
mod.JSONParser=Class("JSONParser", function(publ, supr){
publ.init=function(){
this.libs = {};
var sys = {"ISODate" : ISODate};
this.addLib(sys, "sys", ["ISODate"]);
}
publ.addLib = function(obj, name, exports){
if(exports == null){
this.libs[name] = obj;
}else{
for(var i=0;i<exports.length;i++){
this.libs[name + "." + exports[i]] = obj[exports[i]];
}
}
}
var EmptyValue = {};
var SeqSep = {};
var parseValue = function(tkns, libs){
var tkn = tkns.nextNonWS();
switch(tkn.type){
case mod.tokens.STR:
case mod.tokens.NUM:
return eval(tkn.value);
case mod.tokens.NAME:
return parseName(tkn.value);
case mod.tokens.OP:
switch(tkn.value){
case "[":
return parseArray(tkns, libs);
break;
case "{":
return parseObj(tkns, libs);
break;
case "}": case "]":
return EmptyValue;
case ",":
return SeqSep;
default:
throw new mod.Exception("expected '[' or '{' but found: '" + tkn.value + "'");
}
}
return EmptyValue;
}
var parseArray = function(tkns, libs){
var a = [];
while(! tkns.finished()){
var v = parseValue(tkns, libs);
if(v == EmptyValue){
return a;
}else{
a.push(v);
v = parseValue(tkns, libs);
if(v == EmptyValue){
return a;
}else if(v != SeqSep){
throw new mod.Exception("',' expected but found: '" + v + "'");
}
}
}
throw new mod.Exception("']' expected");
}
var parseObj = function(tkns, libs){
var obj = {};
var nme =""
while(! tkns.finished()){
var tkn = tkns.nextNonWS();
if(tkn.type == mod.tokens.STR){
var nme = eval(tkn.value);
tkn = tkns.nextNonWS();
if(tkn.value == ":"){
var v = parseValue(tkns, libs);
if(v == SeqSep || v == EmptyValue){
throw new mod.Exception("value expected");
}else{
obj[nme] = v;
v = parseValue(tkns, libs);
if(v == EmptyValue){
return transformObj(obj, libs);
}else if(v != SeqSep){
throw new mod.Exception("',' expected");
}
}
}else{
throw new mod.Exception("':' expected but found: '" + tkn.value + "'");
}
}else if(tkn.value == "}"){
return transformObj(obj, libs);
}else{
throw new mod.Exception("String expected");
}
}
throw new mod.Exception("'}' expected.")
}
var transformObj = function(obj, libs){
var o2;
if(obj.jsonclass != null){
var clsName = obj.jsonclass[0];
var params = obj.jsonclass[1]
if(libs[clsName]){
o2 = libs[clsName].apply(this, params);
for(var nme in obj){
if(nme != "jsonclass"){
if(typeof obj[nme] != "function"){
o2[nme] = obj[nme];
}
}
}
}else{
throw new mod.Exception("jsonclass not found: " + clsName);
}
}else{
o2 = obj;
}
return o2;
}
var parseName = function(name){
switch(name){
case "null":
return null;
case "true":
return true;
case "false":
return false;
default:
throw new mod.Exception("'null', 'true', 'false' expected but found: '" + name + "'");
}
}
publ.jsonToObj = function(data){
var t = new mod.Tokenizer(data);
return parseValue(t, this.libs);
}
publ.objToJson=function(obj){
if(obj == null){
return "null";
}else{
return obj.toJSON();
}
}
})
mod.parser = new mod.JSONParser();
/**
Turns JSON code into JavaScript objects.
@param src The source as a String.
*/
mod.jsonToObj=function(src){
return mod.parser.jsonToObj(src);
}
/**
Turns an object into JSON.
This is the same as calling obj.toJSON();
@param obj The object to marshall.
*/
mod.objToJson=function(obj){
return mod.parser.objToJson(obj);
}
///Token constants for the tokenizer.
mod.tokens = {};
mod.tokens.WSP = 0;
mod.tokens.OP =1;
mod.tokens.STR = 2;
mod.tokens.NAME = 3;
mod.tokens.NUM = 4;
mod.tokens.ERR = 5;
mod.tokens.NL = 6;
mod.tokens.COMMENT = 7;
mod.tokens.DOCCOMMENT = 8;
mod.tokens.REGEXP = 9;
//todo:doc
mod.Token=Class(function(publ, supr){
publ.init=function(type, value, pos, err){
this.type = type;
this.value = value;
this.pos = pos;
this.err= err;
}
})
/**
Tokenizer Class which incrementally parses JavaScript code and returns the language tokens.
*/
mod.Tokenizer=Class("Tokenizer", function(publ, supr){
publ.init=function(s){
this._working = s;
this._pos = 0;
}
/**
Returns weather or not the code was parsed.
@return True if the complete code was parsed, false otherwise.
*/
publ.finished=function(){
return this._working.length == 0;
}
publ.nextNonWS = function(nlIsWS){
var tkn = this.next();
while((tkn.type == mod.tokens.WSP) || (nlIsWS && (tkn.type == mod.tokens.NL))){
tkn = this.next();
}
return tkn;
}
/**
Returns the next token.
@return The next token.
*/
publ.next = function(){
if(this._working ==""){
throw new mod.Exception("Empty");
}
var s1 = this._working.charAt(0);
var s2 = s1 + this._working.charAt(1);
var s3 = s2 + this._working.charAt(2);
var rslt=[];
switch(s1){
case '"': case "'":
try{
s1 = extractQString(this._working);
rslt= new mod.Token(mod.tokens.STR, s1, this._pos);
}catch(e){
rslt= new mod.Token(mod.tokens.ERR, s1, this._pos, e);
}
break;
case "\n": case "\r":
rslt =new mod.Token(mod.tokens.NL, s1, this._pos);
break;
case "-": //check for negative numbers
s1=this._working.match(/-\d+\.\d+|-\d+/)[0];
if(/^-\d|-\d\.\d/.test(s1)){//number
rslt = new mod.Token(mod.tokens.NUM, s1, this._pos);
break;
}
case "{": case "}": case "[": case "]": case "(": case ")":
case ":": case ",": case ".": case ";":
case "*": case "-": case "+":
case "=": case "<": case ">": case "!":
case "|": case "&":
switch(s2){
case "==": case "!=": case "<>": case "<=": case ">=":case "||": case "&&":
rslt = new mod.Token(mod.tokens.OP, s2, this._pos);
break;
default:
rslt = new mod.Token(mod.tokens.OP, s1, this._pos);
}
break;
case "/":
if(s2 == "//" || s3 =="///"){
s1 = extractSLComment(this._working);
rslt = new mod.Token(s1.charAt(2) != "/" ? mod.tokens.COMMENT:mod.tokens.DOCCOMMENT, s1, this._pos);
}else if(s2 == "/*" || s3 =="/**"){
try{
s1 = extractMLComment(this._working);
rslt = new mod.Token(s3 !="/**" ? mod.tokens.COMMENT: mod.tokens.DOCCOMMENT, s1, this._pos);
}catch(e){
rslt= new mod.Token(mod.tokens.ERR, s3 != "/**" ? s2 : s3, this._pos, e);
}
}else{
try{
s1 = extractRegExp(this._working);
rslt = new mod.Token(mod.tokens.REGEXP, s1, this._pos);
}catch(e){
rslt = new mod.Token(mod.tokens.OP, s1, this._pos, e);
}
}
break;
case " ":
var i = 0;
var s="";
while(this._working.charAt(i) == " "){
s+=" ";
i++;
}
rslt = new mod.Token(mod.tokens.WSP, s, this._pos);
break;
default:
s1=this._working.match(/\d+\.\d+|\d+|\w+/)[0];
if(/^\d|\d\.\d/.test(s1)){//number
rslt = new mod.Token(mod.tokens.NUM, s1, this._pos);
}else{//name
rslt =new mod.Token(mod.tokens.NAME, s1, this._pos);
}
}
this._working=this._working.slice(rslt.value.length);
this._pos += rslt.value.length;
return rslt;
}
var searchQoute = function(s, q){
if(q=="'"){
return s.search(/[\\']/);
}else{
return s.search(/[\\"]/);
}
}
var extractQString=function(s){
if(s.charAt(0) == "'"){
var q="'";
}else{
var q='"';
}
s=s.slice(1);
var rs="";
var p= searchQoute(s, q);
while(p >= 0){
if(p >=0){
if(s.charAt(p) == q){
rs += s.slice(0, p+1);
s = s.slice(p+1);
return q + rs;
}else{
rs+=s.slice(0, p+2);
s = s.slice(p+2);
}
}
p = searchQoute(s, q);
}
throw new mod.Exception("End of String expected.");
}
var extractSLComment=function(s){
var p = s.search(/\n/);
if(p>=0){
return s.slice(0,p+1);
}else{
return s;
}
}
var extractMLComment=function(s){
var p = s.search(/\*\//);
if(p>=0){
return s.slice(0,p+2);
}else{
throw new mod.Exception("End of comment expected.");
}
}
var extractRegExp=function(s){
var p=0;
for(var i=0;i<s.length;i++){
if(s.charAt(i) == "/"){
p=i;
}
if(s.charAt(i) == "\n"){
i = s.length;
}
}
return s.slice(0,p+1);
}
})
/**
Converts an object to JSON.
*/
Object.prototype.toJSON = function(){
var v=[];
for(attr in this){
if(typeof this[attr] != "function"){
v.push('"' + attr + '": ' + mod.objToJson(this[attr]));
}
}
return "{" + v.join(", ") + "}";
}
/**
Converts a String to JSON.
*/
String.prototype.toJSON = function(){
var s = '"' + this.replace(/(["\\])/g, '\\$1') + '"';
s = s.replace(/(\n)/g,"\\n");
return s;
}
/**
Converts a Number to JSON.
*/
Number.prototype.toJSON = function(){
return this.toString();
}
/**
Converts a Boolean to JSON.
*/
Boolean.prototype.toJSON = function(){
return this.toString();
}
/**
Converts a Date to JSON.
Date representation is not defined in JSON.
*/
Date.prototype.toJSON= function(){
var padd=function(s, p){
s=p+s
return s.substring(s.length - p.length)
}
var y = padd(this.getUTCFullYear(), "0000");
var m = padd(this.getUTCMonth() + 1, "00");
var d = padd(this.getUTCDate(), "00");
var h = padd(this.getUTCHours(), "00");
var min = padd(this.getUTCMinutes(), "00");
var s = padd(this.getUTCSeconds(), "00");
var isodate = y + m + d + "T" + h + ":" + min + ":" + s
return '{"jsonclass":["sys.ISODate", ["' + isodate + '"]]}';
}
/**
Converts an Array to JSON.
*/
Array.prototype.toJSON = function(){
var v = [];
for(var i=0;i<this.length;i++){
v.push(mod.objToJson(this[i])) ;
}
return "[" + v.join(", ") + "]";
}
mod.test=function(){
try{
print(mod.jsonToObj("['sds', -12377,-1212.1212, 12, '-2312']").toJSON());
}catch(e){
print(e.toTraceString());
}
}
})

View File

@@ -0,0 +1,138 @@
/*
Copyright (c) 2004 Jan-Klaas Kollhof
This file is part of the JavaScript o lait library(jsolait).
jsolait is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This software is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this software; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/**
FOR SUGARCRM
This is a stripped down version of lang.php, all it does is:
convert JavaScript objects to JSON (see json.org).
but *does not* add toJSON() function to every class that is derived from Object
*/
Module("langlite", "0.3.7", function(mod){
mod.JSONParser=Class("JSONParser", function(publ, supr){
publ.init=function(){
this.libs = {};
}
publ.addLib = function(obj, name, exports){
if(exports == null){
this.libs[name] = obj;
}else{
for(var i=0;i<exports.length;i++){
this.libs[name + "." + exports[i]] = obj[exports[i]];
}
}
}
publ.objToJson=function(obj){
if(obj == null){
return "null";
}else{
return mod.objToJson(obj);
}
}
})
mod.parser = new mod.JSONParser();
/**
Turns JSON code into JavaScript objects.
@param src The source as a String.
*/
mod.jsonToObj=function(src){
return mod.parser.jsonToObj(src);
}
var json_types = new Object();
json_types['object'] = function(obj){
var v=[];
for(attr in obj){
if(typeof obj[attr] != "function"){
v.push('"' + attr + '": ' + mod.objToJson(obj[attr]));
}
}
return "{" + v.join(", ") + "}";
}
json_types['string'] = function(obj){
var s = '"' + obj.replace(/(["\\])/g, '\\$1') + '"';
s = s.replace(/(\n)/g,"\\n");
return s;
}
json_types['number'] = function(obj){
return obj.toString();
}
json_types['boolean'] = function(obj){
return obj.toString();
}
json_types['date'] = function(obj){
var padd=function(s, p){
s=p+s
return s.substring(s.length - p.length)
}
var y = padd(obj.getUTCFullYear(), "0000");
var m = padd(obj.getUTCMonth() + 1, "00");
var d = padd(obj.getUTCDate(), "00");
var h = padd(obj.getUTCHours(), "00");
var min = padd(obj.getUTCMinutes(), "00");
var s = padd(obj.getUTCSeconds(), "00");
var isodate = y + m + d + "T" + h + ":" + min + ":" + s
return '{"jsonclass":["sys.ISODate", ["' + isodate + '"]]}';
}
json_types['array'] = function(obj){
var v = [];
for(var i=0;i<obj.length;i++){
v.push(mod.objToJson(obj[i])) ;
}
return "[" + v.join(", ") + "]";
}
mod.objToJson=function(obj){
if ( typeof(obj) == 'undefined')
{
return '';
}
if ( typeof(json_types[typeof(obj)]) == 'undefined')
{
alert('class not defined for toJSON():'+typeof(obj));
}
return json_types[typeof(obj)](obj);
}
mod.test=function(){
try{
print(mod.objToJson(['sds', -12377,-1212.1212, 12, '-2312']));
}catch(e){
print(e.toTraceString());
}
}
})

View File

@@ -0,0 +1,312 @@
/*
Copyright (c) 2003 Jan-Klaas Kollhof
This file is part of the JavaScript o lait library(jsolait).
jsolait is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This software is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this software; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/**
Provides methods for making HTTP requests.
*/
Module("urllib","1.1.3", function(mod){
/**
Thrown if no request object could be instanciated.
*/
mod.NoHTTPRequestObject=Class("NoHTTPRequestObject", mod.Exception, function(publ, supr){
/**
Initializes the Exception.
@param trace The error causing this exception.
*/
publ.init=function(trace){
supr(this).init( "Could not create an HTTP request object", trace);
}
})
/**
Thrown if an HTTP request could not be opened.
*/
mod.RequestOpenFailed = Class("RequestOpenFailed", mod.Exception, function(publ, supr){
/**
Initializes the Exception.
@param trace The error causing this exception.
*/
publ.init=function(trace){
supr(this).init( "Opening of HTTP request failed.", trace);
}
})
/**
Thrown is arequest could not be sent to the server.
*/
mod.SendFailed=Class("SendFailed", mod.Exception, function(publ, supr){
/**
Initializes the Exception.
@param trace The error causing this exception.
*/
publ.init = function(trace){
supr(this).init( "Sending of HTTP request failed.", trace);
}
})
/**
Mimics the HTTPRequest object using Adobe's SVG Viewer's postURL and getURL.
It can only process asyncronous connection and the only header that's supported is 'Content-Type'.
*/
var ASVRequest=Class("ASVRequest", function(publ){
/**
Initializes the ASVRequest.
*/
publ.init = function(){
if((getURL==null) || (postURL==null)){
throw "getURL and postURL are not available!";
}else{
this.readyState=0;
this.responseText="";
this.__contType ="";
this.status=200;
}
}
/**
Mimics the open method without actually opening a connection.
@param type "GET" or "POST".
@param url The url to open.
@param async=true True for async. connection. Otherwhise an exception is thrown.
*/
publ.open=function(type,url,async){
if (async == false){
throw "Can only open asynchronous connections!";
}
this.__type = type;
this.__url = url;
this.readyState=0;
}
/**
Sets a header.
@param name The header name. All but "Content-Type" are ignored.
@param value The value of the header.
*/
publ.setRequestHeader=function(name, value){
if (name=="Content-Type"){
this.__contType =value;
}
}
/**
Sends the request.
@param data The data to send when doing a post.
*/
publ.send=function(data){
var self=this;
var cbh=new Object();
cbh.operationComplete = function(rsp){
self.readyState=4;
self.responseText=rsp.content;
if(this.ignoreComplete == false){
if(self.onreadystatechange){
self.onreadystatechange();
}
}
}
cbh.ignoreComplete = false;
try{
if(this.__type =="GET"){
getURL(this.__url,cbh);
}else if (this.__type == "POST"){
postURL(this.__url, data, cbh, this.__contType);
}
}catch(e){
cbh.ignoreComplete=true;
throw e;
}
}
})
/**
Creates an HTTP request object for retreiving files.
@return HTTP request object.
*/
var getHTTP=function() {
var obj;
try{ //to get the mozilla httprequest object
obj = new XMLHttpRequest();
}catch(e){
try{ //to get MS HTTP request object
obj=new ActiveXObject("Msxml2.XMLHTTP.4.0");
}catch(e){
try{ //to get MS HTTP request object
obj=new ActiveXObject("Msxml2.XMLHTTP")
}catch(e){
try{// to get the old MS HTTP request object
obj = new ActiveXObject("microsoft.XMLHTTP");
}catch(e){
try{//to create the ASV request object.
obj = new ASVRequest();
}catch(e){
throw new mod.NoHTTPRequestObject("Neither Mozilla, IE nor ASV found. Can't do HTTP request without them.");
}
}
}
}
}
return obj;
}
/**
Sends a request to a server.
To explain the way the optional arguments work I will give examples:
simple:
sendRequest("get", "url")
sendRequest("post", "url", "data")
with headers:
sendRequest("get", "url", [["headername","value"]])
sendRequest("post", "url", "data", [["headername","value"]])
with user information:
sendRequest("get", "url", "user", "pass")
sendRequest("post", "url", "user", "pass", "data")
with headers and user information:
sendRequest("get", "url", "user", "pass", [["headername","value"]])
sendRequest("post", "url", "user", "pass", "data", [["headername","value"]])
To make the request asynchronous just add a callback function as the last argument to the calls above.
@param type Type of connection (GET, POST, ...).
@param url The URL to retrieve.
@param user=null The username for auth.
@param pass=null The password. (must be set if user is set!)
@param data="" The data to send with the request.
@param headers=[] Array of headers. Each element in the array should be another array containing [headername,value].
@param callback=null Callback for asynchronous connections. The callback is called after completion and is passed the request object as 1st Parameter.
@return HTTP request object.
*/
mod.sendRequest=function(type, url, user, pass, data, headers, callback){
var async=false;
//check if the last argument is a function and treat it as callback;
if(arguments[arguments.length-1] instanceof Function){
var async=true;
callback = arguments[arguments.length-1];
}
//treat sencond last(if callback)/last(if no callback) argument as headers
var headindex=arguments.length-((async || arguments[arguments.length-1] == null) ?2:1);
//is it an array then it's headers
if(arguments[headindex] instanceof Array){
headers=arguments[headindex];
}else{
headers=[];
}
//are user AND password not specified then assume data as 3rd argument.
if(typeof user == "string" && typeof pass == "string"){
if(typeof data != "string"){
data="";
}
}else if (typeof user == "string"){
data = user;
user=null;
pass=null;
}else{
user=null;
pass=null;
}
var xmlhttp= getHTTP();
try{
if(user!=null){
xmlhttp.open(type, url, async, user, pass);
}else{
xmlhttp.open(type, url, async);
}
}catch(e){
throw new mod.RequestOpenFailed(e);
}
//set headers
for(var i=0;i< headers.length;i++){
xmlhttp.setRequestHeader(headers[i][0], headers[i][1]);
}
if(async){//set up a callback
xmlhttp.onreadystatechange=function(){
if (xmlhttp.readyState==4) {
callback(xmlhttp);
xmlhttp = null; //help IE with garbage collection
}else if (xmlhttp.readyState==2){
//status property should be available (MS IXMLHTTPRequest documentation)
//in Mozilla it is not if the request failed(server not reachable)
//in IE it is not available at all ?!
try{//see if it is mozilla otherwise don't care.
var isNetscape = netscape;
try{//if status is not available the request failed.
var s=xmlhttp.status;
}catch(e){//call the callback because Mozilla will not get to readystate 4
callback(xmlhttp);
xmlhttp = null;
}
}catch(e){
}
}
}
}
try{
xmlhttp.send(data);
}catch(e){
if(async){
callback(xmlhttp, e);
xmlhttp=null;
}else{
throw new mod.SendFailed(e);
}
}
return xmlhttp;
}
/**
Shorthand for a GET request.
It calls sendRequest with "GET" as first argument.
See the sendRequest method for more information.
@param url The URL to retrieve.
@param user=null The username for auth.
@param pass=null The password. (must be set if user is set!)
@param headers=[] Array of headers. Each element in the array should be another array containing [headername,value].
@param callback=null Callback for asynchronous connections. The callback is called after completion and is passed the request object as 1st Parameter.
@return HTTP request object.
*/
mod.getURL=function(url, user, pass, headers, callback) {
var a= new Array("GET");
for(var i=0;i<arguments.length;i++){
a.push(arguments[i]);
}
return mod.sendRequest.apply(this,a)
}
/**
Shorthand for a POST request.
It calls sendRequest with "POST" as first argument.
See the sendRequest method for more information.
@param url The URL to retrieve.
@param user=null The username for auth.
@param pass=null The password. (must be set if user is set!)
@param data="" The data to send with the request.
@param headers=[] Array of headers. Each element in the array should be another array containing [headername,value].
@param callback=null Callback for asynchronous connections. The callback is called after completion and is passed the request object as 1st Parameter.
@return HTTP request object.
*/
mod.postURL=function(url, user, pass, data, headers, callback) {
var a= new Array("POST");
for(var i=0;i<arguments.length;i++){
a.push(arguments[i]);
}
return mod.sendRequest.apply(this,a)
}
})

View File

@@ -0,0 +1,247 @@
/*
Copyright (c) 2003 Jan-Klaas Kollhof
This file is part of the JavaScript o lait library(jsolait).
jsolait is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This software is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this software; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/**
Provides parseXML and an importNode implementation.
*/
Module("xml","1.1.2", function(mod){
/**
Thrown if no parser could be instanciated.
*/
mod.NoXMLParser=Class("NoXMLParser", mod.Exception, function(publ, supr){
/**
Initializes the Exception.
@param trace The error causing the Exception.
*/
publ.init=function(trace){
supr(this).init("Could not create an XML parser.", trace);
}
})
/**
Thrown if a document could not be parsed.
*/
mod.ParsingFailed=Class("ParsingFailed", mod.Exception, function(publ, supr){
/**
Initializes the Exception.
@param xml The xml source which could not be parsed.
@param trace The error causing this Exception.
*/
publ.init=function(xml,trace){
supr(this).init("Failed parsing XML document.",trace);
this.xml = xml;
}
///The xml source which could not be parsed.
publ.xml;
})
/**
Parses an xml document.
@param xml The xml text.
@return A DOM of the xml document.
*/
mod.parseXML=function(xml){
var obj=null;
var isMoz=false;
var isIE=false;
var isASV=false;
try{//to get Adobe's SVG parseXML
var p=window.parseXML;
if(p==null){
throw "No ASV paseXML";
}
isASV=true;
}catch(e){
try{//to get the mozilla parser
obj = new DOMParser();
isMoz=true;
}catch(e){
try{//to get the MS XML parser
obj = new ActiveXObject("Msxml2.DomDocument.4.0");
isIE=true;
}catch(e){
try{//to get the MS XML parser
obj = new ActiveXObject("Msxml2.DomDocument");
isIE=true;
}catch(e){
try{//to get the old MS XML parser
obj = new ActiveXObject("microsoft.XMLDOM");
isIE=true;
}catch(e){
throw new mod.NoXMLParser(e);
}
}
}
}
}
try{
if(isMoz){
obj = obj.parseFromString(xml, "text/xml");
return obj;
}else if(isIE){
obj.loadXML(xml);
return obj;
}else if(isASV){
return window.parseXML(xml, null);
}
}catch(e){
throw new mod.ParsingFailed(xml,e);
}
}
/**
DOM2 implimentation of document.importNode().
This will import into the current document. In SVG it will create SVG nodes in HTML it will create HTML nodes....
This might become customizable in the future.
@param importedNode The node to import.
@param deep=true Import all childNodes recursively.
@return The imported Node.
*/
mod.importNode=function(importedNode, deep){
deep = (deep==null) ? true : deep;
//constants from doom2
var ELEMENT_NODE = 1;
var ATTRIBUTE_NODE = 2;
var TEXT_NODE = 3;
var CDATA_SECTION_NODE = 4;
var ENTITY_REFERENCE_NODE = 5;
var ENTITY_NODE = 6;
var PROCESSING_INSTRUCTION_NODE = 7;
var COMMENT_NODE = 8;
var DOCUMENT_NODE = 9;
var DOCUMENT_TYPE_NODE = 10;
var DOCUMENT_FRAGMENT_NODE = 11;
var NOTATION_NODE = 12;
var importChildren=function(srcNode, parent){
if(deep){
for(var i=0; i<srcNode.childNodes.length; i++){
var n=mod.importNode(srcNode.childNodes.item(i), true);
parent.appendChild(n);
}
}
}
var node=null;
switch(importedNode.nodeType){
case ATTRIBUTE_NODE:
node=document.createAttributeNS(importedNode.namespaceURI, importedNode.nodeName);
node.value=importedNode.value;
break;
case DOCUMENT_FRAGMENT_NODE:
node=document.createDocumentFragment();
importChildren(importedNode,node);
break;
case ELEMENT_NODE:
node=document.createElementNS(importedNode.namespaceURI, importedNode.tagName);
//import all attributes
for(var i=0; i<importedNode.attributes.length; i++){
var attr=this.importNode(importedNode.attributes.item(i), deep);
node.setAttributeNodeNS(attr);
}
importChildren(importedNode,node);
break;
case ENTITY_REFERENCE_NODE:
node=importedNode;
break;
case PROCESSING_INSTRUCTION_NODE:
node=document.createProcessingInstruction(importedNode.target, importedNode.data);
break;
case TEXT_NODE:
case CDATA_SECTION_NODE:
case COMMENT_NODE:
node=document.createTextNode(importedNode.nodeValue);
break;
case DOCUMENT_NODE:
//Document nodes cannot be imported.
case DOCUMENT_TYPE_NODE:
//DocumentType nodes cannot be imported.
case NOTATION_NODE:
//readonly in DOM2
case ENTITY_NODE:
//readonly in DOM2
throw "not supported in DOM2";
break;
}
return node;
}
/**
Turns an XML document into a String.
@param node The node to print.
@return A string containing the text for the XML.
*/
mod.node2XML = function(node){
var ELEMENT_NODE = 1;
var ATTRIBUTE_NODE = 2;
var TEXT_NODE = 3;
var CDATA_SECTION_NODE = 4;
var ENTITY_REFERENCE_NODE = 5;
var ENTITY_NODE = 6;
var PROCESSING_INSTRUCTION_NODE = 7;
var COMMENT_NODE = 8;
var DOCUMENT_NODE = 9;
var DOCUMENT_TYPE_NODE = 10;
var DOCUMENT_FRAGMENT_NODE = 11;
var NOTATION_NODE = 12;
var s="";
switch(node.nodeType){
case ATTRIBUTE_NODE:
s+=node.nodeName+'="' + node.value + '"';
break;
case DOCUMENT_NODE:
s+=this.node2XML(node.documentElement);
break;
case ELEMENT_NODE:
s+="<" + node.tagName;
//attributes
for(var i=0; i<node.attributes.length; i++){
s+=" " + this.node2XML(node.attributes.item(i));
}
//children
if(node.childNodes.length==0){
s+="/>\n";
}else{
s+=">";
for(var i=0; i<node.childNodes.length; i++){
s+=this.node2XML(node.childNodes.item(i));
}
s+="</" + node.tagName+ ">\n";
}
break;
case PROCESSING_INSTRUCTION_NODE:
s+="<?" + node.target + " " + node.data + " ?>";
break;
case TEXT_NODE:
s+=node.nodeValue;
break;
case CDATA_SECTION_NODE:
s+="<" +"![CDATA[" + node.nodeValue + "]" + "]>";
break;
case COMMENT_NODE:
s+="<!--" + node.nodeValue + "-->";
break;
case ENTITY_REFERENCE_NODE:
case DOCUMENT_FRAGMENT_NODE:
case DOCUMENT_TYPE_NODE:
case NOTATION_NODE:
case ENTITY_NODE:
throw new mod.Exception("Nodetype(%s) not supported.".format(node.nodeType));
break;
}
return s;
}
})

View File

@@ -0,0 +1,831 @@
/*
Copyright (c) 2003-2004 Jan-Klaas Kollhof
This file is part of the JavaScript o lait library(jsolait).
jsolait is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This software is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this software; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/**
Provides an XML-RPC imlementation.
It is similar to python's xmlrpclib module.
*/
Module("xmlrpc","1.3.3", function(mod){
var xmlext = importModule("xml");
var urllib = importModule("urllib");
/**
Thrown if a server did not respond with response status 200 (OK).
*/
mod.InvalidServerResponse = Class("InvalidServerResponse", mod.Exception, function(publ, supr){
/**
Initializes the Exception.
@param status The status returned by the server.
*/
publ.init= function(status){
supr(this).init("The server did not respond with a status 200 (OK) but with: " + status);
this.status = status;
}
///The status returned by the server.
publ.status;
})
/**
Thrown if an XML-RPC response is not well formed.
*/
mod.MalformedXmlRpc = Class("MalformedXmlRpc", mod.Exception, function(publ, supr){
/**
Initializes the Exception.
@param msg The error message of the user.
@param xml The xml document's source.
@param trace=null The error causing this Exception
*/
publ.init= function(msg, xml, trace){
supr(this).init(msg,trace);
this.xml = xml;
}
///The xml source which was mal formed.
publ.xml;
})
/**
Thrown if the RPC response is a Fault.
*/
mod.Fault = Class("Fault", mod.Exception, function(publ, supr){
/**
Initializes the Exception.
@param faultCode The fault code returned by the rpc call.
@param faultString The fault string returned by the rpc call.
*/
publ.init= function(faultCode, faultString){
supr(this).init("XML-RPC Fault: " + faultCode + "\n\n" + faultString);
this.faultCode = faultCode;
this.faultString = faultString;
}
///The fault code returned from the rpc call.
publ.faultCode;
///The fault string returned from the rpc call.
publ.faultString;
})
/**
Marshalls an object to XML-RPC.(Converts an object into XML-RPC conforming xml.)
It just calls the toXmlRpc function of the objcect.
So, to customize serialization of objects one just needs to specify/override the toXmlRpc method
which should return an xml string conforming with XML-RPC spec.
@param obj The object to marshall
@return An xml representation of the object.
*/
mod.marshall = function(obj){
if(obj.toXmlRpc){
return obj.toXmlRpc();
}else{
var s = "<struct>";
for(var attr in obj){
if(typeof obj[attr] != "function"){
s += "<member><name>" + attr + "</name><value>" + mod.marshall(obj[attr]) + "</value></member>";
}
}
s += "</struct>";
return s;
}
}
/**
Unmarshalls an XML document to a JavaScript object. (Converts xml to JavaScript object.)
It parses the xml source and creates a JavaScript object.
@param xml The xml document source to unmarshall.
@return The JavaScript object created from the XML.
*/
mod.unmarshall = function(xml){
try {//try to parse xml ... this will throw an Exception if failed
var doc = xmlext.parseXML(xml);
}catch(e){
throw new mod.MalformedXmlRpc("The server's response could not be parsed.", xml, e);
}
var rslt = mod.unmarshallDoc(doc, xml);
doc=null;
return rslt;
}
/**
Unmarshalls an XML document to a JavaScript object like unmarshall but expects a DOM document as parameter.
It parses the xml source and creates a JavaScript object.
@param doc The xml document(DOM compatible) to unmarshall.
@return The JavaScript object created from the XML.
*/
mod.unmarshallDoc = function(doc, xml){
try{
var node = doc.documentElement;
if(node==null){//just in case parse xml didn't throw an Exception but returned nothing usefull.
throw new mod.MalformedXmlRpc("No documentElement found.", xml);
}
switch(node.tagName){
case "methodResponse":
return parseMethodResponse(node);
case "methodCall":
return parseMethodCall(node);
default://nothing usefull returned by parseXML.
throw new mod.MalformedXmlRpc("'methodCall' or 'methodResponse' element expected.\nFound: '" + node.tagName + "'", xml);
}
}catch(e){
if(e instanceof mod.Fault){//just rethrow the fault.
throw e;
}else {
throw new mod.MalformedXmlRpc("Unmarshalling of XML failed.", xml, e);
}
}
}
/**
Parses a methodeResponse element.
@param node The methodResponse element.
@return The return value of the XML-RPC.
*/
var parseMethodResponse=function(node){
try{
for(var i=0;i<node.childNodes.length;i++){
var child = node.childNodes.item(i);
if (child.nodeType == 1){
switch (child.tagName){
case "fault": //a fault is thrown as an Exception
throw parseFault(child);
case "params":
var params = parseParams(child);
if(params.length == 1){//params should only have one param
return params[0];
}else{
throw new mod.MalformedXmlRpc("'params' element inside 'methodResponse' must have exactly ONE 'param' child element.\nFound: " + params.length);
}
default:
throw new mod.MalformedXmlRpc("'fault' or 'params' element expected.\nFound: '" + child.tagName + "'");
}
}
}
//no child elements found
throw new mod.MalformedXmlRpc("No child elements found.");
}catch(e){
if(e instanceof mod.Fault){
throw e;
}else{
throw new mod.MalformedXmlRpc("'methodResponse' element could not be parsed.",null,e);
}
}
}
/**
Parses a methodCall element.
@param node The methodCall element.
@return Array [methodName,params].
*/
var parseMethodCall = function(node){
try{
var methodName = null;
var params = new Array();//default is no parameters
for(var i=0;i<node.childNodes.length;i++){
var child = node.childNodes.item(i);
if (child.nodeType == 1){
switch (child.tagName){
case "methodName":
methodName = new String(child.firstChild.nodeValue);
break;
case "params":
params = parseParams(child);
break;
default:
throw new mod.MalformedXmlRpc("'methodName' or 'params' element expected.\nFound: '" + child.tagName + "'");
}
}
}
if(methodName==null){
throw new mod.MalformedXmlRpc("'methodName' element expected.");
}else{
return new Array(methodName, params);
}
}catch(e){
throw new mod.MalformedXmlRpc("'methodCall' element could not be parsed.",null,e);
}
}
/**
Parses a params element.
@param node The params element.
@return Array of params values.
*/
var parseParams = function(node){
try{
var params=new Array();
for(var i=0;i<node.childNodes.length;i++){
var child = node.childNodes.item(i);
if (child.nodeType == 1){
switch (child.tagName){
case "param":
params.push(parseParam(child));
break;
default:
throw new mod.MalformedXmlRpc("'param' element expected.\nFound: '" + child.tagName + "'");
}
}
}
//the specs say a 'params' element can contain any number of 'param' elements. That includes 0 ?!
return params;
}catch(e){
throw new mod.MalformedXmlRpc("'params' element could not be parsed.",null,e);
}
}
/**
Parses a param element.
@param node The param node.
@return The value of the param.
*/
var parseParam = function(node){
try{
for(var i=0;i<node.childNodes.length;i++){
var child = node.childNodes.item(i);
if (child.nodeType == 1){
switch (child.tagName){
case "value":
return parseValue(child);
default:
throw new mod.MalformedXmlRpc("'value' element expected.\nFound: '" + child.tagName + "'");
}
}
}
//no child elements found, that's an error
throw new mod.MalformedXmlRpc("'value' element expected.But none found.");
}catch(e){
throw new mod.MalformedXmlRpc("'param' element could not be parsed.",null,e);
}
}
/**
Parses a value element.
@param node The value element.
@return The value.
*/
var parseValue = function(node){
try{
for(var i=0;i<node.childNodes.length;i++){
var child = node.childNodes.item(i);
if (child.nodeType == 1){
switch (child.tagName){
case "string":
var s=""
//Mozilla has many textnodes with a size of 4096 chars each instead of one large one.
//They all need to be concatenated.
for(var j=0;j<child.childNodes.length;j++){
s+=new String(child.childNodes.item(j).nodeValue);
}
return s;
case "int":
case "i4":
case "double":
return (child.firstChild) ? new Number(child.firstChild.nodeValue) : 0;
case "boolean":
return Boolean(isNaN(parseInt(child.firstChild.nodeValue)) ? (child.firstChild.nodeValue == "true") : parseInt(child.firstChild.nodeValue));
case "base64":
return parseBase64(child);
case "dateTime.iso8601":
return parseDateTime(child);
case "array":
return parseArray(child);
case "struct":
return parseStruct(child);
case "nil": //for python None todo: ??? is this valid XML-RPC
return null;
default:
throw new mod.MalformedXmlRpc("'string','int','i4','double','boolean','base64','dateTime.iso8601','array' or 'struct' element expected.\nFound: '" + child.tagName + "'");
}
}
}
if(node.firstChild){
var s=""
//Mozilla has many textnodes with a size of 4096 chars each instead of one large one.
//They all need to be concatenated.
for(var j=0;j<node.childNodes.length;j++){
s+=new String(node.childNodes.item(j).nodeValue);
}
return s;
}else{
return "";
}
}catch(e){
throw new mod.MalformedXmlRpc("'value' element could not be parsed.",null,e);
}
}
/**
Parses a base64 element.
@param node The base64 element.
@return A string with the decoded base64.
*/
var parseBase64=function(node){
try{
var s = node.firstChild.nodeValue;
return s.decode("base64");
}catch(e){
throw new mod.MalformedXmlRpc("'base64' element could not be parsed.",null,e);
}
}
/**
Parses a dateTime.iso8601 element.
@param node The dateTime.iso8601 element.
@return A JavaScript date.
*/
var parseDateTime=function(node){
try{
if(/^(\d{4})-?(\d{2})-?(\d{2})T(\d{2}):?(\d{2}):?(\d{2})/.test(node.firstChild.nodeValue)){
return new Date(Date.UTC(RegExp.$1, RegExp.$2-1, RegExp.$3, RegExp.$4, RegExp.$5, RegExp.$6));
}else{ //todo error message
throw new mod.MalformedXmlRpc("Could not convert the given date.");
}
}catch(e){
throw new mod.MalformedXmlRpc("'dateTime.iso8601' element could not be parsed.",null,e);
}
}
/**
Parses an array element.
@param node The array element.
@return An Array.
*/
var parseArray=function(node){
try{
for(var i=0;i<node.childNodes.length;i++){
var child = node.childNodes.item(i);
if (child.nodeType == 1){
switch (child.tagName){
case "data":
return parseData(child);
default:
throw new mod.MalformedXmlRpc("'data' element expected.\nFound: '" + child.tagName + "'");
}
}
}
throw new mod.MalformedXmlRpc("'data' element expected. But not found.");
}catch(e){
throw new mod.MalformedXmlRpc("'array' element could not be parsed.",null,e);
}
}
/**
Parses a data element.
@param node The data element.
@return The value of a data element.
*/
var parseData=function(node){
try{
var rslt = new Array();
for(var i=0;i<node.childNodes.length;i++){
var child = node.childNodes.item(i);
if (child.nodeType == 1){
switch (child.tagName){
case "value":
rslt.push(parseValue(child));
break;
default:
throw new mod.MalformedXmlRpc("'value' element expected.\nFound: '" + child.tagName + "'");
}
}
}
return rslt;
}catch(e){
throw new mod.MalformedXmlRpc("'data' element could not be parsed.",null,e);
}
}
/**
Parses a struct element.
@param node The struct element.
@return A JavaScript object. Struct memembers are properties of the object.
*/
var parseStruct=function(node){
try{
var struct = new Object();
for(var i=0;i<node.childNodes.length;i++){
var child = node.childNodes.item(i);
if (child.nodeType == 1){
switch (child.tagName){
case "member":
var member = parseMember(child); //returns [name, value]
if(member[0] != ""){
struct[member[0]] = member[1];
}
break;
default:
throw new mod.MalformedXmlRpc("'data' element expected.\nFound: '" + child.tagName + "'");
}
}
}
return struct;
}catch(e){
throw new mod.MalformedXmlRpc("'struct' element could not be parsed.",null,e);
}
}
/**
Parses a member element.
@param node The member element.
@return Array containing [memberName, value].
*/
var parseMember=function(node){
try{
var name="";
var value=null;
for(var i=0;i<node.childNodes.length;i++){
var child = node.childNodes.item(i);
if (child.nodeType == 1){
switch (child.tagName){
case "value":
value = parseValue(child);
break;
case "name":
if(child.hasChildNodes()){
name = new String(child.firstChild.nodeValue);
}
break;
default:
throw new mod.MalformedXmlRpc("'value' or 'name' element expected.\nFound: '" + child.tagName + "'");
}
}
}
/*if(name == ""){
throw new mod.MalformedXmlRpc("Name for member not found/convertable.");
}else{
return new Array(name, value);
}*/
return [name, value];
}catch(e){
throw new mod.MalformedXmlRpc("'member' element could not be parsed.",null,e);
}
}
/**
Parses a fault element.
@param node The fault element.
@return A Fault Exception object.
*/
var parseFault = function(node){
try{
for(var i=0;i<node.childNodes.length;i++){
var child = node.childNodes.item(i);
if (child.nodeType == 1){
switch (child.tagName){
case "value":
var flt = parseValue(child);
return new mod.Fault(flt.faultCode, flt.faultString);
default:
throw new mod.MalformedXmlRpc("'value' element expected.\nFound: '" + child.tagName + "'");
}
}
}
throw new mod.MalformedXmlRpc("'value' element expected. But not found.");
}catch(e){
throw new mod.MalformedXmlRpc("'fault' element could not be parsed.",null,e);
}
}
/**
Class for creating XML-RPC methods.
Calling the created method will result in an XML-RPC call to the service.
The return value of this call will be the return value of the RPC call.
RPC-Faults will be raised as Exceptions.
Asynchronous operation:
If the last parameter passed to the method is an XMLRPCAsyncCallback object,
then the remote method will be called asynchronously.
The results and errors are passed to the callback.
*/
mod.XMLRPCMethod =Class("XMLRPCMethod", function(publ){
var postData = function(url, user, pass, data, callback){
if(callback == null){
var rslt = urllib.postURL(url, user, pass, data, [["Content-Type", "text/xml"]]);
return rslt;
}else{
urllib.postURL(url, user, pass, data, [["Content-Type", "text/xml"]], callback);
}
}
var handleResponse=function(resp){
var status=null;
try{//see if the server responded with a response code 200 OK.
status = resp.status;
}catch(e){
}
if(status == 200){
var respDoc=null;
try{
respDoc = resp.responseXML;
}catch(e){
}
var respTxt = "";
try{
respTxt=resp.responseText;
}catch(e){
}
if(respDoc == null){
if(respTxt == null || respTxt == ""){
throw new mod.MalformedXmlRpc("The server responded with an empty document.", "");
}else{
return mod.unmarshall(respTxt);
}
}else{ //use the respDoc directly so the xml does not have to be parsed.
return mod.unmarshallDoc(respDoc, respTxt);
}
}else{
throw new mod.InvalidServerResponse(status);
}
}
var getXML = function(methodName, args){
var data='<?xml version="1.0"?><methodCall><methodName>' + methodName + '</methodName>';
if (args.length>0){
data += "<params>";
for(var i=0;i<args.length;i++){
data += '<param><value>' + mod.marshall(args[i]) + '</value></param>';
}
data += '</params>';
}
data += '</methodCall>';
return data;
}
/**
Initializes the XML-RPC method.
@param url The URL of the service providing the method.
@param methodName The name of the method to invoke.
@param user=null The user name to use for HTTP authentication.
@param pass=null The password to use for HTTP authentication.
*/
publ.init = function(url, methodName, user, pass){
//this is pretty much a hack.
//we create a function which mimics this class and return it instead of really instanciating an object.
var fn=function(){
//sync or async call
if(typeof arguments[arguments.length-1] != "function"){
var data=getXML(fn.methodName,arguments);
var resp = postData(fn.url, fn.user, fn.password, data);
return handleResponse(resp);
}else{
var args=new Array();
for(var i=0;i<arguments.length;i++){
args.push(arguments[i]);
}
var cb = args.pop();
var data=getXML(fn.methodName, args);
postData(fn.url, fn.user, fn.password, data, function(resp){
var rslt = null;
var exc =null;
try{
rslt = handleResponse(resp);
}catch(e){
exc = e;
}
try{//call the callback for the async call.
cb(rslt,exc);
}catch(e){
}
args = null;
resp = null;
});
}
}
//make sure the function has the same property as an object created from this class.
fn.methodName = methodName;
fn.url = url;
fn.user = user;
fn.password=pass;
fn.toMulticall = this.toMulticall;
fn.toString = this.toString;
fn.setAuthentication=this.setAuthentication;
fn.constructor = this.constructor;
return fn;
}
/**
Returns the method representation for system.multicall.
@param All params will be passed to the remote method.
@return An object containing a member methodName and a member params(As required by system.multicall).
*/
publ.toMulticall = function(){
var multiCallable = new Object();
multiCallable.methodName = this.methodName;
var params = [];
for(var i=0;i<arguments.length;i++){
params[i] = arguments[i];
}
multiCallable.params = params;
return multiCallable;
}
/**
Sets username and password for HTTP Authentication.
@param user The user name.
@param pass The password.
*/
publ.setAuthentication = function(user, pass){
this.user = user;
this.password = pass;
}
///The name of the remote method.
publ.methodName;
///The url of the remote service containing the method.
publ.url;
///The user name used for HTTP authorization.
publ.user;
///The password used for HTTP authorization.
publ.password;
})
/**
Creates proxy objects which resemble the remote service.
Method calls of this proxy will result in calls to the service.
*/
mod.ServiceProxy=Class("ServiceProxy", function(publ){
/**
Initializes a new ServerProxy.
The arguments are interpreted as shown in the examples:
ServerProxy("url")
ServerProxy("url", ["methodName1",...])
ServerProxy("url", ["methodName1",...], "user", "pass")
ServerProxy("url", "user", "pass")
@param url The url of the service.
@param methodNames=[] Array of names of methods that can be called on the server.
If no methods are given then introspection is used to get the methodnames from the server.
@param user=null The user name to use for HTTP authentication.
@param pass=null The password to use for HTTP authentication.
*/
publ.init = function(url, methodNames, user, pass){
if(methodNames instanceof Array){
if(methodNames.length > 0){
var tryIntrospection=false;
}else{
var tryIntrospection=true;
}
}else{
pass=user;
user=methodNames;
methodNames=[];
var tryIntrospection=true;
}
this._url = url;
this._user = user;
this._password = pass;
this._addMethodNames(methodNames);
if(tryIntrospection){
try{//it's ok if it fails.
this._introspect();
}catch(e){
}
}
}
/**
Adds new XMLRPCMethods to the proxy server which can then be invoked.
@param methodNames Array of names of methods that can be called on the server.
*/
publ._addMethodNames = function(methodNames){
for(var i=0;i<methodNames.length;i++){
var obj = this;
//setup obj.childobj...method
var names = methodNames[i].split(".");
for(var n=0;n<names.length-1;n++){
var name = names[n];
if(obj[name]){
obj = obj[name];
}else{
obj[name] = new Object();
obj = obj[name];
}
}
var name = names[names.length-1];
if(obj[name]){
}else{
var mth = new mod.XMLRPCMethod(this._url, methodNames[i], this._user, this._password);
obj[name] = mth;
this._methods.push(mth);
}
}
}
/**
Sets username and password for HTTP Authentication for all methods of this service.
@param user The user name.
@param pass The password.
*/
publ._setAuthentication = function(user, pass){
this._user = user;
this._password = pass;
for(var i=0;i<this._methods.length;i++){
this._methods[i].setAuthentication(user, pass);
}
}
/**
Initiate XML-RPC introspection to retrieve methodnames from the server
and add them to the server proxy.
*/
publ._introspect = function(){
this._addMethodNames(["system.listMethods","system.methodHelp", "system.methodSignature"]);
var m = this.system.listMethods();
this._addMethodNames(m);
}
///The url of the service to resemble.
publ._url;
///The user used for HTTP authentication.
publ._user;
///The password used for HTTP authentication.
publ._password;
///All methods.
publ._methods=new Array();
})
///@deprecated Use ServiceProxy instead.
mod.ServerProxy= mod.ServiceProxy;
/**
XML-RPC representation of a string.
All '&' and '<' are replaced with the '&amp;' and '&lt'.
@return A string containing the String's representation in XML.
*/
String.prototype.toXmlRpc = function(){
return "<string>" + this.replace(/&/g, "&amp;").replace(/</g, "&lt;") + "</string>";
}
/**
XML-RPC representation of a number.
@return A string containing the Number's representation in XML.
*/
Number.prototype.toXmlRpc = function(){
if(this == parseInt(this)){
return "<int>" + this + "</int>";
}else if(this == parseFloat(this)){
return "<double>" + this + "</double>";
}else{
return false.toXmlRpc();
}
}
/**
XML-RPC representation of a boolean.
@return A string containing the Boolean's representation in XML.
*/
Boolean.prototype.toXmlRpc = function(){
if(this == true) {
return "<boolean>1</boolean>";
}else{
return "<boolean>0</boolean>";
}
}
/**
XML-RPC representation of a date(iso 8601).
@return A string containing the Date's representation in XML.
*/
Date.prototype.toXmlRpc = function(){
var padd=function(s, p){
s=p+s
return s.substring(s.length - p.length)
}
var y = padd(this.getUTCFullYear(), "0000");
var m = padd(this.getUTCMonth() + 1, "00");
var d = padd(this.getUTCDate(), "00");
var h = padd(this.getUTCHours(), "00");
var min = padd(this.getUTCMinutes(), "00");
var s = padd(this.getUTCSeconds(), "00");
var isodate = y + m + d + "T" + h + ":" + min + ":" + s
return "<dateTime.iso8601>" + isodate + "</dateTime.iso8601>";
}
/**
XML-RPC representation of an array.
Each entry in the array is a value in the XML-RPC.
@return A string containing the Array's representation in XML.
*/
Array.prototype.toXmlRpc = function(){
var retstr = "<array><data>";
for(var i=0;i<this.length;i++){
retstr += "<value>" + mod.marshall(this[i]) + "</value>";
}
return retstr + "</data></array>";
}
mod.test = function(){
print("creating ServiceProxy object using introspection for method construction...\n");
var s = new mod.ServiceProxy("http://localhost/testx.py");
print("%s created\n".format(s));
print("creating and marshalling test data:\n");
var o = [1.234, 5, {a:"Hello & < ", b:new Date()}];
print(mod.marshall(o));
print("\ncalling echo() on remote service...\n");
var r = s.echo(o);
print("service returned data(marshalled again):\n")
print(mod.marshall(r));
}
})

View File

@@ -0,0 +1,151 @@
/*
Copyright (c) 2003 Jan-Klaas Kollhof
This file is part of the JavaScript o lait library(jsolait).
jsolait is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This software is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this software; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
if(Function.prototype.apply == null){
Function.prototype.apply = function(thisObj, args){
var a =[];
for(var i=0;i<args.length;i++){
a[i] = "args[" + i + "]";
}
thisObj.__apply__ = this;
a="thisObj.__apply__(" + a.join(",") +")";
var r = eval(a);
delete thisObj.__apply__;
return r;
}
}
if(Function.prototype.call==null){
Function.prototype.call=function(thisObj){
var args=[]; //copy all arguments but the first
for(var i=1;i<arguments.length;i++){
args[i-1] = arguments[i];
}
return this.apply(thisObj, args);
}
}
///----------------------------------Array functions----------------------------------
if(Array.prototype.splice == null){
Array.prototype.splice = function(index, howMany){
var a = this.slice(0, index);
var e = this.slice(index + howMany, this.length);
var r = this.slice(index, index+howMany);
this.length=0;
for(var i=0;i<a.length;i++){
this[this.length] = a[i];
}
for(var i=2;i<arguments.length;i++){
this[this.length] = arguments[i];
}
for(var i=0;i<e.length;i++){
this[this.length] = e[i];
}
return r;
}
}
if(Array.prototype.pop == null){
Array.prototype.pop = function(){
var e=this[this.length-1];
this.length -= 1;
return e;
}
}
if(Array.prototype.push == null){
Array.prototype.push = function(){
for(var i=0;i<arguments.length;i++){
this[this.length] = arguments[i];
}
return this.length;
}
}
if(Array.prototype.shift == null){
Array.prototype.shift = function(){
var e = this[0];
for(var i=1;i<this.length;i++){
this[i-1] = this[i];
}
this.length -= 1;
return e;
}
}
if(Array.prototype.unshift == null){
Array.prototype.unshift = function(){
var a=[]
for(var i=0;i<arguments.length;i++){
a[i] = arguments[i];
}
for(var i=0;i<this.length;i++){
a[a.length] = this[i];
}
this.length=a.length;
for(var i=0;i<a.length;i++){
this[i] = a[i];
}
return this.length;
}
}
/**
Number functions.
Contributed by Wolfgang Dumhs.
*/
if(Number.prototype.toFixed == null){
Number.prototype.toFixed = function(d){
var n = this;
d = d || 0;
var f = Math.pow(10, d);
n = Math.round (f * n) / f;
n = (n >= 0) ? n+Math.pow(10, -(d+1)) : n-Math.pow(10, -(d+1));
n += '';
return d == 0 ? n.substring(0, n.indexOf('.')) : n.substring(0, n.indexOf('.') + d + 1);
}
}
if(Number.prototype.toExponential == null){
Number.prototype.toExponential = function(d){
var n = this;
var e = 0;
if (n != 0){
e = Math.floor(Math.log(Math.abs(n)) / Math.LN10);
}
n /= Math.pow(10, e);
if (isFinite(d)){
if (Math.abs(n) + 5*Math.pow(10, -(d+1)) >= 10.0){
n /= 10;
e += 1;
}
n = n.toFixed(d);
}
n += "e";
if (e >= 0){
n += "+";
}
n += e;
return n;
}
}