function clone (o, append) {
  if(o == null || typeof(o) != 'object')
	return o;	  
	  
  var objectClone = new o.constructor();	  
  for (var property in o)
    if (typeof this[property] == 'object')
      objectClone[property] = clone(o[property]);
    else
      objectClone[property] = o[property];

  for (var i in append){
  	objectClone[i] = append[i];
  }

  return objectClone;
}

function stringBytesUTF8(s) {
	// returns the php lenght of a string (bytes, not chars)
	var 	c, b = 0,
		l = s.length;
	while(l) {
		c = s.charCodeAt(--l);
		b += (c < 128) ? 1 : ((c < 2048) ? 2 : ((c < 65536) ? 3 : 4));
	};
	return b;
}

function serializeString(s) {
	s=s.replace(/\\/g, "\\\\");
	s=s.replace(/\"/g, "\\\"");
	s=s.replace(/\n/g, "\\n");
	s=s.replace(/\r/g, "");

	return 's:' + s.length + ':"' + s + '";';
}

function serializeObject(o) {
    var php = '';
    var total = 0;
    for (var key in o) {
        ++ total;
        // Key
        php += serializeString(key.toString());
        php += serialize(o[key]);
    }

    return "a:" + total + ":{" + php + "}";
}

function serializeArray(o) {
    var php = '';
    var total = 0;
    for (var key = 0; key < o.length; key++) {
        total++;
        // Key
        php += 'i:' + key + ';';
        php += serialize(o[key]);
    }

    return "a:" + total + ":{" + php + "}";
}

function serialize(o){
	if(o.constructor == Object)
		return serializeObject(o);
	else if(o.constructor == Array)
		return serializeArray(o);
	else
		return serializeString(o.toString());
}