Added XML-RPC plug-in
authorThierry Florac <thierry.florac@onf.fr>
Tue, 14 Apr 2015 16:36:24 +0200
changeset 44 1ea9e5a677a3
parent 43 d366c88a0f88
child 45 ad0378995d5a
Added XML-RPC plug-in
src/pyams_skin/resources/js/ext/jquery-xmlrpc.js
src/pyams_skin/resources/js/ext/jquery-xmlrpc.min.js
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_skin/resources/js/ext/jquery-xmlrpc.js	Tue Apr 14 16:36:24 2015 +0200
@@ -0,0 +1,415 @@
+/*jshint browser:true */
+/*global jQuery */
+(function($) {
+	"use strict";
+
+	var XmlRpcFault = function() {
+		Error.apply(this, arguments);
+	};
+	XmlRpcFault.prototype = new Error();
+	XmlRpcFault.prototype.type = 'XML-RPC fault';
+
+	var xmlrpc = $.xmlrpc = function(url, settings) {
+
+		if (arguments.length === 2) {
+			settings.url = url;
+		} else {
+			settings = url;
+			url = settings.url;
+		}
+
+		settings.dataType = 'xml json';
+		settings.type = 'POST';
+		settings.contentType = 'text/xml';
+		settings.converters = {'xml json': xmlrpc.parseDocument};
+
+		var xmlDoc = xmlrpc.document(settings.methodName, settings.params || []);
+
+		if ("XMLSerializer" in window) {
+			settings.data = new window.XMLSerializer().serializeToString(xmlDoc);
+		} else {
+			// IE does not have XMLSerializer
+			settings.data = xmlDoc.xml;
+		}
+
+		return $.ajax(settings);
+	};
+
+	/**
+	* Make an XML document node.
+	*/
+	xmlrpc.createXMLDocument = function () {
+
+		if (document.implementation && "createDocument" in document.implementation) {
+			// Most browsers support createDocument
+			return document.implementation.createDocument(null, null, null);
+
+		} else {
+			// IE uses ActiveXObject instead of the above.
+			var i, length, activeX = [
+				"MSXML6.DomDocument", "MSXML3.DomDocument",
+				"MSXML2.DomDocument", "MSXML.DomDocument", "Microsoft.XmlDom"
+			];
+			for (i = 0, length = activeX.length; i < length; i++) {
+				try {
+					return new ActiveXObject(activeX[i]);
+				} catch(_) {}
+			}
+		}
+	};
+
+	/**
+	* Make an XML-RPC document from a method name and a set of parameters
+	*/
+	xmlrpc.document = function(name, params) {
+		var doc = xmlrpc.createXMLDocument();
+
+
+		var $xml = function(name) {
+			return $(doc.createElement(name));
+		};
+
+		var $methodName = $xml('methodName').text(name);
+		var $params = $xml('params').append($.map(params, function(param) {
+			var $value = $xml('value').append(xmlrpc.toXmlRpc(param, $xml));
+			return $xml('param').append($value);
+		}));
+		var $methodCall = $xml('methodCall').append($methodName, $params);
+		doc.appendChild($methodCall.get(0));
+		return doc;
+	};
+
+	var _isInt = function(x) {
+		return (x === parseInt(x, 10)) && !isNaN(x);
+	};
+
+	/**
+	* Take a JavaScript value, and return an XML node representing the value
+	* in XML-RPC style. If the value is one of the `XmlRpcType`s, that type is
+	* used. Otherwise, a best guess is made as to its type. The best guess is
+	* good enough in the vast majority of cases.
+	*/
+	xmlrpc.toXmlRpc = function(item, $xml) {
+
+		if (item instanceof XmlRpcType) {
+			return item.toXmlRpc($xml);
+		}
+
+		var types = $.xmlrpc.types;
+		var type = $.type(item);
+
+		switch (type) {
+			case "undefined":
+			case "null":
+				return types.nil.encode(item, $xml);
+
+			case "date":
+				return types['datetime.iso8601'].encode(item, $xml);
+
+			case "object":
+				if (item instanceof ArrayBuffer) {
+					return types.base64.encode(item, $xml);
+				} else {
+					return types.struct.encode(item, $xml);
+				}
+				break;
+
+
+			case "number":
+				// Ints and Floats encode differently
+				if (_isInt(item)) {
+					return types['int'].encode(item, $xml);
+				} else {
+					return types['double'].encode(item, $xml);
+				}
+				break;
+
+			case "array":
+			case "boolean":
+			case "string":
+				return types[type].encode(item, $xml);
+
+			default:
+				throw new Error("Unknown type", item);
+		}
+	};
+
+	/**
+	* Take an XML-RPC document and decode it to an equivalent JavaScript
+	* representation.
+	*
+	* If the XML-RPC document represents a fault, then an equivalent
+	* XmlRpcFault will be thrown instead
+	*/
+	xmlrpc.parseDocument = function(doc) {
+		var $doc = $(doc);
+		var $response = $doc.children('methodresponse');
+
+		var $fault = $response.find('> fault');
+		if ($fault.length === 0) {
+			var $params = $response.find('> params > param > value > *');
+			var json = $params.toArray().map(xmlrpc.parseNode);
+			return json;
+		} else {
+			var fault = xmlrpc.parseNode($fault.find('> value > *').get(0));
+			var err = new XmlRpcFault(fault.faultString);
+			err.msg = err.message = fault.faultString;
+			err.type = err.code = fault.faultCode;
+			throw err;
+		}
+	};
+
+	/*
+	* Take an XML-RPC node, and return the JavaScript equivalent
+	*/
+	xmlrpc.parseNode = function(node) {
+
+		// Some XML-RPC services return empty <value /> elements. This is not
+		// legal XML-RPC, but we may as well handle it.
+		if (node === undefined) {
+			return null;
+		}
+		var nodename = node.nodeName.toLowerCase();
+		if (nodename in xmlrpc.types) {
+			return xmlrpc.types[nodename].decode(node);
+		} else {
+			throw new Error('Unknown type ' + nodename);
+		}
+	};
+
+	/*
+	* Take a <value> node, and return the JavaScript equivalent.
+	*/
+	xmlrpc.parseValue = function(value) {
+		var child = $(value).children()[0];
+		if (child) {
+			// Child nodes should be decoded.
+			return xmlrpc.parseNode(child);
+		} else {
+			// If no child nodes, the value is a plain text node.
+			return $(value).text();
+		}
+	};
+
+	var XmlRpcType = function() { };
+
+	$.xmlrpc.types = {};
+
+	/**
+	* Make a XML-RPC type. We use these to encode and decode values. You can
+	* also force a values type using this. See `$.xmlrpc.force()`
+	*/
+	xmlrpc.makeType = function(tagName, simple, encode, decode) {
+		var Type;
+
+		Type = function(value) {
+			this.value = value;
+		};
+		Type.prototype = new XmlRpcType();
+		Type.prototype.tagName = tagName;
+
+		if (simple) {
+			var simpleEncode = encode, simpleDecode = decode;
+			encode = function(value, $xml) {
+				var text = simpleEncode(value);
+				return $xml(Type.tagName).text(text);
+			};
+			decode = function(node) {
+				return simpleDecode($(node).text(), node);
+			};
+		}
+		Type.prototype.toXmlRpc = function($xml) {
+			return Type.encode(this.value, $xml);
+		};
+
+		Type.tagName = tagName;
+		Type.encode = encode;
+		Type.decode = decode;
+
+		xmlrpc.types[tagName.toLowerCase()] = Type;
+	};
+
+
+	// Number types
+	var _fromInt = function(value) { return '' + Math.floor(value); };
+	var _toInt = function(text, _) { return parseInt(text, 10); };
+
+	xmlrpc.makeType('int', true, _fromInt, _toInt);
+	xmlrpc.makeType('i4', true, _fromInt, _toInt);
+	xmlrpc.makeType('i8', true, _fromInt, _toInt);
+	xmlrpc.makeType('i16', true, _fromInt, _toInt);
+	xmlrpc.makeType('i32', true, _fromInt, _toInt);
+
+	xmlrpc.makeType('double', true, String, function(text) {
+		return parseFloat(text, 10);
+	});
+
+	// String type. Fairly simple
+	xmlrpc.makeType('string', true, String, String);
+
+	// Boolean type. True == '1', False == '0'
+	xmlrpc.makeType('boolean', true, function(value) {
+		return value ? '1' : '0';
+	}, function(text) {
+		return text === '1';
+	});
+
+	// Dates are a little trickier
+	var _pad = function(n) { return n<10 ? '0'+n : n; };
+
+	xmlrpc.makeType('dateTime.iso8601', true, function(d) {
+		return [
+			d.getUTCFullYear(), '-', _pad(d.getUTCMonth()+1), '-',
+			_pad(d.getUTCDate()), 'T', _pad(d.getUTCHours()), ':',
+			_pad(d.getUTCMinutes()), ':', _pad(d.getUTCSeconds()), 'Z'
+		].join('');
+	}, function(text) {
+		return new Date(text);
+	});
+
+	// Go between a base64 string and an ArrayBuffer
+	xmlrpc.binary = (function() {
+		var pad = '=';
+		var toChars = ('ABCDEFGHIJKLMNOPQRSTUVWXYZ' +
+			'abcdefghijklmnopqrstuvwxyz0123456789+/').split("");
+		var fromChars = toChars.reduce(function(acc, chr, i) {
+			acc[chr] = i;
+			return acc;
+		}, {});
+
+		/*
+		* In the following, three bytes are added together into a 24-bit
+		* number, which is then split up in to 4 6-bit numbers - or vice versa.
+		* That is why there is lots of shifting by multiples of 6 and 8, and
+		* the magic numbers 3 and 4.
+		*
+		* The modulo 64 is for converting to base 64, and the modulo 256 is for
+		* converting to 8-bit numbers.
+		*/
+		return {
+			toBase64: function(ab) {
+				var acc = [];
+
+				var int8View = new Uint8Array(ab);
+				var int8Index = 0, int24;
+				for (; int8Index < int8View.length; int8Index += 3) {
+
+					// Grab three bytes
+					int24 =
+						(int8View[int8Index + 0] << 16) +
+						(int8View[int8Index + 1] << 8) +
+						(int8View[int8Index + 2] << 0);
+
+					// Push four chars
+					acc.push(toChars[(int24 >> 18) % 64]);
+					acc.push(toChars[(int24 >> 12) % 64]);
+					acc.push(toChars[(int24 >> 6) % 64]);
+					acc.push(toChars[(int24 >> 0)% 64]);
+				}
+
+				// Set the last few characters to the padding character
+				var padChars = 3 - ((ab.byteLength % 3) || 3);
+				while (padChars--) {
+					acc[acc.length - padChars - 1] = pad;
+				}
+
+				return acc.join('');
+			},
+
+			fromBase64: function(base64) {
+				var base64Len = base64.length;
+
+				// Work out the length of the data, accommodating for padding
+				var abLen = (base64Len / 4) * 3;
+				if (base64.charAt(base64Len - 1) === pad) { abLen--; }
+				if (base64.charAt(base64Len - 2) === pad) { abLen--; }
+
+				// Make the ArrayBuffer, and an Int8Array to work with it
+				var ab = new ArrayBuffer(abLen);
+				var int8View = new Uint8Array(ab);
+
+				var base64Index = 0, int8Index = 0, int24;
+				for (; base64Index < base64Len; base64Index += 4, int8Index += 3) {
+
+					// Grab four chars
+					int24 =
+						(fromChars[base64[base64Index + 0]] << 18) +
+						(fromChars[base64[base64Index + 1]] << 12) +
+						(fromChars[base64[base64Index + 2]] << 6) +
+						(fromChars[base64[base64Index + 3]] << 0);
+
+					// Push three bytes
+					int8View[int8Index + 0] = (int24 >> 16) % 256;
+					int8View[int8Index + 1] = (int24 >> 8) % 256;
+					int8View[int8Index + 2] = (int24 >> 0) % 256;
+
+				}
+
+				return ab;
+			}
+		};
+	})();
+
+	xmlrpc.makeType('base64', true, function(ab) {
+		return xmlrpc.binary.toBase64(ab);
+	}, function(text) {
+		return xmlrpc.binary.fromBase64(text);
+	});
+
+	// Nil/null
+	xmlrpc.makeType('nil', false,
+		function(val, $xml) { return $xml('nil'); },
+		function(_) { return null; }
+	);
+
+	// Structs/Objects
+	xmlrpc.makeType('struct', false, function(value, $xml) {
+		var $struct = $xml('struct');
+
+		$.each(value, function(name, value) {
+			var $name = $xml('name').text(name);
+			var $value = $xml('value').append(xmlrpc.toXmlRpc(value, $xml));
+			$struct.append($xml('member').append($name, $value));
+		});
+
+		return $struct;
+
+	}, function(node) {
+		return $(node)
+			.find('> member')
+			.toArray()
+			.reduce(function(struct, el) {
+				var $el = $(el);
+				var key = $el.find('> name').text();
+				var value = xmlrpc.parseValue($el.find('> value'));
+
+				struct[key] = value;
+				return struct;
+			}, {});
+
+	});
+
+	// Arrays
+	xmlrpc.makeType('array', false, function(value, $xml) {
+		var $array = $xml('array');
+		var $data = $xml('data');
+		$.each(value, function(i, val) {
+			$data.append($xml('value').append(xmlrpc.toXmlRpc(val, $xml)));
+		});
+		$array.append($data);
+		return $array;
+	}, function(node) {
+		return $(node).find('> data > value').toArray()
+			.map(xmlrpc.parseValue);
+	});
+
+
+	/**
+	* Force a value to an XML-RPC type. All the usual XML-RPC types are
+	* supported
+	*/
+	xmlrpc.force = function(type, value) {
+		return new xmlrpc.types[type](value);
+	};
+
+})(jQuery);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_skin/resources/js/ext/jquery-xmlrpc.min.js	Tue Apr 14 16:36:24 2015 +0200
@@ -0,0 +1,1 @@
+(function(g){var c=function(){Error.apply(this,arguments)};c.prototype=new Error();c.prototype.type="XML-RPC fault";var a=g.xmlrpc=function(i,j){if(arguments.length===2){j.url=i}else{j=i;i=j.url}j.dataType="xml json";j.type="POST";j.contentType="text/xml";j.converters={"xml json":a.parseDocument};var k=a.document(j.methodName,j.params||[]);if("XMLSerializer" in window){j.data=new window.XMLSerializer().serializeToString(k)}else{j.data=k.xml}return g.ajax(j)};a.createXMLDocument=function(){if(document.implementation&&"createDocument" in document.implementation){return document.implementation.createDocument(null,null,null)}else{var l,m,j=["MSXML6.DomDocument","MSXML3.DomDocument","MSXML2.DomDocument","MSXML.DomDocument","Microsoft.XmlDom"];for(l=0,m=j.length;l<m;l++){try{return new ActiveXObject(j[l])}catch(k){}}}};a.document=function(l,o){var n=a.createXMLDocument();var m=function(p){return g(n.createElement(p))};var j=m("methodName").text(l);var i=m("params").append(g.map(o,function(q){var p=m("value").append(a.toXmlRpc(q,m));return m("param").append(p)}));var k=m("methodCall").append(j,i);n.appendChild(k.get(0));return n};var b=function(i){return(i===parseInt(i,10))&&!isNaN(i)};a.toXmlRpc=function(l,k){if(l instanceof f){return l.toXmlRpc(k)}var i=g.xmlrpc.types;var j=g.type(l);switch(j){case"undefined":case"null":return i.nil.encode(l,k);case"date":return i["datetime.iso8601"].encode(l,k);case"object":if(l instanceof ArrayBuffer){return i.base64.encode(l,k)}else{return i.struct.encode(l,k)}break;case"number":if(b(l)){return i["int"].encode(l,k)}else{return i["double"].encode(l,k)}break;case"array":case"boolean":case"string":return i[j].encode(l,k);default:throw new Error("Unknown type",l)}};a.parseDocument=function(o){var p=g(o);var i=p.children("methodresponse");var l=i.find("> fault");if(l.length===0){var j=i.find("> params > param > value > *");var k=j.toArray().map(a.parseNode);return k}else{var n=a.parseNode(l.find("> value > *").get(0));var m=new c(n.faultString);m.msg=m.message=n.faultString;m.type=m.code=n.faultCode;throw m}};a.parseNode=function(j){if(j===undefined){return null}var i=j.nodeName.toLowerCase();if(i in a.types){return a.types[i].decode(j)}else{throw new Error("Unknown type "+i)}};a.parseValue=function(i){var j=g(i).children()[0];if(j){return a.parseNode(j)}else{return g(i).text()}};var f=function(){};g.xmlrpc.types={};a.makeType=function(j,o,k,m){var i;i=function(p){this.value=p};i.prototype=new f();i.prototype.tagName=j;if(o){var l=k,n=m;k=function(q,p){var r=l(q);return p(i.tagName).text(r)};m=function(p){return n(g(p).text(),p)}}i.prototype.toXmlRpc=function(p){return i.encode(this.value,p)};i.tagName=j;i.encode=k;i.decode=m;a.types[j.toLowerCase()]=i};var e=function(i){return""+Math.floor(i)};var d=function(j,i){return parseInt(j,10)};a.makeType("int",true,e,d);a.makeType("i4",true,e,d);a.makeType("i8",true,e,d);a.makeType("i16",true,e,d);a.makeType("i32",true,e,d);a.makeType("double",true,String,function(i){return parseFloat(i,10)});a.makeType("string",true,String,String);a.makeType("boolean",true,function(i){return i?"1":"0"},function(i){return i==="1"});var h=function(i){return i<10?"0"+i:i};a.makeType("dateTime.iso8601",true,function(i){return[i.getUTCFullYear(),"-",h(i.getUTCMonth()+1),"-",h(i.getUTCDate()),"T",h(i.getUTCHours()),":",h(i.getUTCMinutes()),":",h(i.getUTCSeconds()),"Z"].join("")},function(i){return new Date(i)});a.binary=(function(){var k="=";var i=("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/").split("");var j=i.reduce(function(n,m,l){n[m]=l;return n},{});return{toBase64:function(p){var o=[];var q=new Uint8Array(p);var m=0,n;for(;m<q.length;m+=3){n=(q[m+0]<<16)+(q[m+1]<<8)+(q[m+2]<<0);o.push(i[(n>>18)%64]);o.push(i[(n>>12)%64]);o.push(i[(n>>6)%64]);o.push(i[(n>>0)%64])}var l=3-((p.byteLength%3)||3);while(l--){o[o.length-l-1]=k}return o.join("")},fromBase64:function(m){var l=m.length;var s=(l/4)*3;if(m.charAt(l-1)===k){s--}if(m.charAt(l-2)===k){s--}var q=new ArrayBuffer(s);var r=new Uint8Array(q);var o=0,n=0,p;for(;o<l;o+=4,n+=3){p=(j[m[o+0]]<<18)+(j[m[o+1]]<<12)+(j[m[o+2]]<<6)+(j[m[o+3]]<<0);r[n+0]=(p>>16)%256;r[n+1]=(p>>8)%256;r[n+2]=(p>>0)%256}return q}}})();a.makeType("base64",true,function(i){return a.binary.toBase64(i)},function(i){return a.binary.fromBase64(i)});a.makeType("nil",false,function(j,i){return i("nil")},function(i){return null});a.makeType("struct",false,function(k,j){var i=j("struct");g.each(k,function(l,n){var o=j("name").text(l);var m=j("value").append(a.toXmlRpc(n,j));i.append(j("member").append(o,m))});return i},function(i){return g(i).find("> member").toArray().reduce(function(n,l){var k=g(l);var j=k.find("> name").text();var m=a.parseValue(k.find("> value"));n[j]=m;return n},{})});a.makeType("array",false,function(l,j){var k=j("array");var i=j("data");g.each(l,function(m,n){i.append(j("value").append(a.toXmlRpc(n,j)))});k.append(i);return k},function(i){return g(i).find("> data > value").toArray().map(a.parseValue)});a.force=function(i,j){return new a.types[i](j)}})(jQuery);
\ No newline at end of file