var utils = {

	pack: function(data) {
		var packed = "";
		for(var i = 0; i < data.length; i++) {
			var integer = data[i];
			while(integer & ~0x7F) {
				packed += String.fromCharCode(integer & 0x7F);
				integer = (integer >> 7) & 0x01FFFFFF;
			}
			packed += String.fromCharCode(0x80 | (integer & 0x7F));
		}
		return packed;
	},

	unpack: function(packed) {
		var data = [], code, shift = 0, value = 0;
		for(var i = 0; i < packed.length; i++) {
			code = packed.charCodeAt(i);
			if(code & 0x80) {
				value |= (code & 0x7F) << shift;
				data.push(value);
				value = 0;
				shift = 0;
			} else {
				value |= code << shift;
				shift += 7;
			}
		}
		return data;
	},

	setCookie: function(name, value, expiredays, path, domain, secure) {
		if(expiredays) {
			var exdate = new Date();
			exdate.setDate(exdate.getDate() + expiredays);
			var expires = exdate.toGMTString();
		}
		document.cookie = name + "=" + escape(value) +
			((expiredays) ? "; expires=" + expires : "") +
			((path) ? "; path=" + path : "") +
			((domain) ? "; domain=" + domain : "") +
			((secure) ? "; secure" : "");
	},

	getCookie: function(name) {
		var cookie = " " + document.cookie;
		var search = " " + name + "=";
		var setStr = null;
		var offset = 0;
		var end = 0;
		if(cookie.length > 0) {
			offset = cookie.indexOf(search);
			if (offset != -1) {
				offset += search.length;
				end = cookie.indexOf(";", offset)
				if (end == -1) {
					end = cookie.length;
				}
				setStr = unescape(cookie.substring(offset, end));
			}
		}
		return setStr;
	},

	watchSerial: function(id) {
		var cookie = utils.getCookie("serials");
		var s = cookie ? utils.unpack(utils.base64.decode(cookie)) : [ ];
		s.push(id);
		utils.setCookie("serials", utils.base64.encode(utils.pack(s)), 730, "/");
	},

	base64: {

		set: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",

		encode: function(data) {
			var enc = '', bits, h1, h2, h3, h4, o1, o2, o3;
			for(var i = 0; i < data.length;) {
				o1 = data.charCodeAt(i++);
				o2 = data.charCodeAt(i++);
				o3 = data.charCodeAt(i++);

				bits = o1 << 16 | o2 << 8 | o3;

				h1 = bits >> 18 & 0x3f;
				h2 = bits >> 12 & 0x3f;
				h3 = bits >> 6 & 0x3f;
				h4 = bits & 0x3f;
		  
				enc += this.set.charAt(h1) + this.set.charAt(h2) + this.set.charAt(h3) + this.set.charAt(h4);
			}

			switch(data.length % 3){
			case 1:
				enc = enc.slice(0, -2) + '==';
				break;
			case 2:
				enc = enc.slice(0, -1) + '=';
				break;
			}
			return enc;
		},

		decode: function(data) {
			var enc = '', bits, h1, h2, h3, h4, o1, o2, o3;
			for(var i = 0; i < data.length;) {
				h1 = this.set.indexOf(data.charAt(i++));
				h2 = this.set.indexOf(data.charAt(i++));
				h3 = this.set.indexOf(data.charAt(i++));
				h4 = this.set.indexOf(data.charAt(i++));

				bits = h1 << 18 | h2 << 12 | h3 << 6 | h4;

				o1 = bits >> 16 & 0xff;
				o2 = bits >> 8 & 0xff;
				o3 = bits & 0xff;

				if(h3 == 64) enc += String.fromCharCode(o1);
				else if(h4 == 64) enc += String.fromCharCode(o1, o2);
				else enc += String.fromCharCode(o1, o2, o3);
			}
			return enc;
		}
	}
};


