/**********************************************************\ | | | The implementation of PHPRPC Protocol 3.0 | | | | phpserializer.js | | | | Release 3.0.1 | | Copyright by Team-PHPRPC | | | | WebSite: http://www.phprpc.org/ | | http://www.phprpc.net/ | | http://www.phprpc.com/ | | http://sourceforge.net/projects/php-rpc/ | | | | Authors: Ma Bingyao | | | | This file may be distributed and/or modified under the | | terms of the GNU General Public License (GPL) version | | 2.0 as published by the Free Software Foundation and | | appearing in the included file LICENSE. | | | \**********************************************************/ /* PHP serialize/unserialize library. * * Copyright: Ma Bingyao * Version: 4.2 * LastModified: Apr 12, 2010 * This library is free. You can redistribute it and/or modify it under GPL. */ var PHPSerializer = (function () { function freeEval(s) { return eval(s); } var prototypePropertyOfArray = function() { var result = {}; for (var p in []) { result[p] = true; } return result; }(); var prototypePropertyOfObject = function() { var result = {}; for (var p in {}) { result[p] = true; } return result; }(); return { serialize : function(o) { var p = 0, sb = [], ht = [], hv = 1; function getClassName(o) { if (typeof(o) == 'undefined' || typeof(o.constructor) == 'undefined') return ''; var c = o.constructor.toString(); c = c.substr(0, c.indexOf('(')).replace(/(^\s*function\s*)|(\s*$)/ig, '').toUTF8(); return ((c == '') ? 'Object' : c); } function isInteger(n) { var i, s = n.toString(), l = s.length; if (l > 11) return false; for (i = (s.charAt(0) == '-') ? 1 : 0; i < l; i++) { switch (s.charAt(i)) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': break; default : return false; } } return !(n < -2147483648 || n > 2147483647); } function inHashTable(o) { for (var i = 0; i < ht.length; i++) if (ht[i] === o) return i; return false; } function serializeNull() { sb[p++] = 'N;'; } function serializeBoolean(b) { sb[p++] = (b ? 'b:1;' : 'b:0;'); } function serializeInteger(i) { sb[p++] = 'i:' + i + ';'; } function serializeDouble(d) { if (isNaN(d)) d = 'NAN'; else if (d == Number.POSITIVE_INFINITY) d = 'INF'; else if (d == Number.NEGATIVE_INFINITY) d = '-INF'; sb[p++] = 'd:' + d + ';'; } function serializeString(s) { var utf8 = s.toUTF8(); sb[p++] = 's:' + utf8.length + ':"'; sb[p++] = utf8; sb[p++] = '";'; } function serializeDate(dt) { sb[p++] = 'O:11:"PHPRPC_Date":7:{'; sb[p++] = 's:4:"year";'; serializeInteger(dt.getFullYear()); sb[p++] = 's:5:"month";'; serializeInteger(dt.getMonth() + 1); sb[p++] = 's:3:"day";'; serializeInteger(dt.getDate()); sb[p++] = 's:4:"hour";'; serializeInteger(dt.getHours()); sb[p++] = 's:6:"minute";'; serializeInteger(dt.getMinutes()); sb[p++] = 's:6:"second";'; serializeInteger(dt.getSeconds()); sb[p++] = 's:11:"millisecond";'; serializeInteger(dt.getMilliseconds()); sb[p++] = '}'; } function serializeArray(a) { sb[p++] = 'a:'; var k, lp = p; sb[p++] = 0; sb[p++] = ':{'; for (k in a) { if ((typeof(a[k]) != 'function') && !prototypePropertyOfArray[k]) { isInteger(k) ? serializeInteger(k) : serializeString(k); serialize(a[k]); sb[lp]++; } } sb[p++] = '}'; } function serializeObject(o) { var cn = getClassName(o); if (cn == '') serializeNull(); else if (typeof(o.serialize) != 'function') { sb[p++] = 'O:' + cn.length + ':"' + cn + '":'; var lp = p; sb[p++] = 0; sb[p++] = ':{'; var k; if (typeof(o.__sleep) == 'function') { var a = o.__sleep(); for (k in a) { serializeString(a[k]); serialize(o[a[k]]); sb[lp]++; } } else { for (k in o) { if (typeof(o[k]) != 'function' && !prototypePropertyOfObject[k]) { serializeString(k); serialize(o[k]); sb[lp]++; } } } sb[p++] = '}'; } else { var cs = o.serialize(); sb[p++] = 'C:' + cn.length + ':"' + cn + '":' + cs.length + ':{' +cs + '}'; } } function serializePointRef(R) { sb[p++] = 'R:' + R + ';'; } function serializeRef(r) { sb[p++] = 'r:' + r + ';'; } function serialize(o) { if (typeof(o) == "undefined" || o == null || o.constructor == Function) { hv++; serializeNull(); return; } var className = getClassName(o); switch (o.constructor) { case Boolean: { hv++; serializeBoolean(o); break; } case Number: { hv++; isInteger(o) ? serializeInteger(o) : serializeDouble(o); break; } case String: { hv++; serializeString(o); break; } case Date: { hv += 8; serializeDate(o); break; } default: { if (className == "Object" || o.constructor == Array) { var r = inHashTable(o); if (r) { serializePointRef(r); } else { ht[hv++] = o; serializeArray(o); } break; } else { var r = inHashTable(o); if (r) { hv++; serializeRef(r); } else { ht[hv++] = o; serializeObject(o); } } } } } serialize(o); return sb.join(''); }, unserialize : function(ss) { var p = 0, ht = [], hv = 1; function unserializeNull() { p++; return null; } function unserializeBoolean() { p++; var b = (ss.charAt(p++) == '1'); p++; return b; } function unserializeInteger() { p++; var i = parseInt(ss.substring(p, p = ss.indexOf(';', p))); p++; return i; } function unserializeDouble() { p++; var d = ss.substring(p, p = ss.indexOf(';', p)); switch (d) { case 'NAN': d = NaN; break; case 'INF': d = Number.POSITIVE_INFINITY; break; case '-INF': d = Number.NEGATIVE_INFINITY; break; default: d = parseFloat(d); } p++; return d; } function unserializeString() { p++; var l = parseInt(ss.substring(p, p = ss.indexOf(':', p))); p += 2; var s = ss.substring(p, p += l).toUTF16(); p += 2; return s; } function unserializeEscapedString(len) { p++; var l = parseInt(ss.substring(p, p = ss.indexOf(':', p))); p += 2; var i, sb = new Array(l); for (i = 0; i < l; i++) { if ((sb[i] = ss.charAt(p++)) == '\\') { sb[i] = String.fromCharCode(parseInt(ss.substring(p, p += len), 16)); } } p += 2; return sb.join(''); } function unserializeArray() { p++; var n = parseInt(ss.substring(p, p = ss.indexOf(':', p))); p += 2; var i, k, a = []; ht[hv++] = a; for (i = 0; i < n; i++) { switch (ss.charAt(p++)) { case 'i': k = unserializeInteger(); break; case 's': k = unserializeString(); break; case 'S': k = unserializeEscapedString(2); break; case 'U': k = unserializeEscapedString(4); break; default: return false; } a[k] = unserialize(); } p++; return a; } function unserializeDate(n) { var i, k, a = {}; for (i = 0; i < n; i++) { switch (ss.charAt(p++)) { case 's': k = unserializeString(); break; case 'S': k = unserializeEscapedString(2); break; case 'U': k = unserializeEscapedString(4); break; default: return false; } if (ss.charAt(p++) == 'i') { a[k] = unserializeInteger(); } else { return false; } } p++; var dt = new Date( a.year, a.month - 1, a.day, a.hour, a.minute, a.second, a.millisecond ); ht[hv++] = dt; ht[hv++] = a.year; ht[hv++] = a.month; ht[hv++] = a.day; ht[hv++] = a.hour; ht[hv++] = a.minute; ht[hv++] = a.second; ht[hv++] = a.millisecond; return dt; } function unserializeObject() { p++; var l = parseInt(ss.substring(p, p = ss.indexOf(':', p))); p += 2; var cn = ss.substring(p, p += l).toUTF16(); p += 2; var n = parseInt(ss.substring(p, p = ss.indexOf(':', p))); p += 2; if (cn == "PHPRPC_Date") { return unserializeDate(n); } var i, k, o = createObjectOfClass(cn); ht[hv++] = o; for (i = 0; i < n; i++) { switch (ss.charAt(p++)) { case 's': k = unserializeString(); break; case 'S': k = unserializeEscapedString(2); break; case 'U': k = unserializeEscapedString(4); break; default: return false; } if (k.charAt(0) == '\0') { k = k.substring(k.indexOf('\0', 1) + 1, k.length); } o[k] = unserialize(); } p++; if (typeof(o.__wakeup) == 'function') o.__wakeup(); return o; } function unserializeCustomObject() { p++; var l = parseInt(ss.substring(p, p = ss.indexOf(':', p))); p += 2; var cn = ss.substring(p, p += l).toUTF16(); p += 2; var n = parseInt(ss.substring(p, p = ss.indexOf(':', p))); p += 2; var o = createObjectOfClass(cn); ht[hv++] = o; if (typeof(o.unserialize) != 'function') p += n; else o.unserialize(ss.substring(p, p += n)); p++; return o; } function unserializeRef() { p++; var r = parseInt(ss.substring(p, p = ss.indexOf(';', p))); p++; return ht[r]; } function getObjectOfClass(cn, poslist, i, c) { if (i < poslist.length) { var pos = poslist[i]; cn[pos] = c; var obj = getObjectOfClass(cn, poslist, i + 1, '.'); if (i + 1 < poslist.length) { if (obj == null) { obj = getObjectOfClass(cn, poslist, i + 1, '_'); } } return obj; } var classname = cn.join(''); try { return freeEval('new ' + classname + '()'); } catch (e) { return null; } } function createObjectOfClass(classname) { if (freeEval('typeof(' + classname + ') == "function"')) { return freeEval('new ' + classname + '()'); } var poslist = []; var pos = classname.indexOf("_"); while (pos > -1) { poslist[poslist.length] = pos; pos = classname.indexOf("_", pos + 1); } if (poslist.length > 0) { var cn = classname.split(''); var obj = getObjectOfClass(cn, poslist, 0, '.'); if (obj == null) { obj = getObjectOfClass(cn, poslist, 0, '_'); } if (obj != null) { return obj; } } return freeEval('new function ' + classname + '(){};'); } function unserialize() { switch (ss.charAt(p++)) { case 'N': return ht[hv++] = unserializeNull(); case 'b': return ht[hv++] = unserializeBoolean(); case 'i': return ht[hv++] = unserializeInteger(); case 'd': return ht[hv++] = unserializeDouble(); case 's': return ht[hv++] = unserializeString(); case 'S': return ht[hv++] = unserializeEscapedString(2); case 'U': return ht[hv++] = unserializeEscapedString(4); case 'r': return ht[hv++] = unserializeRef(); case 'a': return unserializeArray(); case 'O': return unserializeObject(); case 'C': return unserializeCustomObject(); case 'R': return unserializeRef(); default: return false; } } return unserialize(); } } })();