aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xjslint.js524
-rw-r--r--offline-submit/collect-inputs.js45
-rw-r--r--offline-submit/form-serialization.js129
-rw-r--r--offline-submit/http-requests.txt28
-rw-r--r--offline-submit/john-resig-offline-app-stub.js43
-rw-r--r--offline-submit/jquery.malsup.com.htm583
-rw-r--r--offline-submit/lazarus.js4418
-rw-r--r--offline-submit/post-data.txt79
8 files changed, 0 insertions, 5849 deletions
diff --git a/jslint.js b/jslint.js
deleted file mode 100755
index a9f9667..0000000
--- a/jslint.js
+++ /dev/null
@@ -1,524 +0,0 @@
-#!/usr/bin/rhino
-// (C)2002 Douglas Crockford
-// www.JSLint.com
-// Rhino Edition
-"use strict";var JSLINT=(function(){var adsafe_id,adsafe_may,adsafe_went,anonname,approved,atrule={media:true,'font-face':true,page:true},bang={'<':true,'<=':true,'==':true,'===':true,'!==':true,'!=':true,'>':true,'>=':true,'+':true,'-':true,'*':true,'/':true,'%':true},banned={'arguments':true,callee:true,caller:true,constructor:true,'eval':true,prototype:true,unwatch:true,valueOf:true,watch:true},boolOptions={adsafe:true,bitwise:true,browser:true,cap:true,css:true,debug:true,eqeqeq:true,evil:true,forin:true,fragment:true,immed:true,laxbreak:true,newcap:true,nomen:true,on:true,onevar:true,passfail:true,plusplus:true,regexp:true,rhino:true,undef:true,safe:true,sidebar:true,strict:true,sub:true,white:true,widget:true},browser={addEventListener:false,alert:false,blur:false,clearInterval:false,clearTimeout:false,close:false,closed:false,confirm:false,console:false,Debug:false,defaultStatus:false,document:false,event:false,focus:false,frames:false,getComputedStyle:false,history:false,Image:false,length:false,location:false,moveBy:false,moveTo:false,name:false,navigator:false,onbeforeunload:true,onblur:true,onerror:true,onfocus:true,onload:true,onresize:true,onunload:true,open:false,opener:false,opera:false,Option:false,parent:false,print:false,prompt:false,removeEventListener:false,resizeBy:false,resizeTo:false,screen:false,scroll:false,scrollBy:false,scrollTo:false,setInterval:false,setTimeout:false,status:false,top:false,XMLHttpRequest:false},cssAttributeData,cssAny,cssColorData={"aliceblue":true,"antiquewhite":true,"aqua":true,"aquamarine":true,"azure":true,"beige":true,"bisque":true,"black":true,"blanchedalmond":true,"blue":true,"blueviolet":true,"brown":true,"burlywood":true,"cadetblue":true,"chartreuse":true,"chocolate":true,"coral":true,"cornflowerblue":true,"cornsilk":true,"crimson":true,"cyan":true,"darkblue":true,"darkcyan":true,"darkgoldenrod":true,"darkgray":true,"darkgreen":true,"darkkhaki":true,"darkmagenta":true,"darkolivegreen":true,"darkorange":true,"darkorchid":true,"darkred":true,"darksalmon":true,"darkseagreen":true,"darkslateblue":true,"darkslategray":true,"darkturquoise":true,"darkviolet":true,"deeppink":true,"deepskyblue":true,"dimgray":true,"dodgerblue":true,"firebrick":true,"floralwhite":true,"forestgreen":true,"fuchsia":true,"gainsboro":true,"ghostwhite":true,"gold":true,"goldenrod":true,"gray":true,"green":true,"greenyellow":true,"honeydew":true,"hotpink":true,"indianred":true,"indigo":true,"ivory":true,"khaki":true,"lavender":true,"lavenderblush":true,"lawngreen":true,"lemonchiffon":true,"lightblue":true,"lightcoral":true,"lightcyan":true,"lightgoldenrodyellow":true,"lightgreen":true,"lightpink":true,"lightsalmon":true,"lightseagreen":true,"lightskyblue":true,"lightslategray":true,"lightsteelblue":true,"lightyellow":true,"lime":true,"limegreen":true,"linen":true,"magenta":true,"maroon":true,"mediumaquamarine":true,"mediumblue":true,"mediumorchid":true,"mediumpurple":true,"mediumseagreen":true,"mediumslateblue":true,"mediumspringgreen":true,"mediumturquoise":true,"mediumvioletred":true,"midnightblue":true,"mintcream":true,"mistyrose":true,"moccasin":true,"navajowhite":true,"navy":true,"oldlace":true,"olive":true,"olivedrab":true,"orange":true,"orangered":true,"orchid":true,"palegoldenrod":true,"palegreen":true,"paleturquoise":true,"palevioletred":true,"papayawhip":true,"peachpuff":true,"peru":true,"pink":true,"plum":true,"powderblue":true,"purple":true,"red":true,"rosybrown":true,"royalblue":true,"saddlebrown":true,"salmon":true,"sandybrown":true,"seagreen":true,"seashell":true,"sienna":true,"silver":true,"skyblue":true,"slateblue":true,"slategray":true,"snow":true,"springgreen":true,"steelblue":true,"tan":true,"teal":true,"thistle":true,"tomato":true,"turquoise":true,"violet":true,"wheat":true,"white":true,"whitesmoke":true,"yellow":true,"yellowgreen":true},cssBorderStyle,cssBreak,cssLengthData={'%':true,'cm':true,'em':true,'ex':true,'in':true,'mm':true,'pc':true,'pt':true,'px':true},cssOverflow,escapes={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','/':'\\/','\\':'\\\\'},funct,functionicity=['closure','exception','global','label','outer','unused','var'],functions,global,htmltag={a:{},abbr:{},acronym:{},address:{},applet:{},area:{empty:true,parent:' map '},b:{},base:{empty:true,parent:' head '},bdo:{},big:{},blockquote:{},body:{parent:' html noframes '},br:{empty:true},button:{},canvas:{parent:' body p div th td '},caption:{parent:' table '},center:{},cite:{},code:{},col:{empty:true,parent:' table colgroup '},colgroup:{parent:' table '},dd:{parent:' dl '},del:{},dfn:{},dir:{},div:{},dl:{},dt:{parent:' dl '},em:{},embed:{},fieldset:{},font:{},form:{},frame:{empty:true,parent:' frameset '},frameset:{parent:' html frameset '},h1:{},h2:{},h3:{},h4:{},h5:{},h6:{},head:{parent:' html '},html:{parent:'*'},hr:{empty:true},i:{},iframe:{},img:{empty:true},input:{empty:true},ins:{},kbd:{},label:{},legend:{parent:' fieldset '},li:{parent:' dir menu ol ul '},link:{empty:true,parent:' head '},map:{},menu:{},meta:{empty:true,parent:' head noframes noscript '},noframes:{parent:' html body '},noscript:{parent:' body head noframes '},object:{},ol:{},optgroup:{parent:' select '},option:{parent:' optgroup select '},p:{},param:{empty:true,parent:' applet object '},pre:{},q:{},samp:{},script:{empty:true,parent:' body div frame head iframe p pre span '},select:{},small:{},span:{},strong:{},style:{parent:' head ',empty:true},sub:{},sup:{},table:{},tbody:{parent:' table '},td:{parent:' tr '},textarea:{},tfoot:{parent:' table '},th:{parent:' tr '},thead:{parent:' table '},title:{parent:' head '},tr:{parent:' table tbody thead tfoot '},tt:{},u:{},ul:{},'var':{}},ids,implied,inblock,indent,jsonmode,lines,lookahead,member,membersOnly,nexttoken,noreach,option,predefined,prereg,prevtoken,rhino={defineClass:false,deserialize:false,gc:false,help:false,load:false,loadClass:false,print:false,quit:false,readFile:false,readUrl:false,runCommand:false,seal:false,serialize:false,spawn:false,sync:false,toint32:false,version:false},scope,sidebar={System:false},src,stack,standard={Array:false,Boolean:false,Date:false,decodeURI:false,decodeURIComponent:false,encodeURI:false,encodeURIComponent:false,Error:false,'eval':false,EvalError:false,Function:false,hasOwnProperty:false,isFinite:false,isNaN:false,JSON:false,Math:false,Number:false,Object:false,parseInt:false,parseFloat:false,RangeError:false,ReferenceError:false,RegExp:false,String:false,SyntaxError:false,TypeError:false,URIError:false},standard_member={E:true,LN2:true,LN10:true,LOG2E:true,LOG10E:true,PI:true,SQRT1_2:true,SQRT2:true,MAX_VALUE:true,MIN_VALUE:true,NEGATIVE_INFINITY:true,POSITIVE_INFINITY:true},strict_mode,syntax={},tab,token,urls,warnings,widget={alert:true,animator:true,appleScript:true,beep:true,bytesToUIString:true,Canvas:true,chooseColor:true,chooseFile:true,chooseFolder:true,closeWidget:true,COM:true,convertPathToHFS:true,convertPathToPlatform:true,CustomAnimation:true,escape:true,FadeAnimation:true,filesystem:true,Flash:true,focusWidget:true,form:true,FormField:true,Frame:true,HotKey:true,Image:true,include:true,isApplicationRunning:true,iTunes:true,konfabulatorVersion:true,log:true,md5:true,MenuItem:true,MoveAnimation:true,openURL:true,play:true,Point:true,popupMenu:true,preferenceGroups:true,preferences:true,print:true,prompt:true,random:true,Rectangle:true,reloadWidget:true,ResizeAnimation:true,resolvePath:true,resumeUpdates:true,RotateAnimation:true,runCommand:true,runCommandInBg:true,saveAs:true,savePreferences:true,screen:true,ScrollBar:true,showWidgetPreferences:true,sleep:true,speak:true,Style:true,suppressUpdates:true,system:true,tellWidget:true,Text:true,TextArea:true,Timer:true,unescape:true,updateNow:true,URL:true,Web:true,widget:true,Window:true,XMLDOM:true,XMLHttpRequest:true,yahooCheckLogin:true,yahooLogin:true,yahooLogout:true},xmode,xquote,ax=/@cc|<\/?|script|\]*s\]|<\s*!|&lt/i,cx=/[\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/,tx=/^\s*([(){}\[.,:;'"~\?\]#@]|==?=?|\/(\*(jslint|members?|global)?|=|\/)?|\*[\/=]?|\+[+=]?|-[\-=]?|%=?|&[&=]?|\|[|=]?|>>?>?=?|<([\/=!]|\!(\[|--)?|<=?)?|\^=?|\!=?=?|[a-zA-Z_$][a-zA-Z0-9_$]*|[0-9]+([xX][0-9a-fA-F]+|\.[0-9]*)?([eE][+\-]?[0-9]+)?)/,hx=/^\s*(['"=>\/&#]|<(?:\/|\!(?:--)?)?|[a-zA-Z][a-zA-Z0-9_\-]*|[0-9]+|--|.)/,nx=/[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/,nxg=/[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,ox=/[>&]|<[\/!]?|--/,lx=/\*\/|\/\*/,ix=/^([a-zA-Z_$][a-zA-Z0-9_$]*)$/,jx=/^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\s*:/i,ux=/&|\+|\u00AD|\.\.|\/\*|%[^;]|base64|url|expression|data|mailto/i,sx=/^\s*([{:#%.=,>+\[\]@()"';]|\*=?|\$=|\|=|\^=|~=|[a-zA-Z_][a-zA-Z0-9_\-]*|[0-9]+|<\/|\/\*)/,ssx=/^\s*([@#!"'};:\-%.=,+\[\]()*_]|[a-zA-Z][a-zA-Z0-9._\-]*|\/\*?|\d+(?:\.\d+)?|<\/)/,qx=/[^a-zA-Z0-9-_\/ ]/,dx=/[\[\]\/\\"'*<>.&:(){}+=#]/,rx={outer:hx,html:hx,style:sx,styleproperty:ssx};function F(){}
-if(typeof Object.create!=='function'){Object.create=function(o){F.prototype=o;return new F();};}
-function is_own(object,name){return Object.prototype.hasOwnProperty.call(object,name);}
-function combine(t,o){var n;for(n in o){if(is_own(o,n)){t[n]=o[n];}}}
-String.prototype.entityify=function(){return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');};String.prototype.isAlpha=function(){return(this>='a'&&this<='z\uffff')||(this>='A'&&this<='Z\uffff');};String.prototype.isDigit=function(){return(this>='0'&&this<='9');};String.prototype.supplant=function(o){return this.replace(/\{([^{}]*)\}/g,function(a,b){var r=o[b];return typeof r==='string'||typeof r==='number'?r:a;});};String.prototype.name=function(){if(ix.test(this)){return this;}
-if(nx.test(this)){return'"'+this.replace(nxg,function(a){var c=escapes[a];if(c){return c;}
-return'\\u'+('0000'+a.charCodeAt().toString(16)).slice(-4);})+'"';}
-return'"'+this+'"';};function assume(){if(!option.safe){if(option.rhino){combine(predefined,rhino);}
-if(option.browser||option.sidebar){combine(predefined,browser);}
-if(option.sidebar){combine(predefined,sidebar);}
-if(option.widget){combine(predefined,widget);}}}
-function quit(m,l,ch){throw{name:'JSLintError',line:l,character:ch,message:m+" ("+Math.floor((l/lines.length)*100)+"% scanned)."};}
-function warning(m,t,a,b,c,d){var ch,l,w;t=t||nexttoken;if(t.id==='(end)'){t=token;}
-l=t.line||0;ch=t.from||0;w={id:'(error)',raw:m,evidence:lines[l-1]||'',line:l,character:ch,a:a,b:b,c:c,d:d};w.reason=m.supplant(w);JSLINT.errors.push(w);if(option.passfail){quit('Stopping. ',l,ch);}
-warnings+=1;if(warnings>=option.maxerr){quit("Too many errors.",l,ch);}
-return w;}
-function warningAt(m,l,ch,a,b,c,d){return warning(m,{line:l,from:ch},a,b,c,d);}
-function error(m,t,a,b,c,d){var w=warning(m,t,a,b,c,d);quit("Stopping, unable to continue.",w.line,w.character);}
-function errorAt(m,l,ch,a,b,c,d){return error(m,{line:l,from:ch},a,b,c,d);}
-var lex=(function lex(){var character,from,line,s;function nextLine(){var at;if(line>=lines.length){return false;}
-character=1;s=lines[line];line+=1;at=s.search(/ \t/);if(at>=0){warningAt("Mixed spaces and tabs.",line,at+1);}
-s=s.replace(/\t/g,tab);at=s.search(cx);if(at>=0){warningAt("Unsafe character.",line,at);}
-if(option.maxlen&&option.maxlen<s.length){warningAt("Line too long.",line,s.length);}
-return true;}
-function it(type,value){var i,t;if(type==='(color)'){t={type:type};}else if(type==='(punctuator)'||(type==='(identifier)'&&is_own(syntax,value))){t=syntax[value]||syntax['(error)'];}else{t=syntax[type];}
-t=Object.create(t);if(type==='(string)'||type==='(range)'){if(jx.test(value)){warningAt("Script URL.",line,from);}}
-if(type==='(identifier)'){t.identifier=true;if(value==='__iterator__'||value==='__proto__'){errorAt("Reserved name '{a}'.",line,from,value);}else if(option.nomen&&(value.charAt(0)==='_'||value.charAt(value.length-1)==='_')){warningAt("Unexpected {a} in '{b}'.",line,from,"dangling '_'",value);}}
-t.value=value;t.line=line;t.character=character;t.from=from;i=t.id;if(i!=='(endline)'){prereg=i&&(('(,=:[!&|?{};'.indexOf(i.charAt(i.length-1))>=0)||i==='return');}
-return t;}
-return{init:function(source){if(typeof source==='string'){lines=source.replace(/\r\n/g,'\n').replace(/\r/g,'\n').split('\n');}else{lines=source;}
-line=0;nextLine();from=1;},range:function(begin,end){var c,value='';from=character;if(s.charAt(0)!==begin){errorAt("Expected '{a}' and instead saw '{b}'.",line,character,begin,s.charAt(0));}
-for(;;){s=s.slice(1);character+=1;c=s.charAt(0);switch(c){case'':errorAt("Missing '{a}'.",line,character,c);break;case end:s=s.slice(1);character+=1;return it('(range)',value);case xquote:case'\\':warningAt("Unexpected '{a}'.",line,character,c);}
-value+=c;}},token:function(){var b,c,captures,d,depth,high,i,l,low,q,t;function match(x){var r=x.exec(s),r1;if(r){l=r[0].length;r1=r[1];c=r1.charAt(0);s=s.substr(l);from=character+l-r1.length;character+=l;return r1;}}
-function string(x){var c,j,r='';if(jsonmode&&x!=='"'){warningAt("Strings must use doublequote.",line,character);}
-if(xquote===x||(xmode==='scriptstring'&&!xquote)){return it('(punctuator)',x);}
-function esc(n){var i=parseInt(s.substr(j+1,n),16);j+=n;if(i>=32&&i<=126&&i!==34&&i!==92&&i!==39){warningAt("Unnecessary escapement.",line,character);}
-character+=n;c=String.fromCharCode(i);}
-j=0;for(;;){while(j>=s.length){j=0;if(xmode!=='html'||!nextLine()){errorAt("Unclosed string.",line,from);}}
-c=s.charAt(j);if(c===x){character+=1;s=s.substr(j+1);return it('(string)',r,x);}
-if(c<' '){if(c==='\n'||c==='\r'){break;}
-warningAt("Control character in string: {a}.",line,character+j,s.slice(0,j));}else if(c===xquote){warningAt("Bad HTML string",line,character+j);}else if(c==='<'){if(option.safe&&xmode==='html'){warningAt("ADsafe string violation.",line,character+j);}else if(s.charAt(j+1)==='/'&&(xmode||option.safe)){warningAt("Expected '<\\/' and instead saw '</'.",line,character);}else if(s.charAt(j+1)==='!'&&(xmode||option.safe)){warningAt("Unexpected '<!' in a string.",line,character);}}else if(c==='\\'){if(xmode==='html'){if(option.safe){warningAt("ADsafe string violation.",line,character+j);}}else if(xmode==='styleproperty'){j+=1;character+=1;c=s.charAt(j);if(c!==x){warningAt("Escapement in style string.",line,character+j);}}else{j+=1;character+=1;c=s.charAt(j);switch(c){case xquote:warningAt("Bad HTML string",line,character+j);break;case'\\':case'\'':case'"':case'/':break;case'b':c='\b';break;case'f':c='\f';break;case'n':c='\n';break;case'r':c='\r';break;case't':c='\t';break;case'u':esc(4);break;case'v':c='\v';break;case'x':if(jsonmode){warningAt("Avoid \\x-.",line,character);}
-esc(2);break;default:warningAt("Bad escapement.",line,character);}}}
-r+=c;character+=1;j+=1;}}
-for(;;){if(!s){return it(nextLine()?'(endline)':'(end)','');}
-while(xmode==='outer'){i=s.search(ox);if(i===0){break;}else if(i>0){character+=1;s=s.slice(i);break;}else{if(!nextLine()){return it('(end)','');}}}
-t=match(rx[xmode]||tx);if(!t){if(xmode==='html'){return it('(error)',s.charAt(0));}else{t='';c='';while(s&&s<'!'){s=s.substr(1);}
-if(s){errorAt("Unexpected '{a}'.",line,character,s.substr(0,1));}}}else{if(c.isAlpha()||c==='_'||c==='$'){return it('(identifier)',t);}
-if(c.isDigit()){if(xmode!=='style'&&!isFinite(Number(t))){warningAt("Bad number '{a}'.",line,character,t);}
-if(xmode!=='style'&&xmode!=='styleproperty'&&s.substr(0,1).isAlpha()){warningAt("Missing space after '{a}'.",line,character,t);}
-if(c==='0'){d=t.substr(1,1);if(d.isDigit()){if(token.id!=='.'&&xmode!=='styleproperty'){warningAt("Don't use extra leading zeros '{a}'.",line,character,t);}}else if(jsonmode&&(d==='x'||d==='X')){warningAt("Avoid 0x-. '{a}'.",line,character,t);}}
-if(t.substr(t.length-1)==='.'){warningAt("A trailing decimal point can be confused with a dot '{a}'.",line,character,t);}
-return it('(number)',t);}
-switch(t){case'"':case"'":return string(t);case'//':if(src||(xmode&&xmode!=='script')){warningAt("Unexpected comment.",line,character);}else if(xmode==='script'&&/<\s*\//i.test(s)){warningAt("Unexpected <\/ in comment.",line,character);}else if((option.safe||xmode==='script')&&ax.test(s)){warningAt("Dangerous comment.",line,character);}
-s='';token.comment=true;break;case'/*':if(src||(xmode&&xmode!=='script'&&xmode!=='style'&&xmode!=='styleproperty')){warningAt("Unexpected comment.",line,character);}
-if(option.safe&&ax.test(s)){warningAt("ADsafe comment violation.",line,character);}
-for(;;){i=s.search(lx);if(i>=0){break;}
-if(!nextLine()){errorAt("Unclosed comment.",line,character);}else{if(option.safe&&ax.test(s)){warningAt("ADsafe comment violation.",line,character);}}}
-character+=i+2;if(s.substr(i,1)==='/'){errorAt("Nested comment.",line,character);}
-s=s.substr(i+2);token.comment=true;break;case'/*members':case'/*member':case'/*jslint':case'/*global':case'*/':return{value:t,type:'special',line:line,character:character,from:from};case'':break;case'/':if(prereg){depth=0;captures=0;l=0;for(;;){b=true;c=s.charAt(l);l+=1;switch(c){case'':errorAt("Unclosed regular expression.",line,from);return;case'/':if(depth>0){warningAt("Unescaped '{a}'.",line,from+l,'/');}
-c=s.substr(0,l-1);q={g:true,i:true,m:true};while(q[s.charAt(l)]===true){q[s.charAt(l)]=false;l+=1;}
-character+=l;s=s.substr(l);return it('(regexp)',c);case'\\':c=s.charAt(l);if(c<' '){warningAt("Unexpected control character in regular expression.",line,from+l);}else if(c==='<'){warningAt("Unexpected escaped character '{a}' in regular expression.",line,from+l,c);}
-l+=1;break;case'(':depth+=1;b=false;if(s.charAt(l)==='?'){l+=1;switch(s.charAt(l)){case':':case'=':case'!':l+=1;break;default:warningAt("Expected '{a}' and instead saw '{b}'.",line,from+l,':',s.charAt(l));}}else{captures+=1;}
-break;case'|':b=false;break;case')':if(depth===0){warningAt("Unescaped '{a}'.",line,from+l,')');}else{depth-=1;}
-break;case' ':q=1;while(s.charAt(l)===' '){l+=1;q+=1;}
-if(q>1){warningAt("Spaces are hard to count. Use {{a}}.",line,from+l,q);}
-break;case'[':c=s.charAt(l);if(c==='^'){l+=1;if(option.regexp){warningAt("Insecure '{a}'.",line,from+l,c);}}
-q=false;if(c===']'){warningAt("Empty class.",line,from+l-1);q=true;}
-klass:do{c=s.charAt(l);l+=1;switch(c){case'[':case'^':warningAt("Unescaped '{a}'.",line,from+l,c);q=true;break;case'-':if(q){q=false;}else{warningAt("Unescaped '{a}'.",line,from+l,'-');q=true;}
-break;case']':if(!q){warningAt("Unescaped '{a}'.",line,from+l-1,'-');}
-break klass;case'\\':c=s.charAt(l);if(c<' '){warningAt("Unexpected control character in regular expression.",line,from+l);}else if(c==='<'){warningAt("Unexpected escaped character '{a}' in regular expression.",line,from+l,c);}
-l+=1;q=true;break;case'/':warningAt("Unescaped '{a}'.",line,from+l-1,'/');q=true;break;case'<':if(xmode==='script'){c=s.charAt(l);if(c==='!'||c==='/'){warningAt("HTML confusion in regular expression '<{a}'.",line,from+l,c);}}
-q=true;break;default:q=true;}}while(c);break;case'.':if(option.regexp){warningAt("Insecure '{a}'.",line,from+l,c);}
-break;case']':case'?':case'{':case'}':case'+':case'*':warningAt("Unescaped '{a}'.",line,from+l,c);break;case'<':if(xmode==='script'){c=s.charAt(l);if(c==='!'||c==='/'){warningAt("HTML confusion in regular expression '<{a}'.",line,from+l,c);}}}
-if(b){switch(s.charAt(l)){case'?':case'+':case'*':l+=1;if(s.charAt(l)==='?'){l+=1;}
-break;case'{':l+=1;c=s.charAt(l);if(c<'0'||c>'9'){warningAt("Expected a number and instead saw '{a}'.",line,from+l,c);}
-l+=1;low=+c;for(;;){c=s.charAt(l);if(c<'0'||c>'9'){break;}
-l+=1;low=+c+(low*10);}
-high=low;if(c===','){l+=1;high=Infinity;c=s.charAt(l);if(c>='0'&&c<='9'){l+=1;high=+c;for(;;){c=s.charAt(l);if(c<'0'||c>'9'){break;}
-l+=1;high=+c+(high*10);}}}
-if(s.charAt(l)!=='}'){warningAt("Expected '{a}' and instead saw '{b}'.",line,from+l,'}',c);}else{l+=1;}
-if(s.charAt(l)==='?'){l+=1;}
-if(low>high){warningAt("'{a}' should not be greater than '{b}'.",line,from+l,low,high);}}}}
-c=s.substr(0,l-1);character+=l;s=s.substr(l);return it('(regexp)',c);}
-return it('(punctuator)',t);case'<!--':l=line;c=character;for(;;){i=s.indexOf('--');if(i>=0){break;}
-i=s.indexOf('<!');if(i>=0){errorAt("Nested HTML comment.",line,character+i);}
-if(!nextLine()){errorAt("Unclosed HTML comment.",l,c);}}
-l=s.indexOf('<!');if(l>=0&&l<i){errorAt("Nested HTML comment.",line,character+l);}
-character+=i;if(s[i+2]!=='>'){errorAt("Expected -->.",line,character);}
-character+=3;s=s.slice(i+3);break;case'#':if(xmode==='html'||xmode==='styleproperty'){for(;;){c=s.charAt(0);if((c<'0'||c>'9')&&(c<'a'||c>'f')&&(c<'A'||c>'F')){break;}
-character+=1;s=s.substr(1);t+=c;}
-if(t.length!==4&&t.length!==7){warningAt("Bad hex color '{a}'.",line,from+l,t);}
-return it('(color)',t);}
-return it('(punctuator)',t);default:if(xmode==='outer'&&c==='&'){character+=1;s=s.substr(1);for(;;){c=s.charAt(0);character+=1;s=s.substr(1);if(c===';'){break;}
-if(!((c>='0'&&c<='9')||(c>='a'&&c<='z')||c==='#')){errorAt("Bad entity",line,from+l,character);}}
-break;}
-return it('(punctuator)',t);}}}}};}());function addlabel(t,type){if(option.safe&&funct['(global)']&&typeof predefined[t]!=='boolean'){warning('ADsafe global: '+t+'.',token);}else if(t==='hasOwnProperty'){warning("'hasOwnProperty' is a really bad name.");}
-if(is_own(funct,t)&&!funct['(global)']){warning(funct[t]===true?"'{a}' was used before it was defined.":"'{a}' is already defined.",nexttoken,t);}
-funct[t]=type;if(funct['(global)']){global[t]=funct;if(is_own(implied,t)){warning("'{a}' was used before it was defined.",nexttoken,t);delete implied[t];}}else{scope[t]=funct;}}
-function doOption(){var b,obj,filter,o=nexttoken.value,t,v;switch(o){case'*/':error("Unbegun comment.");break;case'/*members':case'/*member':o='/*members';if(!membersOnly){membersOnly={};}
-obj=membersOnly;break;case'/*jslint':if(option.safe){warning("ADsafe restriction.");}
-obj=option;filter=boolOptions;break;case'/*global':if(option.safe){warning("ADsafe restriction.");}
-obj=predefined;break;default:}
-t=lex.token();loop:for(;;){for(;;){if(t.type==='special'&&t.value==='*/'){break loop;}
-if(t.id!=='(endline)'&&t.id!==','){break;}
-t=lex.token();}
-if(t.type!=='(string)'&&t.type!=='(identifier)'&&o!=='/*members'){error("Bad option.",t);}
-v=lex.token();if(v.id===':'){v=lex.token();if(obj===membersOnly){error("Expected '{a}' and instead saw '{b}'.",t,'*/',':');}
-if(t.value==='indent'&&o==='/*jslint'){b=+v.value;if(typeof b!=='number'||!isFinite(b)||b<=0||Math.floor(b)!==b){error("Expected a small integer and instead saw '{a}'.",v,v.value);}
-obj.white=true;obj.indent=b;}else if(t.value==='maxerr'&&o==='/*jslint'){b=+v.value;if(typeof b!=='number'||!isFinite(b)||b<=0||Math.floor(b)!==b){error("Expected a small integer and instead saw '{a}'.",v,v.value);}
-obj.maxerr=b;}else if(v.value==='true'){obj[t.value]=true;}else if(v.value==='false'){obj[t.value]=false;}else{error("Bad option value.",v);}
-t=lex.token();}else{if(o==='/*jslint'){error("Missing option value.",t);}
-obj[t.value]=false;t=v;}}
-if(filter){assume();}}
-function peek(p){var i=p||0,j=0,t;while(j<=i){t=lookahead[j];if(!t){t=lookahead[j]=lex.token();}
-j+=1;}
-return t;}
-function advance(id,t){switch(token.id){case'(number)':if(nexttoken.id==='.'){warning("A dot following a number can be confused with a decimal point.",token);}
-break;case'-':if(nexttoken.id==='-'||nexttoken.id==='--'){warning("Confusing minusses.");}
-break;case'+':if(nexttoken.id==='+'||nexttoken.id==='++'){warning("Confusing plusses.");}
-break;}
-if(token.type==='(string)'||token.identifier){anonname=token.value;}
-if(id&&nexttoken.id!==id){if(t){if(nexttoken.id==='(end)'){warning("Unmatched '{a}'.",t,t.id);}else{warning("Expected '{a}' to match '{b}' from line {c} and instead saw '{d}'.",nexttoken,id,t.id,t.line,nexttoken.value);}}else if(nexttoken.type!=='(identifier)'||nexttoken.value!==id){warning("Expected '{a}' and instead saw '{b}'.",nexttoken,id,nexttoken.value);}}
-prevtoken=token;token=nexttoken;for(;;){nexttoken=lookahead.shift()||lex.token();if(nexttoken.id==='(end)'||nexttoken.id==='(error)'){return;}
-if(nexttoken.type==='special'){doOption();}else{if(nexttoken.id!=='(endline)'){break;}}}}
-function parse(rbp,initial){var left;if(nexttoken.id==='(end)'){error("Unexpected early end of program.",token);}
-advance();if(option.safe&&typeof predefined[token.value]==='boolean'&&(nexttoken.id!=='('&&nexttoken.id!=='.')){warning('ADsafe violation.',token);}
-if(initial){anonname='anonymous';funct['(verb)']=token.value;}
-if(initial===true&&token.fud){left=token.fud();}else{if(token.nud){left=token.nud();}else{if(nexttoken.type==='(number)'&&token.id==='.'){warning("A leading decimal point can be confused with a dot: '.{a}'.",token,nexttoken.value);advance();return token;}else{error("Expected an identifier and instead saw '{a}'.",token,token.id);}}
-while(rbp<nexttoken.lbp){advance();if(token.led){left=token.led(left);}else{error("Expected an operator and instead saw '{a}'.",token,token.id);}}}
-return left;}
-function adjacent(left,right){left=left||token;right=right||nexttoken;if(option.white||xmode==='styleproperty'||xmode==='style'){if(left.character!==right.from&&left.line===right.line){warning("Unexpected space after '{a}'.",right,left.value);}}}
-function nospace(left,right){left=left||token;right=right||nexttoken;if(option.white&&!left.comment){if(left.line===right.line){adjacent(left,right);}}}
-function nonadjacent(left,right){if(option.white){left=left||token;right=right||nexttoken;if(left.line===right.line&&left.character===right.from){warning("Missing space after '{a}'.",nexttoken,left.value);}}}
-function nobreaknonadjacent(left,right){left=left||token;right=right||nexttoken;if(!option.laxbreak&&left.line!==right.line){warning("Bad line breaking before '{a}'.",right,right.id);}else if(option.white){left=left||token;right=right||nexttoken;if(left.character===right.from){warning("Missing space after '{a}'.",nexttoken,left.value);}}}
-function indentation(bias){var i;if(option.white&&nexttoken.id!=='(end)'){i=indent+(bias||0);if(nexttoken.from!==i){warning("Expected '{a}' to have an indentation at {b} instead at {c}.",nexttoken,nexttoken.value,i,nexttoken.from);}}}
-function nolinebreak(t){t=t||token;if(t.line!==nexttoken.line){warning("Line breaking error '{a}'.",t,t.value);}}
-function comma(){if(token.line!==nexttoken.line){if(!option.laxbreak){warning("Bad line breaking before '{a}'.",token,nexttoken.id);}}else if(token.character!==nexttoken.from&&option.white){warning("Unexpected space after '{a}'.",nexttoken,token.value);}
-advance(',');nonadjacent(token,nexttoken);}
-function symbol(s,p){var x=syntax[s];if(!x||typeof x!=='object'){syntax[s]=x={id:s,lbp:p,value:s};}
-return x;}
-function delim(s){return symbol(s,0);}
-function stmt(s,f){var x=delim(s);x.identifier=x.reserved=true;x.fud=f;return x;}
-function blockstmt(s,f){var x=stmt(s,f);x.block=true;return x;}
-function reserveName(x){var c=x.id.charAt(0);if((c>='a'&&c<='z')||(c>='A'&&c<='Z')){x.identifier=x.reserved=true;}
-return x;}
-function prefix(s,f){var x=symbol(s,150);reserveName(x);x.nud=(typeof f==='function')?f:function(){this.right=parse(150);this.arity='unary';if(this.id==='++'||this.id==='--'){if(option.plusplus){warning("Unexpected use of '{a}'.",this,this.id);}else if((!this.right.identifier||this.right.reserved)&&this.right.id!=='.'&&this.right.id!=='['){warning("Bad operand.",this);}}
-return this;};return x;}
-function type(s,f){var x=delim(s);x.type=s;x.nud=f;return x;}
-function reserve(s,f){var x=type(s,f);x.identifier=x.reserved=true;return x;}
-function reservevar(s,v){return reserve(s,function(){if(this.id==='this'||this.id==='arguments'){if(strict_mode&&funct['(global)']){warning("Strict violation.",this);}else if(option.safe){warning("ADsafe violation.",this);}}
-return this;});}
-function infix(s,f,p,w){var x=symbol(s,p);reserveName(x);x.led=function(left){if(!w){nobreaknonadjacent(prevtoken,token);nonadjacent(token,nexttoken);}
-if(typeof f==='function'){return f(left,this);}else{this.left=left;this.right=parse(p);return this;}};return x;}
-function relation(s,f){var x=symbol(s,100);x.led=function(left){nobreaknonadjacent(prevtoken,token);nonadjacent(token,nexttoken);var right=parse(100);if((left&&left.id==='NaN')||(right&&right.id==='NaN')){warning("Use the isNaN function to compare with NaN.",this);}else if(f){f.apply(this,[left,right]);}
-if(left.id==='!'){warning("Confusing use of '{a}'.",left,'!');}
-if(right.id==='!'){warning("Confusing use of '{a}'.",left,'!');}
-this.left=left;this.right=right;return this;};return x;}
-function isPoorRelation(node){return node&&((node.type==='(number)'&&+node.value===0)||(node.type==='(string)'&&node.value===' ')||node.type==='true'||node.type==='false'||node.type==='undefined'||node.type==='null');}
-function assignop(s,f){symbol(s,20).exps=true;return infix(s,function(left,that){var l;that.left=left;if(predefined[left.value]===false&&scope[left.value]['(global)']===true){warning('Read only.',left);}
-if(option.safe){l=left;do{if(typeof predefined[l.value]==='boolean'){warning('ADsafe violation.',l);}
-l=l.left;}while(l);}
-if(left){if(left.id==='.'||left.id==='['){if(!left.left||left.left.value==='arguments'){warning('Bad assignment.',that);}
-that.right=parse(19);return that;}else if(left.identifier&&!left.reserved){if(funct[left.value]==='exception'){warning("Do not assign to the exception parameter.",left);}
-that.right=parse(19);return that;}
-if(left===syntax['function']){warning("Expected an identifier in an assignment and instead saw a function invocation.",token);}}
-error("Bad assignment.",that);},20);}
-function bitwise(s,f,p){var x=symbol(s,p);reserveName(x);x.led=(typeof f==='function')?f:function(left){if(option.bitwise){warning("Unexpected use of '{a}'.",this,this.id);}
-this.left=left;this.right=parse(p);return this;};return x;}
-function bitwiseassignop(s){symbol(s,20).exps=true;return infix(s,function(left,that){if(option.bitwise){warning("Unexpected use of '{a}'.",that,that.id);}
-nonadjacent(prevtoken,token);nonadjacent(token,nexttoken);if(left){if(left.id==='.'||left.id==='['||(left.identifier&&!left.reserved)){parse(19);return that;}
-if(left===syntax['function']){warning("Expected an identifier in an assignment, and instead saw a function invocation.",token);}
-return that;}
-error("Bad assignment.",that);},20);}
-function suffix(s,f){var x=symbol(s,150);x.led=function(left){if(option.plusplus){warning("Unexpected use of '{a}'.",this,this.id);}else if((!left.identifier||left.reserved)&&left.id!=='.'&&left.id!=='['){warning("Bad operand.",this);}
-this.left=left;return this;};return x;}
-function optionalidentifier(){if(nexttoken.reserved){warning("Expected an identifier and instead saw '{a}' (a reserved word).",nexttoken,nexttoken.id);}
-if(nexttoken.identifier){advance();return token.value;}}
-function identifier(){var i=optionalidentifier();if(i){return i;}
-if(token.id==='function'&&nexttoken.id==='('){warning("Missing name in function statement.");}else{error("Expected an identifier and instead saw '{a}'.",nexttoken,nexttoken.value);}}
-function reachable(s){var i=0,t;if(nexttoken.id!==';'||noreach){return;}
-for(;;){t=peek(i);if(t.reach){return;}
-if(t.id!=='(endline)'){if(t.id==='function'){warning("Inner functions should be listed at the top of the outer function.",t);break;}
-warning("Unreachable '{a}' after '{b}'.",t,t.value,s);break;}
-i+=1;}}
-function statement(noindent){var i=indent,r,s=scope,t=nexttoken;if(t.id===';'){warning("Unnecessary semicolon.",t);advance(';');return;}
-if(t.identifier&&!t.reserved&&peek().id===':'){advance();advance(':');scope=Object.create(s);addlabel(t.value,'label');if(!nexttoken.labelled){warning("Label '{a}' on {b} statement.",nexttoken,t.value,nexttoken.value);}
-if(jx.test(t.value+':')){warning("Label '{a}' looks like a javascript url.",t,t.value);}
-nexttoken.label=t.value;t=nexttoken;}
-if(!noindent){indentation();}
-if(nexttoken.id==='new'){warning("'new' should not be used as a statement.");}
-r=parse(0,true);if(!t.block){if(!r||!r.exps){warning("Expected an assignment or function call and instead saw an expression.",token);}
-if(nexttoken.id!==';'){warningAt("Missing semicolon.",token.line,token.from+token.value.length);}else{adjacent(token,nexttoken);advance(';');nonadjacent(token,nexttoken);}}
-indent=i;scope=s;return r;}
-function use_strict(){if(nexttoken.value==='use strict'){advance();advance(';');strict_mode=true;return true;}else{return false;}}
-function statements(begin){var a=[],f,p;if(begin&&!use_strict()&&option.strict){warning('Missing "use strict" statement.',nexttoken);}
-if(option.adsafe){switch(begin){case'script':if(!adsafe_may){if(nexttoken.value!=='ADSAFE'||peek(0).id!=='.'||(peek(1).value!=='id'&&peek(1).value!=='go')){error('ADsafe violation: Missing ADSAFE.id or ADSAFE.go.',nexttoken);}}
-if(nexttoken.value==='ADSAFE'&&peek(0).id==='.'&&peek(1).value==='id'){if(adsafe_may){error('ADsafe violation.',nexttoken);}
-advance('ADSAFE');advance('.');advance('id');advance('(');if(nexttoken.value!==adsafe_id){error('ADsafe violation: id does not match.',nexttoken);}
-advance('(string)');advance(')');advance(';');adsafe_may=true;}
-break;case'lib':if(nexttoken.value==='ADSAFE'){advance('ADSAFE');advance('.');advance('lib');advance('(');advance('(string)');comma();f=parse(0);if(f.id!=='function'){error('The second argument to lib must be a function.',f);}
-p=f.funct['(params)'];p=p&&p.join(', ');if(p&&p!=='lib'){error("Expected '{a}' and instead saw '{b}'.",f,'(lib)','('+p+')');}
-advance(')');advance(';');return a;}else{error("ADsafe lib violation.");}}}
-while(!nexttoken.reach&&nexttoken.id!=='(end)'){if(nexttoken.id===';'){warning("Unnecessary semicolon.");advance(';');}else{a.push(statement());}}
-return a;}
-function block(f){var a,b=inblock,old_indent=indent,s=scope,t;inblock=f;scope=Object.create(scope);nonadjacent(token,nexttoken);t=nexttoken;if(nexttoken.id==='{'){advance('{');if(nexttoken.id!=='}'||token.line!==nexttoken.line){indent+=option.indent;while(!f&&nexttoken.from>indent){indent+=option.indent;}
-if(!f){use_strict();}
-a=statements();indent-=option.indent;indentation();}
-advance('}',t);indent=old_indent;}else{warning("Expected '{a}' and instead saw '{b}'.",nexttoken,'{',nexttoken.value);noreach=true;a=[statement()];noreach=false;}
-funct['(verb)']=null;scope=s;inblock=b;return a;}
-function idValue(){return this;}
-function countMember(m){if(membersOnly&&typeof membersOnly[m]!=='boolean'){warning("Unexpected /*member '{a}'.",token,m);}
-if(typeof member[m]==='number'){member[m]+=1;}else{member[m]=1;}}
-function note_implied(token){var name=token.value,line=token.line,a=implied[name];if(typeof a==='function'){a=false;}
-if(!a){a=[line];implied[name]=a;}else if(a[a.length-1]!==line){a.push(line);}}
-function cssName(){if(nexttoken.identifier){advance();return true;}}
-function cssNumber(){if(nexttoken.id==='-'){advance('-');adjacent();nolinebreak();}
-if(nexttoken.type==='(number)'){advance('(number)');return true;}}
-function cssString(){if(nexttoken.type==='(string)'){advance();return true;}}
-function cssColor(){var i,number;if(nexttoken.identifier){if(nexttoken.value==='rgb'){advance();advance('(');for(i=0;i<3;i+=1){if(i){advance(',');}
-number=nexttoken.value;if(nexttoken.type!=='(number)'||number<0){warning("Expected a positive number and instead saw '{a}'",nexttoken,number);advance();}else{advance();if(nexttoken.id==='%'){advance('%');if(number>100){warning("Expected a percentage and instead saw '{a}'",token,number);}}else{if(number>255){warning("Expected a small number and instead saw '{a}'",token,number);}}}}
-advance(')');return true;}else if(cssColorData[nexttoken.value]===true){advance();return true;}}else if(nexttoken.type==='(color)'){advance();return true;}
-return false;}
-function cssLength(){if(nexttoken.id==='-'){advance('-');adjacent();nolinebreak();}
-if(nexttoken.type==='(number)'){advance();if(nexttoken.type!=='(string)'&&cssLengthData[nexttoken.value]===true){adjacent();advance();}else if(+token.value!==0){warning("Expected a linear unit and instead saw '{a}'.",nexttoken,nexttoken.value);}
-return true;}
-return false;}
-function cssLineHeight(){if(nexttoken.id==='-'){advance('-');adjacent();}
-if(nexttoken.type==='(number)'){advance();if(nexttoken.type!=='(string)'&&cssLengthData[nexttoken.value]===true){adjacent();advance();}
-return true;}
-return false;}
-function cssWidth(){if(nexttoken.identifier){switch(nexttoken.value){case'thin':case'medium':case'thick':advance();return true;}}else{return cssLength();}}
-function cssMargin(){if(nexttoken.identifier){if(nexttoken.value==='auto'){advance();return true;}}else{return cssLength();}}
-function cssAttr(){if(nexttoken.identifier&&nexttoken.value==='attr'){advance();advance('(');if(!nexttoken.identifier){warning("Expected a name and instead saw '{a}'.",nexttoken,nexttoken.value);}
-advance();advance(')');return true;}
-return false;}
-function cssCommaList(){while(nexttoken.id!==';'){if(!cssName()&&!cssString()){warning("Expected a name and instead saw '{a}'.",nexttoken,nexttoken.value);}
-if(nexttoken.id!==','){return true;}
-comma();}}
-function cssCounter(){if(nexttoken.identifier&&nexttoken.value==='counter'){advance();advance('(');if(!nexttoken.identifier){}
-advance();if(nexttoken.id===','){comma();if(nexttoken.type!=='(string)'){warning("Expected a string and instead saw '{a}'.",nexttoken,nexttoken.value);}
-advance();}
-advance(')');return true;}
-if(nexttoken.identifier&&nexttoken.value==='counters'){advance();advance('(');if(!nexttoken.identifier){warning("Expected a name and instead saw '{a}'.",nexttoken,nexttoken.value);}
-advance();if(nexttoken.id===','){comma();if(nexttoken.type!=='(string)'){warning("Expected a string and instead saw '{a}'.",nexttoken,nexttoken.value);}
-advance();}
-if(nexttoken.id===','){comma();if(nexttoken.type!=='(string)'){warning("Expected a string and instead saw '{a}'.",nexttoken,nexttoken.value);}
-advance();}
-advance(')');return true;}
-return false;}
-function cssShape(){var i;if(nexttoken.identifier&&nexttoken.value==='rect'){advance();advance('(');for(i=0;i<4;i+=1){if(!cssLength()){warning("Expected a number and instead saw '{a}'.",nexttoken,nexttoken.value);break;}}
-advance(')');return true;}
-return false;}
-function cssUrl(){var c,url;if(nexttoken.identifier&&nexttoken.value==='url'){nexttoken=lex.range('(',')');url=nexttoken.value;c=url.charAt(0);if(c==='"'||c==='\''){if(url.slice(-1)!==c){warning("Bad url string.");}else{url=url.slice(1,-1);if(url.indexOf(c)>=0){warning("Bad url string.");}}}
-if(!url){warning("Missing url.");}
-advance();if(option.safe&&ux.test(url)){error("ADsafe URL violation.");}
-urls.push(url);return true;}
-return false;}
-cssAny=[cssUrl,function(){for(;;){if(nexttoken.identifier){switch(nexttoken.value.toLowerCase()){case'url':cssUrl();break;case'expression':warning("Unexpected expression '{a}'.",nexttoken,nexttoken.value);advance();break;default:advance();}}else{if(nexttoken.id===';'||nexttoken.id==='!'||nexttoken.id==='(end)'||nexttoken.id==='}'){return true;}
-advance();}}}];cssBorderStyle=['none','hidden','dotted','dashed','solid','double','ridge','inset','outset'];cssBreak=['auto','always','avoid','left','right'];cssOverflow=['auto','hidden','scroll','visible'];cssAttributeData={background:[true,'background-attachment','background-color','background-image','background-position','background-repeat'],'background-attachment':['scroll','fixed'],'background-color':['transparent',cssColor],'background-image':['none',cssUrl],'background-position':[2,[cssLength,'top','bottom','left','right','center']],'background-repeat':['repeat','repeat-x','repeat-y','no-repeat'],'border':[true,'border-color','border-style','border-width'],'border-bottom':[true,'border-bottom-color','border-bottom-style','border-bottom-width'],'border-bottom-color':cssColor,'border-bottom-style':cssBorderStyle,'border-bottom-width':cssWidth,'border-collapse':['collapse','separate'],'border-color':['transparent',4,cssColor],'border-left':[true,'border-left-color','border-left-style','border-left-width'],'border-left-color':cssColor,'border-left-style':cssBorderStyle,'border-left-width':cssWidth,'border-right':[true,'border-right-color','border-right-style','border-right-width'],'border-right-color':cssColor,'border-right-style':cssBorderStyle,'border-right-width':cssWidth,'border-spacing':[2,cssLength],'border-style':[4,cssBorderStyle],'border-top':[true,'border-top-color','border-top-style','border-top-width'],'border-top-color':cssColor,'border-top-style':cssBorderStyle,'border-top-width':cssWidth,'border-width':[4,cssWidth],bottom:[cssLength,'auto'],'caption-side':['bottom','left','right','top'],clear:['both','left','none','right'],clip:[cssShape,'auto'],color:cssColor,content:['open-quote','close-quote','no-open-quote','no-close-quote',cssString,cssUrl,cssCounter,cssAttr],'counter-increment':[cssName,'none'],'counter-reset':[cssName,'none'],cursor:[cssUrl,'auto','crosshair','default','e-resize','help','move','n-resize','ne-resize','nw-resize','pointer','s-resize','se-resize','sw-resize','w-resize','text','wait'],direction:['ltr','rtl'],display:['block','compact','inline','inline-block','inline-table','list-item','marker','none','run-in','table','table-caption','table-cell','table-column','table-column-group','table-footer-group','table-header-group','table-row','table-row-group'],'empty-cells':['show','hide'],'float':['left','none','right'],font:['caption','icon','menu','message-box','small-caption','status-bar',true,'font-size','font-style','font-weight','font-family'],'font-family':cssCommaList,'font-size':['xx-small','x-small','small','medium','large','x-large','xx-large','larger','smaller',cssLength],'font-size-adjust':['none',cssNumber],'font-stretch':['normal','wider','narrower','ultra-condensed','extra-condensed','condensed','semi-condensed','semi-expanded','expanded','extra-expanded'],'font-style':['normal','italic','oblique'],'font-variant':['normal','small-caps'],'font-weight':['normal','bold','bolder','lighter',cssNumber],height:[cssLength,'auto'],left:[cssLength,'auto'],'letter-spacing':['normal',cssLength],'line-height':['normal',cssLineHeight],'list-style':[true,'list-style-image','list-style-position','list-style-type'],'list-style-image':['none',cssUrl],'list-style-position':['inside','outside'],'list-style-type':['circle','disc','square','decimal','decimal-leading-zero','lower-roman','upper-roman','lower-greek','lower-alpha','lower-latin','upper-alpha','upper-latin','hebrew','katakana','hiragana-iroha','katakana-oroha','none'],margin:[4,cssMargin],'margin-bottom':cssMargin,'margin-left':cssMargin,'margin-right':cssMargin,'margin-top':cssMargin,'marker-offset':[cssLength,'auto'],'max-height':[cssLength,'none'],'max-width':[cssLength,'none'],'min-height':cssLength,'min-width':cssLength,opacity:cssNumber,outline:[true,'outline-color','outline-style','outline-width'],'outline-color':['invert',cssColor],'outline-style':['dashed','dotted','double','groove','inset','none','outset','ridge','solid'],'outline-width':cssWidth,overflow:cssOverflow,'overflow-x':cssOverflow,'overflow-y':cssOverflow,padding:[4,cssLength],'padding-bottom':cssLength,'padding-left':cssLength,'padding-right':cssLength,'padding-top':cssLength,'page-break-after':cssBreak,'page-break-before':cssBreak,position:['absolute','fixed','relative','static'],quotes:[8,cssString],right:[cssLength,'auto'],'table-layout':['auto','fixed'],'text-align':['center','justify','left','right'],'text-decoration':['none','underline','overline','line-through','blink'],'text-indent':cssLength,'text-shadow':['none',4,[cssColor,cssLength]],'text-transform':['capitalize','uppercase','lowercase','none'],top:[cssLength,'auto'],'unicode-bidi':['normal','embed','bidi-override'],'vertical-align':['baseline','bottom','sub','super','top','text-top','middle','text-bottom',cssLength],visibility:['visible','hidden','collapse'],'white-space':['normal','nowrap','pre','pre-line','pre-wrap','inherit'],width:[cssLength,'auto'],'word-spacing':['normal',cssLength],'word-wrap':['break-word','normal'],'z-index':['auto',cssNumber]};function styleAttribute(){var v;while(nexttoken.id==='*'||nexttoken.id==='#'||nexttoken.value==='_'){if(!option.css){warning("Unexpected '{a}'.",nexttoken,nexttoken.value);}
-advance();}
-if(nexttoken.id==='-'){if(!option.css){warning("Unexpected '{a}'.",nexttoken,nexttoken.value);}
-advance('-');if(!nexttoken.identifier){warning("Expected a non-standard style attribute and instead saw '{a}'.",nexttoken,nexttoken.value);}
-advance();return cssAny;}else{if(!nexttoken.identifier){warning("Excepted a style attribute, and instead saw '{a}'.",nexttoken,nexttoken.value);}else{if(is_own(cssAttributeData,nexttoken.value)){v=cssAttributeData[nexttoken.value];}else{v=cssAny;if(!option.css){warning("Unrecognized style attribute '{a}'.",nexttoken,nexttoken.value);}}}
-advance();return v;}}
-function styleValue(v){var i=0,n,once,match,round,start=0,vi;switch(typeof v){case'function':return v();case'string':if(nexttoken.identifier&&nexttoken.value===v){advance();return true;}
-return false;}
-for(;;){if(i>=v.length){return false;}
-vi=v[i];i+=1;if(vi===true){break;}else if(typeof vi==='number'){n=vi;vi=v[i];i+=1;}else{n=1;}
-match=false;while(n>0){if(styleValue(vi)){match=true;n-=1;}else{break;}}
-if(match){return true;}}
-start=i;once=[];for(;;){round=false;for(i=start;i<v.length;i+=1){if(!once[i]){if(styleValue(cssAttributeData[v[i]])){match=true;round=true;once[i]=true;break;}}}
-if(!round){return match;}}}
-function styleChild(){if(nexttoken.id==='(number)'){advance();if(nexttoken.value==='n'&&nexttoken.identifier){adjacent();advance();if(nexttoken.id==='+'){adjacent();advance('+');adjacent();advance('(number)');}}
-return;}else{switch(nexttoken.value){case'odd':case'even':if(nexttoken.identifier){advance();return;}}}
-warning("Unexpected token '{a}'.",nexttoken,nexttoken.value);}
-function substyle(){var v;for(;;){if(nexttoken.id==='}'||nexttoken.id==='(end)'||xquote&&nexttoken.id===xquote){return;}
-while(nexttoken.id===';'){warning("Misplaced ';'.");advance(';');}
-v=styleAttribute();advance(':');if(nexttoken.identifier&&nexttoken.value==='inherit'){advance();}else{if(!styleValue(v)){warning("Unexpected token '{a}'.",nexttoken,nexttoken.value);advance();}}
-if(nexttoken.id==='!'){advance('!');adjacent();if(nexttoken.identifier&&nexttoken.value==='important'){advance();}else{warning("Expected '{a}' and instead saw '{b}'.",nexttoken,'important',nexttoken.value);}}
-if(nexttoken.id==='}'||nexttoken.id===xquote){warning("Missing '{a}'.",nexttoken,';');}else{advance(';');}}}
-function styleSelector(){if(nexttoken.identifier){if(!is_own(htmltag,nexttoken.value)){warning("Expected a tagName, and instead saw {a}.",nexttoken,nexttoken.value);}
-advance();}else{switch(nexttoken.id){case'>':case'+':advance();styleSelector();break;case':':advance(':');switch(nexttoken.value){case'active':case'after':case'before':case'checked':case'disabled':case'empty':case'enabled':case'first-child':case'first-letter':case'first-line':case'first-of-type':case'focus':case'hover':case'last-of-type':case'link':case'only-of-type':case'root':case'target':case'visited':advance();break;case'lang':advance();advance('(');if(!nexttoken.identifier){warning("Expected a lang code, and instead saw :{a}.",nexttoken,nexttoken.value);}
-advance(')');break;case'nth-child':case'nth-last-child':case'nth-last-of-type':case'nth-of-type':advance();advance('(');styleChild();advance(')');break;case'not':advance();advance('(');if(nexttoken.id===':'&&peek(0).value==='not'){warning("Nested not.");}
-styleSelector();advance(')');break;default:warning("Expected a pseudo, and instead saw :{a}.",nexttoken,nexttoken.value);}
-break;case'#':advance('#');if(!nexttoken.identifier){warning("Expected an id, and instead saw #{a}.",nexttoken,nexttoken.value);}
-advance();break;case'*':advance('*');break;case'.':advance('.');if(!nexttoken.identifier){warning("Expected a class, and instead saw #.{a}.",nexttoken,nexttoken.value);}
-advance();break;case'[':advance('[');if(!nexttoken.identifier){warning("Expected an attribute, and instead saw [{a}].",nexttoken,nexttoken.value);}
-advance();if(nexttoken.id==='='||nexttoken.value==='~='||nexttoken.value==='$='||nexttoken.value==='|='||nexttoken.id==='*='||nexttoken.id==='^='){advance();if(nexttoken.type!=='(string)'){warning("Expected a string, and instead saw {a}.",nexttoken,nexttoken.value);}
-advance();}
-advance(']');break;default:error("Expected a CSS selector, and instead saw {a}.",nexttoken,nexttoken.value);}}}
-function stylePattern(){var name;if(nexttoken.id==='{'){warning("Expected a style pattern, and instead saw '{a}'.",nexttoken,nexttoken.id);}else if(nexttoken.id==='@'){advance('@');name=nexttoken.value;if(nexttoken.identifier&&atrule[name]===true){advance();return name;}
-warning("Expected an at-rule, and instead saw @{a}.",nexttoken,name);}
-for(;;){styleSelector();if(nexttoken.id==='</'||nexttoken.id==='{'||nexttoken.id==='(end)'){return'';}
-if(nexttoken.id===','){comma();}}}
-function styles(){var i;while(nexttoken.id==='@'){i=peek();if(i.identifier&&i.value==='import'){advance('@');advance();if(!cssUrl()){warning("Expected '{a}' and instead saw '{b}'.",nexttoken,'url',nexttoken.value);advance();}
-advance(';');}else{break;}}
-while(nexttoken.id!=='</'&&nexttoken.id!=='(end)'){stylePattern();xmode='styleproperty';if(nexttoken.id===';'){advance(';');}else{advance('{');substyle();xmode='style';advance('}');}}}
-function doBegin(n){if(n!=='html'&&!option.fragment){if(n==='div'&&option.adsafe){error("ADSAFE: Use the fragment option.");}else{error("Expected '{a}' and instead saw '{b}'.",token,'html',n);}}
-if(option.adsafe){if(n==='html'){error("Currently, ADsafe does not operate on whole HTML documents. It operates on <div> fragments and .js files.",token);}
-if(option.fragment){if(n!=='div'){error("ADsafe violation: Wrap the widget in a div.",token);}}else{error("Use the fragment option.",token);}}
-option.browser=true;assume();}
-function doAttribute(n,a,v){var u,x;if(a==='id'){u=typeof v==='string'?v.toUpperCase():'';if(ids[u]===true){warning("Duplicate id='{a}'.",nexttoken,v);}
-if(option.adsafe){if(adsafe_id){if(v.slice(0,adsafe_id.length)!==adsafe_id){warning("ADsafe violation: An id must have a '{a}' prefix",nexttoken,adsafe_id);}else if(!/^[A-Z]+_[A-Z]+$/.test(v)){warning("ADSAFE violation: bad id.");}}else{adsafe_id=v;if(!/^[A-Z]+_$/.test(v)){warning("ADSAFE violation: bad id.");}}}
-x=v.search(dx);if(x>=0){warning("Unexpected character '{a}' in {b}.",token,v.charAt(x),a);}
-ids[u]=true;}else if(a==='class'||a==='type'||a==='name'){x=v.search(qx);if(x>=0){warning("Unexpected character '{a}' in {b}.",token,v.charAt(x),a);}
-ids[u]=true;}else if(a==='href'||a==='background'||a==='content'||a==='data'||a.indexOf('src')>=0||a.indexOf('url')>=0){if(option.safe&&ux.test(v)){error("ADsafe URL violation.");}
-urls.push(v);}else if(a==='for'){if(option.adsafe){if(adsafe_id){if(v.slice(0,adsafe_id.length)!==adsafe_id){warning("ADsafe violation: An id must have a '{a}' prefix",nexttoken,adsafe_id);}else if(!/^[A-Z]+_[A-Z]+$/.test(v)){warning("ADSAFE violation: bad id.");}}else{warning("ADSAFE violation: bad id.");}}}else if(a==='name'){if(option.adsafe&&v.indexOf('_')>=0){warning("ADsafe name violation.");}}}
-function doTag(n,a){var i,t=htmltag[n],x;src=false;if(!t){error("Unrecognized tag '<{a}>'.",nexttoken,n===n.toLowerCase()?n:n+' (capitalization error)');}
-if(stack.length>0){if(n==='html'){error("Too many <html> tags.",token);}
-x=t.parent;if(x){if(x.indexOf(' '+stack[stack.length-1].name+' ')<0){error("A '<{a}>' must be within '<{b}>'.",token,n,x);}}else if(!option.adsafe&&!option.fragment){i=stack.length;do{if(i<=0){error("A '<{a}>' must be within '<{b}>'.",token,n,'body');}
-i-=1;}while(stack[i].name!=='body');}}
-switch(n){case'div':if(option.adsafe&&stack.length===1&&!adsafe_id){warning("ADSAFE violation: missing ID_.");}
-break;case'script':xmode='script';advance('>');indent=nexttoken.from;if(a.lang){warning("lang is deprecated.",token);}
-if(option.adsafe&&stack.length!==1){warning("ADsafe script placement violation.",token);}
-if(a.src){if(option.adsafe&&(!adsafe_may||!approved[a.src])){warning("ADsafe unapproved script source.",token);}
-if(a.type){warning("type is unnecessary.",token);}}else{if(adsafe_went){error("ADsafe script violation.",token);}
-statements('script');}
-xmode='html';advance('</');if(!nexttoken.identifier&&nexttoken.value!=='script'){warning("Expected '{a}' and instead saw '{b}'.",nexttoken,'script',nexttoken.value);}
-advance();xmode='outer';break;case'style':xmode='style';advance('>');styles();xmode='html';advance('</');if(!nexttoken.identifier&&nexttoken.value!=='style'){warning("Expected '{a}' and instead saw '{b}'.",nexttoken,'style',nexttoken.value);}
-advance();xmode='outer';break;case'input':switch(a.type){case'radio':case'checkbox':case'button':case'reset':case'submit':break;case'text':case'file':case'password':case'file':case'hidden':case'image':if(option.adsafe&&a.autocomplete!=='off'){warning("ADsafe autocomplete violation.");}
-break;default:warning("Bad input type.");}
-break;case'applet':case'body':case'embed':case'frame':case'frameset':case'head':case'iframe':case'noembed':case'noframes':case'object':case'param':if(option.adsafe){warning("ADsafe violation: Disallowed tag: "+n);}
-break;}}
-function closetag(n){return'</'+n+'>';}
-function html(){var a,attributes,e,n,q,t,v,w=option.white,wmode;xmode='html';xquote='';stack=null;for(;;){switch(nexttoken.value){case'<':xmode='html';advance('<');attributes={};t=nexttoken;if(!t.identifier){warning("Bad identifier {a}.",t,t.value);}
-n=t.value;if(option.cap){n=n.toLowerCase();}
-t.name=n;advance();if(!stack){stack=[];doBegin(n);}
-v=htmltag[n];if(typeof v!=='object'){error("Unrecognized tag '<{a}>'.",t,n);}
-e=v.empty;t.type=n;for(;;){if(nexttoken.id==='/'){advance('/');if(nexttoken.id!=='>'){warning("Expected '{a}' and instead saw '{b}'.",nexttoken,'>',nexttoken.value);}
-break;}
-if(nexttoken.id&&nexttoken.id.substr(0,1)==='>'){break;}
-if(!nexttoken.identifier){if(nexttoken.id==='(end)'||nexttoken.id==='(error)'){error("Missing '>'.",nexttoken);}
-warning("Bad identifier.");}
-option.white=true;nonadjacent(token,nexttoken);a=nexttoken.value;option.white=w;advance();if(!option.cap&&a!==a.toLowerCase()){warning("Attribute '{a}' not all lower case.",nexttoken,a);}
-a=a.toLowerCase();xquote='';if(is_own(attributes,a)){warning("Attribute '{a}' repeated.",nexttoken,a);}
-if(a.slice(0,2)==='on'){if(!option.on){warning("Avoid HTML event handlers.");}
-xmode='scriptstring';advance('=');q=nexttoken.id;if(q!=='"'&&q!=="'"){error("Missing quote.");}
-xquote=q;wmode=option.white;option.white=false;advance(q);statements('on');option.white=wmode;if(nexttoken.id!==q){error("Missing close quote on script attribute.");}
-xmode='html';xquote='';advance(q);v=false;}else if(a==='style'){xmode='scriptstring';advance('=');q=nexttoken.id;if(q!=='"'&&q!=="'"){error("Missing quote.");}
-xmode='styleproperty';xquote=q;advance(q);substyle();xmode='html';xquote='';advance(q);v=false;}else{if(nexttoken.id==='='){advance('=');v=nexttoken.value;if(!nexttoken.identifier&&nexttoken.id!=='"'&&nexttoken.id!=='\''&&nexttoken.type!=='(string)'&&nexttoken.type!=='(number)'&&nexttoken.type!=='(color)'){warning("Expected an attribute value and instead saw '{a}'.",token,a);}
-advance();}else{v=true;}}
-attributes[a]=v;doAttribute(n,a,v);}
-doTag(n,attributes);if(!e){stack.push(t);}
-xmode='outer';advance('>');break;case'</':xmode='html';advance('</');if(!nexttoken.identifier){warning("Bad identifier.");}
-n=nexttoken.value;if(option.cap){n=n.toLowerCase();}
-advance();if(!stack){error("Unexpected '{a}'.",nexttoken,closetag(n));}
-t=stack.pop();if(!t){error("Unexpected '{a}'.",nexttoken,closetag(n));}
-if(t.name!==n){error("Expected '{a}' and instead saw '{b}'.",nexttoken,closetag(t.name),closetag(n));}
-if(nexttoken.id!=='>'){error("Missing '{a}'.",nexttoken,'>');}
-xmode='outer';advance('>');break;case'<!':if(option.safe){warning("ADsafe HTML violation.");}
-xmode='html';for(;;){advance();if(nexttoken.id==='>'||nexttoken.id==='(end)'){break;}
-if(nexttoken.value.indexOf('--')>=0){warning("Unexpected --.");}
-if(nexttoken.value.indexOf('<')>=0){warning("Unexpected <.");}
-if(nexttoken.value.indexOf('>')>=0){warning("Unexpected >.");}}
-xmode='outer';advance('>');break;case'(end)':return;default:if(nexttoken.id==='(end)'){error("Missing '{a}'.",nexttoken,'</'+stack[stack.length-1].value+'>');}else{advance();}}
-if(stack&&stack.length===0&&(option.adsafe||!option.fragment||nexttoken.id==='(end)')){break;}}
-if(nexttoken.id!=='(end)'){error("Unexpected material after the end.");}}
-type('(number)',idValue);type('(string)',idValue);syntax['(identifier)']={type:'(identifier)',lbp:0,identifier:true,nud:function(){var v=this.value,s=scope[v],f;if(typeof s==='function'){s=undefined;}else if(typeof s==='boolean'){f=funct;funct=functions[0];addlabel(v,'var');s=funct;funct=f;}
-if(funct===s){switch(funct[v]){case'unused':funct[v]='var';break;case'label':warning("'{a}' is a statement label.",token,v);break;}}else if(funct['(global)']){if(option.undef&&predefined[v]!=='boolean'){warning("'{a}' is not defined.",token,v);}
-note_implied(token);}else{switch(funct[v]){case'closure':case'function':case'var':case'unused':warning("'{a}' used out of scope.",token,v);break;case'label':warning("'{a}' is a statement label.",token,v);break;case'outer':case'global':break;default:if(s===true){funct[v]=true;}else if(s===null){warning("'{a}' is not allowed.",token,v);note_implied(token);}else if(typeof s!=='object'){if(option.undef){warning("'{a}' is not defined.",token,v);}else{funct[v]=true;}
-note_implied(token);}else{switch(s[v]){case'function':case'var':case'unused':s[v]='closure';funct[v]=s['(global)']?'global':'outer';break;case'closure':case'parameter':funct[v]=s['(global)']?'global':'outer';break;case'label':warning("'{a}' is a statement label.",token,v);}}}}
-return this;},led:function(){error("Expected an operator and instead saw '{a}'.",nexttoken,nexttoken.value);}};type('(regexp)',function(){return this;});delim('(endline)');delim('(begin)');delim('(end)').reach=true;delim('</').reach=true;delim('<!');delim('<!--');delim('-->');delim('(error)').reach=true;delim('}').reach=true;delim(')');delim(']');delim('"').reach=true;delim("'").reach=true;delim(';');delim(':').reach=true;delim(',');delim('#');delim('@');reserve('else');reserve('case').reach=true;reserve('catch');reserve('default').reach=true;reserve('finally');reservevar('arguments');reservevar('eval');reservevar('false');reservevar('Infinity');reservevar('NaN');reservevar('null');reservevar('this');reservevar('true');reservevar('undefined');assignop('=','assign',20);assignop('+=','assignadd',20);assignop('-=','assignsub',20);assignop('*=','assignmult',20);assignop('/=','assigndiv',20).nud=function(){error("A regular expression literal can be confused with '/='.");};assignop('%=','assignmod',20);bitwiseassignop('&=','assignbitand',20);bitwiseassignop('|=','assignbitor',20);bitwiseassignop('^=','assignbitxor',20);bitwiseassignop('<<=','assignshiftleft',20);bitwiseassignop('>>=','assignshiftright',20);bitwiseassignop('>>>=','assignshiftrightunsigned',20);infix('?',function(left,that){that.left=left;that.right=parse(10);advance(':');that['else']=parse(10);return that;},30);infix('||','or',40);infix('&&','and',50);bitwise('|','bitor',70);bitwise('^','bitxor',80);bitwise('&','bitand',90);relation('==',function(left,right){if(option.eqeqeq){warning("Expected '{a}' and instead saw '{b}'.",this,'===','==');}else if(isPoorRelation(left)){warning("Use '{a}' to compare with '{b}'.",this,'===',left.value);}else if(isPoorRelation(right)){warning("Use '{a}' to compare with '{b}'.",this,'===',right.value);}
-return this;});relation('===');relation('!=',function(left,right){if(option.eqeqeq){warning("Expected '{a}' and instead saw '{b}'.",this,'!==','!=');}else if(isPoorRelation(left)){warning("Use '{a}' to compare with '{b}'.",this,'!==',left.value);}else if(isPoorRelation(right)){warning("Use '{a}' to compare with '{b}'.",this,'!==',right.value);}
-return this;});relation('!==');relation('<');relation('>');relation('<=');relation('>=');bitwise('<<','shiftleft',120);bitwise('>>','shiftright',120);bitwise('>>>','shiftrightunsigned',120);infix('in','in',120);infix('instanceof','instanceof',120);infix('+',function(left,that){var right=parse(130);if(left&&right&&left.id==='(string)'&&right.id==='(string)'){left.value+=right.value;left.character=right.character;if(jx.test(left.value)){warning("JavaScript URL.",left);}
-return left;}
-that.left=left;that.right=right;return that;},130);prefix('+','num');infix('-','sub',130);prefix('-','neg');infix('*','mult',140);infix('/','div',140);infix('%','mod',140);suffix('++','postinc');prefix('++','preinc');syntax['++'].exps=true;suffix('--','postdec');prefix('--','predec');syntax['--'].exps=true;prefix('delete',function(){var p=parse(0);if(!p||(p.id!=='.'&&p.id!=='[')){warning("Expected '{a}' and instead saw '{b}'.",nexttoken,'.',nexttoken.value);}
-this.first=p;return this;}).exps=true;prefix('~',function(){if(option.bitwise){warning("Unexpected '{a}'.",this,'~');}
-parse(150);return this;});prefix('!',function(){this.right=parse(150);this.arity='unary';if(bang[this.right.id]===true){warning("Confusing use of '{a}'.",this,'!');}
-return this;});prefix('typeof','typeof');prefix('new',function(){var c=parse(155),i;if(c&&c.id!=='function'){if(c.identifier){c['new']=true;switch(c.value){case'Object':warning("Use the object literal notation {}.",token);break;case'Array':if(nexttoken.id!=='('){warning("Use the array literal notation [].",token);}else{advance('(');if(nexttoken.id===')'){warning("Use the array literal notation [].",token);}else{i=parse(0);c.dimension=i;if((i.id==='(number)'&&/[.+\-Ee]/.test(i.value))||(i.id==='-'&&!i.right)||i.id==='(string)'||i.id==='['||i.id==='{'||i.id==='true'||i.id==='false'||i.id==='null'||i.id==='undefined'||i.id==='Infinity'){warning("Use the array literal notation [].",token);}
-if(nexttoken.id!==')'){error("Use the array literal notation [].",token);}}
-advance(')');}
-this.first=c;return this;case'Number':case'String':case'Boolean':case'Math':case'JSON':warning("Do not use {a} as a constructor.",token,c.value);break;case'Function':if(!option.evil){warning("The Function constructor is eval.");}
-break;case'Date':case'RegExp':break;default:if(c.id!=='function'){i=c.value.substr(0,1);if(option.newcap&&(i<'A'||i>'Z')){warning("A constructor name should start with an uppercase letter.",token);}}}}else{if(c.id!=='.'&&c.id!=='['&&c.id!=='('){warning("Bad constructor.",token);}}}else{warning("Weird construction. Delete 'new'.",this);}
-adjacent(token,nexttoken);if(nexttoken.id!=='('){warning("Missing '()' invoking a constructor.");}
-this.first=c;return this;});syntax['new'].exps=true;infix('.',function(left,that){adjacent(prevtoken,token);var m=identifier();if(typeof m==='string'){countMember(m);}
-that.left=left;that.right=m;if(!option.evil&&left&&left.value==='document'&&(m==='write'||m==='writeln')){warning("document.write can be a form of eval.",left);}else if(option.adsafe){if(left&&left.value==='ADSAFE'){if(m==='id'||m==='lib'){warning("ADsafe violation.",that);}else if(m==='go'){if(xmode!=='script'){warning("ADsafe violation.",that);}else if(adsafe_went||nexttoken.id!=='('||peek(0).id!=='(string)'||peek(0).value!==adsafe_id||peek(1).id!==','){error("ADsafe violation: go.",that);}
-adsafe_went=true;adsafe_may=false;}}}
-if(!option.evil&&(m==='eval'||m==='execScript')){warning('eval is evil.');}else if(option.safe){for(;;){if(banned[m]===true){warning("ADsafe restricted word '{a}'.",token,m);}
-if(typeof predefined[left.value]!=='boolean'||nexttoken.id==='('){break;}
-if(standard_member[m]===true){if(nexttoken.id==='.'){warning("ADsafe violation.",that);}
-break;}
-if(nexttoken.id!=='.'){warning("ADsafe violation.",that);break;}
-advance('.');token.left=that;token.right=m;that=token;m=identifier();if(typeof m==='string'){countMember(m);}}}
-return that;},160,true);infix('(',function(left,that){adjacent(prevtoken,token);nospace();var n=0,p=[];if(left){if(left.type==='(identifier)'){if(left.value.match(/^[A-Z]([A-Z0-9_$]*[a-z][A-Za-z0-9_$]*)?$/)){if(left.value!=='Number'&&left.value!=='String'&&left.value!=='Boolean'&&left.value!=='Date'){if(left.value==='Math'){warning("Math is not a function.",left);}else if(option.newcap){warning("Missing 'new' prefix when invoking a constructor.",left);}}}}else if(left.id==='.'){if(option.safe&&left.left.value==='Math'&&left.right==='random'){warning("ADsafe violation.",left);}}}
-if(nexttoken.id!==')'){for(;;){p[p.length]=parse(10);n+=1;if(nexttoken.id!==','){break;}
-comma();}}
-advance(')');if(option.immed&&left.id==='function'&&nexttoken.id!==')'){warning("Wrap the entire immediate function invocation in parens.",that);}
-nospace(prevtoken,token);if(typeof left==='object'){if(left.value==='parseInt'&&n===1){warning("Missing radix parameter.",left);}
-if(!option.evil){if(left.value==='eval'||left.value==='Function'||left.value==='execScript'){warning("eval is evil.",left);}else if(p[0]&&p[0].id==='(string)'&&(left.value==='setTimeout'||left.value==='setInterval')){warning("Implied eval is evil. Pass a function instead of a string.",left);}}
-if(!left.identifier&&left.id!=='.'&&left.id!=='['&&left.id!=='('&&left.id!=='&&'&&left.id!=='||'&&left.id!=='?'){warning("Bad invocation.",left);}}
-that.left=left;return that;},155,true).exps=true;prefix('(',function(){nospace();var v=parse(0);advance(')',this);nospace(prevtoken,token);if(option.immed&&v.id==='function'){if(nexttoken.id==='('){warning("Move the invocation into the parens that contain the function.",nexttoken);}else{warning("Do not wrap function literals in parens unless they are to be immediately invoked.",this);}}
-return v;});infix('[',function(left,that){nospace();var e=parse(0),s;if(e&&e.type==='(string)'){if(option.safe&&banned[e.value]===true){warning("ADsafe restricted word '{a}'.",that,e.value);}else if(!option.evil&&(e.value==='eval'||e.value==='execScript')){warning("eval is evil.",that);}else if(option.safe&&(e.value.charAt(0)==='_'||e.value.charAt(0)==='-')){warning("ADsafe restricted subscript '{a}'.",that,e.value);}
-countMember(e.value);if(!option.sub&&ix.test(e.value)){s=syntax[e.value];if(!s||!s.reserved){warning("['{a}'] is better written in dot notation.",e,e.value);}}}else if(!e||e.type!=='(number)'||e.value<0){if(option.safe){warning('ADsafe subscripting.');}}
-advance(']',that);nospace(prevtoken,token);that.left=left;that.right=e;return that;},160,true);prefix('[',function(){var b=token.line!==nexttoken.line;this.first=[];if(b){indent+=option.indent;if(nexttoken.from===indent+option.indent){indent+=option.indent;}}
-while(nexttoken.id!=='(end)'){while(nexttoken.id===','){warning("Extra comma.");advance(',');}
-if(nexttoken.id===']'){break;}
-if(b&&token.line!==nexttoken.line){indentation();}
-this.first.push(parse(10));if(nexttoken.id===','){comma();if(nexttoken.id===']'){warning("Extra comma.",token);break;}}else{break;}}
-if(b){indent-=option.indent;indentation();}
-advance(']',this);return this;},160);(function(x){x.nud=function(){var b,i,s,seen={};b=token.line!==nexttoken.line;if(b){indent+=option.indent;if(nexttoken.from===indent+option.indent){indent+=option.indent;}}
-for(;;){if(nexttoken.id==='}'){break;}
-if(b){indentation();}
-i=optionalidentifier(true);if(!i){if(nexttoken.id==='(string)'){i=nexttoken.value;if(ix.test(i)){s=syntax[i];}
-advance();}else if(nexttoken.id==='(number)'){i=nexttoken.value.toString();advance();}else{error("Expected '{a}' and instead saw '{b}'.",nexttoken,'}',nexttoken.value);}}
-if(seen[i]===true){warning("Duplicate member '{a}'.",nexttoken,i);}
-seen[i]=true;countMember(i);advance(':');nonadjacent(token,nexttoken);parse(10);if(nexttoken.id===','){comma();if(nexttoken.id===','||nexttoken.id==='}'){warning("Extra comma.",token);}}else{break;}}
-if(b){indent-=option.indent;indentation();}
-advance('}',this);return this;};x.fud=function(){error("Expected to see a statement and instead saw a block.",token);};}(delim('{')));function varstatement(prefix){var id,name,value;if(funct['(onevar)']&&option.onevar){warning("Too many var statements.");}else if(!funct['(global)']){funct['(onevar)']=true;}
-this.first=[];for(;;){nonadjacent(token,nexttoken);id=identifier();if(funct['(global)']&&predefined[id]===false){warning("Redefinition of '{a}'.",token,id);}
-addlabel(id,'unused');if(prefix){break;}
-name=token;this.first.push(token);if(nexttoken.id==='='){nonadjacent(token,nexttoken);advance('=');nonadjacent(token,nexttoken);if(peek(0).id==='='&&nexttoken.identifier){error("Variable {a} was not declared correctly.",nexttoken,nexttoken.value);}
-value=parse(0);name.first=value;}
-if(nexttoken.id!==','){break;}
-comma();}
-return this;}
-stmt('var',varstatement).exps=true;function functionparams(){var i,t=nexttoken,p=[];advance('(');nospace();if(nexttoken.id===')'){advance(')');nospace(prevtoken,token);return;}
-for(;;){i=identifier();p.push(i);addlabel(i,'parameter');if(nexttoken.id===','){comma();}else{advance(')',t);nospace(prevtoken,token);return p;}}}
-function doFunction(i){var s=scope;scope=Object.create(s);funct={'(name)':i||'"'+anonname+'"','(line)':nexttoken.line,'(context)':funct,'(breakage)':0,'(loopage)':0,'(scope)':scope};token.funct=funct;functions.push(funct);if(i){addlabel(i,'function');}
-funct['(params)']=functionparams();block(false);scope=s;funct['(last)']=token.line;funct=funct['(context)'];}
-blockstmt('function',function(){if(inblock){warning("Function statements cannot be placed in blocks. Use a function expression or move the statement to the top of the outer function.",token);}
-var i=identifier();adjacent(token,nexttoken);addlabel(i,'unused');doFunction(i);if(nexttoken.id==='('&&nexttoken.line===token.line){error("Function statements are not invocable. Wrap the whole function invocation in parens.");}
-return this;});prefix('function',function(){var i=optionalidentifier();if(i){adjacent(token,nexttoken);}else{nonadjacent(token,nexttoken);}
-doFunction(i);if(funct['(loopage)']&&nexttoken.id!=='('){warning("Be careful when making functions within a loop. Consider putting the function in a closure.");}
-return this;});blockstmt('if',function(){var t=nexttoken;advance('(');nonadjacent(this,t);nospace();parse(20);if(nexttoken.id==='='){warning("Expected a conditional expression and instead saw an assignment.");advance('=');parse(20);}
-advance(')',t);nospace(prevtoken,token);block(true);if(nexttoken.id==='else'){nonadjacent(token,nexttoken);advance('else');if(nexttoken.id==='if'||nexttoken.id==='switch'){statement(true);}else{block(true);}}
-return this;});blockstmt('try',function(){var b,e,s;if(option.adsafe){warning("ADsafe try violation.",this);}
-block(false);if(nexttoken.id==='catch'){advance('catch');nonadjacent(token,nexttoken);advance('(');s=scope;scope=Object.create(s);e=nexttoken.value;if(nexttoken.type!=='(identifier)'){warning("Expected an identifier and instead saw '{a}'.",nexttoken,e);}else{addlabel(e,'exception');}
-advance();advance(')');block(false);b=true;scope=s;}
-if(nexttoken.id==='finally'){advance('finally');block(false);return;}else if(!b){error("Expected '{a}' and instead saw '{b}'.",nexttoken,'catch',nexttoken.value);}
-return this;});blockstmt('while',function(){var t=nexttoken;funct['(breakage)']+=1;funct['(loopage)']+=1;advance('(');nonadjacent(this,t);nospace();parse(20);if(nexttoken.id==='='){warning("Expected a conditional expression and instead saw an assignment.");advance('=');parse(20);}
-advance(')',t);nospace(prevtoken,token);block(true);funct['(breakage)']-=1;funct['(loopage)']-=1;return this;}).labelled=true;reserve('with');blockstmt('switch',function(){var t=nexttoken,g=false;funct['(breakage)']+=1;advance('(');nonadjacent(this,t);nospace();this.condition=parse(20);advance(')',t);nospace(prevtoken,token);nonadjacent(token,nexttoken);t=nexttoken;advance('{');nonadjacent(token,nexttoken);indent+=option.indent;this.cases=[];for(;;){switch(nexttoken.id){case'case':switch(funct['(verb)']){case'break':case'case':case'continue':case'return':case'switch':case'throw':break;default:warning("Expected a 'break' statement before 'case'.",token);}
-indentation(-option.indent);advance('case');this.cases.push(parse(20));g=true;advance(':');funct['(verb)']='case';break;case'default':switch(funct['(verb)']){case'break':case'continue':case'return':case'throw':break;default:warning("Expected a 'break' statement before 'default'.",token);}
-indentation(-option.indent);advance('default');g=true;advance(':');break;case'}':indent-=option.indent;indentation();advance('}',t);if(this.cases.length===1||this.condition.id==='true'||this.condition.id==='false'){warning("This 'switch' should be an 'if'.",this);}
-funct['(breakage)']-=1;funct['(verb)']=undefined;return;case'(end)':error("Missing '{a}'.",nexttoken,'}');return;default:if(g){switch(token.id){case',':error("Each value should have its own case label.");return;case':':statements();break;default:error("Missing ':' on a case clause.",token);}}else{error("Expected '{a}' and instead saw '{b}'.",nexttoken,'case',nexttoken.value);}}}}).labelled=true;stmt('debugger',function(){if(!option.debug){warning("All 'debugger' statements should be removed.");}
-return this;}).exps=true;(function(){var x=stmt('do',function(){funct['(breakage)']+=1;funct['(loopage)']+=1;this.first=block(true);advance('while');var t=nexttoken;nonadjacent(token,t);advance('(');nospace();parse(20);if(nexttoken.id==='='){warning("Expected a conditional expression and instead saw an assignment.");advance('=');parse(20);}
-advance(')',t);nospace(prevtoken,token);funct['(breakage)']-=1;funct['(loopage)']-=1;return this;});x.labelled=true;x.exps=true;}());blockstmt('for',function(){var f=option.forin,s,t=nexttoken;funct['(breakage)']+=1;funct['(loopage)']+=1;advance('(');nonadjacent(this,t);nospace();if(peek(nexttoken.id==='var'?1:0).id==='in'){if(nexttoken.id==='var'){advance('var');varstatement(true);}else{switch(funct[nexttoken.value]){case'unused':funct[nexttoken.value]='var';break;case'var':break;default:warning("Bad for in variable '{a}'.",nexttoken,nexttoken.value);}
-advance();}
-advance('in');parse(20);advance(')',t);s=block(true);if(!f&&(s.length>1||typeof s[0]!=='object'||s[0].value!=='if')){warning("The body of a for in should be wrapped in an if statement to filter unwanted properties from the prototype.",this);}
-funct['(breakage)']-=1;funct['(loopage)']-=1;return this;}else{if(nexttoken.id!==';'){if(nexttoken.id==='var'){advance('var');varstatement();}else{for(;;){parse(0,'for');if(nexttoken.id!==','){break;}
-comma();}}}
-nolinebreak(token);advance(';');if(nexttoken.id!==';'){parse(20);if(nexttoken.id==='='){warning("Expected a conditional expression and instead saw an assignment.");advance('=');parse(20);}}
-nolinebreak(token);advance(';');if(nexttoken.id===';'){error("Expected '{a}' and instead saw '{b}'.",nexttoken,')',';');}
-if(nexttoken.id!==')'){for(;;){parse(0,'for');if(nexttoken.id!==','){break;}
-comma();}}
-advance(')',t);nospace(prevtoken,token);block(true);funct['(breakage)']-=1;funct['(loopage)']-=1;return this;}}).labelled=true;stmt('break',function(){var v=nexttoken.value;if(funct['(breakage)']===0){warning("Unexpected '{a}'.",nexttoken,this.value);}
-nolinebreak(this);if(nexttoken.id!==';'){if(token.line===nexttoken.line){if(funct[v]!=='label'){warning("'{a}' is not a statement label.",nexttoken,v);}else if(scope[v]!==funct){warning("'{a}' is out of scope.",nexttoken,v);}
-this.first=nexttoken;advance();}}
-reachable('break');return this;}).exps=true;stmt('continue',function(){var v=nexttoken.value;if(funct['(breakage)']===0){warning("Unexpected '{a}'.",nexttoken,this.value);}
-nolinebreak(this);if(nexttoken.id!==';'){if(token.line===nexttoken.line){if(funct[v]!=='label'){warning("'{a}' is not a statement label.",nexttoken,v);}else if(scope[v]!==funct){warning("'{a}' is out of scope.",nexttoken,v);}
-this.first=nexttoken;advance();}}
-reachable('continue');return this;}).exps=true;stmt('return',function(){nolinebreak(this);if(nexttoken.id==='(regexp)'){warning("Wrap the /regexp/ literal in parens to disambiguate the slash operator.");}
-if(nexttoken.id!==';'&&!nexttoken.reach){nonadjacent(token,nexttoken);this.first=parse(20);}
-reachable('return');return this;}).exps=true;stmt('throw',function(){nolinebreak(this);nonadjacent(token,nexttoken);this.first=parse(20);reachable('throw');return this;}).exps=true;reserve('void');reserve('class');reserve('const');reserve('enum');reserve('export');reserve('extends');reserve('import');reserve('super');reserve('let');reserve('yield');reserve('implements');reserve('interface');reserve('package');reserve('private');reserve('protected');reserve('public');reserve('static');function jsonValue(){function jsonObject(){var o={},t=nexttoken;advance('{');if(nexttoken.id!=='}'){for(;;){if(nexttoken.id==='(end)'){error("Missing '}' to match '{' from line {a}.",nexttoken,t.line);}else if(nexttoken.id==='}'){warning("Unexpected comma.",token);break;}else if(nexttoken.id===','){error("Unexpected comma.",nexttoken);}else if(nexttoken.id!=='(string)'){warning("Expected a string and instead saw {a}.",nexttoken,nexttoken.value);}
-if(o[nexttoken.value]===true){warning("Duplicate key '{a}'.",nexttoken,nexttoken.value);}else if(nexttoken.value==='__proto__'){warning("Stupid key '{a}'.",nexttoken,nexttoken.value);}else{o[nexttoken.value]=true;}
-advance();advance(':');jsonValue();if(nexttoken.id!==','){break;}
-advance(',');}}
-advance('}');}
-function jsonArray(){var t=nexttoken;advance('[');if(nexttoken.id!==']'){for(;;){if(nexttoken.id==='(end)'){error("Missing ']' to match '[' from line {a}.",nexttoken,t.line);}else if(nexttoken.id===']'){warning("Unexpected comma.",token);break;}else if(nexttoken.id===','){error("Unexpected comma.",nexttoken);}
-jsonValue();if(nexttoken.id!==','){break;}
-advance(',');}}
-advance(']');}
-switch(nexttoken.id){case'{':jsonObject();break;case'[':jsonArray();break;case'true':case'false':case'null':case'(number)':case'(string)':advance();break;case'-':advance('-');if(token.character!==nexttoken.from){warning("Unexpected space after '-'.",token);}
-adjacent(token,nexttoken);advance('(number)');break;default:error("Expected a JSON value.",nexttoken);}}
-var itself=function(s,o){var a,i;JSLINT.errors=[];predefined=Object.create(standard);if(o){a=o.predef;if(a instanceof Array){for(i=0;i<a.length;i+=1){predefined[a[i]]=true;}}
-if(o.adsafe){o.safe=true;}
-if(o.safe){o.browser=false;o.css=false;o.debug=false;o.eqeqeq=true;o.evil=false;o.forin=false;o.nomen=true;o.on=false;o.rhino=false;o.safe=true;o.sidebar=false;o.strict=true;o.sub=false;o.undef=true;o.widget=false;predefined.Date=null;predefined['eval']=null;predefined.Function=null;predefined.Object=null;predefined.ADSAFE=false;predefined.lib=false;}
-option=o;}else{option={};}
-option.indent=option.indent||4;option.maxerr=option.maxerr||50;adsafe_id='';adsafe_may=false;adsafe_went=false;approved={};if(option.approved){for(i=0;i<option.approved.length;i+=1){approved[option.approved[i]]=option.approved[i];}}else{approved.test='test';}
-tab='';for(i=0;i<option.indent;i+=1){tab+=' ';}
-indent=1;global=Object.create(predefined);scope=global;funct={'(global)':true,'(name)':'(global)','(scope)':scope,'(breakage)':0,'(loopage)':0};functions=[funct];ids={};urls=[];src=false;xmode=false;stack=null;member={};membersOnly=null;implied={};inblock=false;lookahead=[];jsonmode=false;warnings=0;lex.init(s);prereg=true;strict_mode=false;prevtoken=token=nexttoken=syntax['(begin)'];assume();try{advance();if(nexttoken.value.charAt(0)==='<'){html();if(option.adsafe&&!adsafe_went){warning("ADsafe violation: Missing ADSAFE.go.",this);}}else{switch(nexttoken.id){case'{':case'[':option.laxbreak=true;jsonmode=true;jsonValue();break;case'@':case'*':case'#':case'.':case':':xmode='style';advance();if(token.id!=='@'||!nexttoken.identifier||nexttoken.value!=='charset'||token.line!==1||token.from!==1){error('A css file should begin with @charset "UTF-8";');}
-advance();if(nexttoken.type!=='(string)'&&nexttoken.value!=='UTF-8'){error('A css file should begin with @charset "UTF-8";');}
-advance();advance(';');styles();break;default:if(option.adsafe&&option.fragment){error("Expected '{a}' and instead saw '{b}'.",nexttoken,'<div>',nexttoken.value);}
-statements('lib');}}
-advance('(end)');}catch(e){if(e){JSLINT.errors.push({reason:e.message,line:e.line||nexttoken.line,character:e.character||nexttoken.from},null);}}
-return JSLINT.errors.length===0;};function is_array(o){return Object.prototype.toString.apply(o)==='[object Array]';}
-function to_array(o){var a=[],k;for(k in o){if(is_own(o,k)){a.push(k);}}
-return a;}
-itself.data=function(){var data={functions:[]},fu,globals,implieds=[],f,i,j,members=[],n,unused=[],v;if(itself.errors.length){data.errors=itself.errors;}
-if(jsonmode){data.json=true;}
-for(n in implied){if(is_own(implied,n)){implieds.push({name:n,line:implied[n]});}}
-if(implieds.length>0){data.implieds=implieds;}
-if(urls.length>0){data.urls=urls;}
-globals=to_array(scope);if(globals.length>0){data.globals=globals;}
-for(i=1;i<functions.length;i+=1){f=functions[i];fu={};for(j=0;j<functionicity.length;j+=1){fu[functionicity[j]]=[];}
-for(n in f){if(is_own(f,n)&&n.charAt(0)!=='('){v=f[n];if(is_array(fu[v])){fu[v].push(n);if(v==='unused'){unused.push({name:n,line:f['(line)'],'function':f['(name)']});}}}}
-for(j=0;j<functionicity.length;j+=1){if(fu[functionicity[j]].length===0){delete fu[functionicity[j]];}}
-fu.name=f['(name)'];fu.param=f['(params)'];fu.line=f['(line)'];fu.last=f['(last)'];data.functions.push(fu);}
-if(unused.length>0){data.unused=unused;}
-members=[];for(n in member){if(typeof member[n]==='number'){data.member=member;break;}}
-return data;};itself.report=function(option){var data=itself.data();var a=[],c,e,err,f,i,k,l,m='',n,o=[],s;function detail(h,s){if(s){o.push('<div><i>'+h+'</i> '+
-s.sort().join(', ')+'</div>');}}
-if(data.errors||data.implieds||data.unused){err=true;o.push('<div id=errors><i>Error:</i>');if(data.errors){for(i=0;i<data.errors.length;i+=1){c=data.errors[i];if(c){e=c.evidence||'';o.push('<p>Problem'+(isFinite(c.line)?' at line '+
-c.line+' character '+c.character:'')+': '+c.reason.entityify()+'</p><p class=evidence>'+
-(e&&(e.length>80?e.slice(0,77)+'...':e).entityify())+'</p>');}}}
-if(data.implieds){s=[];for(i=0;i<data.implieds.length;i+=1){s[i]='<code>'+data.implieds[i].name+'</code>&nbsp;<i>'+
-data.implieds[i].line+'</i>';}
-o.push('<p><i>Implied global:</i> '+s.join(', ')+'</p>');}
-if(data.unused){s=[];for(i=0;i<data.unused.length;i+=1){s[i]='<code><u>'+data.unused[i].name+'</u></code>&nbsp;<i>'+
-data.unused[i].line+'</i> <code>'+
-data.unused[i]['function']+'</code>';}
-o.push('<p><i>Unused variable:</i> '+s.join(', ')+'</p>');}
-if(data.json){o.push('<p>JSON: bad.</p>');}
-o.push('</div>');}
-if(!option){o.push('<br><div id=functions>');if(data.urls){detail("URLs<br>",data.urls,'<br>');}
-if(data.json&&!err){o.push('<p>JSON: good.</p>');}else if(data.globals){o.push('<div><i>Global</i> '+
-data.globals.sort().join(', ')+'</div>');}else{o.push('<div><i>No new global variables introduced.</i></div>');}
-for(i=0;i<data.functions.length;i+=1){f=data.functions[i];o.push('<br><div class=function><i>'+f.line+'-'+
-f.last+'</i> '+(f.name||'')+'('+
-(f.param?f.param.join(', '):'')+')</div>');detail('<big><b>Unused</b></big>',f.unused);detail('Closure',f.closure);detail('Variable',f['var']);detail('Exception',f.exception);detail('Outer',f.outer);detail('Global',f.global);detail('Label',f.label);}
-if(data.member){a=to_array(data.member);if(a.length){a=a.sort();m='<br><pre id=members>/*members ';l=10;for(i=0;i<a.length;i+=1){k=a[i];n=k.name();if(l+n.length>72){o.push(m+'<br>');m=' ';l=1;}
-l+=n.length+2;if(data.member[k]===1){n='<i>'+n+'</i>';}
-if(i<a.length-1){n+=', ';}
-m+=n;}
-o.push(m+'<br>*/</pre>');}
-o.push('</div>');}}
-return o.join('');};itself.jslint=itself;itself.edition='2009-10-04';return itself;}());(function(a){var e,i,input;if(!a[0]){print("Usage: jslint.js file.js");quit(1);}
-input=readFile(a[0]);if(!input){print("jslint: Couldn't open file '"+a[0]+"'.");quit(1);}
-if(!JSLINT(input,{bitwise:true,eqeqeq:true,immed:true,newcap:true,nomen:true,onevar:true,plusplus:true,regexp:true,rhino:true,undef:true,white:true})){for(i=0;i<JSLINT.errors.length;i+=1){e=JSLINT.errors[i];if(e){print('Lint at line '+e.line+' character '+
-e.character+': '+e.reason);print((e.evidence||'').replace(/^\s*(\S*(\s+\S+)*)\s*$/,"$1"));print('');}}
-quit(2);}else{print("jslint: No problems found in "+a[0]);quit();}}(arguments));
diff --git a/offline-submit/collect-inputs.js b/offline-submit/collect-inputs.js
deleted file mode 100644
index d6a2b47..0000000
--- a/offline-submit/collect-inputs.js
+++ /dev/null
@@ -1,45 +0,0 @@
-bzPage.prototype.collectInputs = function (form) {
-
-// form.elements array of all controls ... no, forEach though
-// INPUT, SELECT, TEXTAREA, and BUTTON
-// each interesting control of them have NAME and VALUE
-// You can access a particular element by using either an index or the element name or id.
-//
-// https://developer.mozilla.org/en/DOM/form
-// form.elements.querySelectorAll("*[name]")
-
- var x=this.dok.getElementById("myForm");
-for (var i=0;i<x.length;i++)
-{
-document.write(x.elements[i].value + ", " + x.elements[i].tagName + ", " + x.elements[i].name);
-document.write("<br />");
-}
-
-}
-
-// INTERESTING: http://www.quirksmode.org/js/forms.html
-
-// Example onsubmit handler
-
-function checkscript() {
- if (some value is/is not something) {
- // something is wrong
- alert('alert user of problem');
- return false;
- }
- else if (another value is/is not something) {
- // something else is wrong
- alert('alert user of problem');
- return false;
- }
-
- // If the script makes it to here, everything is OK,
- // so you can submit the form
-
- return true;
-}
-
-// with XPCNativeWrappers you cannot use document.formname.inputname.value
-var form = document.forms.namedItem("gs");
-var input = form.elements.namedItem("q");
-var q = input.value;
diff --git a/offline-submit/form-serialization.js b/offline-submit/form-serialization.js
deleted file mode 100644
index d7c4d07..0000000
--- a/offline-submit/form-serialization.js
+++ /dev/null
@@ -1,129 +0,0 @@
-/* ------------------------------------------------------------------ */
-
-/**
- * @param f : Form|HTMLFormElement
- * @return string
- */
-function serializeForm(f)
-{
- var gotSubmit = false;
-
- /**
- * @param o
- */
- function serializeControl(o)
- {
- /* HTML 4.01: Controls that are disabled cannot be successful. */
- if (!o.disabled)
- {
- /*
- * If a form contains more than one submit button,
- * only the activated submit button is successful.
- * (here: the first one)
- */
- var isSubmit = /(^|\s)(submit|image)(\s|$)/i.test(o.type);
- if (!gotSubmit || !isSubmit)
- {
- if (isSubmit) gotSubmit = true;
-
- /*
- * For menus, the control name is provided by a SELECT element
- * and values are provided by OPTION elements. Only selected
- * options may be successful. When no options are selected,
- * the control is not successful and neither the name nor any
- * values are submitted to the server when the form is submitted.
- */
- var m = /(^|\s)(select(-one)?|undefined)(\s|$)/i.exec(o.type);
- if (m)
- {
- /* select-one */
- if (m[3])
- {
- if (o.selectedIndex > -1)
- {
- items.add(o.name, o.options[o.selectedIndex].value);
- }
- }
-
- /* select */
- else if (m[2])
- {
- for (var i = 0, opts = o.options, len = opts && opts.length;
- i < len; i++)
- {
- var opt = opts[i];
- if (opt.selected)
- {
- items.add(o.name, opt.value);
- }
- }
- }
- }
-
- /*
- * All "on" checkboxes may be successful.
- * For radio buttons that share the same value of the
- * name attribute, only the "on" radio button may be successful.
- */
- else if (!/(^|\s)file|reset(\s|$)/i.test(o.type)
- && !(/(^|\s)object(\s|$)/i.test(o.tagName) && o.declare)
- && !/(^|\s)(checkbox|radio)(\s|$)/i.test(o.type)
- || o.checked)
- {
- items.add(o.name, o.value);
- }
- }
- }
- }
-
- var es = getFeature(f, "elements");
- if (es)
- {
- var items = [];
-
- items.add = function(sName, sValue) {
- var s = esc(sName) + "=" + esc(sValue);
- this.push(s);
- };
-
- if (!isMethod(items, "push"))
- {
- items.push = function() {
- for (var i = 0, len = arguments.length; i < len; i++)
- {
- items[items.length] = arguments[i];
- }
- };
- }
-
- for (var i = 0, len = es.length; i < len; i++)
- {
- var e = es[i];
-
- /*
- * Elements with the same name create a NodeList object,
- * however options of select objects are also indexable in Gecko.
- */
- if (typeof e[0] != "undefined" && typeof e.options == "undefined")
- {
- for (var j = 0, len2 = e.length; j < len2; j++)
- {
- serializeControl(e[j]);
- }
- }
- else
- {
- serializeControl(e);
- }
- }
-
- return items.join("&");
- }
-
- return "";
-}
-
-/* ------------------------------------------------------------------ */
-
-// esc(), getFeature() and isMethod() are user-defined, of course, but you
-// probably get the idea..
diff --git a/offline-submit/http-requests.txt b/offline-submit/http-requests.txt
deleted file mode 100644
index 7800182..0000000
--- a/offline-submit/http-requests.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-00:03:23.973 4.726 2246 4222 POST 200 text/html https://bugzilla.redhat.com/process_bug.cgi
-00:03:28.208 0.149 577 (2635) GET (Cache) text/css https://bugzilla.redhat.com/skins/standard/global.css
-00:03:28.215 0.169 583 (1100) GET (Cache) text/css https://bugzilla.redhat.com/skins/standard/yui/calendar.css
-00:03:28.221 0.173 579 (442) GET (Cache) text/css https://bugzilla.redhat.com/skins/standard/show_bug.css
-00:03:28.237 0.192 583 (1728) GET (Cache) text/css https://bugzilla.redhat.com/skins/contrib/RedHat/global.css
-00:03:28.243 0.197 589 (103) GET (Cache) text/css https://bugzilla.redhat.com/skins/contrib/RedHat/yui/calendar.css
-00:03:28.250 0.209 585 (100) GET (Cache) text/css https://bugzilla.redhat.com/skins/contrib/RedHat/show_bug.css
-00:03:28.257 0.227 575 (100) GET (Cache) text/css https://bugzilla.redhat.com/skins/custom/global.css
-00:03:28.264 0.236 581 (103) GET (Cache) text/css https://bugzilla.redhat.com/skins/custom/yui/calendar.css
-00:03:28.273 0.234 577 (100) GET (Cache) text/css https://bugzilla.redhat.com/skins/custom/show_bug.css
-00:03:28.280 0.293 550 (493) GET (Cache) application/x-javascript https://bugzilla.redhat.com/js/cookies.js
-00:03:28.508 0.220 581 (1568) GET (Cache) text/css https://bugzilla.redhat.com/skins/contrib/Dusk/global.css
-00:03:28.513 1.086 587 477 GET 404 text/html https://bugzilla.redhat.com/skins/contrib/Dusk/yui/calendar.css
-00:03:28.520 1.091 583 473 GET 404 text/html https://bugzilla.redhat.com/skins/contrib/Dusk/show_bug.css
-00:03:28.574 0.222 547 (2033) GET (Cache) application/x-javascript https://bugzilla.redhat.com/js/util.js
-00:03:28.582 0.234 548 (3746) GET (Cache) application/x-javascript https://bugzilla.redhat.com/js/field.js
-00:03:28.589 0.252 562 (9752) GET (Cache) application/x-javascript https://bugzilla.redhat.com/js/yui/yahoo-dom-event.js
-00:03:28.598 0.272 555 (12147) GET (Cache) application/x-javascript https://bugzilla.redhat.com/js/yui/calendar.js
-00:03:28.606 0.283 554 (4985) GET (Cache) application/x-javascript https://bugzilla.redhat.com/js/productform.js
-00:03:28.633 0.276 550 (5467) GET (Cache) application/x-javascript https://bugzilla.redhat.com/js/rpc-min.js
-00:03:28.641 0.284 551 (1047) GET (Cache) application/x-javascript https://bugzilla.redhat.com/js/show_bug.js
-00:03:29.557 0.077 427 (14643) GET (Cache) text/plain http://mcepl.fedorapeople.org/scripts/BugZappers_data.json
-00:03:29.564 0.071 422 (11352) GET (Cache) text/plain http://mcepl.fedorapeople.org/scripts/drm_pciids.json
-00:03:32.916 0.168 566 11698 GET 200 application/vnd.google.safebrowsing-chunk http://safebrowsing-cache.google.com/safebrowsing/rd/goog-malware-shavar_s_25761-25920.25761-25796.25797-25920:
-00:03:34.383 0.275 561 20882 GET 200 application/vnd.google.safebrowsing-chunk http://safebrowsing-cache.google.com/safebrowsing/rd/goog-malware-shavar_a_16771-16780.16771,16773-16780.:
-00:03:34.691 0.080 566 7154 GET 200 application/vnd.google.safebrowsing-chunk http://safebrowsing-cache.google.com/safebrowsing/rd/goog-malware-shavar_a_16781-16800.16781-16791.16792-16800:
-00:03:34.810 0.084 564 3875 GET 200 application/vnd.google.safebrowsing-chunk http://safebrowsing-cache.google.com/safebrowsing/rd/goog-phish-shavar_s_52481-52640.52481-52528.52529-52640:
-00:03:35.195 0.111 564 15346 GET 200 application/vnd.google.safebrowsing-chunk http://safebrowsing-cache.google.com/safebrowsing/rd/goog-phish-shavar_a_78641-78720.78641-78718.78719-78720:
diff --git a/offline-submit/john-resig-offline-app-stub.js b/offline-submit/john-resig-offline-app-stub.js
deleted file mode 100644
index b9d6160..0000000
--- a/offline-submit/john-resig-offline-app-stub.js
+++ /dev/null
@@ -1,43 +0,0 @@
-// stub for the offline application in pseudocode
-// from http://ejohn.org/blog/offline-events/
-
-function saveData( item ){
- if ( navigator.onLine ) {
- saveToServer( item );
- } else {
- toSave.push( item );
- }
-}
-
-function loadData( item ){
- if ( navigator.onLine ) {
- return loadFromServer( item );
- } else {
- var result = loadFromQueue( item );
- if ( !result ) {
- displayError();
- toLoad.push( item );
- }
- return result;
- }
-}
-
-setInterval(function(){
- if ( navigator.onLine ) {
- var item = predictNextItemToBeLoaded();
- loadData( item );
- }
-}, 5000);
-
-window.ononline = function(){
- toSave.forEach( saveData );
- toLoad.forEach( loadData );
-};
-
-window.onload = function(){
- document.getElementById("myform").onsubmit = function(){
- saveData( this );
- return false;
- };
-};
-
diff --git a/offline-submit/jquery.malsup.com.htm b/offline-submit/jquery.malsup.com.htm
deleted file mode 100644
index b0008d7..0000000
--- a/offline-submit/jquery.malsup.com.htm
+++ /dev/null
@@ -1,583 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
-<title>JavaScript Form Serialization Comparison</title>
-<link rel="stylesheet" type="text/css" media="screen" href="../../jq.css" />
-<style type="text/css">
-h1, #intro, #testForm td.hint { font-family: 'trebuchet ms', verdana, arial; }
-h1 { padding-left: 0 }
-#intro { background: #ffc; padding: 10px }
-#banner { text-align: left; }
-code.inline { background-color: #dfe0ff; color: #000 }
-ul { padding-left: 20px; margin: 10px 10px 10px 0 }
-#disclaimer { font-family: arial, sans-serif; font-size: small; font-style: italic; color: #555; margin-bottom: 5px}
-span.name { color: #c22 }
-span.dis { color: #f11 }
-#results { margin: 15px 0 }
-#results div { font-family: monospace; color: #888; }
-#results td { padding: 5px; }
-#testForm { border: 1px solid #888; background-color: #eee; padding: 0px }
-#testForm tr { background-color: #eee; }
-#testForm td { font-family: monospaced; padding: 2px 10px; }
-#testForm td.hint { color: #880; background: #ffc url(infoIcon.png) 5px 50% no-repeat; padding: 5px 5px 5px 30px }
-#toolbar { padding: 5px; border: 1px solid #aaa; border-width: 1px 0; background-color: #eee }
-#main { padding-top: 0; }
-legend, .wrong, span.dis { font-weight: bold }
-.wrong { color: #f00; }
-ul li { list-style-type: square }
-ol li { list-style-type: decimal }
-blockquote { padding: 10px; border: 1px dashed #aaa; line-height: 1.5em; font-family: sans-serif; background-color: #ffe }
-#footer { margin-top: 15px; padding-top: 10px; border-top: 1px solid #ddd; color: #888; }
-#main { padding: 15px }
-</style>
-<script type="text/javascript" src="../../jquery-1.3.2.js"></script>
-<script type="text/javascript" src="../jquery.form.js"></script>
-<script type="text/javascript" src="mochi.base.js"></script>
-<script type="text/javascript" src="mochi.iter.js"></script>
-<script type="text/javascript" src="mochi.dom.js"></script>
-
-<script type="text/javascript" src="dojo.js"></script>
-<script type="text/javascript" src="dojo.xhr.js"></script>
-
-<script type="text/javascript" src="prototype-1.6.0.3.js"></script>
-<!--<script type="text/javascript" src="mootools-1.2.1.js"></script>-->
-<script type="text/javascript" src="yahoo.js"></script>
-<script type="text/javascript" src="yui-event.js"></script>
-<script type="text/javascript" src="yui-connection.js"></script>
-
-<script type="text/javascript" src="firebug.js"></script>
-<script type="text/javascript" src="../../chili-1.7.pack.js"></script>
-<script type="text/javascript"><!--
-
-//
-// note that all usage of $ in this file is using Prototype's $ fn
-//
-var q, iter;
-
-// initialize test harness
-jQuery(init);
-
-function init() {
- // profiling in FF only
- if (!/Firefox/.test(navigator.userAgent)) {
- $('timer').checked = true;
- $('profiler').disabled = true;
- console.open();
- }
-
- // bind the Test buttons to the 'runTest' function
- jQuery('input.tester').click(function() { runTest(this); });
-
- // let's see browser's native form serialization too!
- var match = window.location.href.match(/\?([^#]+)/);
- if (!match) return;
- $('nativeOutput').innerHTML = match[1].escapeHTML();
-}
-
-function runTest(e) {
- $('S5').selectedIndex = -1; // for the S5 test - force selectedIndex to -1
- iter = $('iterations').value;
- var name = e.id;
- var n = '('+iter+') ' + name;
- var useTimer = jQuery('#toolbar :radio').fieldValue() == 1;
-
- // start clock
- useTimer ? console.time(n) : console.profile(n);
-
- try {
- // run the test
- window[name+'Test']();
- } catch(e) {
- q = 'ERROR: ' + e.message;
- }
-
- // stop clock
- useTimer ? console.timeEnd(n) : console.profileEnd(n);
-
- // highlight inaccurate results:
- // - there should not be any "NO" values, this includes the reset input, submit inputs and disabled inputs
- // - S5 should not be submitted (the selected index is -1)
- // - S3 should not be blank
- // - the query string should not have a trailing ampersand (dojo)
- // - the "My Name" input should have been converted to My+Name, not My%20Name
- q = q.replace(/(reset=NO|S5=|&$|sub(\d)=NO|D(\d)=NO)/g, '<span class="wrong">$1</span>');
- q = q.replace(/S3=&/, '<span class="wrong">S3=</span>&');
- q = q.replace(/My(%20)Name/,'<span class="wrong">$1</span>');
- $(name+'Output').innerHTML = q;
-}
-
-function jQueryNativeTest() {
- var form = jQuery('#testForm');
- for (var i=0; i < iter; i++)
- q = form.serialize();
-}
-
-function jQueryFormTest() {
- var form = jQuery('#testForm');
- for (var i=0; i < iter; i++)
- q = form.formSerialize();
-}
-
-function dojoTest() {
- var form = dojo.byId('testForm');
- for (var i=0; i < iter; i++)
- q = dojo.formToQuery(form);
-}
-
-function PrototypeTest() {
- var form = $('testForm');
- for (var i=0; i < iter; i++)
- q = Form.serialize(form);
-}
-
-/*
-function mooTest() {
- var form = $('testForm');
- for (var i=0; i < iter; i++)
- q = form.toQueryString();
-}
-*/
-
-function YUITest() {
- var form = $('testForm');
- for (var i=0; i < iter; i++)
- q = YAHOO.util.Connect.setForm(form);
-}
-
-function MochiKitTest() {
- var form = $('testForm');
- for (var i=0; i < iter; i++)
- q = MochiKit.Base.queryString(form);
-}
-// -->
-</script>
-
-</head>
-<body>
-<h1 id="banner">JavaScript Form Serialization Comparison:&nbsp;&nbsp;&nbsp;jQuery &bull; dojo &bull; Prototype &bull; YUI &bull; MochiKit</h1>
-<div id="intro">
- This page tests two things about JavaScript form serialization: <strong>quality</strong> and <strong>speed</strong>.
- <ul>
-
- <li>Quality is dertermined by analyzing the serialized output according to the <a href="http://www.w3.org/TR/html401/interact/forms.html">W3C Recommendation</a>.</li>
- <li>Speed is measured using <a href="http://www.getfirebug.com/">Firebug</a> to time (or profile in FireFox) numerous iterations of the serialization process.<sup>[1]</sup></li>
- </ul>
- <div id="disclaimer">If you believe the tests or comments on this page are inaccurate
- or unfair - please let me know. It is not my intent to misrepresent any of these libraries.
- Feedback can be sent to: forms at malsup dot com.
- </div>
- <div>&raquo;&raquo; Special thanks to Marius Feraru for adding support for native browser output and the EOL test!</div>
-</div>
-<div id="toolbar">
- <input type="radio" name="time" value="1" checked="checked" id="timer" />Timer <input type="radio" name="time" value="0" id="profiler" />Profiler
- <span style="margin-left: 15px">Iterations:</span>
- <select id="iterations" name="iterations" class="tester">
- <option value="1" selected="selected">1</option>
- <option value="25">25</option>
- <option value="50">50</option>
-
- <option value="100">100</option>
- <option value="200">200</option>
- </select>
- <p />
- <input id="jQueryNative" type="button" class="tester" value="jQuery 1.3.2 core" />
- <input id="jQueryForm" type="button" class="tester" value="jQuery 1.3.2 with Form Plugin" />
- <input id="dojo" type="button" class="tester" value="dojo 1.2.3" />
- <input id="YUI" type="button" class="tester" value="YUI 2.6.0" />
- <input id="MochiKit" type="button" class="tester" value="MochiKit 1.4.2" />
- <input id="Prototype" type="button" class="tester" value="Prototype 1.6.0.3" />
- <!-- <input id="moo" type="button" class="tester" value="Test moo" /> -->
-</div>
-<div id="main">
- <form id="results" action="#">
- <fieldset><legend>Output <span style="color:#666"><em>(errors in red)</em></span></legend>
- <table>
- <tr><td>NATIVE</td><td><div id="nativeOutput" class="output"><a href="#" onclick="$('S5').selectedIndex = -1; $('testForm').submit(); return false">check your browser's *native* form serialization</a></div></td></tr>
- <tr><td>jQuery</td><td><div id="jQueryNativeOutput" class="output"></div></td></tr>
- <tr><td>jQuery Form</td><td><div id="jQueryFormOutput" class="output"></div></td></tr>
- <tr><td>dojo</td><td><div id="dojoOutput" class="output"></div></td></tr>
- <tr><td>YUI</td><td><div id="YUIOutput" class="output"></div></td></tr>
- <tr><td>MochiKit</td><td><div id="MochiKitOutput" class="output"></div></td></tr>
- <tr><td>Prototype</td><td><div id="PrototypeOutput" class="output"></div></td></tr>
- <!--<tr><td>moo</td><td><div id="mooOutput" class="output"></div></td></tr> -->
-
- </table>
- </fieldset>
- </form>
-
- <p>
- The following form contains each of the possible elements that can be submitted (with the exception of <code class="inline">&lt;input type="file"&gt;</code>).
- Which elements, and how they should be submitted, is specified here:
- <a href="http://www.w3.org/TR/html401/interact/forms.html#h-17.13">http://www.w3.org/TR/html401/interact/forms.html#h-17.13</a>
- </p>
-
- <form id="testForm" action="#" method="get"><div>
-
- <table>
- <tr><td class="hint" colspan="2">Most enabled input elements and textareas are handled correctly by each of the libraries.</td></tr>
- <tr><td><code class="html">&lt;textarea name="T3" rows="2" cols="15"&gt;?<br />Z&lt;/textarea&gt;</code></td><td><textarea name="T3" rows="2" cols="15">?Z</textarea></td></tr>
- <tr><td><code class="html">&lt;input type="hidden" name="H1" value="x" /&gt;</code></td><td><input type="hidden" name="H1" value="x" /></td></tr>
- <tr><td><code class="html">&lt;input type="hidden" name="H2" /&gt;</code></td><td><input type="hidden" name="H2" /></td></tr>
-
- <tr><td><code class="html">&lt;input type="password" name="PWD" /&gt;</code></td><td><input name="PWD" type="password" value="" /></td></tr>
- <tr><td><code class="html">&lt;input type="text" name="T1" /&gt;</code></td><td><input name="T1" type="text" /></td></tr>
- <tr><td><code class="html">&lt;input type="text" name="T2" value="YES" readonly="readonly" /&gt;</code></td><td><input name="T2" type="text" value="YES" readonly="readonly" /></td></tr>
- <tr><td><code class="html">&lt;input type="checkbox" name="C1" value="1" /&gt;</code></td><td><input type="checkbox" name="C1" value="1" /></td></tr>
- <tr><td><code class="html">&lt;input type="checkbox" name="C2" /&gt;</code></td><td><input type="checkbox" name="C2" /></td></tr>
- <tr><td><code class="html">&lt;input type="radio" name="R1" value="1" /&gt;</code></td><td><input type="radio" name="R1" value="1" /></td></tr>
-
- <tr><td><code class="html">&lt;input type="radio" name="R1" value="2" /&gt;</code></td><td><input type="radio" name="R1" value="2" /></td></tr>
- <tr><td><code class="html">&lt;input type="text" name="My Name" value="me" /&gt;</code></td><td><input type="text" name="My Name" value="me" /></td></tr>
-
- <tr><td class="hint" colspan="2">The reset input should never be serialized. Prototype and MochiKit get this wrong.</td></tr>
- <tr><td><code class="html">&lt;input type="reset" name="reset" value="NO" /&gt;</code></td><td><input type="reset" name="reset" value="NO" /></td></tr>
-
- <tr><td class="hint" colspan="2">Normal <strong>Single</strong> select elements are handled correctly by each of the libraries.</td></tr>
-
- <tr><td><code class="html">&lt;select name="S1"&gt;</code> <em>(100 options)</em></td><td>
- <select name="S1">
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
-
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
-
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
-
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
-
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
-
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
-
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
-
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
-
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
-
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
-
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
-
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
-
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
-
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
-
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
-
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
-
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
-
- </select>
- </td></tr>
- <tr><td class="hint" colspan="2">Normal <strong>multiple</strong> select elements are handled correctly by each of the libraries.</td></tr>
- <tr><td><code class="html">&lt;select name="S2" multiple="multiple" size="3"&gt;</code> <em>(100 options)</em></td><td>
- <select name="S2" multiple="multiple" size="3">
- <option value="abc">ABC</option>
-
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
-
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
-
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
-
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
-
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
-
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
-
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
-
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
-
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
-
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
-
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
-
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
-
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
-
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
-
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
-
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
-
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- <option value="abc">ABC</option>
- </select></td></tr>
-
- <tr><td class="hint" colspan="2">The following select element has a selected option with no value attribute. The option text value should be submitted.
- <code class="inline">S3=YES</code> is correct. <code class="inline">S3=</code> is incorrect. dojo gets this wrong in IE.</td></tr>
-
- <tr><td><code class="html">&lt;select name="S3"&gt;&lt;option selected="selected"&gt;YES&lt;/option&gt;&lt;/select&gt;</code></td><td><select name="S3">
- <option selected="selected">YES</option>
- </select></td></tr>
- <tr><td class="hint" colspan="2">The following select element has a selected option with a value attribute set to "". <code class="inline">S4=</code> is correct. <code class="inline">S4=NO</code> is incorrect.
- </td></tr>
-
- <tr><td><code class="html">&lt;select name="S4"&gt;&lt;option value="" selected="selected"&gt;NO&lt;/option&gt;&lt;/select&gt;</code></td><td><select name="S4">
- <option value="" selected="selected">NO</option>
- </select></td></tr>
- <tr><td class="hint" colspan="2">The following select element has its <code class="inline">selectedIndex</code> property set to <code class="inline">-1</code> before serialization.
- It should not be submitted. dojo and MochiKit get this wrong.</td></tr>
-
- <tr><td><code class="html">&lt;select name="S5"&gt;&lt;option value="NO"&gt;NO&lt;/option&gt;&lt;/select&gt;</code></td>
- <td><select id="S5" name="S5"><option value="NO">NO</option></select></td></tr>
- <tr><td class="hint" colspan="2">Submit elements should only appear in the query string when they are the element used to submit the form. Only jQuery and dojo get this right.
- YUI always includes the first submit element. Prototype sends all the input submit elements (but not button submit elements).
- MochiKit sends them all.</td></tr>
- <tr><td><code class="html">&lt;input type="submit" name="sub1" value="NO" /&gt;</code></td><td><input type="submit" name="sub1" value="NO" /></td></tr>
- <tr><td><code class="html">&lt;input type="submit" name="sub2" value="NO" /&gt;</code></td><td><input type="submit" name="sub2" value="NO" /></td></tr>
-
- <tr><td><code class="html">&lt;input type="image" name="sub3" src="submit.gif" value="NO" /&gt;</code></td><td><input type="image" name="sub3" value="NO" src="submit.gif" /></td></tr>
- <tr><td><code class="html">&lt;button type="submit" name="sub4" value="NO"&gt;NO&lt;/button&gt;</code></td><td><button name="sub4" type="submit" value="NO">NO</button></td></tr>
-
- <tr><td class="hint" colspan="2">Disabled elements should never be submitted. MochiKit and mootools get this wrong.</td></tr>
- <tr><td><code class="html">&lt;input type="text" name="D1" value="NO" <span class="dis">disabled="disabled"</span> /&gt;</code></td><td><input name="D1" type="text" value="NO" disabled="disabled" /></td></tr>
-
- <tr><td><code class="html">&lt;input type="checkbox" name="D2" value="NO" checked="checked" <span class="dis">disabled="disabled"</span> /&gt;</code></td><td><input type="checkbox" checked="checked" disabled="disabled" name="D2" value="NO" /></td></tr>
- <tr><td><code class="html">&lt;input type="radio" name="D3" value="NO" checked="checked" <span class="dis">disabled="disabled"</span> /&gt;</code></td><td><input type="radio" name="D3" value="NO" checked="checked" disabled="disabled" /></td></tr>
- <tr><td><code class="html">&lt;select name="D4"&gt;&lt;option selected="selected" value="NO" <span class="dis">disabled="disabled"</span>&gt;NO&lt;/option&gt;</code></td><td><select name="D4" disabled="disabled">
-
- <option selected="selected" value="NO">NO</option>
- </select></td></tr>
- <tr><td class="hint" colspan="2">Inputs with a type attribute of something other than<br />
- PASSWORD | CHECKBOX | RADIO | SUBMIT | RESET | FILE | HIDDEN | IMAGE | BUTTON<br />
- should be treated as TEXT inputs.
- </td></tr>
- <tr><td><code class="html">&lt;input type="bogus" name="TYPE-TEST" value="YES" /&gt;</code></td><td><input type="bogus" name="TYPE-TEST" value="YES" /></td></tr>
- <tr><td><code class="html">&lt;input type="search" name="SEARCH" value="YES" /&gt;</code></td><td><input type="search" name="SEARCH" value="YES" /></td></tr>
- </table>
- </div></form>
- <p />
- <h1>Notes</h1>
- This test page does not expose serialization problems that occur during an actual form submit. These include:
- <p />
-
- <ul>
- <li>YUI, Prototype and MochiKit do not support input elements of <code class="inline">type="image"</code>.</li>
- <li>dojo does not capture the click coordinates of input elements of <code class="inline">type="image"</code>. However, it does correctly recognize it as the submitting element.</li>
- <li>dojo does not properly support semantic serialization when the form contains an input of <code class="inline">type="image"</code>. When such an element is used to submit
- the form, it will always appear last in the query string regardless of its semantic position. (This is likely a very
- low-percentage use case.)</li>
-
- <li>mootools is not compatible with Prototype and is not included on this test page. A test page that includes mootools can be found <a href="moo.html">here</a>.
- In summary, mootools does not support semantic serialization and it incorrectly submits disabled fields.
- </li>
- </ul>
- <p />
- <h1>Encoding</h1>
- Each of the libraries tested use JavaScript's <code class="inline">encodeURIComponent</code><sup>[2]</sup> function to encode form data.
- Technically, this does not conform to the HTML spec <a href="http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.1">which
- states</a> the following
- about the <code class="inline">application/x-www-form-urlencoded</code> content type (emphasis added):
- <blockquote>
-
- This is the default content type. Forms submitted with this content type must be encoded as follows:<br />
- <ol>
- <li>Control names and values are escaped. <strong>Space characters are replaced by `+'</strong>, and then reserved
- characters are escaped as described in <a href="http://www.w3.org/TR/html401/references.html#ref-RFC1738">[RFC1738]</a>,
- section 2.2: Non-alphanumeric characters are
- replaced by `%HH', a percent sign and two hexadecimal digits representing the ASCII code of the character.
- <strong>Line breaks are represented as "CR LF" pairs (i.e., `%0D%0A')</strong>.</li>
- <li>The control names/values are listed in the order they appear in the document. The name is separated
- from the value by `=' and name/value pairs are separated from each other by '&amp;'.</li>
-
- </ol>
- </blockquote>
- While this does not seem to cause any problems, it is interesting and noteworthy.
- <p />
- <h1>Links</h1>
- <ul>
- <li><a href="http://jquery.com">jQuery</a></li>
- <li><a href="http://www.dojotoolkit.com/">dojo</a></li>
-
- <li><a href="http://developer.yahoo.com/yui/">YUI</a></li>
- <li><a href="http://mochikit.com/">MochiKit</a></li>
- <li><a href="http://prototypejs.org/">Prototype</a></li>
- <li><a href="http://mootools.net/">mootools</a></li>
- </ul>
- <div id="footer">
- [1] Timing numerous iterations of the form serialization process is a contrived test case.
- This is not something that would ever be done with a real form (I hope). And this is why there
- is an option of 1 in the iterations combobox - so you can run only a single pass if you like.
- Running numerous iterations simply makes it easier to compare the relative performance
- of the libraries tested.
- <p />
-
- [2] dojo optionally will encode form data in ascii format (using dojo.string.encodeAscii).
- </div>
-</div>
-</body>
-</html>
diff --git a/offline-submit/lazarus.js b/offline-submit/lazarus.js
deleted file mode 100644
index 9db59b0..0000000
--- a/offline-submit/lazarus.js
+++ /dev/null
@@ -1,4418 +0,0 @@
-
-//declare namespace
-this.Lazarus = this.Lazarus || {}
-
-Lazarus.STATE_UNINITALIZED = 0;
-Lazarus.STATE_DISABLED = 1;
-Lazarus.STATE_PASSWORD_REQUIRED = 2;
-Lazarus.STATE_ENABLED = 3;
-Lazarus.STATE_DISABLED_FOR_DOMAIN = 4;
-Lazarus.STATE_PRIVATE_BROWSING = 5;
-Lazarus.STATE_GENERATING_KEYS = 6;
-
-
-Lazarus.LOGIN_HOSTNAME = 'chrome://lazarus';
-Lazarus.LOGIN_REALM = 'Private Key Password';
-Lazarus.LOGIN_USERNAME = 'lazarus-private-key';
-
-Lazarus.IFRAME_NAME = '<content-editable-iframes>';
-Lazarus.MIN_TEXT_NEEDED_TO_SHOW_NOTIFICATION = 1024; //characters
-
-//flag to indicate if this browser is ready yet.
-Lazarus.initalized = false;
-
-//timers
-Lazarus.cleanupSavedFormsTimer = 0;
-Lazarus.autoSaveFormTimer = 0;
-
-//pointer to last autosave form.
-Lazarus.currAutoSaveForm = null;
-
-//pointer to the last editor (txetbox or iframe) that a user put input into.
-Lazarus.currentEditor = null;
-
-//flag to say if context menu is currently being shown
-Lazarus.isContextMenuShowing = false;
-
-/* known input types
-case "text":
-case "textarea":
-case "file":
-case "radio":
-case "checkbox":
-case "select":
-case "password":
-case "hidden":
-case "submit":
-case "reset":
-case "button":
-case "image":
-*/
-
-
-
-//array of editor infos that the user has typed into this session
-Lazarus.editorInfos = [];
-
-
-/**
-* window has loaded
-*/
-Lazarus.init = function(){
-
- Lazarus.Global = Components.utils.import("resource://lazarus/global.js").Global;
- Lazarus.Crypto = Components.utils.import("resource://lazarus/crypto.js").Crypto;
-
- Lazarus.initalized = true;
- Lazarus.initDevEnviroment();
-
- //set loading icon
- Lazarus.refreshIcon();
- Lazarus.repositionNotification();
-
- //Update UI elements
- Lazarus.$("lazarus-statusbaricon-tooltip-title").setAttribute("value", Lazarus.getString("lazarus.statusbarpanel.image.tooltip", Lazarus.getVersionStr() +" ["+ Lazarus.build +"]"));
- Lazarus.refreshMenuIcons();
- Lazarus.Pref.addObserver('extensions.lazarus.showContextMenuIcons', Lazarus.refreshMenuIcons);
-
- if (Lazarus.getPref('extensions.lazarus.showDonateNotification')){
- Lazarus.checkForDonateThanks();
- }
-
-
- //check crypto component (breaks a lot with various Linux builds)
- if (Lazarus.checkCrypto()){
- //open the database
- if (Lazarus.initDB()){
- if (Lazarus.initEncryptionKeys()){
- if (Lazarus.loadPublicKey()){
- Lazarus.enable();
- }
-
- Lazarus.refreshIcon();
-
- Lazarus.saveAutoSaveText();
-
- //remove expired forms
- Lazarus.cleanupSavedForms();
-
- //hmmm, interesting. Cleaning the database makes little difference to the database size (33MB -> 32MB),
- // unless a lot of deletions have been made
- //
- if (Lazarus.getPref('extensions.lazarus.cleanDatabaseAtStartup')){
- Lazarus.cleanDB();
- }
- }
- //else we are generating new encryption keys, do nothing
- }
- else {
- //errors *should* have been thrown in the error console.
- //inform the user something went wrong :(
- Lazarus.error("Failed to load database");
- Lazarus.disable();
- }
- }
- else {
- Lazarus.error("Failed to load crypto component");
- Lazarus.disable();
- }
- Lazarus.refreshIcon();
-}
-
-/**
-* turn off the donate notifications if this user has donated.
-*/
-Lazarus.checkForDonateThanks = function(){
-
- var onload = function(uri){
- if (uri && uri.spec && uri.spec.indexOf('//lazarus.interclue.com/donate-thanks.html') > -1){
- Lazarus.setPref('extensions.lazarus.showDonateNotification', false);
- Lazarus.Event.remove("location-change", onload);
- }
- }
- Lazarus.Event.add("location-change", onload);
-}
-
-/**
-* check to make sure the crypto component has loaded correctly
-*/
-Lazarus.checkCrypto = function(){
- try {
- var crypto = Components.classes["@labs.mozilla.com/Weave/Crypto;1"].createInstance(Components.interfaces.IWeaveCrypto);
- return true;
- }
- catch(e){
- return false;
- }
-}
-
-/**
-* reposition the notification bar so that it's always the last element
-*/
-Lazarus.repositionNotification = function(){
- //#124: Zotero compatiilty problem
- var notif = document.getElementById('lazarus-notification');
- notif.parentNode.appendChild(notif);
-}
-
-
-
-/**
-* enables Lazarus for this browser
-*/
-Lazarus.enable = function(){
-
- Lazarus.saveAutoSavedForms();
-
- //add preference observers
- Lazarus.Pref.addObserver("extensions.lazarus.expireSavedForms", Lazarus.startCleanupTimer);
- Lazarus.Pref.addObserver("extensions.lazarus.expireSavedFormsInterval", Lazarus.startCleanupTimer);
- Lazarus.Pref.addObserver("extensions.lazarus.showInStatusbar", Lazarus.refreshIcon);
-
- //we need to capture any onsubmit event from forms within a webpage
- gBrowser.addEventListener("submit", Lazarus.onFormSubmit, false);
- gBrowser.addEventListener("submit", Lazarus.saveLastSubmittedForm, false);
- gBrowser.addEventListener("DOMContentLoaded", Lazarus.autofillEvent, true);
- gBrowser.addEventListener("DOMContentLoaded", Lazarus.initRecoverForm, true);
- gBrowser.addEventListener("reset", Lazarus.onFormReset, false);
- gBrowser.addEventListener("change", Lazarus.onFormChange, false);
- //we also need to save forms if people are typing into them.
- gBrowser.addEventListener("keyup", Lazarus.onKeyUp, false);
-
- //kjd: removing lazarus icon for now
- //gBrowser.addEventListener("keydown", Lazarus.onKeyDown, false);
-
-
- //clear the saved forms if user wants to when "clear private data" is hit.
- Lazarus.$("Tools:Sanitize").addEventListener("command", Lazarus.fireClearPrivateDataIfNoPrompt, false);
-
- //add handlers to the context menu
- Lazarus.$("contentAreaContextMenu").addEventListener("popupshowing", Lazarus.onContextMenuShowing, false);
- Lazarus.$("contentAreaContextMenu").addEventListener("popuphidden", Lazarus.onContextMenuHide, false);
-
- //need events when a user changes the current document
- Lazarus.Event.add("location-change", Lazarus.onLocationChange);
-
- Lazarus.Event.add("extension-uninstall", Lazarus.onUninstall);
- Lazarus.Event.add("extension-uninstall-request", Lazarus.onUninstallRequest);
- Lazarus.Event.add("application-startup", Lazarus.onStartUp);
- Lazarus.Event.add("application-startup", Lazarus.removeOldForms);
- Lazarus.Event.add("application-shutdown", Lazarus.fireClearPrivateDataOnShutdown);
- Lazarus.Event.add("application-shutdown", Lazarus.onShutdown);
- Lazarus.Event.add("clear-private-data", Lazarus.onClearPrivateData);
-
- Lazarus.startCleanupTimer();
-
- //show the statusbar image (if user wants it)
- Lazarus.refreshIcon();
-}
-
-
-Lazarus.onKeyDown = function(evt){
- var ele = evt.target;
-
- //ignore if we have already attached an onblur handler to this element
- if (!ele.lazarusIconAdded){
- switch(Lazarus.getElementType(ele)){
- case "text":
- case "password":
- case "textarea":
- //are we saving this element?
- var form = Lazarus.findFormFromElement(ele);
- var editor = Lazarus.findEditorFromElement(ele);
- if ((form && Lazarus.shouldSaveForm(form)) || (editor && Lazarus.shouldSaveEditorInfo(form))){
- //highlight element
- Lazarus.addBackgroundIcon(ele);
- }
- else {
- //ignore furthur keypresses on this element?
- }
-
- default:
- //ignore this element
- }
- }
-}
-
-
-Lazarus.addBackgroundIcon = function(ele){
-
- if (!ele.lazarusIconAdded){
- ele.lazarusIconAdded = true;
-
- var doc = ele.ownerDocument;
- if (!doc.lazarusIcon){
- var div = doc.createElement('div');
- div.style.width = "11px";
- div.style.height = "14px";
- div.style.position = "absolute";
- div.style.background = "url("+ Lazarus.icon +") no-repeat center center";
- div.title = Lazarus.getString('Lazarus.savingText');
- doc.body.appendChild(div);
- doc.lazarusIcon = div;
- }
- //now position the image over the end of the textbox
- var rect = ele.getBoundingClientRect();
- doc.lazarusIcon.style.top = rect.top +"px";
- doc.lazarusIcon.style.left = (rect.right - parseInt(doc.lazarusIcon.style.width)) +"px";
- doc.lazarusIcon.style.display = "block";
-
- var onBlur = function(){
- //hide the icon
- doc.lazarusIcon.style.display = "none";
- ele.lazarusIconAdded = false;
- }
-
- //when adding the icon, we should hide it on blur
- ele.addEventListener("blur", onBlur, false);
- }
-}
-
-
-/**
-* restart the browser
-*/
-Lazarus.restart = function(){
- var nsIAppStartup = Components.interfaces.nsIAppStartup;
- Components.classes["@mozilla.org/toolkit/app-startup;1"].getService(nsIAppStartup).quit(nsIAppStartup.eRestart | nsIAppStartup.eAttemptQuit);
-}
-
-/**
-* turns Lazarus off for this browser
-*/
-Lazarus.disable = function(){
-
- //add preference observers
- Lazarus.Pref.addObserver("extensions.lazarus.expireSavedForms", Lazarus.startCleanupTimer);
- Lazarus.Pref.addObserver("extensions.lazarus.expireSavedFormsInterval", Lazarus.startCleanupTimer);
- Lazarus.Pref.addObserver("extensions.lazarus.showInStatusbar", Lazarus.refreshIcon);
-
- //we need to capture any onsubmit event from forms within a webpage
- gBrowser.removeEventListener("submit", Lazarus.onFormSubmit, false);
- gBrowser.removeEventListener("submit", Lazarus.saveLastSubmittedForm, false);
- gBrowser.removeEventListener("DOMContentLoaded", Lazarus.autofillEvent, true);
- gBrowser.removeEventListener("DOMContentLoaded", Lazarus.initRecoverForm, true);
- gBrowser.removeEventListener("reset", Lazarus.onFormReset, false);
- gBrowser.removeEventListener("change", Lazarus.onFormChange, false);
- //we also need to save forms if people are typing into them.
- gBrowser.removeEventListener("keyup", Lazarus.onKeyUp, false);
-
- //need events when a user changes the current document
- Lazarus.Event.remove("location-change", Lazarus.onLocationChange);
-
- //clear the saved forms if user wants to when "clear private data" is hit.
- Lazarus.$("Tools:Sanitize").removeEventListener("command", Lazarus.fireClearPrivateDataIfNoPrompt, false);
-
- Lazarus.stopCleanupTimer();
-
- //and close the database
- Lazarus.db.close();
-
- //update the statusbar image
- Lazarus.refreshIcon();
-}
-
-/**
-* return TRUE if we can encrypt a string (ie the Crypto component is working, and the public key exists)
-*/
-Lazarus.canEncrypt = function(){
- return Lazarus.Crypto.publicKey ? true : false;
-}
-
-Lazarus.canDecrypt = function(){
- return Lazarus.Crypto.privateKey ? true : false;
-}
-
-
-
-/**
-* initalizes the lazarus recover-form page
-*/
-Lazarus.initRecoverForm = function(evt){
- var doc = evt.originalTarget;
- if (Lazarus.isDocRecoveryForm(doc)){
- doc.title = Lazarus.getString("recoverform.title");
-
- //Lazarus.$('heading', doc).innerHTML = Lazarus.getString("recoverform.title");
- Lazarus.$('description', doc).innerHTML = Lazarus.getString("recoverform.description");
- Lazarus.$('notes', doc).innerHTML= Lazarus.getString("recoverform.notes");
-
- Lazarus.$('form-url-label', doc).innerHTML= Lazarus.getString("recoverform.form.url");
- Lazarus.$('form-action-label', doc).innerHTML= Lazarus.getString("recoverform.form.action");
- Lazarus.$('notes', doc).innerHTML= Lazarus.getString("recoverform.notes");
-
- var m = doc.URL.match(/[\?&]id=(\d+)/)
- var id = m ? parseInt(m[1]) : -1;
- if (id > -1){
- var row = Lazarus.db.getRow("SELECT * FROM forms WHERE id = ?1", id);
- if (row){
- if (Lazarus.canDecrypt()){
- var formInfo = Lazarus.JSON.decode(Lazarus.decrypt(row["forminfo"]));
-
- Lazarus.$('form-url', doc).innerHTML = formInfo.origURL ? Lazarus.generateLinkFromURL(formInfo.origURL) : '';
- Lazarus.$('form-action', doc).innerHTML = formInfo.action ? Lazarus.generateLinkFromURL(formInfo.action) : '';
-
- var form = Lazarus.buildForm(formInfo, doc);
- form.setAttribute("lazarus-form-id", row["formid"]);
- Lazarus.$('form-box', doc).appendChild(form);
- Lazarus.restoreForm(form, formInfo);
- }
- else {
- //need to explain to user why we cannot fill in the form
- Lazarus.showNotificationBox("password-required");
- }
- }
- else {
- Lazarus.$('form-box', doc).innerHTML = Lazarus.getString("error.form.not.found");
- Lazarus.$('form-box', doc).className = "warning";
- }
- }
- else {
- Lazarus.$('form-box', doc).innerHTML = Lazarus.getString("error.form.not.found");
- Lazarus.$('form-box', doc).className = "warning";
- }
- }
-}
-
-/**
-* return TRUE if the given document is the lazarus Recover Form page.
-*/
-Lazarus.isDocRecoveryForm = function(doc){
- return (doc && doc.URL && doc.URL.indexOf("chrome://lazarus/content/recover-form.html") == 0);
-}
-
-/**
-* generate an HTML link given a url.
-* if url is too long, then truncate url to maxChars
-*/
-Lazarus.generateLinkFromURL = function(url, maxChars){
-
- maxChars = maxChars || 50;
-
- if (/^(file|http|https):/.test(url)){
- var text = url;
- if (text.length > maxChars){
- text = text.substring(0, maxChars -3) +"...";
- }
-
- return '<a href="'+ Lazarus.htmlEncode(url) +'" title="'+ Lazarus.htmlEncode(url) +'">'+ Lazarus.htmlEncode(text) +'</a>';
- }
- else {
- return Lazarus.htmlEncode(url);
- }
-}
-
-/**
-* encode a string for display in an html page
-*/
-Lazarus.htmlEncode = function(str){
- str = str.replace(/&/g, "&amp;");
- str = str.replace(/</g, "&lt;");
- str = str.replace(/>/g, "&gt;");
- str = str.replace(/"/g, "&quot;");
- return str;
-}
-
-/**
-* builds an HTML form from a formInfo object
-*/
-Lazarus.buildForm = function(formInfo, doc){
- var form = doc.createElement("form");
- form.setAttribute("method", formInfo.method || "get");
- form.setAttribute("enctype", formInfo.enctype || "");
- //support for AJAX textareas
- form.isTextarea = formInfo.isTextarea;
-
- for(var name in formInfo.fields){
- for (var i=0; i<formInfo.fields[name].length; i++){
- var fieldInfo = formInfo.fields[name][i];
- var ele = null;
- var eleLabel = '';
- switch(fieldInfo.type){
- case "radio":
- case "checkbox":
- if (formInfo.version && formInfo.version >= 1 && fieldInfo.value && typeof fieldInfo.value.valueAttr != "undefined"){
- ele = doc.createElement("input");
- ele.setAttribute("type", fieldInfo.type);
- ele.setAttribute("value", fieldInfo.value.valueAttr);
- eleLabel = name +"["+ fieldInfo.value.valueAttr +"]";
- }
- break;
-
- case "password":
- case "hidden":
- case "file":
- case "text":
- ele = doc.createElement("input");
- ele.setAttribute("type", fieldInfo.type);
- break;
-
- case "textarea":
- ele = doc.createElement("textarea");
- break;
-
- case "select":
- if (formInfo.version && formInfo.version >= 1 && Lazarus.isArray(fieldInfo.value) && fieldInfo.value.length){
- ele = doc.createElement("select");
-
- for (var i=0; i<fieldInfo.value.length; i++){
- var opt = doc.createElement("option");
- opt.setAttribute("value", fieldInfo.value[i]);
- opt.appendChild(doc.createTextNode(fieldInfo.value[i]));
- ele.appendChild(opt);
- }
- if (fieldInfo.value.length > 1){
- ele.setAttribute("size", fieldInfo.value.length);
- ele.setAttribute("multiple", "true");
- }
- }
- break;
-
- //no saved
- case "submit":
- case "reset":
- case "button":
- case "image":
- break;
-
- case "iframe":
- //ignore iframes for now?
- break;
-
- default:
- Lazarus.error("Unknown element type ["+ fieldInfo.type +"]");
- }
-
- if (ele){
- if (fieldInfo.type == "hidden"){
- form.appendChild(ele);
- }
- else {
- var box = doc.createElement("div");
- box.setAttribute("class", "form-field-box");
-
- var label = doc.createElement("label");
- var text = doc.createTextNode(eleLabel || name);
- label.appendChild(text);
- box.appendChild(label);
-
- ele.setAttribute("name", fieldInfo.name);
- ele.setAttribute("class", "form-field "+ fieldInfo.type);
- box.appendChild(ele);
- form.appendChild(box);
- }
- }
- }
- }
-
- return form;
-}
-
-/**
-* save the last submitted form id for use in auto restore template
-*/
-Lazarus.saveLastSubmittedForm = function(evt){
- var form = Lazarus.findFormFromElement(evt.target);
- if (form){
- Lazarus.lastSubmittedFormId = Lazarus.getFormId(form);
- }
-}
-
-/**
-* call autofill if this is a valid html document.
-*/
-Lazarus.autofillEvent = function(evt){
- if (evt.originalTarget instanceof HTMLDocument){
- Lazarus.autofillDoc(evt.originalTarget);
- }
-}
-
-
-/**
-* convert a string of HTML into human readable text
-*/
-Lazarus.htmlToText = function(html){
-
- //replace headings (</h1>) and paragraph ends with 2 line breaks
- var text = html.replace(/\s*<\/((h\d)|p)\s*>\s*/ig," \n\n");
-
- //replace divs blocks with single line breaks
- text = text.replace(/\s*<(\/div)\b[^>]*>\s*/ig,"\n");
-
- //replace list items with line breaks and dots
- text = text.replace(/\s*<(li)\b[^>]*>\s*/ig,"\n * ");
-
- //replace line breaks
- text = text.replace(/<(br)\b[^>]*>/ig,"\n");
-
- //strip all other tags
- text = text.replace(/<(\/|\w)[^>]*>/g,' ');
-
- //convert html spaces into normal spaces
- text = text.replace(/&nbsp;/g, ' ');
-
- //compress whitespace
- text = text.replace(/[ \t\f\v]+/g, ' ');
-
- //never have more than 2 line breaks in a row.
- text = text.replace(/\n\s*?\n(\s*?\n)*/g, "\n\n");
-
- //and finally trim.
- text = text.replace(/^\s+/, '').replace(/\s+$/, '');
-
- return text;
-}
-
-
-/**
-* return TRUE if forms on the given document should be saved
-*/
-Lazarus.isValidDoc = function(doc){
- return (doc && doc.URL && /^(file|http|https):/.test(doc.URL));
-}
-
-/**
-* autofills forms found in the given document with there respective templates if they exist
-*/
-Lazarus.autofillDoc = function(doc){
-
- if (Lazarus.isValidDoc(doc) && doc.forms && doc.forms.length){
- var rsAutoFillTemplates = Lazarus.db.rs("SELECT id, formid FROM forms WHERE autofill = 1 AND savetype = "+ Lazarus.FORM_TYPE_TEMPLATE +" ORDER BY created DESC");
- if (rsAutoFillTemplates.length > 0){
- var templates = {};
- //convert the template id's to a hash table
- //TODO: there should only ever be one autofill template for a given form
- //raise a warning if this is not the case
- for (var i=0; i<rsAutoFillTemplates.length; i++){
- templates[rsAutoFillTemplates[i]["formid"]] = rsAutoFillTemplates[i]["id"];
- }
-
- for (var i=0; i<doc.forms.length; i++){
- var form = doc.forms[i];
- var formId = Lazarus.getFormId(form);
- //only autofill if the form is empty, and the form hasn't just been submitted.
- if (formId != Lazarus.lastSubmittedFormId && templates[formId] && Lazarus.isFormEmpty(form)){
- //if the user has a password and is not yet logged in, then we cannot autofill the form
- if (Lazarus.canDecrypt()){
- var encryptedFormInfo = Lazarus.db.getStr("SELECT forminfo FROM forms WHERE id = ?1", templates[formId]);
- var formInfo = Lazarus.JSON.decode(Lazarus.decrypt(encryptedFormInfo));
- Lazarus.restoreForm(form, formInfo);
- }
- else {
- //need to explain to user why we cannot autofill the template.
- Lazarus.showNotificationBox("password-required-autofill");
- break;
- }
- }
- }
- }
- }
-
- //if this is the currently visible tab, then clear the lastSubmittedFormId
- if (content.document && doc === content.document){
- Lazarus.lastSubmittedFormId = null;
- }
-}
-
-/**
-* return TRUE if the given form contains no user entered text.
-*/
-Lazarus.isFormEmpty = function(form){
- for (var i=0; i<form.elements.length; i++){
- var ele = form.elements[i];
- switch (Lazarus.getElementType(ele)){
- case "text":
- case "textarea":
- case "file":
- case "password":
- var text = Lazarus.getElementValue(ele);
- if (Lazarus.trim(text)){
- return false;
- }
-
- //ignore other input types
- default:
- }
- }
- return true;
-}
-
-/**
-* initalise any developer specific functionality
-*/
-Lazarus.initDevEnviroment = function(){
-
- if (Lazarus.getExtPref("openErrorConsoleAtStartup", false)){
- //open the javascript console
- toJavaScriptConsole();
- }
-
- if (Lazarus.getExtPref("debugMode") >= 4){
- Lazarus.$('lazarus-statusbar-menuitem-test').hidden = false;
- }
-}
-
-/**
-* handle text within the address bar changing
-*/
-Lazarus.onLocationChange = function(evt){
- //only close the notification if current page was not the result of submitting a form.
- if (!Lazarus.lastSubmittedFormId){
- Lazarus.closeNotificationBox(true);
- }
- Lazarus.refreshIcon();
-}
-
-/**
-* fire the "clear private data" event
-*/
-Lazarus.fireClearPrivateDataIfNoPrompt = function(){
- if (!Lazarus.getPref("privacy.sanitize.promptOnSanitize", true)){
- Lazarus.Event.fire("clear-private-data");
- }
-}
-
-
-/**
-* return the current state of lazarus
-*/
-Lazarus.getState = function(){
- if (!Lazarus.initalized){
- return Lazarus.STATE_UNINITALIZED;
- }
- else if (Lazarus.Crypto.generatingKeys || Lazarus.cleaningDatabase){
- return Lazarus.STATE_GENERATING_KEYS;
- }
- else if (!Lazarus.canEncrypt()){
- return Lazarus.STATE_DISABLED;
- }
- else if (Lazarus.isDisabledByPrivateBrowsing()){
- return Lazarus.STATE_PRIVATE_BROWSING;
- }
- else if (Lazarus.isPageDisabled()){
- return Lazarus.STATE_DISABLED_FOR_DOMAIN;
- }
- else if (!Lazarus.canDecrypt()){
- return Lazarus.STATE_PASSWORD_REQUIRED;
- }
- //all good?
- else {
- return Lazarus.STATE_ENABLED;
- }
-}
-
-/**
-* fix for multiline xul:description elements
-*/
-Lazarus.setDescriptionText = function(ele, text){
- for (var i=ele.childNodes.length-1; i>=0; i--){
- ele.removeChild(ele.childNodes[i]);
- }
- ele.appendChild(ele.ownerDocument.createTextNode(text));
-}
-
-/**
-* updates the statusbar icon
-*/
-Lazarus.refreshIcon = function(){
-
- Lazarus.$("lazarus-statusbarpanel").hidden = !Lazarus.getExtPref("showInStatusbar");
-
- var iconURL = "";
- var tooltipId = "";
-
- switch (Lazarus.getState()){
- case Lazarus.STATE_ENABLED:
- iconURL = "chrome://lazarus/skin/lazarus.png";
- tooltipId = "lazarus-statusbaricon-tooltip-enabled"
- break;
-
- case Lazarus.STATE_GENERATING_KEYS:
- iconURL = 'chrome://lazarus/skin/lazarus-loading.gif';
- tooltipId = 'lazarus-statusbaricon-tooltip-generatingkeys';
- break;
-
- case Lazarus.STATE_PASSWORD_REQUIRED:
- iconURL = "chrome://lazarus/skin/lazarus-login.png";
- tooltipId = "lazarus-statusbaricon-tooltip-passwordrequired";
- break;
-
- case Lazarus.STATE_DISABLED_FOR_DOMAIN:
- iconURL = "chrome://lazarus/skin/lazarus-disabled.png";
- tooltipId = "lazarus-statusbaricon-tooltip-disabledfordomain";
- break;
-
- case Lazarus.STATE_PRIVATE_BROWSING:
- iconURL = "chrome://lazarus/skin/lazarus-disabled.png";
- tooltipId = "lazarus-statusbaricon-tooltip-private-browsing";
- break;
-
- case Lazarus.STATE_UNINITALIZED:
- case Lazarus.STATE_DISABLED:
- default:
- iconURL = "chrome://lazarus/skin/lazarus-disabled.png";
- tooltipId = "lazarus-statusbaricon-tooltip-disabled";
- }
-
- //this appears to screw over firefox, missing images and such, if called during startup?
- //NOTE: firfox must be completely closed for this effect, using "restart" will NOT recreate it.
- //Lazarus.setDescriptionText(Lazarus.$("lazarus-statusbaricon-tooltip-description"), tooltip);
-
- Lazarus.$("lazarus-statusbarpanel-image").setAttribute("src", iconURL);
- Lazarus.$("lazarus-statusbarpanel-image").setAttribute("tooltip", tooltipId);
-}
-
-/**
-* displays the lazarus welcome message
-*/
-Lazarus.showWelcome = function(){
- //dont show the welcome message immediately, need to wait a sec so the
- //browser is open, and we can center the dialog relative to it.
- //~ setTimeout(function(){
- //~ Lazarus.openOptionsDialog("welcome-pane");
- //~ }, 100);
-
- //hmmm, session recovery is happening after this event,
- //which is replacing our tab with the recovered sessions tabs
- setTimeout(function(){
- Lazarus.openLazarusWebsite("oninstall.html?ver="+ Lazarus.getVersionStr());
- }, 3000);
-}
-
-/**
-* opens the lazarus onupdate page for this version of lazarus
-*/
-Lazarus.showUpdatePage = function(){
- //hmmm, session recovery is happening after this event,
- //which is replacing our tab with the recovered sessions tabs
- setTimeout(function(){
- Lazarus.openLazarusWebsite("onupdate.html?ver="+ Lazarus.getVersionStr());
- }, 3000);
-}
-
-
-/**
-* handle when the first browser window is opened.
-*/
-Lazarus.onStartUp = function(){
-
-}
-
-/**
-* onUninstall
-*/
-Lazarus.onUninstall = function(ext){
-
- if (ext.id == Lazarus.guid){
-
- //var msg = '';
- if (Lazarus.getExtPref("uninstall.removeSavedForms", false)){
- //remove database
- //unable to disconnect the database, so the best we can do is empty it.
- Lazarus.emptyDB();
-
- }
- if (Lazarus.getExtPref("uninstall.removeUserSettings", false)){
- //cleanup prefs
- Lazarus.killPref("extensions.lazarus");
- Lazarus.Pref.savePrefFile();
- }
- }
-}
-
-/**
-*
-*/
-Lazarus.onUninstallRequest = function(ext){
- if (ext.id == Lazarus.guid){
- //ask the user if we should remove their preferences/saved forms
- //we need this dialog to appear from the addons dialog (if it exists)
- //~ var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"].getService(Components.interfaces.nsIWindowMediator);
- //~ var win = wm.getMostRecentWindow("Extension:Manager");
-
- //~ //if theres no extension manager window (eg all-in-one-sidebar)
- //~ //use this window to open the dialog
- //~ if (!win){
- //~ win = window;
- //~ }
- //disabling dialog, uninstall process is stuffed up
- //win.openDialog("chrome://lazarus/content/uninstall.xul", "LazarusUninstallOptions", "chrome,dialog,modal,resizable=yes,titlebar=yes");
- }
-}
-
-
-/**
-* return TRUE if the given editor still exists in the browser
-*/
-Lazarus.editorExists = function(info){
- try {
- //KLUDGE:
- //if a page is refreshed then the page remains, even if you then navigate away from it.
- //it appears to still exist, even though the user cannot see it.
- if (Lazarus.isIframe(info.editor) && (!info.editor.contentWindow || !info.editor.contentWindow.document)){
- return false;
- }
- else {
- return (info.editor.ownerDocument.defaultView && (info.url == info.editor.ownerDocument.defaultView.top.location.href));
- }
- }
- catch(e){
- return false;
- }
-}
-
-
-Lazarus.saveEditorInfo = function(info, saveType){
-
-
- if (Lazarus.shouldSaveEditorInfo(info)){
-
- var textHash = Lazarus.md5(info.text);
-
- if (saveType == Lazarus.FORM_TYPE_AUTOSAVE){
- var record = Lazarus.db.getRow("SELECT id, text_hash FROM textdata WHERE domain_hash = ?1 AND savetype = ?2 LIMIT 1", info.domainHash, Lazarus.FORM_TYPE_AUTOSAVE);
- //if form hasn't changed
- if (record && record.text_hash == textHash){
- //do nothing...
- }
- //if it has changed, or doesn't exist yet, save the changes
- else {
- Lazarus.debug("Saving textdata - autosave", info);
- if (record){
- Lazarus.db.exe("DELETE FROM textdata WHERE id = ?1", record.id);
- //and get rid of any fulltext index as well
- Lazarus.db.exe("DELETE FROM textdata_fulltext WHERE docid = ?1", record.id);
- }
- var encText = Lazarus.encrypt(info.text);
- var encSummary = Lazarus.encrypt(info.summary);
-
- var id = Lazarus.db.insert("INSERT INTO textdata (text_encrypted, summary_encrypted, created, domain_hash, url_encrypted, text_hash, text_length, savetype) \
- VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8)",
- encText, encSummary, info.created, info.domainHash, info.urlEncrypted, textHash, info.text.length, Lazarus.FORM_TYPE_AUTOSAVE);
-
- //and update the full text index,
- if (!Lazarus.getPref('extensions.lazarus.disableSearch')){
- //we're going to add domain info into this as well
- var hashedText = Lazarus.hashText(info.text);
- hashedText += ' '+ Lazarus.hashText(info.domain.replace(/\./g, ' '));
- Lazarus.db.exe("INSERT INTO textdata_fulltext (docid, hashed_text) VALUES (?1, ?2)", id, hashedText);
- }
- }
- }
- else {
-
- //if the info object already exists, with exactly the same text, then just update the timestamp
- var id = Lazarus.db.getInt("SELECT id FROM textdata WHERE domain_hash = ?1 AND text_hash = ?2 LIMIT 1", info.domainHash, textHash);
- if (id){
- Lazarus.debug("Updating textdata - perm", info);
- Lazarus.db.exe("UPDATE textdata SET created = ?1, savetype = ?2 WHERE id = ?3", info.created, Lazarus.FORM_TYPE_NORMAL, id);
- }
- //otherwise, insert a new info object
- else {
- Lazarus.debug("Saving textdata - perm", info);
- var encText = Lazarus.encrypt(info.text);
- var encSummary = Lazarus.encrypt(info.summary);
-
- var id = Lazarus.db.insert("INSERT INTO textdata (text_encrypted, summary_encrypted, created, domain_hash, url_encrypted, text_hash, text_length, savetype) \
- VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8)",
- encText, encSummary, info.created, info.domainHash, info.urlEncrypted, textHash, info.text.length, Lazarus.FORM_TYPE_NORMAL);
-
- if (!Lazarus.getPref('extensions.lazarus.disableSearch')){
- var hashedText = Lazarus.hashText(info.text);
- hashedText += ' '+ Lazarus.hashText(info.domain.replace(/\./g, ' '));
- Lazarus.db.exe("INSERT INTO textdata_fulltext (docid, hashed_text) VALUES (?1, ?2)", id, hashedText);
- }
- }
- }
- }
-}
-
-
-/**
-* genereate a random seed for use in the hashing function
-*/
-Lazarus.generateRandomHashSeed = function(){
- var rnd = Math.random().toString() +':'+ Lazarus.timestamp(true).toString();
- return Lazarus.FNV1a(rnd);
-}
-
-
-/**
-* hashes individual words in a bunch of text
-*/
-Lazarus.hashText = function(text){
-
- //we'll need to grab the seed from the database.
- var seed = Lazarus.db.getStr("SELECT value FROM settings WHERE name = 'hash-seed'");
-
- if (!seed){
- seed = Lazarus.generateRandomHashSeed();
- Lazarus.db.exe("INSERT INTO settings (name, value) VALUES ('hash-seed', ?1)", seed);
- //and delete the full text index, because none of the others will work any more
- Lazarus.db.exe("DELETE FROM textdata_fulltext");
- }
-
- //var p = new Profiler("hashedText: "+ text.length);
- var map = {};
- //p.mark("setup");
-
- //remove all non-text characters (strip HTML?)
- text = Lazarus.trim(text.toLowerCase().replace(/[^\s\w\-_]+/g, ' '));
- //p.mark("remove non-text: "+ text.length);
-
- var words = text.split(/\s+/g);
- //p.mark("split into words : "+ words.length);
- //we should also remove useless words (like "the", "and", "as" etc...)
- var len = words.length;
- var hashedWords = [];
- for (var i=0; i<len; i++){
- var word = words[i];
- if (!map[word]){
- map[word] = Lazarus.FNV1a(word, seed);
- }
- hashedWords.push(map[word]);
- }
- //p.mark("hash words");
-
- //hashed text comes out at 70,000 characters for a 56,000 character start.
- //acceptable.
- var hashedText = hashedWords.join(" ");
- //debug(p.stop("join text: "+ hashedText.length));
- return hashedText;
-}
-
-
-/**
-* hash text within a MATCH query whilst keeping SQLite MATCH keywords/characters
-*/
-Lazarus.hashQuery = function(query){
- //phrase searches ('"broccoli cheese"')
- //Excluding terms ('onions -celery')
- //OR queries ('onions OR cheese')
- //Prefix search ('ch*') cannot be used due to hashing of the text strings.
- return query.replace(/\w+/g, function(m){
- if (m.toLowerCase() == "or"){
- return "OR";
- }
- else {
- return Lazarus.hashText(m);
- }
- });
-}
-
-Lazarus.saveAutoSaveText = function(){
- Lazarus.db.exe("UPDATE textdata SET savetype = ?1 WHERE savetype = ?2", Lazarus.FORM_TYPE_NORMAL, Lazarus.FORM_TYPE_AUTOSAVE);
-}
-
-Lazarus.autoSaveEditors = function(){
-
- //NOTE: traversing backwards through the list so we can remove items without it affecting
- //the rest of the list
- var removed = [];
-
- for (var i=Lazarus.editorInfos.length-1; i>=0; i--){
- var info = Lazarus.editorInfos[i];
- //the page may have been submitted, or closed without submitting
- //if the editor is suddenly empty, we should assume it has been submitted (possibly via AJAX)
- if (!Lazarus.editorExists(info) || Lazarus.getEditorInfo(info.editor).isEmpty){
- removed.push(info);
- Lazarus.editorInfos.splice(i, 1);
- }
- }
-
- //and save any that have been removed
- for (var i=0; i<removed.length; i++){
- Lazarus.saveEditorInfo(removed[i]);
- }
-
- //we also want to update the current textbox (if any)
-
- //all others should be saved as "temporary saves"
- for (var i=0; i<Lazarus.editorInfos.length; i++){
- if (Lazarus.editorInfos[i].editor === Lazarus.currentEditor){
- Lazarus.saveEditorInfo(Lazarus.editorInfos[i], Lazarus.FORM_TYPE_AUTOSAVE);
- break;
- }
- }
-
- if (Lazarus.editorInfos.length == 0){
- Lazarus.stopEditorAutoSaveTimer();
- }
-}
-
-
-/**
-* return the previous editosInfo
-*/
-Lazarus.getPreviousEditorInfo = function(editor){
- for (var i=0; i<Lazarus.editorInfos.length; i++){
- if (Lazarus.editorInfos[i].editor === editor){
- return Lazarus.editorInfos[i];
- }
- }
- return null;
-}
-
-
-/**
-* remove an editor info object from our list
-*/
-Lazarus.removeEditorInfo = function(info){
- for (var i=0; i<Lazarus.editorInfos.length; i++){
- if (Lazarus.editorInfos[i].editor === info.editor){
- Lazarus.editorInfos.splice(i, 1);
- return true;
- }
- }
- return false;
-}
-
-
-/**
-* update editor info
-*/
-Lazarus.updateEditorInfo = function(info){
- for (var i=0; i<Lazarus.editorInfos.length; i++){
- if (Lazarus.editorInfos[i].editor === info.editor){
- Lazarus.editorInfos[i] = info;
- return true;
- }
- }
- return false;
-}
-
-
-
-/**
-* save forms if people are typing into them
-*/
-Lazarus.onKeyUp = function(evt){
- //dont save form for every keypress (CPU hog)
- //we'll restart a timer whenever a key is pressed,
- //and save when the timer fires.
- var form = Lazarus.findFormFromElement(evt.target);
-
- if (Lazarus.isPageDisabled()){
- return;
- }
-
- //if the event happened within a form, set a timer to auto save the form
- if (form && form.ownerDocument instanceof HTMLDocument){
- Lazarus.restartAutoSaveTimer(form);
- }
-
- //we'll do the same for textarea's and contentEditable iframes
- var editor = Lazarus.findEditorFromElement(evt.target);
-
- if (editor){
-
- Lazarus.currentEditor = editor;
-
- var info = Lazarus.getEditorInfo(editor);
- var prevInfo = Lazarus.getPreviousEditorInfo(editor);
-
- if (prevInfo){
- //if the textbox is suddenly empty, the form may have been submitted or reset (or all contents removed (ctrl+a + del))
- if (info.isEmpty){
- Lazarus.saveEditorInfo(prevInfo);
- //then remove the editorInfo from the list
- Lazarus.removeEditorInfo(prevInfo);
- }
- //otherwise update the previous editorInfo, and wait for the timer to save it.
- else {
- Lazarus.updateEditorInfo(info);
- }
- }
- //this is the first time the user has typed into this textbox
- //save it, if it's got some text in it
- else if (!info.isEmpty){
- Lazarus.editorInfos.push(info);
- Lazarus.restartEditorAutoSaveTimer();
- }
- else {
- //editor is empty, dont keep it
- }
-
- Lazarus.restartEditorAutoSaveTimer();
- }
-}
-
-
-/**
-* return an editor info object
-*/
-Lazarus.getEditorInfo = function(editor){
- var info = {}
- info.editor = editor;
- info.text = Lazarus.extractText(editor);
- info.isEmpty = Lazarus.isEditorEmpty(editor);
- info.summary = Lazarus.generateSummary(info.text);
- info.created = Lazarus.timestamp();
- info.domain = Lazarus.getDomainFromElement(editor);
- info.domainHash = Lazarus.md5(info.domain);
- info.basedomain = Lazarus.getBaseDomain(info.domain);
- info.url = editor.ownerDocument.defaultView.top.location.href;
- info.urlEncrypted = Lazarus.encrypt(info.url);
- return info;
-}
-
-
-/**
-* return TRUE if the editor doesn't contain any text
-*/
-Lazarus.isEditorEmpty = function(editor){
- var text = Lazarus.extractText(editor);
- var type = editor.nodeName.toLowerCase();
- if (type == "textarea"){
- return text.match(/^\s*$/) ? true : false;
- }
- else if (type == "iframe"){
- return text.replace(/(<(\/|\w)[^>]*>)|(&nbsp;)/g, '').match(/^\s*$/) ? true : false;
- }
- else {
- throw Error("Unknown editor type: "+ type);
- }
-}
-
-/**
-* return the text/html from an editable iframe or textarea
-*/
-Lazarus.extractText = function(ele){
- var text = '';
- if (Lazarus.isTextarea(ele)){
- text = (typeof ele.value == "string") ? ele.value : '';
- }
- else if (Lazarus.isIframe(ele)){
- text = (typeof ele.contentWindow.document.body.innerHTML) ? ele.contentWindow.document.body.innerHTML : '';
- }
- return Lazarus.trim(text);
-}
-
-
-/**
-* generate a safe summary for display within a XUL:menuitem or XUL:tooltip
-*/
-Lazarus.generateSummary = function(text){
- //strip html
- text = Lazarus.htmlToText(text);
- return (text.length > 255) ? (text.substr(0, 252) +"...") : text;
-}
-
-Lazarus.restartEditorAutoSaveTimer = function(){
- Lazarus.stopEditorAutoSaveTimer();
- Lazarus.editorAutoSaveFormTimer = setInterval(Lazarus.autoSaveEditors, Lazarus.getExtPref("autoSaveInterval", 2000));
-}
-Lazarus.stopEditorAutoSaveTimer = function(){
- if (Lazarus.editorAutoSaveFormTimer){
- clearInterval(Lazarus.editorAutoSaveFormTimer);
- }
-}
-
-
-/**
-* start the autosave timer
-*/
-Lazarus.restartAutoSaveTimer = function(form){
- Lazarus.stopAutoSaveTimer();
- //we'll save the form here, so we can retrieve it when the timer fires
- Lazarus.currAutoSaveForm = form;
- Lazarus.autoSaveFormTimer = setTimeout(Lazarus.autoSaveForm, Lazarus.getExtPref("autoSaveInterval", 2000));
-}
-
-/**
-* stops the autosave timer.
-*/
-Lazarus.stopAutoSaveTimer = function(){
- if (Lazarus.autoSaveFormTimer){
- clearTimeout(Lazarus.autoSaveFormTimer);
- }
-}
-
-/**
-* run cleanup for this window
-*/
-Lazarus.cleanup = function(){
- gBrowser.removeEventListener("keyup", Lazarus.onKeyUp, false);
- gBrowser.removeEventListener("submit", Lazarus.onFormSubmit, false);
- gBrowser.removeEventListener("reset", Lazarus.onFormReset, false);
- gBrowser.removeEventListener("change", Lazarus.onFormChange, false);
- Lazarus.$("Tools:Sanitize").removeEventListener("command", Lazarus.fireCLearPrivateDataIfNoDialog, false);
- Lazarus.stopCleanupTimer();
-}
-
-/**
-* handle last browser window shutting down
-*/
-Lazarus.onShutdown = function(){
-
-}
-
-/**
-*
-*/
-Lazarus.onContextMenuHide = function(){
- Lazarus.isContextMenuShowing = false;
-}
-
-
-/**
-* show or hide the menu item depending on what item caused the context menu to appear.
-*/
-Lazarus.onContextMenuShowing = function(evt){
-
- //we need to set a flag to prevent new autosaves whilst the context menu is shown
- Lazarus.isContextMenuShowing = true;
-
- //this event is fired whenever a submenu is shown, as well as when the main context menu it shown
- //bugfix: only re-calculate the popup menu when it's first opened.
- //trying to alter the initial menu when a submenu is opened can cause the browser to hang.
-
- //hmmm this is causing a noticable hang when the form contains a lot (30k) of info
- //as a workaround, we will not calculate any submenu until the submenu is opened.
- var evtTargetId = evt.target.id;
-
- //quick check
- if (evtTargetId != "contentAreaContextMenu" && evtTargetId != "lazarus-restoreform-submenu-menupopup" && evtTargetId != "lazarus-restoretext-submenu-menupopup"){
- return;
- }
-
-
- //did the user click on a form?
- var form = Lazarus.findFormFromElement(gContextMenu.target);
- var editor = Lazarus.findEditorFromElement(gContextMenu.target);
-
- if (evtTargetId == "contentAreaContextMenu"){
-
- //assume we should not show any menuitems
- var showMainMenu = false;
- var showSubMenu = false;
- var showLogin = false;
- var showSaveForm = false;
- var showPageDisabled = false;
- var showPrivateBrowsing = false;
-
- var showRestoreText = false;
- var showRestoreTextDisabled = false;
-
-
- if (!form && !editor){
- //dont show anything
- }
- else if (Lazarus.isDisabledByPrivateBrowsing()){
- showPrivateBrowsing = true;
- }
- else if (Lazarus.isPageDisabled(form.ownerDocument.URL)){
- showPageDisabled = true;
- }
- else if (!Lazarus.canDecrypt()){
- showLogin = true;
- }
- else {
- if (form){
-
- showSaveForm = true;
- var savedForms = Lazarus.getFormInfo(form, "id, formid, created, savetype, forminfohash, formtext, formname");
-
- //just show the one menu item, but dont show it if the form is identical to this one.
- if (savedForms.length == 1){
- showMainMenu = true;
- var info = Lazarus.formInfo(form);
-
- var infoHash = Lazarus.generateHash(info.fields);
-
- if (infoHash == savedForms[0]["forminfohash"]){
- Lazarus.$('lazarus-restoreform-contextmenuitem').setAttribute('src', "chrome://lazarus/skin/lazarus-disable.png");
- Lazarus.$('lazarus-restoreform-contextmenuitem').setAttribute('disabled', "true");
- Lazarus.$('lazarus-restoreform-contextmenuitem').setAttribute('tooltiptext', Lazarus.getString("form.is.equal"));
- }
- else {
- var savedForm = savedForms[0];
- Lazarus.$('lazarus-restoreform-contextmenuitem').setAttribute('src', "chrome://lazarus/skin/lazarus.png");
- Lazarus.$('lazarus-restoreform-contextmenuitem').setAttribute('lazarus-forms-id', savedForm["id"]);
- Lazarus.$('lazarus-restoreform-contextmenuitem').setAttribute('tooltiptext', Lazarus.generateSavedFormTooltip(savedForm));
- Lazarus.$('lazarus-restoreform-contextmenuitem').setAttribute('disabled', "");
- }
- }
- //show submenu
- else if (savedForms.length > 1){
- showSubMenu = true;
- }
- }
-
- if (editor){
- showRestoreTextDisabled = true;
- //do we have any text saved for this domain/basedomain?
- var domain = Lazarus.getDomainFromElement(editor);
- if (domain){
- var domainHash = Lazarus.md5(domain);
- if (Lazarus.db.getInt("SELECT count(id) FROM textdata WHERE domain_hash = ?1 LIMIT 1", domainHash)){
- showRestoreText = true;
- showRestoreTextDisabled = false;
- }
- }
- }
- }
-
- //only show our menu item if over a form.
- Lazarus.$('lazarus-restoretextdisabled-contextmenuitem').hidden = !showRestoreTextDisabled;
- Lazarus.$('lazarus-restoretext-submenu').hidden = !showRestoreText;
- Lazarus.$('lazarus-restoreform-contextmenuitem').hidden = !showMainMenu;
- Lazarus.$('lazarus-restoreform-submenu').hidden = !showSubMenu;
- Lazarus.$('lazarus-enterpassword-contextmenuitem').hidden = !showLogin;
- Lazarus.$('lazarus-domaindisabled-contextmenuitem').hidden = !showPageDisabled;
- Lazarus.$('lazarus-privatebrowsing-contextmenuitem').hidden = !showPrivateBrowsing;
- Lazarus.$('lazarus-saveform-contextmenuitem').hidden = !(showSaveForm && Lazarus.getExtPref("includeExperimental", false));
- }
- else if (evtTargetId == "lazarus-restoreform-submenu-menupopup" && form){
- Lazarus.buildSubMenu(form);
- }
- else if (evtTargetId == "lazarus-restoretext-submenu-menupopup" && editor){
- Lazarus.buildRestoreTextSubMenu(editor);
- }
-}
-
-
-
-Lazarus.getDomainFromElement = function(ele){
- try {
- return ele.ownerDocument.defaultView.top.location.host;
- }
- catch(e){
- return null;
- }
-}
-
-/**
-* builds the list of items that can be restored for this editor element
-*/
-Lazarus.buildRestoreTextSubMenu = function(editor){
- //
- var menu = Lazarus.$("lazarus-restoretext-submenu-menupopup");
- //remove all the current submenu items
- while(menu.lastChild){
- menu.removeChild(menu.lastChild);
- }
-
- var domainHash = Lazarus.md5(Lazarus.getDomainFromElement(editor));
-
- //and build the new ones
- var items = Lazarus.db.rs("SELECT id, text_hash, summary_encrypted, created FROM textdata WHERE domain_hash = ?1 ORDER BY created DESC LIMIT ?2", domainHash, Lazarus.getPref('extensions.lazarus.maxTextItemsInSubmenu', 20));
-
- var text = Lazarus.extractText(editor);
- var textHash = Lazarus.md5(text);
-
- for (var i=0; i<items.length; i++){
- var item = items[i];
- var menuitem = document.createElement("menuitem");
-
- if (Lazarus.getExtPref("showFormTextInSubMenu") && Lazarus.canDecrypt()){
- var summary = Lazarus.decrypt(item["summary_encrypted"]);
- menuitem.setAttribute("label", summary);
- menuitem.setAttribute("tooltiptext", summary);
- }
- else {
- var time = Lazarus.timestamp();
- menuitem.setAttribute("label", Lazarus.getTimeString(time - item["created"]));
- //show the tooltip if possible
- if (Lazarus.canDecrypt()){
- menuitem.setAttribute("tooltiptext", Lazarus.decrypt(item["summary_encrypted"]));
- }
- }
-
- menuitem.setAttribute("lazarus-restoretext-id", item["id"]);
- menuitem.setAttribute("oncommand", "Lazarus.onRestoreTextMenuItem(this)");
-
- //disable the menu item if the form is identical
- if (item["text_hash"] == textHash){
- menuitem.setAttribute('tooltiptext', Lazarus.getString("text.is.equal"));
- menuitem.setAttribute('disabled', "true");
- }
- menu.appendChild(menuitem);
- }
-}
-
-/**
-*
-*/
-Lazarus.getFormRestoredNotificationText = function(charsRestored, msgId){
- //we're trying out a bunch of text at the moment
- var numChars = Lazarus.formatNumber(charsRestored);
- var numForms = Lazarus.formatNumber(Lazarus.db.getInt("SELECT COUNT(*) FROM forms"));
- var numText = Lazarus.formatNumber(Lazarus.db.getInt("SELECT COUNT(*) FROM textdata"));
-
- var msgs = [
- 'Lazarus has just saved you from having to retype '+ numChars +' characters. If you feel this has helped you, then please consider donating to this project so we can make Lazarus even better.',
- 'Lazarus restored '+ numChars +' characters.\nDatabase contains '+ numForms +' Forms and '+ numText +' Text-blocks.',
- 'Lazarus restored '+ numChars +' characters.\nDatabase contains '+ numForms +' Saved Forms and '+ numText +' Textareas.',
- 'Lazarus resurrected '+ numChars +' characters.\nLazarus is securely storing '+ numForms +' Forms and '+ numText +' Text-blocks'
- ];
-
- return msgs[msgId];
-}
-
-
-/**
-*
-*/
-Lazarus.onRestoreTextMenuItem = function(menuitem){
- if (!Lazarus.canDecrypt()){
- Lazarus.debug("Unable to restore form, password required");
- Lazarus.showNotificationBox("password-required");
- return;
- }
-
- var editor = Lazarus.findEditorFromElement(gContextMenu.target);
-
- if (editor){
- var id = parseInt(menuitem.getAttribute("lazarus-restoretext-id"));
-
- Lazarus.debug("Attempting to restore text: "+ id);
-
- var enc_text = Lazarus.db.getStr("SELECT text_encrypted FROM textdata WHERE id = ?1", id);
- if (enc_text){
- var text = Lazarus.decrypt(enc_text);
- if (text){
- Lazarus.setElementValue(editor, text);
- Lazarus.incPref("extensions.lazarus.restoreFormCount");
- if ((text.length > Lazarus.MIN_TEXT_NEEDED_TO_SHOW_NOTIFICATION) && Lazarus.getPref("extensions.lazarus.showDonateNotification") && Lazarus.getPref("extensions.lazarus.restoreFormCount", 0) > 3){
- var msgId = Math.floor(Math.random() * 4);
- Lazarus.showNotificationBox("form-restored", Lazarus.getFormRestoredNotificationText(text.length, msgId), "msgid-"+ msgId);
- }
- }
- else {
- alert(Lazarus.getString("error.form.db.corrupt"));
- }
- }
- else {
- Lazarus.error("Unable to find textdata: "+ id);
- alert(Lazarus.getString("error.form.not.found"));
- }
- }
- else {
- //should never get here
- alert(Lazarus.getString("error.form.object.not.found"));
- }
-}
-
-
-/**
-* generates an md5 hash of a javascript object
-*/
-Lazarus.generateHash = function(obj){
- return Lazarus.md5(Lazarus.JSON.encode(obj));
-}
-
-/**
-* return the current unix timestamp
-*/
-Lazarus.timestamp = function(asFloat){
- var s = new Date().getTime() / 1000;
- return asFloat ? s : Math.floor(s);
-}
-
-/**
-* return text usable by a menuitem (XUL Label)
-*/
-Lazarus.getMenuItemText = function(text){
-
- //strip any html found in the text
- text = Lazarus.trim(Lazarus.cleanText(text));
-
- //labels only handle a single line of text
- text = text.split(/\n/, 2)[0];
- //and we dont want it to be too long
- if (text.length > 48){
- text = text.substr(0, 48) +"...";
- }
- return Lazarus.trim(text);
-}
-
-
-/**
-* ask the user for their Lazarus password
-*/
-Lazarus.showEnterPasswordDialog = function(){
-
- var prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService(Components.interfaces.nsIPromptService);
-
- //keep asking until they hit cancel
- while(true){
- var password = {value: ""};
- var check = {value: false};
- //if a user has a master password set, then allow the lazarus password to be saved in the SSD
- var checkText = Lazarus.isMasterPasswordSet() ? Lazarus.getString('password.dialog.checkbox.label') : null;
- //
- if (prompts.promptPassword(null, Lazarus.getString("password.dialog.title"), Lazarus.getString("password.dialog.label"), password, checkText, check)){
- if (Lazarus.loadPrivateKey(password.value)){
- if (check.value){
- Lazarus.savePassword(password.value);
- }
- return true;
- }
- }
- else {
- break;
- }
- }
-
- return false;
-}
-
-
-Lazarus.savePassword = function(password){
- //remove the existing password first.
- Lazarus.removePassword();
- var nsLoginInfo = new Components.Constructor("@mozilla.org/login-manager/loginInfo;1", Components.interfaces.nsILoginInfo, "init");
- var loginInfo = new nsLoginInfo(Lazarus.LOGIN_HOSTNAME, null, Lazarus.LOGIN_REALM, Lazarus.LOGIN_USERNAME, password, '', '');
- var nsLoginManager = Components.classes["@mozilla.org/login-manager;1"].getService(Components.interfaces.nsILoginManager);
- nsLoginManager.addLogin(loginInfo);
-}
-
-
-Lazarus.removePassword = function(){
-
- // Get Login Manager
- var nsLoginManager = Components.classes["@mozilla.org/login-manager;1"].getService(Components.interfaces.nsILoginManager);
- // Find users for this extension
- var logins = nsLoginManager.findLogins({}, Lazarus.LOGIN_HOSTNAME, null, Lazarus.LOGIN_REALM);
- for (var i = 0; i < logins.length; i++) {
- if (logins[i].username == Lazarus.LOGIN_USERNAME){
- nsLoginManager.removeLogin(logins[i]);
- }
- }
-}
-
-/**
-* load the password from the loginManager
-*/
-Lazarus.loadPassword = function(){
-
- if (Lazarus.isMasterPasswordSet() && !Lazarus.isMasterPasswordRequired()){
- // Get Login Manager
- var nsLoginManager = Components.classes["@mozilla.org/login-manager;1"].getService(Components.interfaces.nsILoginManager);
-
- // Find users for the given parameters
- var logins = nsLoginManager.findLogins({}, Lazarus.LOGIN_HOSTNAME, null, Lazarus.LOGIN_REALM);
-
- // Find user from returned array of nsILoginInfo objects
- for (var i = 0; i < logins.length; i++) {
- if (logins[i].username == Lazarus.LOGIN_USERNAME){
- return logins[i].password;
- }
- }
- }
- //we default to an empty password
- return '';
-}
-
-Lazarus.logout = function(){
- Lazarus.unloadPrivateKey();
- Lazarus.refreshIcon();
-}
-
-/**
-* generate a label for saved form menuitem
-*/
-Lazarus.generateSavedFormLabel = function(savedForm, time){
- var label = '';
-
- //template should ALWAYS use their template name as a label
- if (savedForm["savetype"] == Lazarus.FORM_TYPE_TEMPLATE){
- label = savedForm["formname"];
- }
- //use summary
- else if (Lazarus.getExtPref("showFormTextInSubMenu") && Lazarus.canDecrypt()){
- label = Lazarus.getMenuItemText(Lazarus.decrypt(savedForm["formtext"])) || ("["+ Lazarus.getString("untitled") +"]");
- }
- //use timestamps if we are unable to decrypt the forms
- else {
- time = time || Lazarus.timestamp();
- label = Lazarus.getTimeString(time - savedForm["created"]);
- }
-
- //mark autosaved forms so users can easily tell the difference.
- switch(savedForm["savetype"]){
- case Lazarus.FORM_TYPE_AUTOSAVE:
- case Lazarus.FORM_TYPE_STALE_AUTOSAVE:
- label += " "+ Lazarus.getString("menuitem.label.append.autosave");
- break;
-
- case Lazarus.FORM_TYPE_TEMPLATE:
- label += " "+ Lazarus.getString("menuitem.label.append.template");
- break;
-
- default:
- label += " "+ Lazarus.getString("menuitem.label.append.normal");
- break;
- }
-
- return label;
-}
-
-/**
-* generate a tooltip for saved form menuitem
-*/
-Lazarus.generateSavedFormTooltip = function(savedForm, /**/time){
-
- time = time || Lazarus.timestamp();
-
- var tooltip = '';
-
- //show time sting as tooltip
- if (Lazarus.getExtPref("showFormTextInSubMenu")){
-
- tooltip = Lazarus.getTimeString(time - savedForm["created"]);
- }
- //show date and time of save
- else {
- var date = new Date(savedForm["created"] * 1000);
- tooltip = Lazarus.formatDate(date);
- }
-
- //mark autosaved forms so users can easily tell the difference.
- switch(savedForm["savetype"]){
- case Lazarus.FORM_TYPE_AUTOSAVE:
- case Lazarus.FORM_TYPE_STALE_AUTOSAVE:
- tooltip += " "+ Lazarus.getString("menuitem.tooltip.append.autosave");
- break;
-
- case Lazarus.FORM_TYPE_TEMPLATE:
- tooltip += " "+ Lazarus.getString("menuitem.tooltip.append.template");
- break;
-
- default:
- tooltip += " "+ Lazarus.getString("menuitem.tooltip.append.normal");
- break;
- //do nothing
- }
-
- return tooltip;
-}
-
-/**
-* builds the list of available restore point into the submenu
-*/
-Lazarus.buildSubMenu = function(form){
-
-
- var menu = Lazarus.$("lazarus-restoreform-submenu-menupopup");
- //remove all the current submenu items
- for (var i=menu.childNodes.length-1; i>=0; i--){
- var node = menu.childNodes[i];
- if (node.getAttribute("lazarus-dynamic-submenu")){
- menu.removeChild(node);
- }
- }
-
- var time = Lazarus.timestamp();
- var separator = Lazarus.$("lazarus-submenu-separator");
- //now build the new ones
- var lastSaveType = -1;
- var savedForms = Lazarus.getFormInfo(form, "id, formid, created, savetype, forminfohash, formtext, formname, forminfo");
- var info = Lazarus.formInfo(form);
- var infoHash = Lazarus.generateHash(info.fields);
-
- for (var i=0; i<savedForms.length; i++){
- var savedForm = savedForms[i];
- var menuitem = document.createElement("menuitem");
-
- //generate text for the label
- //menuitems can only handle a single line of text, and we don't want it to be too long
- var label = Lazarus.generateSavedFormLabel(savedForm, time);
- var tooltip = Lazarus.generateSavedFormTooltip(savedForm, time);
-
- menuitem.setAttribute("label", label);
- //menuitem.setAttribute('tooltiptext', tooltip);
- menuitem.setAttribute('oncommand', "Lazarus.onRestoreFormMenuItem(this)");
- menuitem.setAttribute('lazarus-forms-id', savedForm["id"]);
- menuitem.setAttribute('lazarus-dynamic-submenu', "true");
-
- //disable the menu item if the form is identical
- if (savedForm["forminfohash"] == infoHash){
- menuitem.setAttribute('tooltiptext', Lazarus.getString("form.is.equal"));
- menuitem.setAttribute('disabled', "true");
- }
- else {
- menuitem.setAttribute('tooltiptext', tooltip);
- menuitem.setAttribute('disabled', "");
- }
-
- //add separators between templates, normal saves, and autosaves
- if (lastSaveType != -1 && lastSaveType !== savedForm["savetype"] && savedForm["savetype"] != Lazarus.FORM_TYPE_STALE_AUTOSAVE){
- var newSeparator = document.createElement("menuseparator");
- newSeparator.setAttribute('lazarus-dynamic-submenu', "true");
- menu.insertBefore(newSeparator, separator);
- }
- lastSaveType = savedForm["savetype"];
- menu.insertBefore(menuitem, separator);
- }
-}
-
-
-/**
-* return the period (in seconds) that forms should be saved for
-*/
-Lazarus.getExpiryTime = function(){
-
- if (Lazarus.getExtPref("expireSavedForms")){
- return (Lazarus.getExtPref("expireSavedFormsInterval") * Lazarus.getExtPref("expireSavedFormsUnit") * 60);
- }
- else {
- return 0;
- }
-}
-
-/**
-* retrieves a list of details about a form from the database.
-*/
-Lazarus.getFormInfo = function(form, fields){
- var formId = Lazarus.getFormId(form);
-
- var expires = Lazarus.getExpiryTime();
- var cutoffTime = (expires > 0) ? (Lazarus.timestamp() - expires) : 0;
-
- fields = fields || "*";
- //we need to get ALL the templates for this form first
- var forms = [];
- forms = forms.concat(Lazarus.db.rs("SELECT "+ fields +" FROM forms WHERE formid = ?1 AND created >= ?2 AND savetype = "+ Lazarus.FORM_TYPE_TEMPLATE +" ORDER BY savetype DESC, created DESC", formId, cutoffTime));
- //and then the autosaves
- var maxAutoSaves = Lazarus.getExtPref("maxAutosavesPerForm", 3);
- forms = forms.concat(Lazarus.db.rs("SELECT "+ fields +" FROM forms WHERE formid = ?1 AND created >= ?2 AND savetype IN ("+ Lazarus.FORM_TYPE_AUTOSAVE +","+ Lazarus.FORM_TYPE_STALE_AUTOSAVE +") ORDER BY created DESC LIMIT ?3", formId, cutoffTime, maxAutoSaves));
- //and then add normal saved forms
- var maxForms = Lazarus.getExtPref("maxSavesPerForm", 10);
- forms = forms.concat(Lazarus.db.rs("SELECT "+ fields +" FROM forms WHERE formid = ?1 AND created >= ?2 AND savetype = "+ Lazarus.FORM_TYPE_NORMAL +" ORDER BY created DESC LIMIT ?3", formId, cutoffTime, maxForms));
- return forms;
-}
-
-
-/**
-* return a fieldInfo object filled with information about the given field
-*/
-Lazarus.fieldInfo = function(ele){
-
- var getPassword = Lazarus.getExtPref("savePasswordFields");
- var getHidden = Lazarus.getExtPref("saveHiddenFields");
-
- var info = {};
- info.name = ele.getAttribute("name");
- info.type = Lazarus.getElementType(ele);
- info.value = Lazarus.getElementValue(ele);
- if (info.type == "password" && !getPassword){
- info.value = null;
- }
- if (info.type == "hidden" && !getHidden){
- info.value = null;
- }
-
- switch (info.type){
- case "text":
- case "textarea":
- case "file":
- case "password":
- case "iframe":
- if (info.value && Lazarus.trim(info.value)){
- info.text = Lazarus.trim(info.value);
- }
- break;
-
- default:
- }
-
- return info;
-}
-
-/**
-* clean HTML tags and entities from an html string
-*/
-Lazarus.cleanText = function(text){
- return text.replace(/<[^>]*>/g, ' ').replace(/&\w+;?/g, ' ').replace(/ +/g, ' ');
-}
-
-/**
-* return a formInfo object filled with details about a form
-*/
-Lazarus.formInfo = function(form){
-
- var info = {};
- info.version = Lazarus.FORM_INFO_VERSION;
- info.formid = Lazarus.getFormId(form);
- info.action = Lazarus.getUrlPage(form.action || form.ownerDocument.URL);
- info.origURL = form.ownerDocument.URL;
- info.domain = Lazarus.getDomainFromElement(form);
- info.method = (form.method && form.method.toLowerCase()) == "post" ? "post" : "get";
- info.enctype = form.enctype ? form.enctype.toLowerCase() : '';
- info.fields = {};
- info.formtext = [];
- info.textLen = 0;
- for (var i=0; i<form.elements.length; i++){
- var ele = form.elements[i];
- var name = ele.getAttribute("name");
- if (name){
- switch (Lazarus.getElementType(ele)){
- case "text":
- case "textarea":
- case "file":
- case "radio":
- case "checkbox":
- case "select":
- case "password":
- case "hidden":
- var fieldInfo = Lazarus.fieldInfo(ele);
- info.fields[name] = info.fields[name] || [];
- info.fields[name].push(fieldInfo);
-
- if (fieldInfo.text){
- info.formtext.push(fieldInfo.text);
- info.textLen += fieldInfo.text.length;
- }
- break;
-
- default:
- //ignore all other types
- }
- }
- //support for ajax textareas
- else if (form.isTextarea && Lazarus.getElementType(ele) == "textarea"){
- var fieldInfo = Lazarus.fieldInfo(ele);
- info.isTextarea = true;
- info.fields["textarea"] = [fieldInfo];
- if (fieldInfo.text){
- info.formtext.push(fieldInfo.text);
- info.textLen += fieldInfo.text.length;
- }
- }
- //support for ajax textareas
- else if (form.isIframe && Lazarus.getElementType(ele) == "iframe"){
- var fieldInfo = Lazarus.fieldInfo(ele);
- info.isIframe = true;
- info.fields["iframe"] = [fieldInfo];
- if (fieldInfo.text){
- info.formtext.push(fieldInfo.text);
- info.textLen += fieldInfo.text.length;
- }
- }
- }
- //we need to add any WYSIWYG iframes into the form as well
- var iframes = Lazarus.getEditableIframes(form);
- if (iframes.length > 0){
- info.fields[Lazarus.IFRAME_NAME] = [];
- info.isIframe = true; for (var i=0; i<iframes.length; i++){
- var name = Lazarus.IFRAME_NAME;
- var fieldInfo = Lazarus.fieldInfo(iframes[i]);
-
- info.fields[name] = info.fields[name] || [];
- info.fields[name].push(fieldInfo);
-
- if (fieldInfo.text){
- info.formtext.push(fieldInfo.text);
- info.textLen += fieldInfo.text.length;
- }
- }
- }
-
- info.formtext = Lazarus.trim(info.formtext.join("\n\n"));
-
- return info;
-}
-
-
-/**
-* return an array of editable iframes found within the given node
-*/
-Lazarus.getEditableIframes = function(ele){
- var editableIframes = [];
- if (ele && ele.getElementsByTagName){
- var iframes = ele.getElementsByTagName('iframe');
-
- for (var i=0; i<iframes.length; i++){
- if (Lazarus.isEditableDoc(iframes[i].contentWindow.document)){
- editableIframes.push(iframes[i]);
- }
- //better get iframes within the iframes as well
- if (iframes[i].contentWindow.document.body){
- editableIframes = editableIframes.concat(Lazarus.getEditableIframes(iframes[i].contentWindow.document.body));
- }
- }
- }
- return editableIframes;
-}
-
-/**
-* return TRUE if the given document is in edit mode
-*/
-Lazarus.isEditableDoc = function(doc){
- return (doc && (doc.designMode == "on" || (doc.body && doc.body.contentEditable === "true")));
-}
-
-/**
-* return the base domain (wikipedia.org) given a full domain (en.wikipedia.org)
-*/
-Lazarus.getBaseDomain = function(domain){
-
- //if domain is an ip address return that
- var regexIp = /\d+\.\d+\.\d+\.\d+$/
- var m = domain.match(regexIp);
- if (m){return m[0]}
-
- //known top level domains (TLDs) including country specific ones
-
- //http://en.wikipedia.org/wiki/Country_code_top-level_domain
- //all domains *should* either end in a 2 letter tld (google.co.nz, google.com.au) or none (google.com) for american sites
- //that should be preceeded by the generic tld
- //and then the basedomain
- var regex = /[^\.]+\.[^\.]+(\.\w{2})?$/;
- var m = domain.match(regex);
- //if we cant figure it out then return the whole domain
- return m ? m[0] : domain;
-}
-
-
-
-/**
-* restores a form to the given state
-*/
-Lazarus.restoreForm = function(form, formInfo){
-
- //attempt to restore the saved fields for this form
- var restorePassword = Lazarus.getExtPref("savePasswordFields");
- var restoreHidden = Lazarus.getExtPref("saveHiddenFields");
-
- //try and recover as many fields as possible for this form.
- var iRestored = 0;
- var iNamedElements = 0;
- var formFields = {};
- for (var i=0; i<form.elements.length; i++){
- var ele = form.elements[i];
- var name = ele.getAttribute("name");
- var eleType = Lazarus.getElementType(ele);
- var eleValue = Lazarus.getElementValue(ele);
-
- if (name){
- switch (eleType){
- case "text":
- case "textarea":
- case "file":
- case "radio":
- case "checkbox":
- case "select":
- case "password":
- case "hidden":
- //try to restore this element
- iNamedElements++;
- //do we have an match for this element in our saved form
- if (formInfo.fields[name]){
- for (var j=0; j<formInfo.fields[name].length; j++){
- var info = formInfo.fields[name][j];
- if (!info.restored && info.type == eleType){
- switch (eleType){
- case "text":
- case "textarea":
- case "file":
- case "select":
- Lazarus.setElementValue(ele, info.value);
- iRestored++;
- break;
-
- case "radio":
- case "checkbox":
- if (info.value && (eleValue.valueAttr == info.value.valueAttr)){
- Lazarus.setElementValue(ele, info.value.checked);
- iRestored++;
- }
- break;
-
- case "password":
- if (restorePassword){
- Lazarus.setElementValue(ele, info.value);
- }
- iRestored++;
- break;
-
- case "hidden":
- if (restoreHidden){
- Lazarus.setElementValue(ele, info.value);
- }
- iRestored++;
- break;
-
- default:
- //no need to restore
- iRestored++;
- }
- }
- }
- }
- default:
- //ignore other types of elements
- }
- }
- else if (form.isTextarea && Lazarus.isTextarea(ele)){
- var info = formInfo.fields["textarea"][0];
- Lazarus.setElementValue(ele, info.value);
- iRestored++;
- iNamedElements++;
- }
- else if (form.isIframe && ele.tagName == "iframe"){
- var info = formInfo.fields["iframe"][0];
- Lazarus.setElementValue(ele, info.value);
- iRestored++;
- iNamedElements++;
- }
- }
- //try and restore any WYSIWYG editors as well
- var iframes = Lazarus.getEditableIframes(form);
- if (iframes && formInfo.fields[Lazarus.IFRAME_NAME]){
- for (var i=0; i<iframes.length; i++){
- var info = formInfo.fields[Lazarus.IFRAME_NAME][i];
- if (info){
- Lazarus.setElementValue(iframes[i], info.value);
- }
- }
- }
-
-
- //check for errors
- if (iRestored == 0){
- alert(Lazarus.getString("error.restore.none"));
- return false;
- }
- //tell them if we couldn't restore some fields
- else if (iRestored < iNamedElements){
- //only show the partial restore message if the form is not an old style form
- if (formInfo.version && formInfo.version >= 1){
- alert(Lazarus.getString("error.restore.partial"));
- }
- return (iRestored / iNamedElements);
- }
- else {
- return true;
- }
-}
-
-/**
-* handle the onselectmenuitem event
-*/
-Lazarus.onRestoreFormMenuItem = function(menuitem){
-
- if (!Lazarus.canDecrypt()){
- Lazarus.debug("Unable to restore form, password required");
- Lazarus.showNotificationBox("password-required");
- return;
- }
-
- var id = parseInt(menuitem.getAttribute("lazarus-forms-id"));
-
- Lazarus.debug("Attempting to restore form "+ id);
- var form = Lazarus.findFormFromElement(gContextMenu.target, "form");
- if (form){
- var row = Lazarus.db.getRow("SELECT * FROM forms WHERE id = ?1", id);
- if (row){
- var formInfo;
- try {
- formInfo = Lazarus.JSON.decode(Lazarus.decrypt(row["forminfo"]));
- }
- catch(e){
- Lazarus.error(e);
- }
-
- if (formInfo){
- //if we fully restore a form, then show the "donate" popup
- if (Lazarus.restoreForm(form, formInfo) === true){
- Lazarus.incPref("extensions.lazarus.restoreFormCount");
- if ((formInfo.textLen > Lazarus.MIN_TEXT_NEEDED_TO_SHOW_NOTIFICATION) && Lazarus.getPref("extensions.lazarus.showDonateNotification") && Lazarus.getPref("extensions.lazarus.restoreFormCount", 0) > 3){
- var msgId = Math.floor(Math.random() * 4);
- Lazarus.showNotificationBox("form-restored", Lazarus.getFormRestoredNotificationText(formInfo.textLen, msgId), "msgid-"+ msgId);
- }
- }
- }
- else {
- alert(Lazarus.getString("error.form.db.corrupt"));
- }
- }
- else {
- alert(Lazarus.getString("error.form.not.found"));
- }
- }
- else {
- alert(Lazarus.getString("error.form.object.not.found"));
- }
-}
-
-/**
-* return TRUE if form is a form we should save
-*/
-Lazarus.shouldSaveForm = function(form){
- //only save forms on file/http/https sites
- var doc = form.ownerDocument;
- if (doc && doc instanceof HTMLDocument && doc.URL && /^(file|http|https):/.test(doc.URL) && !Lazarus.isPageDisabled(doc.URL) && !Lazarus.isDisabledByPrivateBrowsing()){
- return (Lazarus.isSearchForm(form)) ? Lazarus.getPref("extensions.lazarus.saveSearchForms") : true;
- }
- else {
- return false;
- }
-}
-
-/**
-* return TRUE if we should be saving this info
-*/
-Lazarus.shouldSaveEditorInfo = function(info){
- if (Lazarus.isPageDisabled(info.url)){
- return false;
- }
- else if (Lazarus.isDisabledByPrivateBrowsing()){
- return false;
- }
- else {
- return true;
- }
-}
-
-
-
-Lazarus.disabledDomains = null;
-
-Lazarus.isPageDisabled = function(url){
- if (!url && content.document && content.document.URL){
- url = content.document.URL;
- }
- if (url){
- var domainId = Lazarus.urlToDomainId(url);
- if (domainId){
- var domains = Lazarus.getDisabledDomains();
- return (typeof domains[domainId] !== "undefined") ? domains[domainId] : false;
- }
- }
- return false;
-}
-
-/**
-* return TRUE if lazarus can save forms from this site
-* return FALSE for non-valid sites (eg about:config, chrome://... etc..)
-*/
-Lazarus.isValidSite = function(url){
- //default to the current documents url
- if (!url && content.document && content.document.URL){
- url = content.document.URL;
- }
- return (url && Lazarus.urlToDomainId(url)) ? true : false;
-}
-
-Lazarus.getDisabledDomains = function(){
- var domainlist = Lazarus.getPref('extensions.lazarus.domainBlacklist', '');
-
- if (!Lazarus.disabledDomains || Lazarus.disabledDomains['__origList__'] != domainlist){
- //rebuild the list
- Lazarus.disabledDomains = {
- '__origList__': domainlist
- }
- var domains = domainlist.split(/\s*,\s*/g);
- for (var i=0; i<domains.length; i++){
- Lazarus.disabledDomains[domains[i]] = true;
- }
- }
- return Lazarus.disabledDomains;
-}
-
-Lazarus.saveDisabledDomains = function(domainsTable){
- //convert the table back into an array and save it.
- var domains = [];
- for(var domain in domainsTable){
- if (domainsTable[domain] && /^\w+:/.test(domain)){
- domains.push(domain);
- }
- }
-
- return Lazarus.setPref('extensions.lazarus.domainBlacklist', domains.join(','));
-}
-
-
-Lazarus.enableForCurrentDomain = function(){
- //fetch the current domain, and disable Lazarus
- if (content.document && content.document.URL){
- var domainId = Lazarus.urlToDomainId(content.document.URL);
- //and add to disabled domains list.
-
- var domains = Lazarus.getDisabledDomains();
- if (!domains[domainId]){
- domains[domainId] = true;
- Lazarus.saveDisabledDomains(domains);
- Lazarus.debug('Domain disabled ['+ domainId +']');
- }
- else {
- //should already be disabled!
- Lazarus.warning('Domain is already disabled ['+ domainId +']');
- }
-
- //and refresh the statusbar icon
- Lazarus.refreshIcon();
- }
- else {
- alert(Lazarus.getString("error.no.document"));
- }
-}
-
-
-/**
-* enables or disabled on the current website
-*/
-Lazarus.toggleCurrentDomain = function(enable){
- //fetch the current domain, and disable Lazarus
- if (content.document && content.document.URL){
- var domains = Lazarus.getDisabledDomains();
- var domainId = Lazarus.urlToDomainId(content.document.URL);
-
- if (domainId){
- //add/remove from disabled domains list
- domains[domainId] = enable ? false : true;
- Lazarus.saveDisabledDomains(domains);
- Lazarus.debug('Domain ['+ domainId +'] enabled = '+ enable);
- //and refresh the statusbar icon
- Lazarus.refreshIcon();
- }
- else {
- Lazarus.error("Failed to extract domainId from URL ["+ content.document.URL +"]");
- }
- }
- else {
- alert(Lazarus.getString("error.no.document"));
- }
-}
-
-
-Lazarus.onStatusbarMenuShowing = function(popupmenu){
- var validSite = Lazarus.isValidSite();
- var siteDisabled = Lazarus.isPageDisabled();
- var isPrivate = Lazarus.isDisabledByPrivateBrowsing();
-
- Lazarus.$('lazarus-statusbar-menuitem-toggledomain-separator').hidden = !(validSite && !isPrivate);
- Lazarus.$('lazarus-statusbar-menuitem-enablefordomain').hidden = !(validSite && siteDisabled && !isPrivate);
- Lazarus.$('lazarus-statusbar-menuitem-disablefordomain').hidden = !(validSite && !siteDisabled && !isPrivate);
- Lazarus.$('lazarus-statusbar-menuitem-logout').hidden = !(Lazarus.Crypto.isPasswordEntered);
-}
-
-/**
-* return a website identifier
-* http://google.com is different from https://google.com
-*/
-Lazarus.urlToDomainId = function(url){
- var uri = Lazarus.urlToURI(url);
- return (uri && uri.scheme && uri.host && (/^(http|https|file)$/.test(uri.scheme))) ? (uri.scheme +":"+ ((uri.port > -1 && uri.port != 80) ? uri.port : '') +'//'+ Lazarus.getBaseDomain(uri.host) +'/') : '';
-}
-
-
-/**
-* return TRUE if form appears to be a search form
-*/
-Lazarus.isSearchForm = function(form){
- //search forms are forms that have exactly one textbox, and may contain a number of other non-text fields
- var MAX_TEXT_FIELDS = 1;
- var MAX_NON_TEXT_FIELDS = 5;
-
- var iTextFields = 0;
- var iNonTextFields = 0;
-
- for (var i=0; i<form.elements.length; i++){
- var ele = form.elements[i];
- switch(Lazarus.getElementType(ele)){
- case "text":
- iTextFields++;
- break;
-
- case "radio":
- case "checkbox":
- case "select":
- iNonTextFields++;
- break;
-
- case "file":
- case "password":
- case "textarea":
- return false;
-
- case "hidden":
- case "submit":
- case "reset":
- case "button":
- case "image":
- default:
- //ignore all other types
- }
- }
- //NOTE: we MUST have a single text field
- return (iTextFields == MAX_TEXT_FIELDS && iNonTextFields <= MAX_NON_TEXT_FIELDS);
-}
-
-
-/**
-* check a submit event, and saves form details if the event is from a valid form
-*/
-Lazarus.onFormSubmit = function(evt){
- var form = Lazarus.findFormFromElement(evt.target);
- //is the form on an html document?
- if (form && form.ownerDocument instanceof HTMLDocument){
- Lazarus.stopAutoSaveTimer();
- Lazarus.saveForm(form, Lazarus.FORM_TYPE_NORMAL);
- }
-}
-
-/**
-* return "post" of "get" depending on the given forms method
-*/
-Lazarus.getFormMethod = function(form){
- var method = form.getAttribute("method");
- return (method && method.toLowerCase() == "post") ? "post" : "get";
-}
-
-/**
-* autosave a form if we change anything about it.
-*/
-Lazarus.onFormChange = function(evt){
- var form = Lazarus.findFormFromElement(evt.target);
-
- if (form && form.ownerDocument instanceof HTMLDocument){
- //I think we should chuck a timer in here, because we might end up saving a lot.
- Lazarus.restartAutoSaveTimer(form);
- }
-}
-
-/**
-* check a reset event, and saves form details if the event is from a valid form
-*/
-Lazarus.onFormReset = function(evt){
- var form = Lazarus.findFormFromElement(evt.target);
- //is the form on an html document?
- if (form && form.ownerDocument instanceof HTMLDocument){
- Lazarus.stopAutoSaveTimer();
- Lazarus.saveForm(form, Lazarus.FORM_TYPE_AUTOSAVE);
- }
-}
-
-/**
-* create a searchable index of hashed words
-*/
-Lazarus.indexFormText = function(id, text, url){
- //and update the full text index,
- if (!Lazarus.getPref('extensions.lazarus.disableSearch')){
- //we're going to add domain info into this as well so a user can search for domain fragments too
- var hashedText = Lazarus.hashText(text);
-
- //extract the domain from the url
- var domain = Lazarus.urlToURI(url).host;
-
- hashedText += ' '+ Lazarus.hashText(domain.replace(/\./g, ' '));
-
- Lazarus.db.exe("DELETE FROM forms_fulltext WHERE docid = ?1", id);
- Lazarus.db.exe("INSERT INTO forms_fulltext (docid, hashed_text) VALUES (?1, ?2)", id, hashedText);
- }
-}
-
-/**
-* save all the named elements in a form to the permanent store
-*/
-Lazarus.saveForm = function(form, formType, templateName, autofill){
-
- autofill = autofill ? 1 : 0;
-
- if (Lazarus.shouldSaveForm(form)){
-
- templateName = templateName || '';
-
- var info = Lazarus.formInfo(form);
-
- //dont save empty forms?
- //No. what about forms with lots of radio buttons (eg multichoice surveys)
- var infoJSON = Lazarus.JSON.encode(info)
- var encryptedInfo = Lazarus.encrypt(infoJSON);
- var encryptedText = Lazarus.encrypt(Lazarus.getMenuItemText(info.formtext));
- var encryptedFormURL = Lazarus.encrypt(Lazarus.getFormURL(form));
-
- var infoHash = Lazarus.generateHash(info.fields);
-
- //each form type needs to be saved differently
- switch(formType){
- case Lazarus.FORM_TYPE_AUTOSAVE:
- case Lazarus.FORM_TYPE_STALE_AUTOSAVE:
-
- var savedForm = Lazarus.db.getRow("SELECT id, savetype FROM forms WHERE formid = ?1 AND forminfohash = ?2 AND savetype IN ("+ Lazarus.FORM_TYPE_AUTOSAVE +","+ Lazarus.FORM_TYPE_STALE_AUTOSAVE +") LIMIT 1", info.formid, infoHash);
-
- //add or update the current autosave
- if (!savedForm){
- var lastAutoSaveId = Lazarus.db.getInt("SELECT id FROM forms WHERE formid = ?1 AND savetype = "+ Lazarus.FORM_TYPE_AUTOSAVE +" ORDER BY created DESC LIMIT 1", info.formid);
- var lastAutoSave = (lastAutoSaveId && Lazarus.lastAutoSaveForm && Lazarus.lastAutoSaveForm["formid"] == info.formid) ? Lazarus.lastAutoSaveForm : null;
- var newId = 0;
-
- if (lastAutoSave && Lazarus.shouldCreateNewAutosave(info, lastAutoSave)){
- //if the saved form is smaller than the last saved form by a substantial amount,
- //create a new restore point.
- Lazarus.debug("Creating additional autosave point "+ info.formid);
- Lazarus.db.exe("INSERT INTO forms (formid, created, forminfo, formtext, forminfohash, formurl, text_length, savetype) \
- VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, "+ Lazarus.FORM_TYPE_AUTOSAVE +")", info.formid, Lazarus.timestamp(), encryptedInfo, encryptedText, infoHash, encryptedFormURL, info.textLen);
- newId = Lazarus.db.getInt("SELECT MAX(id) FROM forms");
- }
- else if (lastAutoSave){
- Lazarus.debug("Updating autosave form "+ info.formid);
- Lazarus.db.exe("UPDATE forms SET created = ?1, forminfo = ?2, formtext = ?3, forminfohash = ?4, formurl = ?5, text_length = ?6 \
- WHERE id = ?7", Lazarus.timestamp(), encryptedInfo, encryptedText, infoHash, encryptedFormURL, info.textLen, lastAutoSaveId);
- newId = lastAutoSaveId;
- }
- else {
- Lazarus.debug("Creating new autosave form "+ info.formid);
- Lazarus.db.exe("INSERT INTO forms (formid, created, forminfo, formtext, forminfohash, formurl, text_length, savetype) \
- VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, "+ Lazarus.FORM_TYPE_AUTOSAVE +")", info.formid, Lazarus.timestamp(), encryptedInfo, encryptedText, infoHash, encryptedFormURL, info.textLen);
- newId = Lazarus.db.getInt("SELECT MAX(id) FROM forms");
- }
-
- //update the full text search as well
- Lazarus.indexFormText(newId, info.formtext, info.origURL);
-
- //and save this forminfo as the last autosave point
- Lazarus.lastAutoSaveForm = info;
- }
- else {
- Lazarus.debug("No need to autosave form, form already exists: "+ info.formid);
- }
-
- break;
-
- case Lazarus.FORM_TYPE_NORMAL:
- //delete all autosaves
- Lazarus.removeForms(Lazarus.db.getColumn("SELECT id FROM forms WHERE formid = ?1 AND savetype IN ("+ Lazarus.FORM_TYPE_AUTOSAVE +","+ Lazarus.FORM_TYPE_STALE_AUTOSAVE +")", info.formid));
-
- //if this form already exists, delete it
- Lazarus.removeForms(Lazarus.db.getColumn("SELECT id FROM forms WHERE formid = ?1 AND forminfohash = ?2 AND savetype = "+ Lazarus.FORM_TYPE_NORMAL, info.formid, infoHash));
-
- //and save this form
- Lazarus.db.exe("INSERT INTO forms (formid, created, forminfo, formtext, forminfohash, formname, formurl, text_length, savetype, autofill) \
- VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, 0)",
- info.formid, Lazarus.timestamp(), encryptedInfo, encryptedText, infoHash, templateName, encryptedFormURL, info.textLen, formType);
- Lazarus.debug("form saved ["+ info.formid +"]");
-
- //update the full text search as well
- var newId = Lazarus.db.getInt("SELECT MAX(id) FROM forms");
- Lazarus.indexFormText(newId, info.formtext, info.origURL);
- break;
-
- case Lazarus.FORM_TYPE_TEMPLATE:
- //if another template with the same name exists, delete it
- Lazarus.removeForms(Lazarus.db.getColumn("SELECT id FROM forms WHERE formname = ?1 AND savetype = "+ Lazarus.FORM_TYPE_TEMPLATE, templateName));
-
- //likewise we are not allowed to have more then one autofill for the same form.
- if (autofill){
- Lazarus.db.exe("UPDATE forms SET autofill = 0 WHERE formid = ?1", info.formid);
- }
-
- //and save this form
- Lazarus.db.exe("INSERT INTO forms (formid, created, forminfo, formtext, forminfohash, formname, formurl, text_length, savetype, autofill) \
- VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10)",
- info.formid, Lazarus.timestamp(), encryptedInfo, encryptedText, infoHash, templateName, encryptedFormURL, info.textLen, formType, autofill);
-
- var newId = Lazarus.db.getInt("SELECT MAX(id) FROM forms");
- Lazarus.indexFormText(newId, info.formtext, info.origURL);
- Lazarus.debug("template saved ["+ info.formid +"]");
- break;
-
- default:
- Lazarus.error(Error("Unknown form type ["+ row["formtype"] +"]"));
-
- }
- Lazarus.startCleanupTimer();
- }
- else {
- Lazarus.debug("Form not saved: invalid form");
- }
-}
-
-
-/**
-* remove forms from the database
-*/
-Lazarus.removeForms = function(ids){
- Lazarus.debug("removing forms", ids);
- if (!ids || (Lazarus.isArray(ids) && ids.length === 0)){
- return;
- }
-
- if (!Lazarus.isArray(ids)){
- ids = [ids];
- }
- //make sure the ids are safe.
- for(var i=0; i<ids.length; i++){
- ids[i] = parseInt(ids[i]);
- }
- Lazarus.db.exe("DELETE FROM forms WHERE id IN ("+ ids.join(",") +")");
- Lazarus.db.exe("DELETE FROM forms_fulltext WHERE docid IN ("+ ids.join(",") +")");
-
- Lazarus.debug(ids.length +" forms removed");
-}
-
-
-/**
-* return the URL of the page this form is currently on, but leave any query info
-*/
-Lazarus.getFormURL = function(form){
- //we'll strip any anchor tags from the URL
- return form.ownerDocument.URL.replace(/#.*/, '');
-}
-
-/**
-* return an integer representing how different one form is from another
-* 0 being identical
-* 100 being 100 characters/values are different
-*/
-Lazarus.shouldCreateNewAutosave = function(newForm, oldForm){
-
- //number of characters to ignore when calculating if the form has changed substantially
- var TEXT_DIFFERENCE = 32; //
-
- if (oldForm.formtext.length > (TEXT_DIFFERENCE * 2)){
- var str = oldForm.formtext.substr(0, oldForm.formtext.length - TEXT_DIFFERENCE);
- //if new form is a continuation of old form (ie the first (X - TEXT_DIFFERENCE) characters are still the same),
- //then overwrite current autosave,
- //otherwise create a new autosave.
- return (newForm.formtext.indexOf(str) == -1);
- }
- //form contains little text, overwrite the current autosave
- else {
- return false;
- }
-}
-
-/**
-* automatically save the form the user is working on.
-*/
-Lazarus.autoSaveForm = function(){
- //does the form still exist?
- if (Lazarus.currAutoSaveForm && !Lazarus.isContextMenuShowing){
- Lazarus.saveForm(Lazarus.currAutoSaveForm, Lazarus.FORM_TYPE_AUTOSAVE);
- }
-}
-
-/**
-* start the cleanup timer
-*/
-Lazarus.startCleanupTimer = function(){
-
- Lazarus.stopCleanupTimer();
-
- if (Lazarus.getExpiryTime()){
- Lazarus.cleanupSavedFormsTimer = setInterval(Lazarus.cleanupSavedForms, 1000 * 60);
- }
-}
-
-/**
-* stop the cleanup timer
-*/
-Lazarus.stopCleanupTimer = function(){
- if (Lazarus.cleanupSavedFormsTimer){
- clearInterval(Lazarus.cleanupSavedFormsTimer);
- }
-}
-
-/**
-* remove old forms from the database
-*/
-Lazarus.cleanupSavedForms = function(){
-
- //dont cleanup any forms if a user might be trying to retore them
- if (Lazarus.isContextMenuShowing){return}
-
- var expires = Lazarus.getExpiryTime();
-
- if (expires > 0){
- //add a couple of minutes to the expiry time, so we don't accidentally
- //remove a form whilst we are current restoring it.
- var cutoffTime = Lazarus.timestamp() - (expires + 120);
- var ids = Lazarus.db.getColumn("SELECT id FROM forms WHERE created < ?1 AND savetype != "+ Lazarus.FORM_TYPE_TEMPLATE, cutoffTime);
- Lazarus.removeForms(ids);
-
- var ids = Lazarus.db.getColumn("SELECT id FROM textdata WHERE created < ?1", cutoffTime);
- if (ids.length > 0){
- Lazarus.db.exe("DELETE FROM textdata WHERE id IN ("+ ids.join(",") +")");
- Lazarus.db.exe("DELETE FROM textdata_fulltext WHERE docid IN ("+ ids.join(",") +")");
- }
- }
- else {
- Lazarus.stopCleanupTimer();
- }
-}
-
-/**
-* return an identifier for a url
-*/
-Lazarus.getUrlPage = function(url){
- var uri = Lazarus.urlToURI(url);
- if (uri){
- return uri.scheme +"://"+ uri.hostPort + uri.path.replace(/[\?#].*$/, '');
- }
- //for testing on file systems
- else if ((Lazarus.getExtPref("debugMode") >= 3) && form.action.match(/^file:\/\//i)){
- return "file://just/testing";
- }
- else {
- return null;
- }
-}
-
-/**
-* return the user editable fields within a form.
-*/
-Lazarus.getEditableFields = function(form){
- var fields = [];
- var saveHidden = Lazarus.getExtPref("saveHiddenFields");
- var savePassword = Lazarus.getExtPref("savePasswordFields");
-
- for (var i=0; i<form.elements.length; i++){
- var ele = form.elements[i];
- //ignore fields with no name (they dont get submitted to the server)
- if (ele.getAttribute("name")){
- switch(Lazarus.getElementType(ele)){
- case "text":
- case "textarea":
- case "file":
- case "radio":
- case "checkbox":
- case "select":
- fields.push(ele);
- break;
-
- case "password":
- if (savePassword){
- fields.push(ele);
- }
- break;
-
- case "hidden":
- if (saveHidden){
- fields.push(ele);
- }
- break;
-
- //ignore buttons
- case "submit":
- case "reset":
- case "button":
- case "image":
- //and unknown elements
- default:
- //unknown element type
- break;
- }
- }
- }
- return fields;
-}
-
-
-/**
-* return TRUE if element is a textarea
-*/
-Lazarus.isTextarea = function(ele){
- return (ele && ele.nodeName && ele.nodeName.toLowerCase() == "textarea");
-}
-
-
-/**
-* return TRUE if element is an iframe
-*/
-Lazarus.isIframe = function(ele){
- return (ele && ele.nodeName && ele.nodeName.toLowerCase() == "iframe");
-}
-
-/**
-* generate a formid for this form
-*/
-Lazarus.getFormId = function(form){
-
- //if this form is from the Lazarus Form Recovery page, then use the id specified in the form
- if (Lazarus.isDocRecoveryForm(form.ownerDocument)){
- return form.getAttribute("lazarus-form-id");
- }
-
-
- //forms with no "action" attribute default to sending data to the current page
- var action = form.action || form.ownerDocument.URL;
- var uri = Lazarus.urlToURI(action);
-
- var formId = (uri && uri.host) ? Lazarus.getBaseDomain(uri.host) : '';
- //debugging (on local file system)
- if (!formId && (Lazarus.getExtPref("debugMode") >= 3) && action.match(/^file:\/\//i)){
- formId = "file://just/testing";
- }
-
- //and point to the same place
- if (formId){
-
- //support for ajax textareas
- if (form.isTextarea){
- formId += "<textarea>";
- }
- //and iframes not contained within forms
- else if (form.isIframe){
- formId += "<iframe>";
- }
- //#7: Not saving trac "comment" forms
- //sometimes forms will add additional hidden fields
-
- //if the form has a name, formId , or class we'll add that as well.
- //no not class. If a form has an error the classname might be changed to highlight
- //the error to the user
-
- //we will generate an formId from the editable fields name property
- //only fields with a name property are submitted.
- else if (form.name || form.id){
- formId += form.name ? ("@"+ form.name) : "";
- //KLUDGE: gmails email form changes the id of the form every time you start a new email
- formId += form.id && (form.ownerDocument.domain.indexOf("google") == -1) ? ("#"+ form.id) : "";
- }
- //fall back to using an identifier generated form the elements within the page
- else {
- var names = [];
- for (var i=0; i<form.elements.length; i++){
- var ele = form.elements[i];
- var name = ele.getAttribute("name");
- if (name){
- switch(Lazarus.getElementType(ele)){
- case "text":
- case "textarea":
- case "file":
- case "radio":
- case "checkbox":
- case "select":
- names.push(name.toLowerCase());
- }
- }
- }
-
- //sort and remove duplicate names
- names.sort();
- names = Lazarus.arrayUnique(names);
-
- formId += "["+ names.join(",") +"]";
- }
-
- //#48: including the domain within the formId constitutes a privacy risk.
- formId = Lazarus.md5(formId);
- return formId;
- }
- else {
- Lazarus.warning("Lazarus: Unable to convert url to uri ["+ action +"]");
- return '';
- }
-}
-
-/**
-* return a new array containing members of the given array with no duplicates
-*/
-Lazarus.arrayUnique = function(arr){
- var newArr = [];
- for (var i=0; i<arr.length; i++){
- if (!Lazarus.inArray(arr[i], newArr)){
- newArr.push(arr[i]);
- }
- }
- return newArr;
-}
-
-/**
-* return a user friendly string stating the elapsed time in seconds, minutes, hours or days
-*/
-Lazarus.getTimeString = function(sec){
-
- if (sec < 1){sec = 1}
-
- var units = {
- "day" : 60 * 60 * 24,
- "hour" : 60 * 60,
- "minute": 60,
- "second": 1
- }
-
- for(var unit in units){
- if (sec >= units[unit]){
- var numUnits = Math.floor(sec / units[unit]);
- if (numUnits == 1){
- return Lazarus.getString("elapsed."+ unit);
- }
- else {
- return Lazarus.getString("elapsed."+ unit +"s", numUnits);
- }
- }
- }
- //should never get here
- return Lazarus.getString("elapsed.second");
-}
-
-/**
-* returns an elements value
-*/
-Lazarus.getElementValue = function(ele){
- switch(Lazarus.getElementType(ele)){
- //text fields
- case "text":
- case "password":
- case "textarea":
- case "file":
- case "hidden":
- return ele.value;
-
- case "radio":
- case "checkbox":
- return {
- "valueAttr": ele.value,
- "checked": ele.checked
- }
-
- //buttons
- case "submit":
- case "reset":
- case "button":
- case "image":
- return ele.value;
-
- case "select":
- //select boxes have the option to allow multiple selections
- var selected = [];
- if (ele.options){
- for (var i=0; i<ele.options.length; i++){
- if (ele.options[i].selected){
- selected.push(ele.options[i].value);
- }
- }
- }
- return selected;
-
- case "iframe":
- var doc = ele.contentWindow.document;
- return (doc && doc.body && doc.body.innerHTML) ? doc.body.innerHTML : '';
-
- default:
- //unknown element type
- return null;
- }
-}
-
-/**
-* returns an elements value
-*/
-Lazarus.setElementValue = function(ele, value){
- switch(Lazarus.getElementType(ele)){
- //text fields
- case "text":
- case "password":
- case "textarea":
- case "file":
- case "hidden":
- ele.value = value;
- break;
-
- case "radio":
- case "checkbox":
- ele.checked = value;
- break;
-
- //buttons
- case "submit":
- case "reset":
- case "button":
- case "image":
- ele.value = value;
- break;
-
- case "select":
- //select boxes have the option to allow multiple selections
- var selected = [];
- if (ele.options){
- //bugfix: RT: 101284
- //inArray is taking too long for large (10,000+) select boxes, so we'll convert the values array into
- //a hash table instead
- //hmmm, the problem is not actually in the inArray function
- //but rather the line
- //ele.options[i].selected = table[ele.options[i].value] ? true : false;
- // it appears that a lot goes on behind the scenes when a selectbox option
- //is set, even if the value doesn't change.
- var table = Lazarus.arrayToHashTable(value);
- for (var i=0; i<ele.options.length; i++){
- var selectOption = table[ele.options[i].value] ? true : false;
- if (ele.options[i].selected != selectOption){
- ele.options[i].selected = selectOption;
- }
- }
- }
- break;
-
- case "iframe":
- var doc = ele.contentWindow.document;
- if (doc && doc.body){
- doc.body.innerHTML = value;
- }
- break;
-
- default:
- //unknown element type
- break;
- }
-}
-
-
-/**
-* return a string explaining the type of a form element
-* differentiates between different input types.
-*/
-Lazarus.getElementType = function(ele){
- if (ele.nodeName.toLowerCase() == "input"){
- return ele.type.toLowerCase();
- }
- else {
- return ele.nodeName.toLowerCase();
- }
-}
-
-/**
-* return a fake form object
-*/
-Lazarus.createFakeForm = function(ele, type){
- return {
- ownerDocument: ele.ownerDocument,
- elements: [ele],
- action: Lazarus.urlToDomainId(ele.ownerDocument.URL) || '',
- isTextarea: (type == "textarea"),
- isIframe: (type == "iframe"),
- isFakeForm: true
- };
-}
-
-Lazarus.getParentIframe = function(ele){
- var win = ele.ownerDocument.defaultView.frameElement;
- var win = doc && doc.defaultView;
- return win.frameElement;
-}
-
-
-/**
-* return the first content editable iframe or textarea from a given element
-*/
-Lazarus.findEditorFromElement = function(ele){
-
- while(ele){
- if (Lazarus.isTextarea(ele)){
- return ele;
- }
- else if (Lazarus.isEditableDoc(ele.ownerDocument) && ele.ownerDocument.defaultView.frameElement){
- return ele.ownerDocument.defaultView.frameElement;
- }
- else {
- ele = ele.parentNode;
- }
- }
-}
-
-/**
-* finds a parent form from this element
-*/
-Lazarus.findFormFromElement = function(ele){
-
- var iframe = false;
-
- while(ele){
- if (ele.nodeName && ele.nodeName.toLowerCase() == "form"){
- return ele;
- }
- else if (ele.form && ele.form.nodeName.toLowerCase() == "form"){
- return ele.form;
- }
- //add support for AJAX textareas that are not contained within a form.
- else if (Lazarus.isTextarea(ele)){
- //we're going to build a fake form here, that contains the , so the rest of the code can handle
- return Lazarus.createFakeForm(ele, "textarea");
- }
- else if (Lazarus.isEditableDoc(ele.ownerDocument)){
- iframe = ele.ownerDocument.defaultView.frameElement;
- //move to parent iframe
- //Hmmm. Problem exists when the editable iframe is contained within another iframe (eg FCKEditor)
- //we'll need to iterate up through all the frames. But we also need to check if this frame contains the form element
- ele = iframe;
- }
- else if (ele.parentNode && ele.parentNode.tagName){
- ele = ele.parentNode;
- }
- //an iframe has been detected, but no form was found in this iframe
- //so move up to the containing frame (if any)
- else if (iframe){
- ele = ele.ownerDocument.defaultView.frameElement;
- }
- else {
- return null;
- }
- }
-
- if (iframe){
- //we have an editable iframe that is NOT contained within a form!
- //probably some type of AJAX form
- //we'll need to build a fake form and the iframe in there
- return Lazarus.createFakeForm(iframe, "iframe");
- }
-
- return null;
-}
-/**
-* finds the first node of type nodeName from ele up the dom tree
-*/
-Lazarus.findParent = function(ele, nodeName){
- nodeName = nodeName.toLowerCase();
- while(ele){
- if (ele.nodeName && ele.nodeName.toLowerCase() == nodeName){
- return ele;
- }
- else {
- ele = ele.parentNode;
- }
- }
- return null;
-}
-
-/**
-*
-*/
-Lazarus.onStatusbarImageClick = function(evt){
-
- var state = Lazarus.getState()
-
- if (state == Lazarus.STATE_DISABLED){
- evt.preventDefault();
- Lazarus.openGenerateKeysDialog();
- if (Lazarus.reloadKeys()){
- Lazarus.enable();
- }
- return false;
- }
-
- //only on left click
- if (evt.which == 1){
- switch (state){
- case Lazarus.STATE_ENABLED:
- Lazarus.openStatusbarMenu(evt);
- return;
-
- case Lazarus.STATE_PASSWORD_REQUIRED:
- Lazarus.showEnterPasswordDialog();
- return
-
- case Lazarus.STATE_PRIVATE_BROWSING:
- alert(Lazarus.getString('private.browsing.mode'));
- return;
-
- case Lazarus.STATE_GENERATING_KEYS:
- return;
-
- case Lazarus.STATE_DISABLED_FOR_DOMAIN:
- alert(Lazarus.getString('status.disabledfordomain'))
- return;
-
- case Lazarus.STATE_UNINITALIZED:
- default:
- Lazarus.error("Not initalized");
- return
- }
- }
-}
-
-
-/**
-* show the statusbar menu
-*/
-Lazarus.openStatusbarMenu = function(evt){
- Lazarus.$('lazarus-statusbar-menupopup').openPopup(Lazarus.$('lazarus-statusbarpanel'), 'before_end', 0, 0, true);
-}
-
-/**
-* open the options dialog
-*/
-Lazarus.openOptionsDialog = function(optionsPane){
- optionsPane = optionsPane || null;
-
- var features = "chrome,titlebar,toolbar,centerscreen,modal";
- features += Lazarus.getPref("browser.preferences.animateFadeIn", false) ? "" : ",resizable";
-
- window.open("chrome://lazarus/content/options.xul", "LazarusOptions", features, optionsPane);
-}
-
-/**
-* open the about dialog
-*/
-Lazarus.openAboutDialog = function(){
- window.open("chrome://lazarus/content/about.xul", "LazarusAbout", "chrome,titlebar,toolbar,centerscreen,modal,resizable");
-}
-
-/**
-* open the about dialog
-*/
-Lazarus.openLazarusWebsite = function(page){
- page = page || '';
- Lazarus.openURL(Lazarus.website + page, true, true);
-}
-
-/**
-* open a URL in the current browser
-*/
-Lazarus.openURL = function(url, newTab, selectTab){
- var browser = document.getElementById('content');
-
- if (newTab){
- var tab = browser.addTab(url);
- if (tab && selectTab){
- browser.selectedTab = tab;
- }
- }
- else {
- content.location = url;
- }
-}
-
-
-/**
-* returns a localized string
-*/
-Lazarus.getString = function(strId){
- try {
- var strbundle = Lazarus.$("lazarus-strings");
-
- if (arguments.length == 1){
- return strbundle.getString(strId);
- }
- else {
- var replacements = [];
- //NOTE: first argument is the strId
- for (var i=1; i<arguments.length; i++){
- replacements.push(arguments[i])
- }
- return strbundle.getFormattedString(strId, replacements);
- }
- }
- catch(e){
- Lazarus.error(e, "failed to getString ["+ strId +"]");
- return '';
- }
-}
-
-
-Lazarus.checkDatabase = function(db){
- //build the database tables
- try {
- //forms
- db.exe('CREATE TABLE IF NOT EXISTS forms (\
- id INTEGER PRIMARY KEY, formid TEXT, \
- created INT, \
- formname TEXT, \
- forminfo TEXT, \
- formtext TEXT, \
- savetype INT, \
- forminfohash TEXT, \
- formurl TEXT, \
- text_length INT, \
- autofill INT);');
- db.exe('CREATE INDEX IF NOT EXISTS index_forms_created ON forms (created DESC)');
- db.exe('CREATE INDEX IF NOT EXISTS index_forms_formid ON forms (formid ASC)');
-
- //settings
- db.exe('CREATE TABLE IF NOT EXISTS settings (name TEXT PRIMARY KEY, value TEXT)');
-
- //texdata
- db.exe('CREATE TABLE IF NOT EXISTS textdata (\
- id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, \
- text_encrypted TEXT, \
- text_hash TEXT, \
- text_length INT, \
- summary_encrypted TEXT, \
- created INTEGER DEFAULT \'0\' NOT NULL, \
- domain_hash TEXT, \
- url_encrypted TEXT, \
- savetype INTEGER \
- )');
-
- Lazarus.debug("DB: Creating indexes");
-
- db.exe('CREATE INDEX IF NOT EXISTS index_textdata_domain ON textdata (domain_hash ASC)');
- db.exe('CREATE INDEX IF NOT EXISTS index_textdata_created ON textdata (created DESC)');
-
- Lazarus.debug("DB: Creating Full Text indexes");
-
- //textdata full text index
- if (!db.tableExists('textdata_fulltext')){
- db.exe('CREATE VIRTUAL TABLE textdata_fulltext USING fts3(hashed_text)');
- }
-
- //forms: full text index
- if (!db.tableExists('forms_fulltext')){
- db.exe('CREATE VIRTUAL TABLE forms_fulltext USING fts3(hashed_text)');
- }
-
- Lazarus.debug("DB: Testing read/write");
-
- //test read and write
- var now = (new Date()).getTime();
- db.exe("DELETE FROM settings WHERE name = 'last-accessed'");
- db.exe("INSERT INTO settings (name, value) VALUES ('last-accessed', ?1)", now);
- var lastAccessed = db.getInt("SELECT value FROM settings WHERE name = 'last-accessed'");
- var success = (lastAccessed === now);
- Lazarus.debug("DB: read/write success? "+ success);
- return success;
- }
- catch(e){
- Lazarus.error(e);
- return false;
- }
-}
-
-/**
-* initalizes the database
-*/
-Lazarus.initDB = function(){
- //create / connect to the database
- //we might have already connected in an update script.
- if (!Lazarus.Global.db){
-
- if (Lazarus.getPref("extensions.lazarus.deleteDatabase", false)){
- Lazarus.killPref("extensions.lazarus.deleteDatabase", false);
- Lazarus.killDB();
- }
-
- if (Lazarus.getPref("extensions.lazarus.restoreDatabase", false)){
- Lazarus.killPref("extensions.lazarus.restoreDatabase");
- if (Lazarus.file.exists("%profile%/lazarus-backup.sqlite")){
- Lazarus.file.move("%profile%/lazarus-backup.sqlite", "%profile%/lazarus.sqlite", true);
- }
- else {
- Lazarus.error("Unable to restore database: backup not found");
- }
- }
-
- //if a backup exists, and the original database is missing, then try and use the backup database
- if (Lazarus.file.exists("%profile%/lazarus-backup.sqlite") && !Lazarus.file.exists("%profile%/lazarus.sqlite")){
- Lazarus.file.move("%profile%/lazarus-backup.sqlite", "%profile%/lazarus.sqlite");
- }
- else if (Lazarus.getPref("extensions.lazarus.restoreFromBackup", false) && Lazarus.file.exists("%profile%/lazarus-backup.sqlite")){
- Lazarus.file.move("%profile%/lazarus-backup.sqlite", "%profile%/lazarus.sqlite");
- }
-
- var db = new Lazarus.SQLite("%profile%/lazarus.sqlite", false);
-
- if (!Lazarus.checkDatabase(db)){
- //save the corrupted database file
- Lazarus.warning("Database is corrupted, saving corrupt database");
- var d = Lazarus.formatDate(new Date(), true);
- Lazarus.file.kill("%profile%/lazarus-"+ d +"-corrupted.sqlite");
- Lazarus.file.move("%profile%/lazarus.sqlite", "%profile%/lazarus-"+ d +"-corrupted.sqlite");
- db = null;
- }
-
- //use the backup database if it exists.
- if (!db && Lazarus.file.exists("%profile%/lazarus-backup.sqlite")){
- Lazarus.warning("Restoring previous backup database");
- Lazarus.file.move("%profile%/lazarus-backup.sqlite", "%profile%/lazarus.sqlite");
- db = new Lazarus.SQLite("%profile%/lazarus.sqlite", false);
- if (!Lazarus.checkDatabase(db)){
- //delete the broken backup file
- Lazarus.file.kill("%profile%/lazarus.sqlite");
- db = null;
- }
- }
-
- if (!db){
- //delete any existing database, and build a new one from scratch
- Lazarus.file.kill("%profile%/lazarus.sqlite");
- db = new Lazarus.SQLite("%profile%/lazarus.sqlite", false);
- if (!Lazarus.checkDatabase(db)){
- //oh, so screwed
- Lazarus.error("Unable to create the Lazarus database");
- db = null;
- }
- }
-
- if (db){
- //ok we should now have a valid and checked database
- //make a backup of it.
- //remove the old backup (if it exists)
- if (Lazarus.getPref("extensions.lazarus.backupDatabase")){
- Lazarus.debug("Backing up database");
- Lazarus.file.copy("%profile%/lazarus.sqlite", "%profile%/lazarus-backup.sqlite", true);
- }
- }
-
- Lazarus.Global.db = db;
- }
-
- Lazarus.db = Lazarus.Global.db;
- return Lazarus.db ? true : false;
-}
-
-
-Lazarus.cleanDB = function(callback){
- //takes ages to clean the database
- Lazarus.debug("Cleaning database");
- Lazarus.cleaningDatabase = true;
- Lazarus.refreshIcon();
- Lazarus.backgroundTask(function(){
- Lazarus.db.exe("VACUUM");
- }, function(){
- Lazarus.cleaningDatabase = false;
- Lazarus.refreshIcon();
- if (callback){
- callback();
- }
- });
-}
-
-/**
-* convert autosaved forms to semi-permanent save points
-*/
-Lazarus.saveAutoSavedForms = function(){
-
- //convert autosaved forms to semi-permanent points
- var rs = Lazarus.db.rs("SELECT id, formid FROM forms WHERE savetype = "+ Lazarus.FORM_TYPE_AUTOSAVE +" ORDER BY formid, created DESC");
- var lastFormId = '';
- var lastFormCnt = 0;
- var MAX_AUTOSAVES_TO_KEEP = 2;
- for (var i=0; i<rs.length; i++){
- var savedForm = rs[i];
- if (lastFormId != savedForm["formid"]){
- lastFormId = savedForm["formid"];
- lastFormCnt = 1;
- }
- else {
- lastFormCnt++;
- }
-
- if (lastFormCnt <= MAX_AUTOSAVES_TO_KEEP){
- Lazarus.db.exe('UPDATE forms SET savetype = '+ Lazarus.FORM_TYPE_STALE_AUTOSAVE +' WHERE id = ?1', savedForm["id"]);
- }
- else {
- //excess saved form, remove it
- Lazarus.removeForms(savedForm["id"]);
- }
- }
-}
-
-/**
-* removes old/excess forms from the database
-*/
-Lazarus.removeOldForms = function(){
- var rs = Lazarus.db.rs("SELECT count(*) as cnt, formid FROM forms WHERE savetype = "+ Lazarus.FORM_TYPE_NORMAL +" GROUP BY formid");
- var maxForms = Lazarus.getExtPref("maxSavesPerForm", 10);
- for (var i=0; i<rs.length; i++){
- var save = rs[i];
- if (save["cnt"] > maxForms){
- Lazarus.debug("Removing excess forms "+ save["formid"]);
- var ids = Lazarus.db.getColumn("SELECT id FROM forms WHERE formid = ?1 AND savetype = "+ Lazarus.FORM_TYPE_NORMAL +" ORDER BY created DESC LIMIT -1 OFFSET ?2", save["formid"], maxForms);
- if (ids.length){
- //and remove
- Lazarus.debug("cleaning up forms "+ ids.join(","));
- Lazarus.removeForms(ids);
- }
- }
- }
-}
-
-/**
-* empties all the tables in the database
-* except those specified.
-*/
-Lazarus.emptyDB = function(ignoreFormTypes){
- //always remove text data
- Lazarus.db.exe('DELETE FROM textdata');
- Lazarus.db.exe('DELETE FROM textdata_fulltext');
-
- if (typeof ignoreFormTypes == "undefined"){
- Lazarus.db.exe('DELETE FROM forms');
- Lazarus.db.exe('DELETE FROM forms_fulltext');
- }
- else {
- var ids = Lazarus.db.getColumn('SELECT id FROM forms WHERE savetype NOT IN ('+ ignoreFormTypes +')');
- Lazarus.removeForms(ids);
- }
-}
-
-/**
-* completely remove the database
-*/
-Lazarus.killDB = function(){
- Lazarus.file.kill("%profile%/lazarus.sqlite");
- Lazarus.file.kill("%profile%/lazarus-backup.sqlite");
-}
-
-/**
-* run any update functions
-*/
-Lazarus.runUpdates = function(prevVersion){
- for(var key in Lazarus.updates){
- if (Lazarus.versionCompare(key, prevVersion) == 1){
- Lazarus.debug("running update "+ key);
- try {
- Lazarus.updates[key](prevVersion);
- }catch(e){
- Lazarus.error(e);
- }
- }
- }
-}
-
-/**
-* fire a "clear-private-data" event if the user has asked to clear private data on shutdown with no prompt
-*/
-Lazarus.fireClearPrivateDataOnShutdown = function(){
- if (Lazarus.getPref("privacy.sanitize.sanitizeOnShutdown", false) && !Lazarus.getPref("privacy.sanitize.promptOnSanitize", true)){
- Lazarus.Event.fire("clear-private-data");
- }
-}
-
-/**
-* clear private data if all the preferences say so
-*/
-Lazarus.onClearPrivateData = function(action){
- if (Lazarus.getExtPref("privacy.item.saved.forms")){
- Lazarus.emptyDB(Lazarus.FORM_TYPE_TEMPLATE);
- Lazarus.debug("ClearPrivateData: removing all forms");
- }
-}
-
-/**
-* return TRUE if lazarus requires a password before data can be decrypted
-*/
-Lazarus.isPasswordSet = function(){
- //we test this by attempting to decrypt the private key with a blank password
- var encb64Key = Lazarus.db.getStr("SELECT value FROM settings WHERE name = 'private-key'");
- //we need to unencrypt the private key
- return Lazarus.Crypto.AESDecrypt(encb64Key, "") ? false : true;
-}
-
-/*
-* encrypts a string
-*/
-Lazarus.encrypt = function(str){
- return Lazarus.Crypto.encrypt(str);
-}
-
-/*
-* encrypts a string
-*/
-Lazarus.decrypt = function(str){
- return Lazarus.Crypto.decrypt(str);
-}
-
-
-/*
-* encrypts a string
-*/
-Lazarus.encrypt2 = function(str){
- //hmmm interesting, the encrypted string is not always the same.
- //a certain amount of decryption information must be kept within the encrypted string
- //so we cannot compare encrypted string against each other to test if they are the same
- //all encrypted string must be DECRYPTED before comparison.
-
- //Unable to decrypt extended characters (eg \u8888)!
- //IMPORTANT: extended characters are not correctly encoded/decoded in the bsao function used by the encryptor, so (as of 2008-07-24)
- //we'll be encoding all strings before encrypting them, and then decoding afterwards.
- //by adding a 4 character header ("uri:") we can tell which type of string we have (encodeURIComponent).
-
- Lazarus.decoderRing = Lazarus.decoderRing || Components.classes["@mozilla.org/security/sdr;1"].getService(Components.interfaces.nsISecretDecoderRing);
- var encStr = encodeURIComponent(str);
- return "uri:"+ Lazarus.decoderRing.encryptString(encStr);
-}
-
-/**
-* decrypt a string
-*/
-Lazarus.decrypt2 = function(str){
- //IMPORTANT: extended characters (eg \u8888) are not correctly encoded/decoded, so (as of 2008-07-24)
- //we'll be encoding all strings before encrypting them, and then decoding afterwards.
- //by inspecting the 4 character header we can tell which type of string we have.
- Lazarus.decoderRing = Lazarus.decoderRing || Components.classes["@mozilla.org/security/sdr;1"].getService(Components.interfaces.nsISecretDecoderRing);
- if (str.indexOf("uri:") == 0){
- str = str.substr(4);
- var strEnc = Lazarus.decoderRing.decryptString(str);
- return decodeURIComponent(strEnc);
- }
- else {
- return Lazarus.decoderRing.decryptString(str);
- }
-}
-
-/**
-* calulate md5 hash of a string
-* ref: http://developer.mozilla.org/en/docs/nsICryptoHash#Computing_the_Hash_of_a_String
-*/
-Lazarus.md5 = function(str){
-
- var nsICryptoHash = Components.classes['@mozilla.org/security/hash;1'].createInstance(Components.interfaces.nsICryptoHash);
-
- var converter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
- converter.charset = "UTF-8";
- // result is an out parameter,
- // result.value will contain the array length
- var result = {};
- // data is an array of bytes
- var data = converter.convertToByteArray(str, result);
-
- nsICryptoHash.init(Components.interfaces.nsICryptoHash.MD5);
- nsICryptoHash.update(data, data.length);
- var hash = nsICryptoHash.finish(false);
-
- // Unpack the binary data bin2hex style
- var ascii = [];
- var len = hash.length;
- for (var i = 0; i < len; ++i) {
- var c = hash.charCodeAt(i);
- var ones = c % 16;
- var tens = c >> 4;
- ascii.push(String.fromCharCode(tens + (tens > 9 ? 87 : 48)) + String.fromCharCode(ones + (ones > 9 ? 87 : 48)));
- }
- return ascii.join('');
-}
-
-
-/**
-* return TRUE if master password is set
-*/
-Lazarus.isMasterPasswordSet = function(){
- var secmodDB = Components.classes["@mozilla.org/security/pkcs11moduledb;1"].getService(Components.interfaces.nsIPKCS11ModuleDB);
- var slot = secmodDB.findSlotByName("");
- return (slot && (slot.status == Components.interfaces.nsIPKCS11Slot.SLOT_NOT_LOGGED_IN || slot.status == Components.interfaces.nsIPKCS11Slot.SLOT_LOGGED_IN));
-}
-
-/**
-* return TRUE if a user has set the firefox master password and has not yet logged in.
-*/
-Lazarus.isMasterPasswordRequired = function(){
- var secmodDB = Components.classes["@mozilla.org/security/pkcs11moduledb;1"].getService(Components.interfaces.nsIPKCS11ModuleDB);
- var slot = secmodDB.findSlotByName("");
- return (slot && slot.status == Components.interfaces.nsIPKCS11Slot.SLOT_NOT_LOGGED_IN);
-}
-
-/**
-*
-*/
-Lazarus.enterMasterPassword = function(){
-
- //encrypting a string should open the enter master password dialog
- try {
- var decoderRing = Components.classes["@mozilla.org/security/sdr;1"].getService(Components.interfaces.nsISecretDecoderRing);
- decoderRing.encryptString("dummy");
- return true;
- }
- catch(e){
- return false;
- }
-}
-
-
-Lazarus.openGenerateKeysDialog = function(){
- window.open("chrome://lazarus/content/generate-keys.xul", "LazarusGenerateKeys", "chrome,dialog,modal,resizable,centerscreen");
-}
-
-/**
-* dictionary of notification to display in the popup.
-*/
-Lazarus.notifications = {};
-Lazarus.notifications["password-required"] = {
- "buttons" : [
- {
- "label-string": "notification.password.required.button1.label",
- "accessKey-string": "notification.password.required.button1.accesskey",
- "callback": function(notif, label){
- Lazarus.showEnterPasswordDialog();
- Lazarus.refreshIcon();
- }
- }
- ],
- "text-string" : "notification.password.required.text",
- "iconUrl" : "chrome://lazarus/skin/lazarus-error.png"
-}
-
-Lazarus.notifications["password-required-autofill"] = {
- "buttons" : [
- {
- "label-string": "notification.password.required.autofill.button1.label",
- "accessKey-string": "notification.password.required.autofill.button1.accesskey",
- "callback": function(notif, label){
- Lazarus.showEnterPasswordDialog();
- Lazarus.refreshIcon();
- Lazarus.autofillDoc(content.document);
- }
- }
- ],
- "text-string" : "notification.password.required.autofill.text",
- "iconUrl" : "chrome://lazarus/skin/lazarus-error.png"
-}
-
-Lazarus.notifications["form-restored"] = {
- "buttons" : [
- {
- "label-string": "notification.form.restored.button1.label",
- "accessKey-string": "notification.form.restored.button1.accesskey",
- "callback": function(notif, label){
-
- var data = Lazarus.$('lazarus-notification').getAttribute('lazarus-data');
- var page = 'donate.html';
- page += (data) ? ('?'+ data) : '';
- Lazarus.openLazarusWebsite(page);
- }
- }
- ],
- "text-string" : "notification.form.restored.text",
- "iconUrl" : "chrome://lazarus/skin/lazarus.png"
-}
-
-/**
-* displays the lazarus notification box
-*/
-Lazarus.showNotificationBox = function(id, text, data){
- var notif = Lazarus.notifications[id];
-
- if (Lazarus.$('lazarus-notification').currentNotification && Lazarus.$('lazarus-notification').currentNotificationId == id){
- //do nothing, notification box is already shown
- }
- else if (notif){
- //translate text, and buttons
- if (text){
- notif["text"] = text;
- }
- else if (!notif["text"] && notif["text-string"]){
- notif["text"] = Lazarus.getString(notif["text-string"]);
- }
-
- for (var i=0; i<notif.buttons.length; i++){
- var button = notif.buttons[i];
- if (!button["label"] && button["label-string"]){
- button["label"] = Lazarus.getString(button["label-string"]);
- }
- if (!button["accessKey"] && button["accessKey-string"]){
- button["accessKey"] = Lazarus.getString(button["accessKey-string"]);
- }
- }
-
- var notificationBox = Lazarus.$('lazarus-notification');
- notificationBox.setAttribute('lazarus-data', data || '');
- notificationBox.currentNotificationId = id;
- notificationBox.appendNotification(notif["text"], id, notif["iconUrl"], notificationBox.PRIORITY_INFO_LOW, notif["buttons"]);
- }
- else {
- Lazarus.error(Error("Lazarus: invalid notification id ["+ id +"]"));
- }
-}
-
-/**
-* closes the notification box
-*/
-Lazarus.closeNotificationBox = function(immediate){
- Lazarus.$('lazarus-notification').removeAllNotifications(immediate);
-}
-
-/**
-* returns a list of the templates found in the database
-*/
-Lazarus.getTemplateNames = function(){
- return Lazarus.db.getColumn("SELECT formname FROM forms WHERE savetype = "+ Lazarus.FORM_TYPE_TEMPLATE +" ORDER BY formname");
-}
-
-/**
-* handle user clicking on the "Save form as template..." menuitem
-*/
-Lazarus.onSaveFormMenuItem = function(){
- //find the current form
- var form = Lazarus.findFormFromElement(gContextMenu.target, "form");
-
- //and show the save as template dialog
- if (form){
- var info = Lazarus.formInfo(form, Lazarus.FORM_TYPE_NORMAL);
- var args = {};
- args.templateName = '';
- //add the names of the current templates within the database
- args.templateNames = Lazarus.getTemplateNames();
- //suggest using the default name for this form
- args.defaultName = Lazarus.getMenuItemText(info.formtext) || ("["+ Lazarus.getString("untitled") +"]");
- //WYSIWYG and TEXTAREAs cannot be autofilled
- args.isTextarea = form.isTextarea;
- args.isIframe = form.isIframe;
-
- //IMPORTANT: must use open dialog here otherwise the arguments are not passed.
- window.openDialog("chrome://lazarus/content/template-save.xul", "LazarusTemplateSave", "chrome,modal,resizable", args);
- if (args.templateName){
- Lazarus.saveForm(form, Lazarus.FORM_TYPE_TEMPLATE, args.templateName, args.autofill);
- }
- }
- //or throw an error
- else {
- alert(Lazarus.getString("error.form.object.not.found"));
- Lazarus.error(Error("Unable to find form in the document"));
- }
-}
-
-/**
-* compare two version numbers (eg 2.0.0.1beta3, 2.0.0rc1)
-* return 1 if version1 > version2
-* return 0 if version1 == version2
-* return -1 if version1 < version2
-*/
-Lazarus.versionCompare = function(version1, version2){
-
- function getValueOfVersionSegment(seg){
-
- if (typeof seg === "undefined"){
- return 0;
- }
- else if (/^\d+$/.test(seg)){
- return parseInt(seg);
- }
- else {
- switch(seg){
- case "rc": return -1;
- case "beta": return -2;
- case "alpha": return -3;
- case "dev": return -4;
- default:
- throw Error("Lazarus.versionCompare: Unknown version fragment ["+ seg +"]");
- }
- }
- }
-
- //verify version strings
- var regexVerify = /^[\d\.(dev|alpha|beta|rc)]+$/i;
-
- if (!regexVerify.test(version1)){
- Lazarus.error("Lazarus.versionCompare: Invalid version string ["+ version1 +"]");
- version1 = "0";
- }
- else if (!regexVerify.test(version2)){
- Lazarus.error("Lazarus.versionCompare: Invalid version string ["+ version2 +"]");
- version2 = "0";
- }
-
- //split each version into sections
- var ver1 = version1.toLowerCase().replace(/(\w)(\d)/g, "$1.$2").replace(/(\d)(\w)/g, "$1.$2").split(/[\.\b]/g);
- var ver2 = version2.toLowerCase().replace(/(\w)(\d)/g, "$1.$2").replace(/(\d)(\w)/g, "$1.$2").split(/[\.\b]/g);
-
- //compare each section until a non match occurs
- var maxLen = Math.max(ver1.length, ver2.length);
- for (var i=0; i<maxLen; i++){
- //convert the version segment into a numeric value
- var seg1 = (typeof ver1[i] === "undefined") ? 0 : getValueOfVersionSegment(ver1[i]);
- var seg2 = (typeof ver2[i] === "undefined") ? 0 : getValueOfVersionSegment(ver2[i]);
-
- if (seg1 > seg2){
- return 1;
- }
- else if (seg1 < seg2){
- return -1;
- }
- }
- //all parts are equal
- return 0;
-}
-
-
-/**
-* return the path to this extension install directory
-* gives correct path even if extension is not installed in a users profile directory.
-*/
-Lazarus.getExtensionDir = function(extId){
- // the extension's id from install.rdf
- extId = extId || Lazarus.guid;
- var em = Components.classes["@mozilla.org/extensions/manager;1"].getService(Components.interfaces.nsIExtensionManager);
- return em.getInstallLocation(extId).getItemFile(extId, "install.rdf").parent.path;
-}
-
-/**
-* check the website to see if there is a new update available
-*/
-Lazarus.checkForUpdates = function(){
- //never check more than once a day
- if (Lazarus.getExtPref("lastUpdateCheck") + (24 * 60 * 60) < Lazarus.timestamp()){
- Lazarus.setExtPref("lastUpdateCheck", Lazarus.timestamp());
-
- // create browser
- var browser = document.createElement("browser");
- browser.collapsed = true;
- //browser.style.height = "0px";
- document.documentElement.appendChild(browser);
-
- // set restrictions as needed
- browser.webNavigation.allowAuth = false;
- browser.webNavigation.allowImages = true;
- browser.webNavigation.allowJavascript = true; // so the google analytic code works
- browser.webNavigation.allowMetaRedirects = false;
- browser.webNavigation.allowPlugins = false;
- browser.webNavigation.allowSubframes = false;
-
- // listen for load
- browser.addEventListener("DOMContentReady", function(evt){
- // the document of the HTML in the DOM
- var doc = evt.originalTarget;
- //check URL (could be about:blank)
- if (doc && doc.URL != "about:blank"){
- var ele = doc.getElementById('latest-stable');
- if (ele && ele.innerHTML){
- Lazarus.setExtPref("lastestStableVersion", ele.innerHTML);
- }
- var ele = doc.getElementById('latest-beta');
- if (ele && ele.innerHTML){
- Lazarus.setExtPref("lastestBetaVersion", ele.innerHTML);
- }
- // remove browser element when done
- //mouse pointer has loading symbol unless we do this?
- browser.contentDocument.location = "about:blank";
- browser.parentNode.removeChild(browser);
-
- Lazarus.updateVersionIcons();
- }
- }, true);
-
- // load update check
- browser.contentDocument.location.href = "http://lazarus.interclue.com/version-check.php";
-
- //check again tomorrow
- setTimeout(Lazarus.checkForUpdates, 24 * 60 * 60 * 1000);
- }
- else {
- //didn't check, so check again in 10 minutes
- setTimeout(Lazarus.checkForUpdates, 10 * 60 * 1000);
- }
-}
-
-/**
-* displays the "new beta" or "new stable" icons is a newer version is available.
-*/
-Lazarus.updateVersionIcons = function(){
- var stable = Lazarus.getExtPref("lastestStableVersion", "");
- var beta = Lazarus.getExtPref("lastestBetaVersion", "");
- var thisVersion = Lazarus.getVersionStr();
- if (beta && Lazarus.getExtPref("checkForUpdatesBeta") && Lazarus.versionCompare(thisVersion, beta) == -1){
- //show the new beta icon
- Lazarus.$("lazarus-update-beta-statusbar-image").hidden = false;
- }
- else if (stable && Lazarus.getExtPref("checkForUpdates") && Lazarus.versionCompare(thisVersion, stable) == -1){
- //show the new stable version icon
- Lazarus.$("lazarus-update-stable-statusbar-image").hidden = false;
- }
-}
-
-/**
-* attempts to download the latest versin of Lazarus
-*/
-Lazarus.getUpdate = function(version){
- var urls = {
- "stable": "http://lazarus.interclue.com/downloads/lazarus.xpi",
- "beta" : "http://lazarus.interclue.com/downloads/lazarus-beta.xpi"
- }
-
- var url = urls[version] ? urls[version] : urls["stable"];
- Lazarus.getBrowser().content.location = url;
-}
-
-/**
-* return TRUE if the user is in private Browsing mode (Fx 3.1+)
-*/
-Lazarus.isPrivateBrowsing = function(){
-
- try {
- return Components.classes["@mozilla.org/privatebrowsing;1"] && Components.classes["@mozilla.org/privatebrowsing;1"].getService(Components.interfaces.nsIPrivateBrowsingService).privateBrowsingEnabled;
- }
- catch(e){
- return false;
- }
-}
-
-/**
-* return TRUE if Lazarus is currently disabled because the user is in private browsing mode
-*/
-Lazarus.isDisabledByPrivateBrowsing = function(){
- return (Lazarus.isPrivateBrowsing() && !Lazarus.getPref("extensions.lazarus.enableInPrivateBrowsingMode"));
-}
-
-/**
-* return an FNV1a hash of the given string
-*/
-Lazarus.FNV1a = function(str, seed){
-
- //hash = offset_basis
- var hash = seed ? parseInt(seed, 16) : 2166136261;
-
- //only calculate the length once
- var len = str.length;
-
- //for each octet_of_data to be hashed
- for (var i=0; i<len; i++){
-
- hash ^= str.charCodeAt(i);
-
- //hash = hash * FNV_prime (apparently this bitshifting does the same thing)
- hash += ((hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24));
- }
-
- return Math.abs(Number(hash & 0x00000000ffffffff)).toString(16);
-}
-
-
-Lazarus.openTextManager = function(){
-
- //if not logged in close window
- if (!Lazarus.canDecrypt()){
- //try loggin in immediately
- Lazarus.showEnterPasswordDialog();
- }
-
- //if they still can't login do nothing
- if (Lazarus.canDecrypt()){
- window.open("chrome://lazarus/content/text-manager.xul", "", "chrome,centerscreen,resizable");
- }
-}
-
-/**
-*
-**/
-Lazarus.refreshMenuIcons = function(){
-
- var items = {
- 'lazarus-enterpassword-contextmenuitem': 'chrome://lazarus/skin/lazarus-login.png',
- 'lazarus-restoretext-submenu': 'chrome://lazarus/skin/lazarus.png',
- 'lazarus-restoretextdisabled-contextmenuitem': 'chrome://lazarus/skin/lazarus-disable.png',
- 'lazarus-restoreform-contextmenuitem': 'chrome://lazarus/skin/lazarus.png',
- 'lazarus-restoreform-submenu': 'chrome://lazarus/skin/lazarus.png',
- 'lazarus-submenu-menuitem-donate': 'chrome://lazarus/skin/donate.png',
- 'lazarus-saveform-contextmenuitem': 'chrome://lazarus/skin/lazarus-save.png',
- 'lazarus-domaindisabled-contextmenuitem': 'chrome://lazarus/skin/lazarus-disabled.png',
- 'lazarus-privatebrowsing-contextmenuitem': 'chrome://lazarus/skin/lazarus-disabled.png'
- };
-
- var show = Lazarus.getPref('extensions.lazarus.showContextMenuIcons');
-
- for(var id in items){
- Lazarus.setMenuIcon(document.getElementById(id), show ? items[id] : null);
- }
-}
-
-
-/**
-*
-*/
-Lazarus.setMenuIcon = function(ele, iconURL){
- var classname = ele.tagName.toLowerCase() +"-iconic";
-
- if (iconURL){
- ele.setAttribute("image", iconURL);
- Lazarus.addClass(ele, classname);
- }
- else {
- //remove the icon
- ele.setAttribute("image", "");
- Lazarus.removeClass(ele, classname);
- }
-}
-
-
-/**
-* return TRUE if class exists
-*/
-Lazarus.classExists = function(ele, classname){
- var currName = ele.getAttribute('class') || '';
- return ((" "+ currName.toLowerCase() +" ").indexOf(" "+ classname.toLowerCase() +" ") > -1);
-}
-
-
-/**
-* adds a classname to an element if the name doesn't exist
-*/
-Lazarus.addClass = function(ele, classname){
- if (!Lazarus.classExists(ele, classname)){
- ele.setAttribute('class', (ele.getAttribute('class') || '') +" "+ classname);
- }
-}
-
-
-/**
-* remove a classname from an element
-*/
-Lazarus.removeClass = function(ele, classname){
- if (Lazarus.classExists(ele, classname)){
- var newClassname = ele.getAttribute('class').toLowerCase().replace(classname.toLowerCase(), "").replace(/\s+/g, ' ').replace(/^\s+|\s+$/g, '');
- ele.setAttribute('class', newClassname);
- }
-}
-
-/**
-*
-*/
-Lazarus.test = function(evt){
-
-
- Lazarus.cleanDB();
- return;
-
-
- alert(1);
- Lazarus.backgroundTask(function(){
-
- var x = 1234
- for(var i=0; i<20000000; i++){
- x = x/100;
- }
-
- //try throwing an error in the middle of the function
- x = a.b.c;
-
- return x;
-
-
- }, function(result){
- alert(result);
- })
-
-
- return;
-
-
- alert("Private = "+ Lazarus.isPrivateBrowsing());
- return;
-
-
-
-//~ Unit.assert("Lazarus.canEncrypt()", true, "should be able to encrypt");
-
-//~ alert(Unit.getLog());
-//~ return;
-
-
- var len = 10;
-
- var p = new Profiler("decrypt");
- var enc = [];
- var dec = [];
- for (var i=0; i<len; i++){
- enc[i] = Lazarus.encrypt("abc"+ Math.random());
- }
- p.mark("encrypted "+ len +" strings");
- for (var i=0; i<len; i++){
- dec[i] = Lazarus.decrypt(enc[i]);
- }
-
- debug(p.stop("decrypted"));
- return;
-
-
-
-
- debug(Lazarus.db.rs("SELECT hashed_text FROM textdata_fulltext LIMIT 1"));
- return;
-
- Lazarus.openTextManager();
- return;
-
- var str = prompt("Enter search string");
- if (str){
- debug(str, Lazarus.hashQuery(str));
- var rs = Lazarus.db.rs("SELECT id, text_encrypted FROM textdata JOIN textdata_fulltext ON textdata.id = textdata_fulltext.docid WHERE textdata_fulltext.hashed_text MATCH ?1", Lazarus.hashQuery(str));
- debug(rs);
-
- var text = '';
- for (var i=0; i<rs.length; i++){
- text += rs[i].id +":"+ Lazarus.decrypt(rs[i].text_encrypted) +"\n";
- }
- alert(text ? text : "== no results ==");
- }
- return;
-
-
-
- alert(Lazarus.hash("chongo <Landon Curt Noll> /\\../\\"));
- return;
-
-
- var p = new Profiler('encrypt large file');
- var s = Lazarus.file.readBinary("%profile%/test.sqlite");
- p.mark("Read file");
- var enc = Lazarus.encrypt(s);
- p.mark("Encrypt file");
- var dec = Lazarus.decrypt(enc);
- p.mark("Decrypt file : "+ (dec == s));
-
- //Lazarus.file.readBinary("%profile%/test.sqlite");
- alert(p.stop("finished"));
- return;
-
-
-
- alert(Lazarus.enterMasterPassword());
- return;
-
- alert(1);
- Lazarus.isMasterPasswordSet();
- alert(2);
-
-
- Lazarus.isMasterPasswordSet();
- return;
-
-
- Lazarus.db.exe("DELETE FROM settings WHERE name = 'public-key' OR name = 'private-key'");
- return;
-
-
- var p = new Profiler("encryption");
-
- var str = "{testing...}";
-
- var str = '';
- for (var i=0; i<200000; i++){
- str += "A";
- }
-
- var enc = Lazarus.Crypto.encrypt(str);
- debug(enc);
- p.mark("Encrypted string (Hybrid) of length "+ str.length);
-
- var dec = Lazarus.Crypto.decrypt(enc);
- p.mark("Decrypted string (Hybrid): "+ ((dec == str) ? "success" : "FAILED!"));
-
- //compare with SSD encryption
- var enc = Lazarus.encrypt(str);
- p.mark("Encrypted string (SSD) of length "+ str.length);
-
- var dec = Lazarus.decrypt(enc);
-
- alert(p.stop("Decrypted string (SSD): "+ ((dec == str) ? "success" : "FAILED!")));
- return;
-
-
- var keyPair = Lazarus.Crypto.generateRSAKeyPair("{password}");
-
- p.mark("Generate RSA key pair");
-
- var symKey = Lazarus.Crypto.crypto.generateRandomKey();
-
- //attempting to amke a smaller symkey
- symKey = btoa(atob(symKey).substr(0, 16));
-
- p.mark("Generate symetric key ["+ atob(symKey).length +" characters]");
-
- var wrapped = Lazarus.Crypto.crypto.wrapSymmetricKey(symKey, keyPair.pubkey);
-
- p.mark("RSA Encrypt symetric key");
-
- var unwrapped = Lazarus.Crypto.crypto.unwrapSymmetricKey(wrapped, keyPair.privkey,
- keyPair.password,
- keyPair.passphraseSalt,
- keyPair.privkeyWrapIV);
-
-
- p.mark("RSA Decrypt symetric key");
-
- debug(unwrapped, symKey == unwrapped);
-
- alert(p.stop(symKey == unwrapped ? "success" : "failed!"));
-
-
- return;
-
-
- var str = '';
- for (var i=0; i<200000; i++){
- str += "A";
- }
-
-
- str = "a very short string.";
-
- //speed test
- var p = new Profiler("Encrypting a str of length :"+ str.length);
-
- var keypair = Lazarus.Crypto.generateKeyPair(512);
-
- p.mark("generate RSA key pair (512 bit)");
-
-
- debug(Lazarus.Crypto.crypto);
-
- var enc = Lazarus.Crypto.encrypt(str, keypair.public);
- p.mark("hybrid encrypt a string");
-
-
- var dec = Lazarus.Crypto.decrypt(enc, keypair.private);
- debug(dec);
-
-
- p.mark("hybrid decrypt a string"+ ((str == dec) ? "success" : "FAILED!"));
-
- alert(p.stop());
- //var enc = Lazarus.Crypto.encrypt("a string \u5555");
-
- //debug(atob(Lazarus.Crypto.crypto.generateRandomIV()));
- //debug(atob(Lazarus.Crypto.crypto.generateRandomKey()));
-
- return;
-
-
- //labs.mozilla.com/Weave/Crypto
- //interclue.com/Lazarus/Crypto2
-
- try {
- var xx = Components.classes["@labs.mozilla.com/Weave/Crypto;1"].
- createInstance(Components.interfaces.IWeaveCrypto);
- }
- catch(e){
- if (confirm("Failed to create Weave:crypto object, weave not installed?\nInstall Weave now?")){
- Lazarus.openURL('http://dev.izeal.com/xpi/lazarus/weave-0.2.98.xpi', true, true);
- }
- }
-
-
- debug(xx);
- return;
-
-
- var randIV = xx.generateRandomIV();
- //debug(randIV);
-
- var randKey = xx.generateRandomKey();
- //debug(randKey);
-
- var str = '';
- for (var i=0; i<200000; i++){
- str += "A";
- }
-
- //speed test
- var p = new Profiler("Encrypting a str of length :"+ str.length);
- var enc = xx.encrypt(str, randKey, randIV);
- p.mark("weave (aes-256-cbc): encrypted");
- var dec = xx.decrypt(enc, randKey, randIV);
- p.mark("weave (aes-256-cbc): decrypted : "+ ((str == dec) ? "success" : "FAILED!"));
- var enc = Lazarus.encrypt(str);
- p.mark("SecretKeyRing: encrypted");
- var dec = Lazarus.decrypt(enc);
- p.mark("SecretKeyRing: decrypted : "+ ((str == dec) ? "success" : "FAILED!"));
-
- alert(p.stop());
-
-
- //alert("Private = "+ Lazarus.isPrivateBrowsing());
-
- return;
- //~ var pbs = Components.classes["@mozilla.org/privatebrowsing;1"].getService(Components.interfaces.nsIPrivateBrowsingService);
-
- //~ // are we currently in the Private Browsing mode?
- //~ var inPrivateBrowsingMode = pbs.privateBrowsingEnabled;
- //~ alert(inPrivateBrowsingMode);
- //~ return;
-
-
-
- //~ var pbs = Components.classes["@mozilla.org/browser/privatebrowsing;1"]
- //~ .getService(Components.interfaces.nsIPrivateBrowsingService);
-
- //~ pbs.privateBrowsing = !pbs.privateBrowsing;
- //~ alert(pbs.privateBrowsing);
-
- //~ return;
-
-
- //http://lazarus.interclue.com/
- var url = "http://tinyurl.com/5qhvvw";
- var log = [];
- var xmlhttp = new XMLHttpRequest();
- xmlhttp.open("HEAD", url);
- xmlhttp.onreadystatechange = function(){
- try {
- //debug(xmlhttp.readyState);
- //debug(xmlhttp.status);
- //debug(xmlhttp.getAllResponseHeaders());
- }catch(e){}
-
- if (xmlhttp.readyState == 4){
- Lazarus.dump(xmlhttp.channel.originalURI);
- Lazarus.dump(xmlhttp.channel.URI);
- }
-
- }
- xmlhttp.send(null);
- return;
-
- //Lazarus.checkForUpdates();
- return;
-
- alert(decodeURIComponent(encodeURIComponent("\u2663")))
-
- var str = "\u2663";
- alert(str +" ["+ str.length +"]");
- var enc = Lazarus.encrypt(str);
- alert(enc);
- var s = Lazarus.decrypt(enc);
- alert(s);
- //~ var alertsService = Components.classes["@mozilla.org/alerts-service;1"]
- //~ .getService(Components.interfaces.nsIAlertsService);
-//~ alertsService.showAlertNotification("chrome://mozapps/skin/downloads/downloadIcon.png",
- //~ "Alert title", "Alert text goes here.",
- //~ false, "", null);
-
-//~ function setToNormalZ(aWindow) {
- //~ aWindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
- //~ var webnav = aWindow.getInterface(Components.interfaces.nsIWebNavigation);
- //~ var dsti = webnav.QueryInterface(Components.interfaces.nsIDocShellTreeItem);
- //~ var treeowner = dsti.treeOwner;
- //~ var ifreq = treeowner.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
- //~ var xulwin = ifreq.getInterface(Components.interfaces.nsIXULWindow);
- //~ xulwin.zLevel = 9;
-//~ }
-
-
- //~ var win = window.open("chrome://lazarus/content/test.xul", "test", "chrome");
-
-
-//~ setTimeout(function(){
- //~ //
- //~ //alert("a");
- //~ setToNormalZ(win);
-
-//~ }, 3000);
-
-//~ <?xml-stylesheet href="chrome://global/skin/alerts/alert.css" type="text/css"?>
-
-//~ <window id="alertNotification"
- //~ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- //~ windowtype="alert:alert"
- //~ xmlns:xhtml2="http://www.w3.org/TR/xhtml2"
- //~ xmlns:wairole="http://www.w3.org/2005/01/wai-rdf/GUIRoleTaxonomy#"
- //~ xhtml2:role="wairole:alert"
- //~ align="start"
- //~ onload="onAlertLoad()">
-
-
- //~ if (Lazarus.state == Lazarus.STATE_DISABLED){
- //~ Lazarus.enable();
- //~ }
- //~ else {
- //~ Lazarus.disable();
- //~ }
-
- //Lazarus.warning("test");
- //Lazarus.updates["1.0.1beta4"]();
-
- //~ Lazarus.debug(Lazarus.getBaseDomain('www.127.0.0.1'));
- //~ Lazarus.debug(Lazarus.getBaseDomain('domain.tv.com'));
- //~ Lazarus.debug(Lazarus.getBaseDomain('domain.com.tv'));
- //~ Lazarus.debug(Lazarus.getBaseDomain('domain.tv'));
- //~ Lazarus.debug(Lazarus.getBaseDomain('domain.com'));
- //~ Lazarus.debug(Lazarus.getBaseDomain('secure.email.website.co.uk'));
- //~ Lazarus.debug(Lazarus.getBaseDomain('this.is.a.worst.shortly.subdomain.thisIsMyMainWebsite.com.cl'));
-}
-
-
-
-
-Lazarus.icon = "data:image/png;base64,\
-iVBORw0KGgoAAAANSUhEUgAAAAsAAAAOCAYAAAD5YeaVAAAALHRFWHRDcmVhdGlvbiBUaW1lAFRo\
-dSAxMiBOb3YgMjAwOSAxMzoxOToxNiArMTIwMJCaV2oAAAAHdElNRQfZCwwAFimayURVAAAACXBI\
-WXMAAAsSAAALEgHS3X78AAAABGdBTUEAALGPC/xhBQAAASZJREFUeNq1ks1KAmEUhh+/GZkGs6IS\
-gzYhhREEwbRw56IbSaIbaNe+K2gvFEWB11Cgm4LUKKGfRRqVpKVTpkJpOpOJow6ufVfn8D7nfC8f\
-B4YlR39zesHc8wPrRpNx9xildJrw9hZZyxdWkUggV3XWLhPcn8XZcQoyX2W0/mVdODPSesWBojh5\
-D+/yYTp4q+g93wZ//mA6Fc4XFlnaO8L38sS8XuIuEukxslWsSISaE3xLPvzVCv56g9rGJpVcltWW\
-fWiDYzHU/Ct4vDy6RwlcX3Fyk4Ji0f4JbWlae1CKpwjsH3MQCrHciSkGMieTNEwTwzSYUhQmJRVv\
-xzIG4H9Fo4haHa8QuFwqs8GgPYLc3xQ8iN9bpvM51GqZmUKhvaw5tJPo6g+jvlxgBqGatwAAAABJ\
-RU5ErkJggg=="; \ No newline at end of file
diff --git a/offline-submit/post-data.txt b/offline-submit/post-data.txt
deleted file mode 100644
index 85a8e0a..0000000
--- a/offline-submit/post-data.txt
+++ /dev/null
@@ -1,79 +0,0 @@
-delta_ts=2009-12-09+19%3A42%3A04&longdesclength=6&id=544623&token=1260958169-c8aa4a3bf3735866fc1e8a398d5c878c&short_desc=%5Babrt%5D+crash+detected+in+compiz-0.8.2-20.fc12+%230++in+__longjmp+%28%29+from+%2Flib64%2Fld-linux-x86-64.so.2&newalias=__longjmp&product=Fedora&component=compiz&version=12&rep_platform=x86_64&op_sys=Linux&priority=low&bug_severity=medium&assigned_to=adel.gadllah%40gmail.com&qa_contact=extras-qa%40fedoraproject.org&bug_file_loc=&status_whiteboard=abrt_hash%3A9d6ed64860473c6d40b0b90137f67f48417a51e7&keywords=&dependson=&blocked=&newcc=&cf_fixed_in=&cf_cust_facing=---&cf_issuetracker=&cf_internal_whiteboard=&cf_devel_whiteboard=&cf_qa_whiteboard=&cf_release_notes=&cf_build_id=&cf_targetrelease=---&defined_cf_partner=&defined_cf_verified=&cf_clone_of=&defined_cf_conditional_nak=&cf_environment=&flag_type-65=X&flag_type-67=X&flag_type-16=X&requestee_type-16=&flag_type-66=X&defined_bit-41=1&defined_bit-68=1&defined_bit-31=1&defined_bit-58=1&defined_bit-50=1&defined_bit-83=1&defined_bit-21=1&defined_bit-32=1&defined_bit-15=1&defined_bit-12=1&defined_bit-161=1&defined_bit-44=1&defined_bit-22=1&defined_bit-11=1&defined_bit-48=1&defined_bit-10=1&defined_bit-93=1&estimated_time=0.0&work_time=0&remaining_time=0.0&deadline=&external_id=0&external_bug_id=&comment=&needinfo_role=&needinfo_from=&bug_status=NEW&resolution=NOTABUG&dup_id=&defined_isprivate_2522533=1&defined_isprivate_2521233=1&defined_isprivate_2520112=1&defined_isprivate_2519826=1&defined_isprivate_2518162=1&defined_isprivate_2518161=1
-
-which is
-
-delta_ts 2009-12-09 19:42:04
-longdesclength 6
-id 544623
-token 1260958169-c8aa4a3bf3735866fc1e8a398d5c878c
-short_desc [abrt] crash detected in compiz-0.8.2-20.fc12 #0 in __longjmp () from /lib64/ld-linux-x86-64.so.2
-newalias __longjmp
-product Fedora
-component compiz
-version 12
-rep_platform x86_64
-op_sys Linux
-priority low
-bug_severity medium
-assigned_to adel.gadllah@gmail.com
-qa_contact extras-qa@fedoraproject.org
-bug_file_loc
-status_whiteboard abrt_hash:9d6ed64860473c6d40b0b90137f67f48417a51e7
-keywords
-dependson
-blocked
-newcc
-cf_fixed_in
-cf_cust_facing ---
-cf_issuetracker
-cf_internal_whiteboard
-cf_devel_whiteboard
-cf_qa_whiteboard
-cf_release_notes
-cf_build_id
-cf_targetrelease ---
-defined_cf_partner
-defined_cf_verified
-cf_clone_of
-defined_cf_conditional_nak
-cf_environment
-flag_type-65 X
-flag_type-67 X
-flag_type-16 X
-requestee_type-16
-flag_type-66 X
-defined_bit-41 1
-defined_bit-68 1
-defined_bit-31 1
-defined_bit-58 1
-defined_bit-50 1
-defined_bit-83 1
-defined_bit-21 1
-defined_bit-32 1
-defined_bit-15 1
-defined_bit-12 1
-defined_bit-161 1
-defined_bit-44 1
-defined_bit-22 1
-defined_bit-11 1
-defined_bit-48 1
-defined_bit-10 1
-defined_bit-93 1
-estimated_time 0.0
-work_time 0
-remaining_time 0.0
-deadline
-external_id 0
-external_bug_id
-comment
-needinfo_role
-needinfo_from
-bug_status NEW
-resolution NOTABUG
-dup_id
-defined_isprivate_2522533 1
-defined_isprivate_2521233 1
-defined_isprivate_2520112 1
-defined_isprivate_2519826 1
-defined_isprivate_2518162 1
-defined_isprivate_2518161 1