Page 1 of 1

Javascript Serialization Issues

Posted: Thu Feb 23, 2006 3:53 pm
by d3ad1ysp0rk
I've downloaded a javascript array serialization script. Once I get the serialized array (string format), I then pass it to a PHP page (xmlHttpRequest).

Problem is, even before it leaves the javascript (I did an "alert(str)" to test the value), it's different depending on browser.
It works in everything except Safari. It's Safari 2.0.3, so it's not old or anything.

Here's the code:

Code: Select all

//alert("Changes Saved!");
			var bigArray = new Array();
	
			var i = 0;
			while(currentDiv = document.getElementById('b['+i+']')){
				currentid = document.getElementById('ids['+i+']').value;
								
				if(deleted[i] == true){
					var isdeleted = true;
				}
				else {
					var isdeleted = false;
				}

				captionObj = document.getElementById('caption['+i+']');
				caption = captionObj.value;

				orderObj = document.getElementById('o['+i+']');
				order = orderObj.value;
				
				bigArray[i] = new Array();
				bigArray[i]['id'] = currentid;
				bigArray[i]['deleted'] = isdeleted;
				bigArray[i]['caption'] = caption;
				bigArray[i]['order'] = order;
				i++;
			}
			var php = new PHP_Serializer();
			var str = php.serialize(bigArray);	
			alert(str);
			createRequest('gallery.process.php',str);
And the class I'm using:

Code: Select all

/**
 * Object PHP_Serializer
 * 	JavaScript to PHP serialize / unserialize class.
 * This class is designed to convert php variables to javascript
 * and javascript variables to php with a php serialize unserialize
 * compatible way.
 *
 * PARSABLE PHP TO JAVASCRIPT VARIABLES:
 * 	[ PHP TYPE ]			[ JAVASCRIPT TYPE ]
 * 	array				Array
 * 	class				Object (*)
 * 	string				String
 * 	boolean				Boolean
 * 	undefined or null		null
 * 	integer / double 		Number
 *
 * PARSABLE JAVASCRIPT TO PHP VARIABLES:
 *	[ JAVASCRIPT TYPE ]		[ PHP TYPE ]
 *	Array				array
 *	Object				class (*)
 *	String				string
 *	Boolean				boolean
 *	null				null
 *	Number				int or double
 *	Date				class
 *	Error				class
 *	Function			anything (*)
 *	__class				anything (*)
 *
 * (*) NOTE:
 * Any PHP serialized class requires the native PHP class to be used, then it's not a
 * PHP => JavaScript converter, it's just a usefull serilizer class for each
 * compatible JS and PHP variable types.
 * However is possible to change public parameters.
 * Lambda, Resources or other dedicated PHP variables are not usefull for JavaScript.
 * (i.e.
 * 	$v = create_function('', 'return 1;'); serialize($v);
 *	$conn = mydb_connect(); serialize($conn);
 * )
 * There are same restrictions for javascript functions too then these will not be sent
 * (but will be filtered / ignored automatically).
 *
 * NEW ON V 1.6a and greater:
 * You can use experimental version of utf8 compatible serialized / unserialized strings
 * with true while you declare your php_serializer var:
 * var php = new PHP_Serializer(true); // enable experimental multybyte convertion
 * _____________________________________________
 *
 * EXAMPLE:
 *	var php = new PHP_Serializer();
 *	alert(php.unserialize(php.serialize(somevar)));
 *	// should alert the original value of somevar
 * ---------------------------------------------
 * @author              Andrea Giammarchi
 * @site		www.devpro.it
 * @date                2005/11/26
 * @lastmod             2006/01/13 07:00 [updated experimental UTF-8 compatible header and utf8_encode php function]
 * @credits		Special thanks to Fabio Sutto for some ideas and some debug
 *			Special thanks to kentaromiura for a faster loop idea while unserialize
 * @version             1.6b, tested on FireFox 1.5, IE 6 SP2 and Opera 8
 */
function PHP_Serializer() {
	this.__cut = (String(Object).indexOf('(')!=16)?9:10;
	if(arguments.length == 1 && arguments[0] == true) {
		this.__m = Math;
		PHP_Serializer.prototype.encode = PHP_Serializer__Encoded_length;
		PHP_Serializer.prototype[String] =
		PHP_Serializer.prototype.__string = PHP_Serializer__String__2;
		PHP_Serializer.prototype.s = PHP_UnSerializer__String_2;
	}
	else {
		PHP_Serializer.prototype[String] =
		PHP_Serializer.prototype.__string = PHP_Serializer__String__1;
		PHP_Serializer.prototype.s = PHP_UnSerializer__String_1;
	}
}
function PHP_Serializer__String__1(__s) {
	return ('s:'+__s.length+':"'+__s+'";');
}
function PHP_UnSerializer__String_1() {
	this.__c += 2;
	var sls = this.__s.substr(this.__c,(this.__s.indexOf(':',this.__c)-this.__c));
	var sli = parseInt(sls);
	sls = this.__c + sls.length + 2;
	this.__c = sls + sli + 2;
	return this.__s.substr(sls,sli);
}
function PHP_Serializer__Encoded_length(__s) {
	__s = __s.replace(/\r\n/g, '\n');
	var a = b = c = 0;
	var len = __s.length;
	while(a < len) {
		c = __s.charCodeAt(a++);
		b += (c<128)?1:((c<2048)?2:((c<65536)?3:4));
	}
	return b;
}
function PHP_Serializer__String__2(__s) {
	return ('s:'+this.encode(__s)+':"'+__s+'";');
}
function PHP_UnSerializer__String_2() {
	this.__c += 2;
	var sls = this.__s.substr(this.__c,(this.__s.indexOf(':',this.__c)-this.__c));
	var sli = parseInt(sls);
	sls = this.__c + sls.length + 2;
	if(sli > 0) {
		var a = sli > 4 ? this.__m.floor(sli/4) : 1;
		while(a > 0) {
			if(this.encode(this.__s.substr(sls,a++)) === sli) {
				sli = a - 1;
				a = 0;
			}
		}
	}
	this.__c = sls + sli + 2;
	return this.__s.substr(sls,sli);
}
function PHP_Serializer__Boolean(__s) {
	return ('b:'+(__s==false?'0':'1')+';');
}
function PHP_UnSerializer__Boolean() {
	var tmp = (this.__s.substr((this.__c+2),1)=='1'?true:false);
	this.__c += 4;
	return tmp;
}
function PHP_Serializer__Number(__s) {
	__s = String(__s);
	return ((__s.indexOf('.')==-1)?'i:'+__s+';':'d:'+__s+';');
}
function PHP_UnSerializer__Number() {
	var sli = this.__s.indexOf(';',(this.__c+1))-2;
	var tmp = Number(this.__s.substr((this.__c+2),(sli-this.__c)));
	this.__c = sli + 3;
	return tmp;
}
function PHP_Serializer__Function() {
	return '';
}
function PHP_Serializer__Undefined() {
	return 'N;';
}
function PHP_UnSerializer__Undefined() {
	this.__c += 2;
	return null;
}
function PHP_Serializer__Common_ArrayObject(__s) {
	var n;
	var a = 0;
	var ser = new Array();
	for(var b in __s) {
		n = (__s[b] == null);
		if(n || (__s[b].constructor != Function && b != '__class')) {
			ser[a++]=((!isNaN(b))?this.__number(b):this.__string(b))+
			(n?this.__undefined():this[__s[b].constructor](__s[b]));
		}
	}
	return [a,ser.join('')];
}
function PHP_UnSerializer__Common_ArrayObject(tmp) {
	this.__c += 2;
	var a = this.__s.indexOf(':',this.__c);
	var k = parseInt(this.__s.substr(this.__c,(a-this.__c))) + 1;
	this.__c = a + 2;
	while(--k)
		tmp[this[this.__s.substr(this.__c,1)]()] = this[this.__s.substr(this.__c,1)]();
	return tmp;
}
function PHP_Serializer__Object(__s) {
	var o = String(__s.constructor);
	var oname = o.substr(this.__cut,o.indexOf('(')-this.__cut);
	var ser = this.__common_array_object(__s);
	return ('O:'+oname.length+':"'+oname+'":'+ser[0]+':{'+ser[1]+'}');
}
function PHP_UnSerializer__Object() {
	var tmp = 's'+this.__s.substr(++this.__c,(this.__s.indexOf(':',(this.__c+3))-this.__c))+';';
	var a = tmp.substr(2,(tmp.indexOf(':',2)-2));
	var o = tmp.substr((a.length+4),parseInt(a));
	if(eval("typeof("+o+") == 'undefined'"))
		eval('function '+o+'(){}');
	this.__c += (tmp.length-3);
	eval('tmp = this.__common(new '+o+'());');
	++this.__c;
	return tmp;
}
function PHP_Serializer__Array(__s) {
	var ser = this.__common_array_object(__s);
	return ('a:'+ser[0]+':{'+ser[1]+'}');
}
function PHP_UnSerializer__Array() {
	var tmp = this.__common(new Array());
	++this.__c;
	return tmp;
}
function PHP_Serializer__serialize(what) {
	if(what==null)
		var ser = this.__undefined();
	else if(!this[what.constructor])
		var ser = this[Object](what);
	else
		var ser = this[what.constructor](what);
	return ser;
}
function PHP_UnSerializer__unserialize(what) {
	this.__c = 0;
	this.__s = what;
	delete what;
	return this[this.__s.substr(this.__c,1)]();
}
PHP_Serializer.prototype[Boolean] = PHP_Serializer__Boolean;
PHP_Serializer.prototype[Number] =
PHP_Serializer.prototype.__number = PHP_Serializer__Number;
PHP_Serializer.prototype[Function] = PHP_Serializer__Function;
PHP_Serializer.prototype[Date] = 
PHP_Serializer.prototype[Error] = 
PHP_Serializer.prototype[Object] = PHP_Serializer__Object;
PHP_Serializer.prototype[Array] = PHP_Serializer__Array;
PHP_Serializer.prototype.__common_array_object = PHP_Serializer__Common_ArrayObject;
PHP_Serializer.prototype.__undefined = PHP_Serializer__Undefined;
PHP_Serializer.prototype.serialize = PHP_Serializer__serialize;
PHP_Serializer.prototype.b = PHP_UnSerializer__Boolean;
PHP_Serializer.prototype.i =
PHP_Serializer.prototype.d = PHP_UnSerializer__Number;
PHP_Serializer.prototype.N = PHP_UnSerializer__Undefined;
PHP_Serializer.prototype.__common = PHP_UnSerializer__Common_ArrayObject;
PHP_Serializer.prototype.O = PHP_UnSerializer__Object;
PHP_Serializer.prototype.a = PHP_UnSerializer__Array;
PHP_Serializer.prototype.unserialize = PHP_UnSerializer__unserialize;
and the "serialized" arrays:

Code: Select all

a:3:{i:0;a:4:{s:2:"id";s:1:"9";s:7:"deleted";b:0;s:7:"caption";s:15:"vroom vroom?212";s:5:"order";s:1:"0";}i:1;a:4:{s:2:"id";s:1:"7";s:7:"deleted";b:0;s:7:"caption";s:13:"Weird picture";s:5:"order";s:1:"1";}i:2;a:4:{s:2:"id";s:2:"10";s:7:"deleted";b:0;s:7:"caption";s:17:"$25k+ used? Yup.";s:5:"order";s:1:"2";}}
- Firefox


s:3:",,";
- Safari
Now remember; it does work in most browsers. I assume that means it wouldn't be a syntax error?

I've also printed (alert'd) out the variables going into the array, and they look fine.

I'm thinking either safari doesn't like part of the class, or it doesn't like the way I'm putting the values in the array.

Thanks for the help!

Posted: Thu Feb 23, 2006 5:06 pm
by feyd
I'd suggest JSON. Will save you a LOT of time..

Posted: Fri Feb 24, 2006 10:50 pm
by d3ad1ysp0rk
Thanks Feyd, it works perfect now. Heck, now I have another hype word to put on my resume. ;)