// ==UserScript==
// @name localStorage emulation
// @author Lex1
// @version 1.0
// @include http://*
// @description localStorage emulation for Opera 8.5-10.1. Need MIME-type "text/lse".
// @ujs:download http://ruzanow.ru/userjs/aa_localStorage.js
// ==/UserScript==

(function(){
//storage begin
var storage = {};
//storage end

// JSON support
var jsonParse = (function(){var j='(?:-?\\b(?:0|[1-9][0-9]*)(?:\\.[0-9]+)?(?:[eE][+-]?[0-9]+)?\\b)';var k='(?:[^\\0-\\x08\\x0a-\\x1f\"\\\\]'+'|\\\\(?:[\"/\\\\bfnrt]|u[0-9A-Fa-f]{4}))';var l='(?:\"'+k+'*\")';var m=new RegExp('(?:false|true|null|[\\{\\}\\[\\]]'+'|'+j+'|'+l+')','g');var o=new RegExp('\\\\(?:([^u])|u(.{4}))','g');var p={'"':'"','/':'/','\\':'\\','b':'\b','f':'\f','n':'\n','r':'\r','t':'\t'};function unescapeOne(_,a,b){return a?p[a]:String.fromCharCode(parseInt(b,16))}var q=new String('');var r='\\';var s={'{':Object,'[':Array};var t=Object.hasOwnProperty;return function(a){var b=a.match(m);var c;var d=b[0];var e=false;if('{'===d){c={}}else if('['===d){c=[]}else{c=[];e=true}var f;var g=[c];for(var i=1-e,n=b.length;i<n;++i){d=b[i];var h;switch(d.charCodeAt(0)){default:h=g[0];h[f||h.length]=+(d);f=void 0;break;case 0x22:d=d.substring(1,d.length-1);if(d.indexOf(r)!==-1){d=d.replace(o,unescapeOne)}h=g[0];if(!f){if(h instanceof Array){f=h.length}else{f=d||q;break}}h[f]=d;f=void 0;break;case 0x5b:h=g[0];g.unshift(h[f||h.length]=[]);f=void 0;break;case 0x5d:g.shift();break;case 0x66:h=g[0];h[f||h.length]=false;f=void 0;break;case 0x6e:h=g[0];h[f||h.length]=null;f=void 0;break;case 0x74:h=g[0];h[f||h.length]=true;f=void 0;break;case 0x7b:h=g[0];g.unshift(h[f||h.length]={});f=void 0;break;case 0x7d:g.shift();break}}if(e){if(g.length!==1){throw new Error();}c=c[0]}else{if(g.length){throw new Error();}}return c}})();
var jsonStringify = (function(){var g=/[\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff\"\\]/g;var h={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'};var j=function(b){return'"'+b.replace(g,function(a){if(!h[a])h[a]='\\u'+('0000'+a.charCodeAt(0).toString(16)).slice(-4);return h[a]})+'"'};var l=function(d){function f(v){return v<10?'0'+v:v}return'"'+d.getUTCFullYear()+'-'+f(d.getUTCMonth()+1)+'-'+f(d.getUTCDate())+'T'+f(d.getUTCHours())+':'+f(d.getUTCMinutes())+':'+f(d.getUTCSeconds())+'Z"'};var m=function(a,b,e){return a.length===0?b+e:b+'\n'+a.join(',\n').replace(/^/gm,'\t')+'\n'+e};var n=function(a,b){var i,k,v,p=[],o=b[a],t=typeof o,c=Object.prototype.toString.call(o);if(c==='[object Date]')return l(o);if(t==='string'||c==='[object String]')return j(o);if(t==='boolean'||c==='[object Boolean]')return String(o);if(t==='number'||c==='[object Number]')return isFinite(o)?String(o):'null';if(t==='object'){if(!o)return'null';if(Object.prototype.toString.apply(o)==='[object Array]'){for(i=0;i<o.length;i++){p[i]=n(i,o)||'null'};return m(p,'[',']')};for(k in o){if(Object.hasOwnProperty.call(o,k)){v=n(k,o);if(v){p.push(j(k)+': '+v)}}};return m(p,'{','}')}};return function(a){return n('',{'':a})}})();

// UserJS
if(typeof window == 'object' && !window.localStorage){
	var encodeBase64 = function(string){var out='',charCode=0,i=0,endBytes='',length=string.length;var puffer=[];var base64EncodeChars="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";while(charCode=string.charCodeAt(i++)){if(charCode<0x80){puffer[puffer.length]=charCode}else if(charCode<0x800){puffer[puffer.length]=0xc0|(charCode>>6);puffer[puffer.length]=0x80|(charCode&0x3f)}else if(charCode<0x10000){puffer[puffer.length]=0xe0|(charCode>>12);puffer[puffer.length]=0x80|((charCode>>6)&0x3f);puffer[puffer.length]=0x80|(charCode&0x3f)}else{puffer[puffer.length]=0xf0|(charCode>>18);puffer[puffer.length]=0x80|((charCode>>12)&0x3f);puffer[puffer.length]=0x80|((charCode>>6)&0x3f);puffer[puffer.length]=0x80|(charCode&0x3f)}if(i==length){while(puffer.length%3){puffer[puffer.length]=0;endBytes+='='}}if(puffer.length>2){out+=base64EncodeChars.charAt(puffer[0]>>2);out+=base64EncodeChars.charAt(((puffer.shift()&3)<<4)|(puffer[0]>>4));out+=base64EncodeChars.charAt(((puffer.shift()&0xf)<<2)|(puffer[0]>>6));out+=base64EncodeChars.charAt(puffer.shift()&0x3f)}}return(out+endBytes)};
	var saveFile = function(txt){if(txt.length>131072){alert('Error! String too long!');return};var src='data:text/lse;charset=UTF-8;base64,'+encodeBase64(txt);if(top==self){var f=document.createElement('iframe');f.width=0;f.height=0;f.frameBorder='no';f.scrolling='no';document.documentElement.appendChild(f);f.src=src;setTimeout(function(){f.parentNode.removeChild(f)},1)}else{location.href=src}};

	window.localStorage = storage[location.hostname] || {};
	window.localStorage.getItem = function(name){return this[name]};
	window.localStorage.setItem = function(name, value){this[name] = value; saveFile(jsonStringify({domain: location.hostname, name: name, value: value}))};
	window.localStorage.removeItem = function(name){delete this[name]; saveFile(jsonStringify({domain: location.hostname, name: name, value: undefined}))};
};

// WSH
if(typeof WScript == 'object' && WScript.Arguments){
	if(WScript.Arguments.length){
		var fso = new ActiveXObject('Scripting.FileSystemObject');
		var path = WScript.Arguments(0);
		if(!fso.FileExists(path) || fso.GetFile(path).Size > 131072){
			WScript.Echo('Error! File not exist: '+path);
			return;
		};

		var f = fso.OpenTextFile(path, 1, 0);
		var s = f.ReadAll().replace(/\0/g, '');
		f.Close();
		f = fso.OpenTextFile(WScript.ScriptFullName, 1, 0);
		var str = f.ReadAll().replace(/\0/g, '');
		f.Close();

		var add = jsonParse(s);
		if(!add.domain){
			WScript.Echo('Error! Domain not defined!');
			return;
		};
		if(!storage[add.domain])storage[add.domain] = {};
		storage[add.domain][add.name] = add.value;

		var startStr = '//storage begin\n', endStr = '\n//storage end', startLen = startStr.length;
		var startPos = str.indexOf(startStr);
		var endPos = str.indexOf(endStr, startPos+startLen);
		if(startPos != -1 && endPos != -1){
			f = fso.OpenTextFile(WScript.ScriptFullName, 2, 0);
			f.Write(str.slice(0, startPos+startLen)+'var storage = '+jsonStringify(storage)+';'+str.slice(endPos));
			f.Close();
		};
	}
	else{
		WScript.Echo('localStorage emulation for Opera 8.5-10.1');
	};
	return;
};
})();
