~alpine/devel

This thread contains a patchset. You're looking at the original emails, but you may wish to use the patch review UI. Review patch
1

[alpine-devel] [PATCH] Upgrade Weblog to Weblog 2.0

Luke Stuart <lukestu@gmail.com>
Details
Message ID
<1298643294-15858-1-git-send-email-lukestu@gmail.com>
Sender timestamp
1298643294
DKIM signature
missing
Download raw message
Patch: +1405 -234
---
 Makefile                      |   15 +-
 bypass.png                    |  Bin 0 -> 1395 bytes
 denied.png                    |  Bin 0 -> 1376 bytes
 dodgy.png                     |  Bin 0 -> 1357 bytes
 jquery.min.js                 |  154 ++++++++
 newviewfunctions.lua          |   52 +++
 template-silent.lsp           |    9 +
 weblog-adhocquery-html.lsp    |    2 +-
 weblog-config-html.lsp        |    5 +-
 weblog-controller.lua         |   69 +++-
 weblog-editfile-html.lsp      |    1 +
 weblog-listfiles-html.lsp     |   42 ++
 weblog-maintenance-html.lsp   |   17 +
 weblog-model.lua              |  873 +++++++++++++++++++++++++++++++----------
 weblog-summary-html.lsp       |   17 +
 weblog-viewwatchlist-html.lsp |    2 +-
 weblog-viewweblog-html.lsp    |  301 ++++++++++++++-
 weblog.menu                   |    4 +-
 weblog.roles                  |    4 +-
 weblog_notify_daily           |   36 ++
 weblog_notify_weekly          |   36 ++
 21 files changed, 1405 insertions(+), 234 deletions(-)
 create mode 100644 bypass.png
 create mode 100644 denied.png
 create mode 100644 dodgy.png
 create mode 100644 jquery.min.js
 create mode 100644 newviewfunctions.lua
 create mode 100644 template-silent.lsp
 create mode 120000 weblog-editfile-html.lsp
 create mode 100644 weblog-listfiles-html.lsp
 create mode 100644 weblog-maintenance-html.lsp
 create mode 100644 weblog-summary-html.lsp
 mode change 120000 => 100644 weblog-viewweblog-html.lsp
 create mode 100755 weblog_notify_daily
 create mode 100755 weblog_notify_weekly

diff --git a/Makefile b/Makefile
index 64962e6..b79753b 100644
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,11 @@
APP_NAME=weblog
PACKAGE=acf-$(APP_NAME)
VERSION=0.5.9
VERSION=0.9.1

CRON_FILE=weblogimport
TEMPLATE_FILE=template-silent.lsp
JAVA_FILE=jquery.min.js
LIB_FILE=newviewfunctions.lua

APP_DIST=$(filter-out $(CRON_FILE), $(wildcard weblog*))

@@ -16,6 +19,9 @@ P=$(PACKAGE)-$(VERSION)
tarball=$(P).tar.bz2
install_dir=$(DESTDIR)/$(appdir)/$(APP_NAME)
cron_dir=$(DESTDIR)/etc/periodic/daily
template_dir=$(DESTDIR)/$(appdir)
java_dir=$(DESTDIR)/www/js/
lib_dir=$(DESTDIR)/lib/

all:
clean:
@@ -24,10 +30,13 @@ clean:
dist: $(tarball)

install:
	mkdir -p "$(install_dir)" "$(cron_dir)"
	mkdir -p "$(install_dir)" "$(cron_dir)" "$(template_dir)" "$(java_dir)" "$(lib_dir)"
	cp -a $(APP_DIST) "$(install_dir)"
	cp -a $(CRON_FILE) "$(cron_dir)"

	cp -a $(JAVA_FILE) "$(java_dir)"
	cp -a $(TEMPLATE_FILE) "$(template_dir)"
	cp -a $(LIB_FILE) "$(lib_dir)"
	
$(tarball):	$(DISTFILES)
	rm -rf $(P)
	mkdir -p $(P)
diff --git a/bypass.png b/bypass.png
new file mode 100644
index 0000000000000000000000000000000000000000..896070ebbcd862d47abd2f3f087e70b5e6054cae
GIT binary patch
literal 1395
zcmeAS@N?(olHy`uVBq!ia0vp^B0wy_!3-o7kFD1PQjEnx?oJHr&dIz4a#+$GeH|GX
zHuiJ>Nn~YUU}gyL32_CAr)e|HWB?-LnLvg%kW8By$}lt3_zVNX8EqgkJ`>7tCe-*p
zP$V?%e`wmwhO{#c#{V0P&ord{2clI#?#wf*X8v!O`G3{SGgpE7M!{$Z42=-z6nZTV
z%qI*bL4LviM>b#x{?4unj5W>zkH}&M2EM}}%y>M1MG8<*qQo_#Bsf2<q&%@Gl_4N8
zGp|I?&oxA$%vjIZY~}MuAdP1{T^vI+f^8=>79COGaN#{_<``c5!nOGC|My!il=Vr<
z)*NQaj*wH%<E;4iOzfbay4cKOhhNfs=U(XNR-H}x@a>deWVVVWixuy(ya`4DvB%Wk
z=mm$pc#ze9e9>|%=Yt%-(|>OG=%aUa@=`Mvt%TRFPepUz=P7vbF0wGw`;PeHKo2g<
zJ@2FzYz(uxEElI?7d<=DfbEIJA))yJ0Z(uLxw4n*_ouvMGusx6Ytz=QuioBkpno+p
xcmJOE@-cr8*q+s#{QsoANzazti>Gwz7~WY`_dk)Gy$h6#Jzf1=);T3K0RY8Tv2p+a

literal 0
HcmV?d00001

diff --git a/denied.png b/denied.png
new file mode 100644
index 0000000000000000000000000000000000000000..0238f3d4149a144b94186f26102baf097b5fe665
GIT binary patch
literal 1376
zcmeAS@N?(olHy`uVBq!ia0vp^f<P?5!3-pizfZ{pQjEnx?oJHr&dIz4a#+$GeH|GX
zHuiJ>Nn~YUU}gyL32_CAr)e|HWB?-LnLvg%kW8By$}lt3_zVNX8EqgkJ`>7tCe-*p
zP$V?%e`wmwhO{#c#{V0P&ord{2clI#?#wf*X8v!O`G3{SGgpE7M!{$Z42=-z6nZTV
z%qI*bL4LviM>b#x{?4unj5W>zkH}&M2EM}}%y>M1MG8<*qQo_#Bsf2<q&%@Gl_4N8
zGp|I?&oxA$%vjIZY~}MuAdNdcT^vI+f_3{F^A0QUxOAp(J5n$~Qfkh(|NAG;ESshi
z>3{8V?2K%;J3=2S?jPJP+&zQW<Nt(%l7CnF>U)1zn!D+mM-j)BpmHb472XHbyH4`R
z#uz?-zocDEq-R6@^z~1bE>B)+#-f!_{_xr%b7q+x>sM!Z-%(#2=)q-Kz<Xha@w`la
z|0%1^I$JRm$s~4(hE!JG*%kh9szKys=Z@suo3X1|-vpV4|JAv^`(@+pJ*=1OFCU$-
dP4`#xd3onE-usi{4g`bJtf#A=%Q~loCIHSBsL%ia

literal 0
HcmV?d00001

diff --git a/dodgy.png b/dodgy.png
new file mode 100644
index 0000000000000000000000000000000000000000..b035ba9218d6aa0caa4644ef3cdda37c4729ce60
GIT binary patch
literal 1357
zcmeAS@N?(olHy`uVBq!ia0vp^f*{Pn3?z9rZ$AN~7>k44ofy`glX(f`u%tWsIx;Y9
z?C1WI$jZRL%n;xc;tCWu);2a~NHf+>OJhh&1CpV}X`yMx3^UV!NE=9=Nz*=)7CLh#
z!_1l5K=RB??K3lh+|V;;LeI=>m^pLR%$W^mX0AGOreWrpRWr{toH+wzulj%H>X|cF
z|Np;w=0A}9{~u`4C>RZa!4?AXI<-E)e8Nx?<QEJ|rXv_I1b=5&1;!6&fk$L90|Vb-
z5N14{zaj-FC{f}XQ4*Y=R#Ki=l*$m0n3-3i=jR%tP-d)WY_{_GBap^ro-U3d8o{v_
z5`~)-c-S6vd6^ruW{Nmn`S-uxWZ9jkTl>%7OHOWox}Q(l=iJU)QLR-<MmN@~Jv#Aw
zVul0HY>TdmGlh8-Rw~_%QBXf8rROi`-v8xX%FJqA#fcXun@%*&u;@ydnSAz)J~xL~
z$|WfiquWA_ZYm4R%-?c)&0UsjHBGNR>cF=sa~BqmK&9_m3$4Yor%sxBJzmE<V@lR3
hY5SY;OX8B<<2RZ0KJ|U}UIdgBJzf1=);T3K0RRn0sU`pb

literal 0
HcmV?d00001

diff --git a/jquery.min.js b/jquery.min.js
new file mode 100644
index 0000000..7c24308
--- /dev/null
+++ b/jquery.min.js
@@ -0,0 +1,154 @@
/*!
 * jQuery JavaScript Library v1.4.2
 * http://jquery.com/
 *
 * Copyright 2010, John Resig
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * Includes Sizzle.js
 * http://sizzlejs.com/
 * Copyright 2010, The Dojo Foundation
 * Released under the MIT, BSD, and GPL Licenses.
 *
 * Date: Sat Feb 13 22:33:48 2010 -0500
 */
(function(A,w){function ma(){if(!c.isReady){try{s.documentElement.doScroll("left")}catch(a){setTimeout(ma,1);return}c.ready()}}function Qa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function X(a,b,d,f,e,j){var i=a.length;if(typeof b==="object"){for(var o in b)X(a,o,b[o],f,e,d);return a}if(d!==w){f=!j&&f&&c.isFunction(d);for(o=0;o<i;o++)e(a[o],b,f?d.call(a[o],o,e(a[o],b)):d,j);return a}return i?
e(a[0],b):w}function J(){return(new Date).getTime()}function Y(){return false}function Z(){return true}function na(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function oa(a){var b,d=[],f=[],e=arguments,j,i,o,k,n,r;i=c.data(this,"events");if(!(a.liveFired===this||!i||!i.live||a.button&&a.type==="click")){a.liveFired=this;var u=i.live.slice(0);for(k=0;k<u.length;k++){i=u[k];i.origType.replace(O,"")===a.type?f.push(i.selector):u.splice(k--,1)}j=c(a.target).closest(f,a.currentTarget);n=0;for(r=
j.length;n<r;n++)for(k=0;k<u.length;k++){i=u[k];if(j[n].selector===i.selector){o=j[n].elem;f=null;if(i.preType==="mouseenter"||i.preType==="mouseleave")f=c(a.relatedTarget).closest(i.selector)[0];if(!f||f!==o)d.push({elem:o,handleObj:i})}}n=0;for(r=d.length;n<r;n++){j=d[n];a.currentTarget=j.elem;a.data=j.handleObj.data;a.handleObj=j.handleObj;if(j.handleObj.origHandler.apply(j.elem,e)===false){b=false;break}}return b}}function pa(a,b){return"live."+(a&&a!=="*"?a+".":"")+b.replace(/\./g,"`").replace(/ /g,
"&")}function qa(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function ra(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var f=c.data(a[d++]),e=c.data(this,f);if(f=f&&f.events){delete e.handle;e.events={};for(var j in f)for(var i in f[j])c.event.add(this,j,f[j][i],f[j][i].data)}}})}function sa(a,b,d){var f,e,j;b=b&&b[0]?b[0].ownerDocument||b[0]:s;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&b===s&&!ta.test(a[0])&&(c.support.checkClone||!ua.test(a[0]))){e=
true;if(j=c.fragments[a[0]])if(j!==1)f=j}if(!f){f=b.createDocumentFragment();c.clean(a,b,f,d)}if(e)c.fragments[a[0]]=j?f:1;return{fragment:f,cacheable:e}}function K(a,b){var d={};c.each(va.concat.apply([],va.slice(0,b)),function(){d[this]=a});return d}function wa(a){return"scrollTo"in a&&a.document?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var c=function(a,b){return new c.fn.init(a,b)},Ra=A.jQuery,Sa=A.$,s=A.document,T,Ta=/^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/,
Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&&
(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this,
a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b===
"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this,
function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b<d;b++)if((e=arguments[b])!=null)for(j in e){i=a[j];o=e[j];if(a!==o)if(f&&o&&(c.isPlainObject(o)||c.isArray(o))){i=i&&(c.isPlainObject(i)||
c.isArray(i))?i:c.isArray(o)?[]:{};a[j]=c.extend(f,i,o)}else if(o!==w)a[j]=o}return a};c.extend({noConflict:function(a){A.$=Sa;if(a)A.jQuery=Ra;return c},isReady:false,ready:function(){if(!c.isReady){if(!s.body)return setTimeout(c.ready,13);c.isReady=true;if(Q){for(var a,b=0;a=Q[b++];)a.call(s,c);Q=null}c.fn.triggerHandler&&c(s).triggerHandler("ready")}},bindReady:function(){if(!xa){xa=true;if(s.readyState==="complete")return c.ready();if(s.addEventListener){s.addEventListener("DOMContentLoaded",
L,false);A.addEventListener("load",c.ready,false)}else if(s.attachEvent){s.attachEvent("onreadystatechange",L);A.attachEvent("onload",c.ready);var a=false;try{a=A.frameElement==null}catch(b){}s.documentElement.doScroll&&a&&ma()}}},isFunction:function(a){return $.call(a)==="[object Function]"},isArray:function(a){return $.call(a)==="[object Array]"},isPlainObject:function(a){if(!a||$.call(a)!=="[object Object]"||a.nodeType||a.setInterval)return false;if(a.constructor&&!aa.call(a,"constructor")&&!aa.call(a.constructor.prototype,
"isPrototypeOf"))return false;var b;for(b in a);return b===w||aa.call(a,b)},isEmptyObject:function(a){for(var b in a)return false;return true},error:function(a){throw a;},parseJSON:function(a){if(typeof a!=="string"||!a)return null;a=c.trim(a);if(/^[\],:{}\s]*$/.test(a.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return A.JSON&&A.JSON.parse?A.JSON.parse(a):(new Function("return "+
a))();else c.error("Invalid JSON: "+a)},noop:function(){},globalEval:function(a){if(a&&Va.test(a)){var b=s.getElementsByTagName("head")[0]||s.documentElement,d=s.createElement("script");d.type="text/javascript";if(c.support.scriptEval)d.appendChild(s.createTextNode(a));else d.text=a;b.insertBefore(d,b.firstChild);b.removeChild(d)}},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,b,d){var f,e=0,j=a.length,i=j===w||c.isFunction(a);if(d)if(i)for(f in a){if(b.apply(a[f],
d)===false)break}else for(;e<j;){if(b.apply(a[e++],d)===false)break}else if(i)for(f in a){if(b.call(a[f],f,a[f])===false)break}else for(d=a[0];e<j&&b.call(d,e,d)!==false;d=a[++e]);return a},trim:function(a){return(a||"").replace(Wa,"")},makeArray:function(a,b){b=b||[];if(a!=null)a.length==null||typeof a==="string"||c.isFunction(a)||typeof a!=="function"&&a.setInterval?ba.call(b,a):c.merge(b,a);return b},inArray:function(a,b){if(b.indexOf)return b.indexOf(a);for(var d=0,f=b.length;d<f;d++)if(b[d]===
a)return d;return-1},merge:function(a,b){var d=a.length,f=0;if(typeof b.length==="number")for(var e=b.length;f<e;f++)a[d++]=b[f];else for(;b[f]!==w;)a[d++]=b[f++];a.length=d;return a},grep:function(a,b,d){for(var f=[],e=0,j=a.length;e<j;e++)!d!==!b(a[e],e)&&f.push(a[e]);return f},map:function(a,b,d){for(var f=[],e,j=0,i=a.length;j<i;j++){e=b(a[j],j,d);if(e!=null)f[f.length]=e}return f.concat.apply([],f)},guid:1,proxy:function(a,b,d){if(arguments.length===2)if(typeof b==="string"){d=a;a=d[b];b=w}else if(b&&
!c.isFunction(b)){d=b;b=w}if(!b&&a)b=function(){return a.apply(d||this,arguments)};if(a)b.guid=a.guid=a.guid||b.guid||c.guid++;return b},uaMatch:function(a){a=a.toLowerCase();a=/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version)?[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||!/compatible/.test(a)&&/(mozilla)(?:.*? rv:([\w.]+))?/.exec(a)||[];return{browser:a[1]||"",version:a[2]||"0"}},browser:{}});P=c.uaMatch(P);if(P.browser){c.browser[P.browser]=true;c.browser.version=P.version}if(c.browser.webkit)c.browser.safari=
true;if(ya)c.inArray=function(a,b){return ya.call(b,a)};T=c(s);if(s.addEventListener)L=function(){s.removeEventListener("DOMContentLoaded",L,false);c.ready()};else if(s.attachEvent)L=function(){if(s.readyState==="complete"){s.detachEvent("onreadystatechange",L);c.ready()}};(function(){c.support={};var a=s.documentElement,b=s.createElement("script"),d=s.createElement("div"),f="script"+J();d.style.display="none";d.innerHTML="   <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected,
parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent=
false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="<input type='radio' name='radiotest' checked='checked'/>";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n=
s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true,
applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando];
else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this,
a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b===
w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i,
cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1)if(e.className){for(var j=" "+e.className+" ",
i=e.className,o=0,k=b.length;o<k;o++)if(j.indexOf(" "+b[o]+" ")<0)i+=" "+b[o];e.className=c.trim(i)}else e.className=a}return this},removeClass:function(a){if(c.isFunction(a))return this.each(function(k){var n=c(this);n.removeClass(a.call(this,k,n.attr("class")))});if(a&&typeof a==="string"||a===w)for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1&&e.className)if(a){for(var j=(" "+e.className+" ").replace(Aa," "),i=0,o=b.length;i<o;i++)j=j.replace(" "+b[i]+" ",
" ");e.className=c.trim(j)}else e.className=""}return this},toggleClass:function(a,b){var d=typeof a,f=typeof b==="boolean";if(c.isFunction(a))return this.each(function(e){var j=c(this);j.toggleClass(a.call(this,e,j.attr("class"),b),b)});return this.each(function(){if(d==="string")for(var e,j=0,i=c(this),o=b,k=a.split(ca);e=k[j++];){o=f?o:!i.hasClass(e);i[o?"addClass":"removeClass"](e)}else if(d==="undefined"||d==="boolean"){this.className&&c.data(this,"__className__",this.className);this.className=
this.className||a===false?"":c.data(this,"__className__")||""}})},hasClass:function(a){a=" "+a+" ";for(var b=0,d=this.length;b<d;b++)if((" "+this[b].className+" ").replace(Aa," ").indexOf(a)>-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j<d;j++){var i=
e[j];if(i.selected){a=c(i).val();if(b)return a;f.push(a)}}return f}if(Ba.test(b.type)&&!c.support.checkOn)return b.getAttribute("value")===null?"on":b.value;return(b.value||"").replace(Za,"")}return w}var o=c.isFunction(a);return this.each(function(k){var n=c(this),r=a;if(this.nodeType===1){if(o)r=a.call(this,k,n.val());if(typeof r==="number")r+="";if(c.isArray(r)&&Ba.test(this.type))this.checked=c.inArray(n.val(),r)>=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected=
c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed");
a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g,
function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split(".");
k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a),
C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B<r.length;B++){u=r[B];if(d.guid===u.guid){if(i||k.test(u.namespace)){f==null&&r.splice(B--,1);n.remove&&n.remove.call(a,u)}if(f!=
null)break}}if(r.length===0||f!=null&&r.length===1){if(!n.teardown||n.teardown.call(a,o)===false)Ca(a,e,z.handle);delete C[e]}}else for(var B=0;B<r.length;B++){u=r[B];if(i||k.test(u.namespace)){c.event.remove(a,n,u.handler,B);r.splice(B--,1)}}}if(c.isEmptyObject(C)){if(b=z.handle)b.elem=null;delete z.events;delete z.handle;c.isEmptyObject(z)&&c.removeData(a)}}}}},trigger:function(a,b,d,f){var e=a.type||a;if(!f){a=typeof a==="object"?a[G]?a:c.extend(c.Event(e),a):c.Event(e);if(e.indexOf("!")>=0){a.type=
e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&&
f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive;
if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e<j;e++){var i=d[e];if(b||f.test(i.namespace)){a.handler=i.handler;a.data=i.data;a.handleObj=i;i=i.handler.apply(this,arguments);if(i!==w){a.result=i;if(i===false){a.preventDefault();a.stopPropagation()}}if(a.isImmediatePropagationStopped())break}}}return a.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
fix:function(a){if(a[G])return a;var b=a;a=c.Event(b);for(var d=this.props.length,f;d;){f=this.props[--d];a[f]=b[f]}if(!a.target)a.target=a.srcElement||s;if(a.target.nodeType===3)a.target=a.target.parentNode;if(!a.relatedTarget&&a.fromElement)a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement;if(a.pageX==null&&a.clientX!=null){b=s.documentElement;d=s.body;a.pageX=a.clientX+(b&&b.scrollLeft||d&&d.scrollLeft||0)-(b&&b.clientLeft||d&&d.clientLeft||0);a.pageY=a.clientY+(b&&b.scrollTop||
d&&d.scrollTop||0)-(b&&b.clientTop||d&&d.clientTop||0)}if(!a.which&&(a.charCode||a.charCode===0?a.charCode:a.keyCode))a.which=a.charCode||a.keyCode;if(!a.metaKey&&a.ctrlKey)a.metaKey=a.ctrlKey;if(!a.which&&a.button!==w)a.which=a.button&1?1:a.button&2?3:a.button&4?2:0;return a},guid:1E8,proxy:c.proxy,special:{ready:{setup:c.bindReady,teardown:c.noop},live:{add:function(a){c.event.add(this,a.origType,c.extend({},a,{handler:oa}))},remove:function(a){var b=true,d=a.origType.replace(O,"");c.each(c.data(this,
"events").live||[],function(){if(d===this.origType.replace(O,""))return b=false});b&&c.event.remove(this,a.origType,oa)}},beforeunload:{setup:function(a,b,d){if(this.setInterval)this.onbeforeunload=d;return false},teardown:function(a,b){if(this.onbeforeunload===b)this.onbeforeunload=null}}}};var Ca=s.removeEventListener?function(a,b,d){a.removeEventListener(b,d,false)}:function(a,b,d){a.detachEvent("on"+b,d)};c.Event=function(a){if(!this.preventDefault)return new c.Event(a);if(a&&a.type){this.originalEvent=
a;this.type=a.type}else this.type=a;this.timeStamp=J();this[G]=true};c.Event.prototype={preventDefault:function(){this.isDefaultPrevented=Z;var a=this.originalEvent;if(a){a.preventDefault&&a.preventDefault();a.returnValue=false}},stopPropagation:function(){this.isPropagationStopped=Z;var a=this.originalEvent;if(a){a.stopPropagation&&a.stopPropagation();a.cancelBubble=true}},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=Z;this.stopPropagation()},isDefaultPrevented:Y,isPropagationStopped:Y,
isImmediatePropagationStopped:Y};var Da=function(a){var b=a.relatedTarget;try{for(;b&&b!==this;)b=b.parentNode;if(b!==this){a.type=a.data;c.event.handle.apply(this,arguments)}}catch(d){}},Ea=function(a){a.type=a.data;c.event.handle.apply(this,arguments)};c.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){c.event.special[a]={setup:function(d){c.event.add(this,b,d&&d.selector?Ea:Da,a)},teardown:function(d){c.event.remove(this,b,d&&d.selector?Ea:Da)}}});if(!c.support.submitBubbles)c.event.special.submit=
{setup:function(){if(this.nodeName.toLowerCase()!=="form"){c.event.add(this,"click.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="submit"||d==="image")&&c(b).closest("form").length)return na("submit",this,arguments)});c.event.add(this,"keypress.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="text"||d==="password")&&c(b).closest("form").length&&a.keyCode===13)return na("submit",this,arguments)})}else return false},teardown:function(){c.event.remove(this,".specialSubmit")}};
if(!c.support.changeBubbles){var da=/textarea|input|select/i,ea,Fa=function(a){var b=a.type,d=a.value;if(b==="radio"||b==="checkbox")d=a.checked;else if(b==="select-multiple")d=a.selectedIndex>-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data",
e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a,
"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a,
d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j<o;j++)c.event.add(this[j],d,i,f)}return this}});c.fn.extend({unbind:function(a,b){if(typeof a==="object"&&
!a.preventDefault)for(var d in a)this.unbind(d,a[d]);else{d=0;for(var f=this.length;d<f;d++)c.event.remove(this[d],a,b)}return this},delegate:function(a,b,d,f){return this.live(b,d,f,a)},undelegate:function(a,b,d){return arguments.length===0?this.unbind("live"):this.die(b,null,d,a)},trigger:function(a,b){return this.each(function(){c.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){a=c.Event(a);a.preventDefault();a.stopPropagation();c.event.trigger(a,b,this[0]);return a.result}},
toggle:function(a){for(var b=arguments,d=1;d<b.length;)c.proxy(a,b[d++]);return this.click(c.proxy(a,function(f){var e=(c.data(this,"lastToggle"+a.guid)||0)%d;c.data(this,"lastToggle"+a.guid,e+1);f.preventDefault();return b[e].apply(this,arguments)||false}))},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var Ga={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};c.each(["live","die"],function(a,b){c.fn[b]=function(d,f,e,j){var i,o=0,k,n,r=j||this.selector,
u=j?this:c(this.context);if(c.isFunction(f)){e=f;f=w}for(d=(d||"").split(" ");(i=d[o++])!=null;){j=O.exec(i);k="";if(j){k=j[0];i=i.replace(O,"")}if(i==="hover")d.push("mouseenter"+k,"mouseleave"+k);else{n=i;if(i==="focus"||i==="blur"){d.push(Ga[i]+k);i+=k}else i=(Ga[i]||i)+k;b==="live"?u.each(function(){c.event.add(this,pa(i,r),{data:f,selector:r,handler:e,origType:i,origHandler:e,preType:n})}):u.unbind(pa(i,r),e)}}return this}});c.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),
function(a,b){c.fn[b]=function(d){return d?this.bind(b,d):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});A.attachEvent&&!A.addEventListener&&A.attachEvent("onunload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}});(function(){function a(g){for(var h="",l,m=0;g[m];m++){l=g[m];if(l.nodeType===3||l.nodeType===4)h+=l.nodeValue;else if(l.nodeType!==8)h+=a(l.childNodes)}return h}function b(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];
if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1&&!p){t.sizcache=l;t.sizset=q}if(t.nodeName.toLowerCase()===h){y=t;break}t=t[g]}m[q]=y}}}function d(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1){if(!p){t.sizcache=l;t.sizset=q}if(typeof h!=="string"){if(t===h){y=true;break}}else if(k.filter(h,[t]).length>0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift();
t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D||
g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h<g.length;h++)g[h]===g[h-1]&&g.splice(h--,1)}return g};k.matches=function(g,h){return k(g,null,null,h)};k.find=function(g,h,l){var m,q;if(!g)return[];
for(var p=0,v=n.order.length;p<v;p++){var t=n.order[p];if(q=n.leftMatch[t].exec(g)){var y=q[1];q.splice(1,1);if(y.substr(y.length-1)!=="\\"){q[1]=(q[1]||"").replace(/\\/g,"");m=n.find[t](q,h,l);if(m!=null){g=g.replace(n.match[t],"");break}}}}m||(m=h.getElementsByTagName("*"));return{set:m,expr:g}};k.filter=function(g,h,l,m){for(var q=g,p=[],v=h,t,y,S=h&&h[0]&&x(h[0]);g&&h.length;){for(var H in n.filter)if((t=n.leftMatch[H].exec(g))!=null&&t[2]){var M=n.filter[H],I,D;D=t[1];y=false;t.splice(1,1);if(D.substr(D.length-
1)!=="\\"){if(v===p)p=[];if(n.preFilter[H])if(t=n.preFilter[H](t,v,l,p,m,S)){if(t===true)continue}else y=I=true;if(t)for(var U=0;(D=v[U])!=null;U++)if(D){I=M(D,t,U,v);var Ha=m^!!I;if(l&&I!=null)if(Ha)y=true;else v[U]=false;else if(Ha){p.push(D);y=true}}if(I!==w){l||(v=p);g=g.replace(n.match[H],"");if(!y)return[];break}}}if(g===q)if(y==null)k.error(g);else break;q=g}return v};k.error=function(g){throw"Syntax error, unrecognized expression: "+g;};var n=k.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
CLASS:/\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(g){return g.getAttribute("href")}},
relative:{"+":function(g,h){var l=typeof h==="string",m=l&&!/\W/.test(h);l=l&&!m;if(m)h=h.toLowerCase();m=0;for(var q=g.length,p;m<q;m++)if(p=g[m]){for(;(p=p.previousSibling)&&p.nodeType!==1;);g[m]=l||p&&p.nodeName.toLowerCase()===h?p||false:p===h}l&&k.filter(h,g,true)},">":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m<q;m++){var p=g[m];if(p){l=p.parentNode;g[m]=l.nodeName.toLowerCase()===h?l:false}}}else{m=0;for(q=g.length;m<q;m++)if(p=g[m])g[m]=
l?p.parentNode:p.parentNode===h;l&&k.filter(h,g,true)}},"":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("parentNode",h,m,g,p,l)},"~":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("previousSibling",h,m,g,p,l)}},find:{ID:function(g,h,l){if(typeof h.getElementById!=="undefined"&&!l)return(g=h.getElementById(g[1]))?[g]:[]},NAME:function(g,h){if(typeof h.getElementsByName!=="undefined"){var l=[];
h=h.getElementsByName(g[1]);for(var m=0,q=h.length;m<q;m++)h[m].getAttribute("name")===g[1]&&l.push(h[m]);return l.length===0?null:l}},TAG:function(g,h){return h.getElementsByTagName(g[1])}},preFilter:{CLASS:function(g,h,l,m,q,p){g=" "+g[1].replace(/\\/g,"")+" ";if(p)return g;p=0;for(var v;(v=h[p])!=null;p++)if(v)if(q^(v.className&&(" "+v.className+" ").replace(/[\t\n]/g," ").indexOf(g)>=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},
CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m,
g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},
text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},
setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return h<l[3]-0},gt:function(g,h,l){return h>l[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h=
h[3];l=0;for(m=h.length;l<m;l++)if(h[l]===g)return false;return true}else k.error("Syntax error, unrecognized expression: "+q)},CHILD:function(g,h){var l=h[1],m=g;switch(l){case "only":case "first":for(;m=m.previousSibling;)if(m.nodeType===1)return false;if(l==="first")return true;m=g;case "last":for(;m=m.nextSibling;)if(m.nodeType===1)return false;return true;case "nth":l=h[2];var q=h[3];if(l===1&&q===0)return true;h=h[0];var p=g.parentNode;if(p&&(p.sizcache!==h||!g.nodeIndex)){var v=0;for(m=p.firstChild;m;m=
m.nextSibling)if(m.nodeType===1)m.nodeIndex=++v;p.sizcache=h}g=g.nodeIndex-q;return l===0?g===0:g%l===0&&g/l>=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m===
"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g,
h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l<m;l++)h.push(g[l]);else for(l=0;g[l];l++)h.push(g[l]);return h}}var B;if(s.documentElement.compareDocumentPosition)B=function(g,h){if(!g.compareDocumentPosition||
!h.compareDocumentPosition){if(g==h)i=true;return g.compareDocumentPosition?-1:1}g=g.compareDocumentPosition(h)&4?-1:g===h?0:1;if(g===0)i=true;return g};else if("sourceIndex"in s.documentElement)B=function(g,h){if(!g.sourceIndex||!h.sourceIndex){if(g==h)i=true;return g.sourceIndex?-1:1}g=g.sourceIndex-h.sourceIndex;if(g===0)i=true;return g};else if(s.createRange)B=function(g,h){if(!g.ownerDocument||!h.ownerDocument){if(g==h)i=true;return g.ownerDocument?-1:1}var l=g.ownerDocument.createRange(),m=
h.ownerDocument.createRange();l.setStart(g,0);l.setEnd(g,0);m.setStart(h,0);m.setEnd(h,0);g=l.compareBoundaryPoints(Range.START_TO_END,m);if(g===0)i=true;return g};(function(){var g=s.createElement("div"),h="script"+(new Date).getTime();g.innerHTML="<a name='"+h+"'/>";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&&
q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML="<a href='#'></a>";
if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="<p class='TEST'></p>";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}();
(function(){var g=s.createElement("div");g.innerHTML="<div class='test e'></div><div class='test'></div>";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}:
function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q<p;q++)k(g,h[q],l);return k.filter(m,l)};c.find=k;c.expr=k.selectors;c.expr[":"]=c.expr.filters;c.unique=k.uniqueSort;c.text=a;c.isXMLDoc=x;c.contains=E})();var eb=/Until$/,fb=/^(?:parents|prevUntil|prevAll)/,
gb=/,/;R=Array.prototype.slice;var Ia=function(a,b,d){if(c.isFunction(b))return c.grep(a,function(e,j){return!!b.call(e,j,e)===d});else if(b.nodeType)return c.grep(a,function(e){return e===b===d});else if(typeof b==="string"){var f=c.grep(a,function(e){return e.nodeType===1});if(Ua.test(b))return c.filter(b,f,!d);else b=c.filter(b,f)}return c.grep(a,function(e){return c.inArray(e,b)>=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f<e;f++){d=b.length;
c.find(a,this[f],b);if(f>0)for(var j=d;j<b.length;j++)for(var i=0;i<d;i++)if(b[i]===b[j]){b.splice(j--,1);break}}return b},has:function(a){var b=c(a);return this.filter(function(){for(var d=0,f=b.length;d<f;d++)if(c.contains(this,b[d]))return true})},not:function(a){return this.pushStack(Ia(this,a,false),"not",a)},filter:function(a){return this.pushStack(Ia(this,a,true),"filter",a)},is:function(a){return!!a&&c.filter(a,this).length>0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j=
{},i;if(f&&a.length){e=0;for(var o=a.length;e<o;e++){i=a[e];j[i]||(j[i]=c.expr.match.POS.test(i)?c(i,b||this.context):i)}for(;f&&f.ownerDocument&&f!==b;){for(i in j){e=j[i];if(e.jquery?e.index(f)>-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a===
"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",
d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?
a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType===
1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/<tbody/i,jb=/<|&#?\w+;/,ta=/<script|<object|<embed|<option|<style/i,ua=/checked\s*(?:[^=]|=\s*.checked.)/i,Ma=function(a,b,d){return hb.test(d)?
a:b+"></"+d+">"},F={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div<div>","</div>"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d=
c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this},
wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})},
prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,
this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild);
return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja,
""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b<d;b++)if(this[b].nodeType===1){c.cleanData(this[b].getElementsByTagName("*"));this[b].innerHTML=a}}catch(f){this.empty().append(a)}}else c.isFunction(a)?this.each(function(e){var j=c(this),i=j.html();j.empty().append(function(){return a.call(this,e,i)})}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&
this[0].parentNode){if(c.isFunction(a))return this.each(function(b){var d=c(this),f=d.html();d.replaceWith(a.call(this,b,f))});if(typeof a!=="string")a=c(a).detach();return this.each(function(){var b=this.nextSibling,d=this.parentNode;c(this).remove();b?c(b).before(a):c(d).append(a)})}else return this.pushStack(c(c.isFunction(a)?a():a),"replaceWith",a)},detach:function(a){return this.remove(a,true)},domManip:function(a,b,d){function f(u){return c.nodeName(u,"table")?u.getElementsByTagName("tbody")[0]||
u.appendChild(u.ownerDocument.createElement("tbody")):u}var e,j,i=a[0],o=[],k;if(!c.support.checkClone&&arguments.length===3&&typeof i==="string"&&ua.test(i))return this.each(function(){c(this).domManip(a,b,d,true)});if(c.isFunction(i))return this.each(function(u){var z=c(this);a[0]=i.call(this,u,b?z.html():w);z.domManip(a,b,d)});if(this[0]){e=i&&i.parentNode;e=c.support.parentNode&&e&&e.nodeType===11&&e.childNodes.length===this.length?{fragment:e}:sa(a,this,o);k=e.fragment;if(j=k.childNodes.length===
1?(k=k.firstChild):k.firstChild){b=b&&c.nodeName(j,"tr");for(var n=0,r=this.length;n<r;n++)d.call(b?f(this[n],j):this[n],n>0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]);
return this}else{e=0;for(var j=d.length;e<j;e++){var i=(e>0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["",
""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]==="<table>"&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e=
c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]?
c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja=
function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter=
Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a,
"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f=
a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=
a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=/<script(.|\s)*?\/script>/gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!==
"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("<div />").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this},
serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),
function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,
global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&&
e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)?
"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache===
false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B=
false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since",
c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E||
d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x);
g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status===
1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b===
"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional;
if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");
this[a].style.display=d||"";if(c.css(this[a],"display")==="none"){d=this[a].nodeName;var f;if(la[d])f=la[d];else{var e=c("<"+d+" />").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a<b;a++)this[a].style.display=c.data(this[a],"olddisplay")||"";return this}},hide:function(a,b){if(a||a===0)return this.animate(K("hide",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");!d&&d!=="none"&&c.data(this[a],
"olddisplay",c.css(this[a],"display"))}a=0;for(b=this.length;a<b;a++)this[a].style.display="none";return this}},_toggle:c.fn.toggle,toggle:function(a,b){var d=typeof a==="boolean";if(c.isFunction(a)&&c.isFunction(b))this._toggle.apply(this,arguments);else a==null||d?this.each(function(){var f=d?a:c(this).is(":hidden");c(this)[f?"show":"hide"]()}):this.animate(K("toggle",3),a,b);return this},fadeTo:function(a,b,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,d)},
animate:function(a,b,d,f){var e=c.speed(b,d,f);if(c.isEmptyObject(a))return this.each(e.complete);return this[e.queue===false?"each":"queue"](function(){var j=c.extend({},e),i,o=this.nodeType===1&&c(this).is(":hidden"),k=this;for(i in a){var n=i.replace(ia,ja);if(i!==n){a[n]=a[i];delete a[i];i=n}if(a[i]==="hide"&&o||a[i]==="show"&&!o)return j.complete.call(this);if((i==="height"||i==="width")&&this.style){j.display=c.css(this,"display");j.overflow=this.style.overflow}if(c.isArray(a[i])){(j.specialEasing=
j.specialEasing||{})[i]=a[i][1];a[i]=a[i][0]}}if(j.overflow!=null)this.style.overflow="hidden";j.curAnim=c.extend({},a);c.each(a,function(r,u){var z=new c.fx(k,j,r);if(Ab.test(u))z[u==="toggle"?o?"show":"hide":u](a);else{var C=Bb.exec(u),B=z.cur(true)||0;if(C){u=parseFloat(C[2]);var E=C[3]||"px";if(E!=="px"){k.style[r]=(u||1)+E;B=(u||1)/z.cur(true)*B;k.style[r]=B+E}if(C[1])u=(C[1]==="-="?-1:1)*u+B;z.custom(B,u,E)}else z.custom(B,u,"")}});return true})},stop:function(a,b){var d=c.timers;a&&this.queue([]);
this.each(function(){for(var f=d.length-1;f>=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration===
"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||
c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;
this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=
this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem,
e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b<a.length;b++)a[b]()||a.splice(b--,1);a.length||
c.fx.stop()},stop:function(){clearInterval(W);W=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){c.style(a.elem,"opacity",a.now)},_default:function(a){if(a.elem.style&&a.elem.style[a.prop]!=null)a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit;else a.elem[a.prop]=a.now}}});if(c.expr&&c.expr.filters)c.expr.filters.animated=function(a){return c.grep(c.timers,function(b){return a===b.elem}).length};c.fn.offset="getBoundingClientRect"in s.documentElement?
function(a){var b=this[0];if(a)return this.each(function(e){c.offset.setOffset(this,a,e)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);var d=b.getBoundingClientRect(),f=b.ownerDocument;b=f.body;f=f.documentElement;return{top:d.top+(self.pageYOffset||c.support.boxModel&&f.scrollTop||b.scrollTop)-(f.clientTop||b.clientTop||0),left:d.left+(self.pageXOffset||c.support.boxModel&&f.scrollLeft||b.scrollLeft)-(f.clientLeft||b.clientLeft||0)}}:function(a){var b=
this[0];if(a)return this.each(function(r){c.offset.setOffset(this,a,r)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);c.offset.initialize();var d=b.offsetParent,f=b,e=b.ownerDocument,j,i=e.documentElement,o=e.body;f=(e=e.defaultView)?e.getComputedStyle(b,null):b.currentStyle;for(var k=b.offsetTop,n=b.offsetLeft;(b=b.parentNode)&&b!==o&&b!==i;){if(c.offset.supportsFixedPosition&&f.position==="fixed")break;j=e?e.getComputedStyle(b,null):b.currentStyle;
k-=b.scrollTop;n-=b.scrollLeft;if(b===d){k+=b.offsetTop;n+=b.offsetLeft;if(c.offset.doesNotAddBorder&&!(c.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(b.nodeName))){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=d;d=b.offsetParent}if(c.offset.subtractsBorderForOverflowNotVisible&&j.overflow!=="visible"){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=j}if(f.position==="relative"||f.position==="static"){k+=o.offsetTop;n+=o.offsetLeft}if(c.offset.supportsFixedPosition&&
f.position==="fixed"){k+=Math.max(i.scrollTop,o.scrollTop);n+=Math.max(i.scrollLeft,o.scrollLeft)}return{top:k,left:n}};c.offset={initialize:function(){var a=s.body,b=s.createElement("div"),d,f,e,j=parseFloat(c.curCSS(a,"marginTop",true))||0;c.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"});b.innerHTML="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";
a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b);
c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a,
d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top-
f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset":
"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in
e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window);
diff --git a/newviewfunctions.lua b/newviewfunctions.lua
new file mode 100644
index 0000000..2695c6d
--- /dev/null
+++ b/newviewfunctions.lua
@@ -0,0 +1,52 @@
require("html")
require("session")

-- Split a string to an array by delimiter or pattern
function split(str, pat)
   if string.find(str, pat) == nil then
   	return str
   end
   local t = {} 
   local fpat = "(.-)" .. pat
   local last_end = 1
   local s, e, cap = str:find(fpat, 1)
   while s do
     if s ~= 1 or cap ~= "" then
        table.insert(t,cap)
     end
     last_end = e+1
     s, e, cap = str:find(fpat, last_end)
   end
   if last_end <= #str then
      cap = str:sub(last_end)
      table.insert(t, cap)
   end
   return t
end

-- Insert a string into another string
function string.insert(value, insert, place)

   if place == nil then
       place = string.len(value)+1
   end

   return string.sub(value, 1,place-1) .. tostring(insert) .. string.sub(value, place, string.len(value))
					
end

--Highlight occurences of a word in a string
function string.highlight(txtvalue, searchval, fcolour, bcolour)

  if txtvalue ~=nil and searchval ~= nil then
      sStart = string.find(string.lower(txtvalue),string.lower(searchval))
      if sStart ~= nil then
        sEnd = sStart + string.len(searchval)
      	txtvalue = string.insert(txtvalue,"</font>", sEnd)
      	txtvalue = string.insert(txtvalue,"<font style='color:"..fcolour.."; background-color:"..bcolour..";'>", sStart)
     end
    end 
  
  return txtvalue

end
diff --git a/template-silent.lsp b/template-silent.lsp
new file mode 100644
index 0000000..45a8ad4
--- /dev/null
+++ b/template-silent.lsp
@@ -0,0 +1,9 @@
<% local viewtable, viewlibrary, pageinfo, session = ... %>
Status: 204 No content 
Content-Type: <% print(viewtable.option or "application/octet-stream") %>
<% if viewtable.length then %>
Content-Length: <%= viewtable.length %>
<% end %>
<% if viewtable.label ~= "" then %>
Content-Disposition: attachment; filename="<%= viewtable.label %>"
<% end %>
diff --git a/weblog-adhocquery-html.lsp b/weblog-adhocquery-html.lsp
index 002dba3..49675cd 100644
--- a/weblog-adhocquery-html.lsp
+++ b/weblog-adhocquery-html.lsp
@@ -4,7 +4,7 @@ require("viewfunctions")

<style type="text/css">
  #content table { border-collapse: collapse; width: 100%; }
  #content table td { white-space: nowrap; padding-right:20px; border-bottom:1px solid #999; }
  #content table td { white-space: normal; padding-right:20px; border-bottom:1px solid #999; }
  #content table tr.mark { background: #E9E9E9; }
</style>

diff --git a/weblog-config-html.lsp b/weblog-config-html.lsp
index 35f3ca5..7107721 100644
--- a/weblog-config-html.lsp
+++ b/weblog-config-html.lsp
@@ -1,9 +1,8 @@
<% local form, viewlibrary, page_info = ... 
require("viewfunctions")
%>

<H1><%= html.html_escape(form.label) %></H1>
<%
	local order = {"auditstart", "auditend", "historydays", "watchdays", "purgedays", "window", "shorturi", "shortreason", "groupby"}
	displayform(form, order, nil, page_info)
        local order = {"auditstart", "auditend", "badyesno", "sortby", "minimumscore", "window", "shorturi", "shortreason", "historydays", "watchdays", "purgedays" }
        displayform(form, order, nil, page_info)
%>
diff --git a/weblog-controller.lua b/weblog-controller.lua
index 26a69ae..eb9ff8c 100644
--- a/weblog-controller.lua
+++ b/weblog-controller.lua
@@ -50,25 +50,63 @@ function deletewatchlistentry(self)
end

function viewweblog(self)
	return self.model.getweblog(self.clientdata.clientuserid, self.clientdata.starttime, self.clientdata.endtime, self.clientdata.clientip, clientdata.focus)
	return self.model.getweblog(self.clientdata.activelog, self.clientdata.clientuserid, self.clientdata.starttime, self.clientdata.endtime, self.clientdata.clientip, self.clientdata.badyesno, self.clientdata.deniedyesno, self.clientdata.bypassyesno, self.clientdata.score, self.clientdata.urisearch, self.clientdata.sortby, self.clientdata.selected, clientdata.focus)
end

function downloadweblog(self)
	self.conf.viewtype = "stream"
	local retval = viewweblog(self)
	local file = cfe({ type="longtext", value="", label=retval.value.clientuserid.value .. ".log" })
	local content = {"sourcename\tclientip\tclientuserid\tlogdatetime\turi\tbytes\treason\tscore"}
	local file = cfe({ type="longtext", value="", label=retval.value.clientuserid.value .. ".csv" })
	local content = {"clientuserid,clientip,logdatetime,uri,bytes,reason,score,reason,badyesno,deniedyesno,bypassyesno"}
	for i,log in ipairs(retval.value.log.value) do
		content[#content+1] = string.format("%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t",
			log.sourcename, log.clientip, log.clientuserid, log.logdatetime,
			log.uri, log.bytes, log.reason or "", log.score or "0")
		content[#content+1] = string.format("%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,",
			log.clientuserid, log.clientip, log.logdatetime, log.uri, log.bytes, log.reason, log.score or "0", log.reason, log.badyesno, log.deniedyesno, log.bypassyesno )
			
	end
	file.value = table.concat(content, "\n")
	return file
end

function viewblocklog(self)
	return self.model.getblocklog(self.clientdata.clientuserid, self.clientdata.starttime, self.clientdata.endtime, self.clientdata.clientip, clientdata.focus)
function downloadlogview(self)
	thisdate=os.date()
	self.conf.viewtype = "stream"
	local retval = viewweblog(self)
	local file = cfe({ type="longtext", value="", label="Weblog-resnet-"..thisdate..".tab" })
	local content = {"clientuserid\tclientip\tlogdatetime\turi\tbytes\treason\tscore\treason\tbadyesno\tdeniedyesno\tbypassyesno"}
	for i,log in ipairs(retval.value.log.value) do
		content[#content+1] = string.format("%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t",
			log.clientuserid, log.clientip, log.logdatetime, log.uri, log.bytes, log.reason, log.score or "0", log.reason, log.badyesno, log.deniedyesno, log.bypassyesno )
	end
	file.value = table.concat(content, "\n")
	return file
end

function downloadselected(self)
	thisdate=os.date()
	self.conf.viewtype = "stream"
	local retval = viewselected(self)	
	local file = cfe({ type="longtext", value="", label="Weblog-resnet-selected-"..thisdate..".tab" })
	local content = {"clientuserid\tclientip\tlogdatetime\turi\tbytes\treason\tscore\treason\tbadyesno\tdeniedyesno\tbypassyesno"}
	for i,log in ipairs(retval.value.log.value) do
		content[#content+1] = string.format("%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t",
		log.clientuserid, log.clientip, log.logdatetime, log.uri, log.bytes, log.reason, log.score or "0", log.reason, log.badyesno, log.deniedyesno, log.bypassyesno )
	end	
	file.value = table.concat(content, "\n") 
	return file
end

function checkselected(self)
	self.conf.viewtype = "silent"
	return self.model.editselected(self.clientdata.chkdata)
	--return file
end	
function clearselected(self)
	 return self:redirect_to_referrer(self.model.clearselected())
end

function viewselected(self)
	--return self.model.getselected(self.clientdata.csvdata, self.clientdata.starttime, self.clientdata.endtime)
	return self.model.getweblog(self.clientdata.activelog, self.clientdata.clientuserid, self.clientdata.starttime, self.clientdata.endtime, self.clientdata.clientip, self.clientdata.badyesno, self.clientdata.deniedyesno, self.clientdata.bypassyesno, self.clientdata.score, self.clientdata.urisearch, self.clientdata.sortby, self.clientdata.getselected, clientdata.focus)
end

function viewusagestats(self)
@@ -120,3 +158,18 @@ end
function createdatabase(self)
	return controllerfunctions.handle_form(self, self.model.getnewdatabase, self.model.create_database, self.clientdata, "Create", "Create New Database", "Database Created")
end

function listfiles(self)
	return self.model.listfiles(self)
end
function createfile(self)
        return controllerfunctions.handle_form(self, self.model.getnewfile, self.model.createfile, self.clientdata, "Create", "Create New Weblog File", "Weblog File Created")
end
        
function editfile(self)
        return controllerfunctions.handle_form(self, function() return self.model.readfile(self.clientdata.filename) end, self.model.updatefile, self.clientdata, "Save", "Edit Weblog File", "Weblog File Saved" )
end
              
function deletefile(self)
        return self:redirect_to_referrer(self.model.deletefile(self.clientdata.filename))
end
diff --git a/weblog-editfile-html.lsp b/weblog-editfile-html.lsp
new file mode 120000
index 0000000..15b1930
--- /dev/null
+++ b/weblog-editfile-html.lsp
@@ -0,0 +1 @@
../filedetails-html.lsp
\ No newline at end of file
diff --git a/weblog-listfiles-html.lsp b/weblog-listfiles-html.lsp
new file mode 100644
index 0000000..c2fe301
--- /dev/null
+++ b/weblog-listfiles-html.lsp
@@ -0,0 +1,42 @@
<% local view, viewlibrary, page_info, session = ... 
require("viewfunctions")
%>

<% displaycommandresults({"editfile", "deletefile", "startstop"}, session) %>
<% displaycommandresults({"createfile"}, session, true) %>


<H1>File List</H1>
<DL>
<TABLE>
	<TR style="background:#eee;font-weight:bold;">
		<TD style="padding-right:20px;white-space:nowrap;text-align:left;" class="header">Action</TD>
		<TD style="white-space:nowrap;text-align:left;" class="header">File</TD>
	</TR>
<% for i,file in ipairs(view.value) do %>
	<TR>
		<TD style="padding-right:20px;white-space:nowrap;">
		<% if viewlibrary.check_permission("editfile") then %>	
			<%= html.link{value=page_info.script..page_info.prefix..page_info.controller.."/editfile?filename="..file.."&redir="..page_info.orig_action, label="Edit "} %>
		<% end %>
		<% if viewlibrary.check_permission("deletefile") then %>	
			<%= html.link{value=page_info.script..page_info.prefix..page_info.controller.."/deletefile?filename="..file, label="Delete "} %>
		<% end %>
		</TD>
		<TD style="white-space:nowrap;"><%= html.html_escape(file) %></TD>
	</TR>
<% end %>
</TABLE>
</DL>

<% if viewlibrary and viewlibrary.dispatch_component and viewlibrary.check_permission("createfile") then
	local createform = viewlibrary.dispatch_component("createfile", nil, true) %>
<H2><%= html.html_escape(createform.label) %></H2>
<%
	createform.action = page_info.script .. page_info.prefix .. page_info.controller .. "/createfile"
	displayform(createform)
end %>

<% if viewlibrary and viewlibrary.dispatch_component and viewlibrary.check_permission("startstop") then
	viewlibrary.dispatch_component("startstop")
end %>
diff --git a/weblog-maintenance-html.lsp b/weblog-maintenance-html.lsp
new file mode 100644
index 0000000..2ca1dc7
--- /dev/null
+++ b/weblog-maintenance-html.lsp
@@ -0,0 +1,17 @@
<% local form, viewlibrary, page_info = ... 
require("viewfunctions")
%>

<style type="text/css">
  #content table { border-collapse: collapse; width: 100%; }
  #content table td { white-space: normal; padding-right:20px; border-bottom:1px solid #999; }
  #content table tr.mark { background: #E9E9E9; }
</style>

<H1>Maintenance</H1>
<% displayformstart(form, page_info) %>
<% displayformitem(form.value.query, "query") %>
<% displayformend(form) %>
<H2>Purge Database Operations</H2>
<H3>Analysis Operations</H3>
<H4>Actions</H4>
diff --git a/weblog-model.lua b/weblog-model.lua
index 8db7490..4c5ae8f 100644
--- a/weblog-model.lua
+++ b/weblog-model.lua
@@ -6,44 +6,40 @@ require("fs")
require("format")
require("validator")
require("luasql.postgres")
require("date")

local DatabaseName = "webproxylog"
local DatabaseName = "weblog"
local DatabaseOwner = "weblogowner"
local DatabaseUser = "webloguser"

local path = "PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin "
local env
local con
local configfile = "/etc/weblog.conf"
local configfile = "/etc/weblog/weblog.conf"
local configcontent = fs.read_file(configfile) or ""
local config = format.parse_ini_file(configcontent, "") or {}
local goodwordslist = "/etc/weblog/goodwords"
local badwordslist = "/etc/weblog/badwords"
local baseurl = "/etc/weblog/"

local database_creation_script = {
	"CREATE TABLE dbhistlog (logdatetime timestamp(3) without time zone NOT NULL, msgtext text)",
	"CREATE TABLE pubblocklog(sourcename character varying(40), clientip inet NOT NULL, clientuserid character varying(64) NOT NULL, logdatetime timestamp(3) without time zone NOT NULL, uri text NOT NULL, bytes bigint NOT NULL, reason text, score integer, shortreason text)",
	"CREATE TABLE blocklog(sourcename character varying(40), clientip inet NOT NULL, clientuserid character varying(64) NOT NULL, logdatetime timestamp(0) without time zone NOT NULL, uri text NOT NULL, bytes bigint NOT NULL, reason text, score integer, shortreason text)",
	"CREATE TABLE pubweblog(sourcename character varying(40), clientip inet NOT NULL, clientuserid character varying(64) NOT NULL, logdatetime timestamp(3) without time zone NOT NULL, uri text NOT NULL, bytes bigint NOT NULL, reason text, score integer, shortreason text)",
	"CREATE TABLE weblog(sourcename character varying(40), clientip inet NOT NULL, clientuserid character varying(64) NOT NULL, logdatetime timestamp(3) without time zone NOT NULL, uri text NOT NULL, bytes bigint NOT NULL, reason text, score integer, shortreason text)",
	"CREATE TABLE pubweblog(sourcename character varying(40), clientip inet NOT NULL, clientuserid character varying(64) NOT NULL, logdatetime timestamp(3) without time zone NOT NULL, uri text NOT NULL, bytes bigint NOT NULL, reason text, score integer, shortreason text, badyesno int, deniedyesno int, bypassyesno int, wordloc text, goodwordloc text, selected boolean, id serial)",
	"CREATE TABLE pubweblog_history(sourcename character varying(40), clientip inet NOT NULL, clientuserid character varying(64) NOT NULL, logdatetime timestamp(3) without time zone NOT NULL, uri text NOT NULL, bytes bigint NOT NULL, reason text, score integer, shortreason text, badyesno int, deniedyesno int, bypassyesno int, wordloc text, goodwordloc text, selected boolean, id int)",
	"CREATE TABLE source (sourcename character varying(40) NOT NULL, method character varying(100) NOT NULL, userid character varying(32), passwd character varying(255), source character varying(255) NOT NULL, tzislocal boolean, enabled boolean)",
	"CREATE TABLE usagestat (sourcename character varying(40) NOT NULL, date timestamp(0) without time zone NOT NULL, numrequest integer, numblock integer)",
	"CREATE TABLE watchlist (clientuserid character varying(64) NOT NULL, expiredatetime timestamp(0) without time zone NOT NULL)",
	"CREATE TABLE usagestat(sourcename character varying(40) NOT NULL, date timestamp(0) without time zone NOT NULL, numrequest integer, numblock integer)",
	"CREATE TABLE watchlist(clientuserid character varying(64) NOT NULL, expiredatetime timestamp(0) without time zone NOT NULL)",
	"ALTER TABLE ONLY source ADD CONSTRAINT source_pkey PRIMARY KEY (sourcename)",
	"CREATE INDEX blocklogclientididx ON blocklog USING btree (clientuserid)",
	"CREATE INDEX blocklogclientidx ON blocklog USING btree (clientip, clientuserid)",
	"CREATE INDEX dbhistlogdatetimeidx ON dbhistlog USING btree (logdatetime)",
	"CREATE INDEX pubblocklogclientididx ON pubblocklog USING btree (clientuserid)",
	"CREATE INDEX pubblocklogclientidx ON pubblocklog USING btree (clientip, clientuserid)",
	"CREATE INDEX pubweblogclientdateidx ON pubweblog USING btree (logdatetime, clientuserid)",
	"CREATE INDEX pubweblogclientidx ON pubweblog USING btree (clientip, clientuserid)",
	"CREATE INDEX pubweblogclientipidx ON pubweblog USING btree (clientip)",
	"CREATE INDEX pubweblogclientuserididx ON pubweblog USING btree (clientuserid)",
	"CREATE INDEX pubwebloglogdatetimeidx ON pubweblog USING btree (logdatetime)",
	"CREATE INDEX weblogclientidx ON weblog USING btree (clientip, clientuserid)",
	"CREATE INDEX weblogclientipidx ON weblog USING btree (clientip)",
	"CREATE INDEX weblogclientuserididx ON weblog USING btree (clientuserid)",
	"CREATE INDEX pubweblog_historyclientdateidx ON pubweblog_history USING btree (logdatetime, clientuserid)",
	"CREATE INDEX pubweblog_historyclientuserididx ON pubweblog_history USING btree (clientuserid)",
	"CREATE INDEX pubweblog_historylogdatetimeidx ON pubweblog_history USING btree (logdatetime)",
	"GRANT SELECT ON dbhistlog TO "..DatabaseUser,
	"GRANT SELECT ON pubblocklog TO "..DatabaseUser,
	"GRANT SELECT ON pubweblog TO "..DatabaseUser,
	"GRANT SELECT ON pubweblog_history TO "..DatabaseUser,
	"GRANT SELECT, UPDATE, INSERT, DELETE ON source TO "..DatabaseUser,
	"GRANT SELECT ON usagestat TO "..DatabaseUser,
	"GRANT SELECT, UPDATE, INSERT, DELETE ON watchlist TO "..DatabaseUser,
@@ -137,7 +133,7 @@ local runSQLscript = function(filename)
end

-- Create the database and tables
--- pg_dump -U postgres -c webproxylog > makeweblog.postgres
-- pg_dump -U postgres -c weblog > makeweblog.postgres
--runSQLscript("/root/work/weblog/makeweblog.postgres")

local databaseconnect = function(username, password)
@@ -181,21 +177,39 @@ end

local importsquidlog = function(entry, sourcename)
	if entry then
		local sql = string.format("INSERT INTO weblog VALUES ('%s', '%s', '%s', '%s', '%s', '%s')",
		local sql = string.format("INSERT INTO pubweblog VALUES ('%s', '%s', '%s', '%s', '%s', '%s','%s','%s','%s','%s','%s','%s','%s')",
			escape(sourcename), escape(entry.clientip), escape(entry.clientuserid, 64):lower(),
			escape(entry.logdatetime), escape(entry.URL), escape(entry.bytes))
			escape(entry.logdatetime), escape(entry.URL), escape(entry.bytes), escape(entry.reason), escape(entry.score), escape(entry.shortreason), escape(entry.badyesno), escape(entry.deniedyesno), escape(entry.bypassyesno), escape(entry.wordloc), escape(entry.goodwordloc))
			
		local res = assert (con:execute(sql))
	end
end

local importsquarklog = function(entry, sourcename)
        if entry then
           local sql = string.format("INSERT INTO pubweblog VALUES ('%s', '%s', '%s', '%s', '%s', '%s','%s','%s','%s','%s','%s','%s','%s')",
	          escape(sourcename), escape(entry.clientip), escape(entry.clientuserid, 64):lower(),
                  escape(entry.logdatetime), escape(entry.URL), escape(entry.bytes), escape(entry.reason), escape(entry.score), escape(entry.shortreason), escape(entry.badyesno), escape(entry.deniedyesno), escape(entry.bypassyesno), escape(entry.wordloc), escape(entry.gwordloc))
           local res = assert (con:execute(sql))
        end
end

local importdglog = function(entry, sourcename)
	if entry then
		local sql = string.format("INSERT INTO blocklog VALUES ('%s', '0.0.0.0', '%s', '%s', '%s', '%s', '%s', '%s', '%s')",
			escape(sourcename), escape(entry.clientuserid:lower(), 64), escape(entry.logdatetime), escape(entry.URL),
			escape(entry.bytes), escape(entry.reason), escape(entry.score or "0"), escape(entry.shortreason))
		local res = assert (con:execute(sql))
           local sql = string.format("INSERT INTO pubweblog VALUES ('%s', '%s', '%s', '%s', '%s', '%s','%s','%s','%s','%s','%s','%s','%s')",
	          escape(sourcename), escape(entry.clientip), escape(entry.clientuserid, 64):lower(),
                  escape(entry.logdatetime), escape(entry.URL), escape(entry.bytes), escape(entry.reason), escape(entry.score), escape(entry.shortreason), escape(entry.badyesno), escape(entry.deniedyesno), escape(entry.bypassyesno), escape(entry.wordloc), escape(entry.gwordloc))
           local res = assert (con:execute(sql))
	end
end
end 
local importdumplog = function(entry, sourcename)
	if entry then
           local sql = string.format("INSERT INTO pubweblog VALUES ('%s', '%s', '%s', '%s', '%s', '%s','%s','%s','%s','%s','%s','%s','%s')",
	          escape(sourcename), escape(entry.clientip), escape(entry.clientuserid, 64):lower(),
                  escape(entry.logdatetime), escape(entry.URL), escape(entry.bytes), escape(entry.reason), escape(entry.score), escape(entry.shortreason), escape(entry.badyesno), escape(entry.deniedyesno), escape(entry.bypassyesno), escape(entry.wordloc), escape(entry.gwordloc))
           local res = assert (con:execute(sql))
	end
end 

local listsourceentries = function(sourcename)
	local sources = {}
@@ -245,7 +259,7 @@ local addtowatchlist = function()
	local watchdays = config.watchdays or 14
	local sql = "insert into watchlist select clientuserid, " ..
		"(max(logdatetime) + INTERVAL '"..watchdays.." days') as expiredatetime " ..
		"from blocklog group by clientuserid"
		"from pubweblog where bypassyesno > '0' group by clientuserid"
	local res1 = assert (con:execute(sql))
	sql = "delete from watchlist where exists " ..
		"(select * from watchlist w where w.clientuserid = watchlist.clientuserid " ..
@@ -258,67 +272,11 @@ end
local updateusagestats = function()
	-- update the usagestat table from weblog
	-- (will result in multiple rows where logs rotated on partial hours)
	local sql = "insert into usagestat select weblog.sourcename, " ..
		"date_trunc('hour', weblog.logdatetime) as date, " ..
		"count(*), 0 from weblog group by sourcename,date"
	local sql = "insert into usagestat select pubweblog.sourcename, " ..
		"date_trunc('hour', pubweblog.logdatetime) as date, " ..
		"count(*), SUM(deniedyesno) from pubweblog group by sourcename,date"
	local res = assert (con:execute(sql))

	-- update the usagestat table from blocklog
	-- (will result in multiple rows where logs rotated on partial hours)
	-- (also, numrequest and numblock end up in different rows)
	sql= "insert into usagestat select blocklog.sourcename, " ..
		"date_trunc('hour', blocklog.logdatetime) as date, " ..
		"0, count(*) from blocklog group by sourcename,date"
	res = assert (con:execute(sql))
end

--- Process weblog and blocklog, combine into pubweblog and pubblocklog
--- empties weblog and blocklog
local importpubweblog = function()
	local sql = "ANALYZE"
	res = assert (con:execute(sql))
	-- Merge equal blocks into weblog
	sql = "update weblog set reason=blocklog.reason, " ..
		"score=blocklog.score, shortreason=blocklog.shortreason from blocklog where " ..
		"blocklog.logdatetime >= date_trunc('second', weblog.logdatetime) and " ..
		"blocklog.logdatetime < (weblog.logdatetime + INTERVAL '45' second) and " ..
		"blocklog.sourcename=weblog.sourcename and "..
		"blocklog.clientuserid=weblog.clientuserid and "..
		"weblog.uri like (blocklog.uri || '%')"
	res = assert (con:execute(sql))
	logme("importpubweblog merged " .. res .. " blocks with matching timestamps.")

	sql = "insert into weblog select * from blocklog where " ..
		" NOT EXISTS (select * from weblog where " ..
		"blocklog.logdatetime >= date_trunc('second', weblog.logdatetime) and " ..
		"blocklog.logdatetime < (weblog.logdatetime + INTERVAL '45' second) and " ..
		"blocklog.sourcename=weblog.sourcename and "..
		"blocklog.clientuserid=weblog.clientuserid and "..
		"weblog.uri like (blocklog.uri || '%') )"
	res = assert (con:execute(sql))
	if ( res > 0 ) then
		logme("NOTE: importpubweblog found and merged " .. res .. " unmatched blocks (source IP will not match)")
	end

	-- Move weblog to pubweblog
	sql= "insert into pubweblog select * from weblog"
	res = assert (con:execute(sql))
	logme("importpubweblog imported " .. res .. " new rows into database.")

	-- update pubblocklog table
	sql = "insert into pubblocklog select * from weblog where reason is not null"
	res = assert (con:execute(sql))
	logme("importpubweblog imported " .. res .. " new blocks into block table.")

	-- grab the bypass info
	sql = "insert into pubblocklog select * from weblog where uri like '%?GBYPASS%'"
	res = assert (con:execute(sql))
	logme("importpubweblog imported " .. res .. " dg bybass events into block table.")

	-- Truncate the staging tables
	assert (con:execute("truncate weblog"))
	assert (con:execute("truncate blocklog"))
	logme("truncated staging tables")
end

-- Delete people from the watchlist when they have expired out
@@ -344,41 +302,38 @@ end
-- Delete old junk from pub tables
local groompublogs = function()
	local purgedays = config.purgedays or 30
	local watchdays = config.watchdays or 14
	local historydays = config.historydays or 14
	--local watchdays = config.watchdays or 14
	--local historydays = config.historydays or 14
	
	local now = os.time()

	local temp = os.date("%Y-%m-%d %H:%M:%S", now - purgedays*86400)
	logme("Purgedate is " .. temp .. ". Nothing will exist beyond purgedate.")
	logme("Purgedate is " .. temp .. ". Nothing will exist in pubweblog beyond purgedate.")

	-- purge anything older than purgedate
	sql = "delete from pubweblog where logdatetime < '" .. temp .."'"
	-- Move flagged records to histoy and then purge anything older than purgedate
	sql = "Insert into pubweblog_history select * from pubweblog where logdatetime < '" .. temp .."' and (badyesno > 0 or deniedyesno > 0 or bypassyesno > 0 or selected = 'true')"
	res = assert (con:execute(sql))
	logme("Purged " .. res .. " old records from pubweblog")

	sql = "delete from pubblocklog where logdatetime < '" .. temp .. "'"
	logme("Moved " .. res .. " old records to history")
	
	sql = "Delete from pubweblog where logdatetime < '" .. temp .."'"
	res = assert (con:execute(sql))
	logme("Purged " .. res .. " old records from pubblocklog")
	logme("Deleted " .. res .. " old records to from pubweblog")

	-- purge anything older than startddate+historydays+watchdays
	local temp = config.auditstart
	if not temp or temp == "" then temp = os.date("%Y-%m-%d %H:%M:%S") end
	logme("Purge date since last audit is " .. tostring(watchdays+historydays) .. " days before " .. temp .. ".")

	sql = "delete from pubweblog where logdatetime < (timestamp '"..temp.."' - INTERVAL '"..tostring(watchdays+historydays).." days')"
	res = assert (con:execute(sql))
        logme("removed " .. res .. " old pubweblog records that are older than history+watchdays")
	--local temp = config.auditstart
	--if not temp or temp == "" then temp = os.date("%Y-%m-%d %H:%M:%S") end
	--logme("Purge date since last audit is " .. tostring(watchdays+historydays) .. " days before " .. temp .. ".")

	sql = "delete from pubblocklog where logdatetime < (timestamp '"..temp.."' - INTERVAL '"..tostring(watchdays+historydays).." days')"
	res = assert (con:execute(sql))
        logme("removed " .. res .. " old pubblocklog records that are older than history+watchdays")
	--sql = "delete from pubweblog where logdatetime < (timestamp '"..temp.."' - INTERVAL '"..tostring(watchdays+historydays).." days')"
	--res = assert (con:execute(sql))
        --logme("removed " .. res .. " old pubweblog records that are older than history+watchdays")

	-- purge good people after historydays
	logme("The delete date for non-watchlist users is " .. tostring(historydays) .. " days before " .. temp .. ".")
	--logme("The delete date for non-watchlist users is " .. tostring(historydays) .. " days before " .. temp .. ".")

	sql = "delete from pubweblog where logdatetime < (timestamp '".. temp.."' - INTERVAL '"..tostring(historydays).." days') and clientuserid NOT IN (select clientuserid from watchlist)"
	res = assert (con:execute(sql))
	logme("removed " .. res .. " records for users not on the watchlist.")
	--sql = "delete from pubweblog where logdatetime < (timestamp '".. temp.."' - INTERVAL '"..tostring(historydays).." days') and clientuserid NOT IN (select clientuserid from watchlist)"
	--res = assert (con:execute(sql))
	--logme("removed " .. res .. " records for users not on the watchlist.")
end

local listwatchlistentries = function()
@@ -408,11 +363,11 @@ local deletewatchlistentry = function(clientuserid)
	return res
end

local generatewhereclause = function(clientuserid, starttime, endtime, clientip)
local generatewhereclause = function(clientuserid, starttime, endtime, clientip, badyesno, deniedyesno, bypassyesno, score, urisearch, selected)
	local sql = ""
	local where = {}
	if clientuserid and clientuserid ~= "" then
		where[#where+1] = "clientuserid = '"..escape(clientuserid).."'"
		where[#where+1] = "clientuserid LIKE '%"..escape(clientuserid).."%'"
	end
	if starttime and starttime ~= "" then
		where[#where+1] = "logdatetime >= '"..escape(starttime).."'"
@@ -423,25 +378,46 @@ local generatewhereclause = function(clientuserid, starttime, endtime, clientip)
	if clientip and clientip ~= "" then
		where[#where+1] = "clientip = '"..escape(clientip).."'"
	end
	if badyesno and badyesno ~= "" then
		where[#where+1] = "badyesno = '"..escape(badyesno).."'"
	end
	if deniedyesno and deniedyesno ~= "" then
		where[#where+1] = "deniedyesno = '"..escape(deniedyesno).."'"
	end
	if bypassyesno and bypassyesno ~= "" then
		where[#where+1] = "bypassyesno = '"..escape(bypassyesno).."'"
	end
	if score and score ~= "" then
		where[#where+1] = "score >= '"..escape(score).."'"
	end
	if urisearch and urisearch ~= "" then 
	    	where[#where+1] = "lower(uri) LIKE '%"..escape(urisearch).."%'"
	end
	
	if selected and selected == "true" then
		where[#where+1] = "selected = 'true'"
	end
	
	if #where > 0 then
		sql = " WHERE " .. table.concat(where, " AND ")
	end
	 
	return sql
end

local listlogentries = function(logname, clientuserid, starttime, endtime, clientip)
local listlogentries = function(activelog, clientuserid, starttime, endtime, clientip, badyesno, deniedyesno, bypassyesno, score, urisearch, sortby, selected)
	local entries = {}
	-- retrieve a cursor
	local sql = "SELECT * from "..logname
	sql = sql .. generatewhereclause(clientuserid, starttime, endtime, clientip)
	sql = sql .. " ORDER BY logdatetime"
	local sql = "SELECT * FROM "..activelog
	sql = sql .. generatewhereclause(clientuserid, starttime, endtime, clientip, badyesno, deniedyesno, bypassyesno, score, urisearch, selected)
	sql = sql .. " ORDER BY "..sortby
	cur = assert (con:execute(sql))
	row = cur:fetch ({}, "a")
	while row do
		if config.shorturi == "true" then
			shorturi=string.gsub(row.uri, "[;?].*", "...")
		end
		entries[#entries+1] = {sourcename=row.sourcename, clientip=row.clientip, clientuserid=row.clientuserid, logdatetime=row.logdatetime, uri=row.uri, shorturi=shorturi, bytes=row.bytes, reason=row.reason, score=row.score, shortreason=row.shortreason}
		entries[#entries+1] = {sourcename=row.sourcename, clientip=row.clientip, clientuserid=row.clientuserid, logdatetime=row.logdatetime, uri=row.uri, shorturi=shorturi, bytes=row.bytes, reason=row.reason, score=row.score, shortreason=row.shortreason, badyesno=row.badyesno, deniedyesno=row.deniedyesno, bypassyesno=row.bypassyesno, wordloc=row.wordloc, id=row.id, selected=row.selected }
		if (config.shortreason ~= "true") then
			entries[#entries].shortreason = nil
		end
@@ -452,31 +428,8 @@ local listlogentries = function(logname, clientuserid, starttime, endtime, clien
	return entries
end

local listpubblocklogentries = function(...)
	return listlogentries("pubblocklog", ...)
end

local listpubweblogentries = function(...)
	return listlogentries("pubweblog", ...)
end

local grouppubblocklogentries = function(starttime, endtime, groupby)
	groupby = groupby or "clientuserid"
	local entries = {}
	-- retrieve a cursor
	local sql = "SELECT "..groupby..", count(*) AS numblock, max(score) AS maxscore FROM pubblocklog"
	sql = sql .. generatewhereclause(nil, starttime, endtime)
	sql = sql .. " GROUP BY "..groupby.. " ORDER BY numblock DESC"
	cur = assert (con:execute(sql))
	row = cur:fetch ({}, "a")
	while row do
		entries[#entries+1] = {numblock=row.numblock, maxscore=row.maxscore}
		entries[#entries][groupby] = row[groupby]
		row = cur:fetch (row, "a")
	end
	-- close everything
	cur:close()
	return entries
	return listlogentries(...)
end

local listusagestats = function()
@@ -561,9 +514,87 @@ local function parsesquidlog(line)
	-- Format of squid log (space separated):
	-- time elapsed remotehost code/status bytes method URL rfc931 peerstatus/peerhost
	local words = {}
	
	for word in string.gmatch(line, "%S+") do
		words[#words+1] = word
	end
	
	local goodwordloc=""
	local badwordloc=""
	-- logme("value of word7 is "..words[7])
	local wrdcnt=0
	local isbad=0
	local isdenied=0
	local isbypass=0
	local ignoreme=false
	
	--check for ignored records first
	for thisline in io.lines("/etc/weblog/ignorewords") do
		if not thisline then
			break
		end
		_,instcnt = string.lower(words[7]):gsub(thisline, " ")
		if instcnt ~= 0 then
		   ignoreme = true
		   break
		end
	end

	if ignoreme ~= true then
	 --proceed with record analysis
	  for thisline in io.lines("/etc/weblog/badwords") do
		if not thisline then
			break
		end
		
		_,instcnt = string.lower(words[7]):gsub(thisline, " ")  
		--if string.find(words[7],thisline) ~= nil then
		if instcnt ~= 0 then
		 -- logme("instcnt =  "..instcnt)
		  isbad=1
		  wrdcnt= wrdcnt + instcnt 
		  if badwordloc ~= "" then 
		    badwordloc = badwordloc.."|"..thisline
		  else
		    badwordloc=thisline
		  end
		 
	        end
		
		if string.find(words[7],"*DENIED*") then
		   logme("*Denied*")
		   isdenied=1
		elseif string.find(words[7],"GBYPASS") then
		   logme("GBYPASS")
		   isbypass=1
		elseif string.find(words[7],"*OVERRIDE*") then
		   logme("*OVERRIDE*")
		   isbypass=1
		end
	  end
	  for goodline in io.lines("/etc/weblog/goodwords") do
		if not goodline then
		  break
		end
		_,instcnt = string.lower(words[7]):gsub(goodline, " ")
		--if string.find(words[7],goodline) then
		if instcnt ~= 0 then
		  if wrdcnt ~= 0 then
		     wrdcnt = wrdcnt - instcnt
		     if goodwordloc ~= "" then
		        goodwordloc = goodwordloc.."|"..goodline
		     else 
		        goodwordloc = goodline
		     end
		  end
		end
	  end	
	end
	-- Reset bad to reduce number of bad hits if score is zero
	-- if wrdcnt == 0 then
	-- isbad=0
	-- end
		
	local logentry = {logdatetime=words[1],
		elapsed=words[2],
		clientip=words[3],
@@ -574,32 +605,334 @@ local function parsesquidlog(line)
		URL=words[7],
		clientuserid=words[8],
		peerstatus=string.match(words[9] or "", "^[^/]*"),
		peerhost=string.match(words[9] or "", "[^/]*$")}
		peerhost=string.match(words[9] or "", "[^/]*$"),
		score=wrdcnt,
		badyesno=isbad,
		deniedyesno=isdenied,
		bypassyesno=isbypass,		
		wordloc=badwordloc,
		gwordloc=goodwordloc}	

	-- Don't care about local requests (from DG) (this check also removes blank lines)
	if logentry.clientip and logentry.clientip ~= "127.0.0.1" then
	   if logentry.clientuserid and logentry.clientuserid ~= "-" then
		logentry.logdatetime = os.date("%Y-%m-%d %H:%M:%S", logentry.logdatetime)..string.match(logentry.logdatetime, "%..*")
		return logentry
           end
	end
	return nil
end

local function parsesquarklog(line)
	-- Format of squid log (space separated):
	-- time elapsed remotehost code/status bytes method URL rfc931 peerstatus/peerhost
	local words = {}
	
	for word in string.gmatch(line, "%S+") do
		words[#words+1] = word
	end

	local goodwordloc=""
	local badwordloc=""
	local wrdcnt=0
	local isbad=0
	local isdenied=0
	local isbypass=0
	local ignoreme=false
	
	--check for ignored records first
	for thisline in io.lines("/etc/weblog/ignorewords") do
		if not thisline then
			break
		end
		_,instcnt = string.lower(words[5]):gsub(thisline, " ")
		if instcnt ~= 0 then
		   ignoreme = true
		   break
		end
	end

 	if ignoreme ~= true then	
	  for thisline in io.lines(baseurl.."badwords") do
		if not thisline then
			-- logme("This line is apparently empty...")
			break
		end
		
		_,instcnt = string.lower(words[5]):gsub(thisline, " ")
	--	if string.find(words[5],thisline) ~= nil then
		--logme("checking "..thisline.." against "..words[5])
		if instcnt ~= 0 then
		  isbad=1
		  wrdcnt = wrdcnt + instcnt
		if badwordloc ~= "" then 
		    badwordloc = badwordloc.."|"..thisline
		else
		    badwordloc=thisline
		end
		 
		  -- logme("bad "..badwordloc)
	        end
	
		if string.find(words[6],"*DENIED*") then	
		   isdenied=1
		end
		if string.find(words[6],"*OVERRIDE*") then
		   isbypass=1
		end
	end
	for goodline in io.lines(baseurl.."goodwords") do
		if not goodline then
		  -- logme("This line is apparently empty...")
		  break
		end
		_,instcnt = string.lower(words[5]):gsub(goodline, " ")
		--if string.find(words[4],goodline) then
		  if instcnt ~= 0 then
		   if wrdcnt ~= 0 then
		     wrdcnt = wrdcnt - instcnt
		     if goodwordloc ~= "" then
		        goodwordloc = goodwordloc.."|"..goodline
		     else 
		        goodwordloc = goodline
		     end
		  end
		end
	  end
	end
	
	local words = format.string_to_table(line, "\t")	
	local logentry = {logdatetime=words[1],
			clientuserid=words[2],
			clientip=words[3],
			URL=words[4],
			reason=words[5],
			method=words[6],
			bytes=words[7],
			shortreason=words[9],
			score=wrdcnt,
			badyesno=isbad,
			deniedyesno=isdenied,
			bypassyesno=isbypass,		
			wordloc=badwordloc,
			gwordloc=goodwordloc}	

	if logentry.reason and logentry.reason ~= "" then
           	if logentry.shortreason == "" then
           		logentry.shortreason = logentry.reason
           	end
	   	return logentry
	end
	return nil
end

local function parsedglog(line)
	local words = format.string_to_table(line, "\t")
	local logentry = { logdatetime=words[1], clientuserid=words[2], clientip=words[3],
		URL=words[4], reason=words[5], method=words[6], bytes=words[7],
		shortreason=words[9]}
	-- Format of squid log (space separated):
	-- time elapsed remotehost code/status bytes method URL rfc931 peerstatus/peerhost
	local words = {}
	
	for word in string.gmatch(line, "%S+") do
		words[#words+1] = word
	end

	local goodwordloc=""
	local badwordloc=""
	-- logme("value of word4 is "..words[4])
	local wrdcnt=0
	local isbad=0
	local isdenied=0
	local isbypass=0
	local ignoreme=false

	--check for ignored records first
	for thisline in io.lines("/etc/weblog/ignorewords") do
		if not thisline then
			break
		end
		_,instcnt = string.lower(words[4]):gsub(thisline, " ")
		if instcnt ~= 0 then
		   ignoreme = true
		   break
		end
	end

	if ignoreme ~= true then
	  for thisline in io.lines("/etc/weblog/badwords") do
		if not thisline then
			-- logme("This line is apparently empty...")
			break
		end
		
		_,instcnt = string.lower(words[4]):gsub(thisline, " ")
		--if string.find(words[4],thisline) ~= nil then
		  if instcnt ~= 0 then
		   if wrdcnt ~= 0 then
		     isbad=1
		     wrdcnt= wrdcnt + instcnt
		     if badwordloc ~= "" then 
		       badwordloc = badwordloc.."|"..thisline
		     else
		       badwordloc=thisline
		     end
		 
		  -- logme("bad "..badwordloc)
	        end
		
		if string.find(words[5],"*DENIED*") then
		   isdenied=1
		elseif string.find(words[5],"GBYPASS") then
		   isdenied=1 
		elseif string.find(words[5],"*OVERRIDE*") then
		   isbypass=1
		end
	  end
	  for goodline in io.lines("/etc/weblog/goodwords") do
		if not goodline then
		  -- logme("This line is apparently empty...")
		  break
		end
		_,instcnt = string.lower(words[4]):gsub(goodline, " ")
		--if string.find(words[4],goodline) then
		  
		  if instcnt ~= 0 then
		     wrdcnt = wrdcnt - instcnt
		     if goodwordloc ~= "" then
		        goodwordloc = goodwordloc.."|"..goodline
		     else 
		        goodwordloc = goodline
		     end
		  end
		end
	  end	
	
	end
	
	local words = format.string_to_table(line, "\t")	
	local logentry = {logdatetime=words[1],
			clientuserid=words[2],
			clientip=words[3],
			URL=words[4],
			reason=words[5],
			method=words[6],
			bytes=words[7],
			shortreason=words[9],
			score=wrdcnt,
			badyesno=isbad,
			deniedyesno=isdenied,
			bypassyesno=isbypass,		
			wordloc=badwordloc,
			gwordloc=goodwordloc}	

	if logentry.reason and logentry.reason ~= "" then
		if logentry.shortreason == "" then
			logentry.shortreason = logentry.reason
           	if logentry.shortreason == "" then
           		logentry.shortreason = logentry.reason
           	end
	   	return logentry
	end
	return nil
end

local function parsedumplog(line)
	-- Format of squid log (space separated):
	-- time elapsed remotehost code/status bytes method URL rfc931 peerstatus/peerhost
	local words = {}
	
	for word in string.gmatch(line, "%S+") do
		words[#words+1] = word
	end
	goodwordloc=""
	badwordloc=""
	wrdcnt=0
	isbad=0
	isdenied=0
	isbypass=0
	for thisline in io.lines("/etc/weblog/badwords") do
		if not thisline then
			 logme("This line is apparently empty...")
			break
		end
		logentry.score = string.match(logentry.reason, "^.*: ([0-9]+) ")
		logentry.logdatetime = string.gsub(logentry.logdatetime, "%.", "-")
		return logentry
		_,instcnt = string.lower(words[5]):gsub(thisline, " ")
		if instcnt ~= 0 then
		  isbad=1
		  wrdcnt = wrdcnt + instcnt
		  if badwordloc ~= "" then 
		    badwordloc = badwordloc.."|"..thisline
		  else
		    badwordloc=thisline
		  end
		 
		   -- logme("bad "..badwordloc)
	        end
		if string.find(words[6],"*DENIED*") then	
		   isdenied=1
		end
		if string.find(words[5],"GBYPASS") then
		   isbypass=1
		elseif string.find(words[6],"*OVERRIDE*") then
		   isbypass=1
		end
	end
	for goodline in io.lines("/etc/weblog/goodwords") do
		if not goodline then
		  -- logme("This line is apparently empty...")
		  break
		end
		_,instcnt = string.lower(words[4]):gsub(goodline, " ")
		--if string.find(words[4],goodline) then
		  if instcnt ~= 0 then
		   if wrdcnt ~= 0 then
		     wrdcnt = wrdcnt - instcnt
		     if goodwordloc ~= "" then
		        goodwordloc = goodwordloc.."|"..goodline
		     else 
		        goodwordloc = goodline
		     end
		  end
		end
	end	
	
	local words = format.string_to_table(line, "\t")	
	local logentry = {logdatetime=words[1],
			clientuserid=words[2],
			clientip=words[3],
			URL=words[4],
			reason=words[6],
			method=words[5],
			bytes=words[7],
			shortreason=words[9],
			score=wrdcnt,
			badyesno=isbad,
			deniedyesno=isdenied,
			bypassyesno=isbypass,		
			wordloc=badwordloc,
			gwordloc=goodwordloc}	

	if logentry.reason and logentry.reason ~= "" then
           	if logentry.shortreason == "" then
           		logentry.shortreason = logentry.reason
           	end
	   	return logentry
	end
	return nil
end

--local function parsedglog(line)
--	local words = format.string_to_table(line, "\t")
--	local logentry = { logdatetime=words[1], clientuserid=words[2], clientip=words[3],
--		URL=words[4], reason=words[5], method=words[6], bytes=words[7],
--		shortreason=words[9]}
--	if logentry.reason and logentry.reason ~= "" then
--		if logentry.shortreason == "" then
--			logentry.shortreason = logentry.reason
--		end
--		logentry.score = string.match(logentry.reason, "^.*: ([0-9]+) ")
--		logentry.logdatetime = string.gsub(logentry.logdatetime, "%.", "-")
--		return logentry
--	end
--	return nil
--end


-- ################################################################################
-- DOWNLOAD FILE FUNCTIONS

@@ -880,7 +1213,7 @@ local function importlogfile(source, cookiesfile, file, parselog_func, importlog
				end
				pcall(function() logme("Exception on line:"..line) end)
				if err2 then
					pcall(function() logme(err2) end)
					pcall(function() logme("err2 "..err2) end)
				end
				if (config.stoponerror == "true") then
					assert(res2, "Import halted on exception")
@@ -914,10 +1247,16 @@ function importlogs()

	local res, err = pcall(function()
		databaseconnect(DatabaseOwner, config.password)
		-- Determine sources
		local sources = listsourceentries(sourcename)

		-- Download, parse, and import the logs
		logme("Executing importlogs")
		logme("Analyzing...")
		local sql = "ANALYZE"
		res = assert (con:execute(sql))
		
		-- Determine sources
		local sources = listsourceentries(sourcename)
		
		for i,source in ipairs(sources) do
			if source.enabled then
				logme("Getting logs from source " .. source.sourcename)
@@ -928,10 +1267,19 @@ function importlogs()
						if string.match(file, "dansguardian/access%.log[%.%-]") then
							count = count + 1
							success = importlogfile(source, cookiesfile, file, parsedglog, importdglog) and success
						elseif string.match(file, "squid/access%.log[%.%-]") then
						end
						if string.match(file, "squark/access%.log[%.%-]") then
							count = count + 1
							success = importlogfile(source, cookiesfile, file, parsesquarklog, importsquarklog) and success
						end
						if string.match(file, "squid/access%.log[%.%-]") then
							count = count + 1
							success = importlogfile(source, cookiesfile, file, parsesquidlog, importsquidlog) and success
						end
						if string.match(file, "dump/access%.log[%.%-]") then
							count = count + 1
							success = importlogfile(source, cookiesfile, file, parsedumplog, importdumplog) and success
						end
					end
				end
				os.remove(cookiesfile)
@@ -942,7 +1290,6 @@ function importlogs()
		if success then
			addtowatchlist()
			updateusagestats()
			importpubweblog()
			groomwatchlist()
		end
		-- Purge old database entries
@@ -1112,55 +1459,116 @@ local validateparameters = function(params)
	return success
end

local handleparameters = function(clientuserid, starttime, endtime, clientip, focus)
local handleparameters = function(activelog, clientuserid, starttime, endtime, clientip, badyesno, deniedyesno, bypassyesno, score, urisearch, sortby, selected, focus)
	local result = {}
	result.activelog = cfe({ value=activelog or "pubweblog", label="Active Weblog" })
	result.clientuserid = cfe({ value=clientuserid or "", label="User ID" })
	result.starttime = cfe({ value=starttime or "", label="Start Time" })
	result.endtime = cfe({ value=endtime or "", label="End Time" })
	result.clientip = cfe({ value=clientip or "", label="Client IP" })
	result.badyesno = cfe({ value=badyesno, label="Show Dodgy Records", descr="Limit search to Dodgy records"})
	result.deniedyesno = cfe({ value=deniedyesno, label="Show Denied Records", descr="Limit search to Denied uri"})
	result.bypassyesno = cfe({ value=bypassyesno, label="Show Bypass Actions", descr="Limit search to Bypass attempts"})
	result.score = cfe({ value=score, label="Minimum Score", descr="Minimum score to search on"})
	result.urisearch = cfe({ value=urisearch or "", label="URI Contains", descr="Retrieve records where the URI contains this word"})
	result.sortby = cfe({ value=sortby, label="Sort By field", descr="Sort by this field when displaying records"})
	result.selected = cfe({ value=selected, label="Show Selected Records", descr="Show only records that have been selected"})
	result.window = cfe({ value=config.window or "5", label="Time Window" })
	result.focus = cfe({ value=focus or "", label="Focus Time" })
	return result
end

function getweblog(clientuserid, starttime, endtime, clientip, focus)
function getselected(csvdata)
	local result = {}
	result.id = cfe({ value=csvdata or "", label="Record ID", descr="Id of Record"})
        result.log = cfe({ type="list", value={}, label="Weblog Access Log" })
        local res, err = pcall(function()
	 	databaseconnect(DatabaseUser)
		local entries = {}
		-- retrieve a cursor
		local sql = "SELECT * FROM pubweblog where selected = true and logdatetime >= '" .. starttime .. "' and logdatetime <= '" .. endtime .. "'" 
		local idcnt = 0
		sql = sql .. " ORDER BY logdatetime;"
		cur = assert (con:execute(sql))
		row = cur:fetch ({}, "a")
		while row do
			entries[#entries+1] = {sourcename=row.sourcename, clientip=row.clientip, clientuserid=row.clientuserid, logdatetime=row.logdatetime, uri=row.uri, shorturi=shorturi, bytes=row.bytes, reason=row.reason, core=row.score, shortreason=row.shortreason, badyesno=row.badyesno, deniedyesno=row.deniedyesno, bypassyesno=row.bypassyesno, wordloc=row.wordloc, selected=row.selected }
			row = cur:fetch (row, "a")
		end
		-- close everything
		cur:close()
		result.log.value = entries or {} 
		--result.log.value = sql
		databasedisconnect()
 	end)
	return cfe({ type="group", value=result, errtxt=err, label="Weblog Selected" })	
end

function editselected(chkdata)
	keycnt = 0
	sql = "UPDATE pubweblog SET selected = "
	databaseconnect(DatabaseOwner)
	idarray = split(chkdata,"|")
	  for key,x in pairs(idarray) do
	    keycnt = keycnt + 1
	    if keycnt == 1 then 
	      sql = sql..x.." WHERE id = "
	    else 
	      sql = sql..x
	    end
	  end
	assert (con:execute(sql))
	databasedisconnect()
end

function clearselected()
        local retval = cfe({ label="Clear selected records", errtxt = "Failed to clear selected records - who knows why" })
	sql = "UPDATE pubweblog SET selected = false WHERE selected = true"
	databaseconnect(DatabaseOwner)
	assert (con:execute(sql))
	databasedisconnect()
	retval.value = "Cleared"
	retval.errtxt = nil
	return retval 
end

function getweblog(activelog, clientuserid, starttime, endtime, clientip, badyesno, deniedyesno, bypassyesno, score, urisearch, sortby, selected, focus )

	if (not activelog or activelog=="") then
		activelog = "pubweblog"
	end
	
	if (not starttime or starttime=="") and (not endtime or endtime=="") and config.auditstart~="" and config.auditend~="" then
		starttime = config.auditstart
		endtime = config.auditend
		
		 starttime = config.auditstart
		 endtime = config.auditend
	
		if config.badyesno=="true" then
		   badyesno = '1'
		end
	end
	local result = handleparameters(clientuserid, starttime, endtime, clientip, focus)
	if (not score or score=="") and config.minimumscore~="" then
	  score = config.minimumscore
	end
	
	if (not sortby or sortby=="") and config.sortby~="" then
	   sortby = config.sortby
	end
	
	local result = handleparameters(activelog, clientuserid, starttime, endtime, clientip, badyesno, deniedyesno, bypassyesno, score, urisearch, sortby, selected, focus)
	result.log = cfe({ type="list", value={}, label="Weblog Access Log" })
	local success = validateparameters(result)
	if success then
		local res, err = pcall(function()
			databaseconnect(DatabaseUser)
			result.log.value = listpubweblogentries(clientuserid, starttime, endtime, clientip) or {}
			result.log.value = listpubweblogentries(activelog, clientuserid, starttime, endtime, clientip, badyesno, deniedyesno, bypassyesno, score, urisearch, sortby, selected ) or {}
			databasedisconnect()
		end)
	else
		err = "Invalid search parameters"
	end
	return cfe({ type="group", value=result, errtxt=err, label="Weblog Access Log" })
end

function getblocklog(clientuserid, starttime, endtime, clientip, focus)
	if (not starttime or starttime=="") and (not endtime or endtime=="") and config.auditstart~="" and config.auditend~="" then
		starttime = config.auditstart
		endtime = config.auditend
	end
	local result = handleparameters(clientuserid, starttime, endtime, clientip, focus)
	result.log = cfe({ type="list", value={}, label="Weblog Block Log" })
	local success = validateparameters(result)
	if success then
		local res, err = pcall(function()
			databaseconnect(DatabaseUser)
			result.log.value = listpubblocklogentries(clientuserid, starttime, endtime, clientip) or {}
			databasedisconnect()
		end)
	else
		err = "Invalid search parameters"
	end
	return cfe({ type="group", value=result, errtxt=err, label="Weblog Block Log" })
end

function getusagestats()
@@ -1177,53 +1585,26 @@ function getusagestats()
	return retval
end

function getauditstats()
	local result = {}
	result.auditstart = cfe({ value=config.auditstart or "", label="Audit Start Time" })
	result.auditend = cfe({ value=config.auditend or "", label="Audit End Time" })
	result.groupby = cfe({ value=config.groupby or "clientuserid", label="Group By" })
	result.stats = cfe({ type="list", value={}, label="Audit Block Statistics" })
	local res, err = pcall(function()
		if config.auditstart ~= "" and config.auditend ~= "" then
			databaseconnect(DatabaseUser)
			result.stats.value = grouppubblocklogentries(config.auditstart, config.auditend, result.groupby.value) or {}
			databasedisconnect()
		end
	end)
	return cfe({ type="group", value=result, errtxt=err, label="Weblog Audit Statistics" })
end

function completeaudit(timestamp)
	local conf = getconfig()
	conf.value.auditstart.value = conf.value.auditend.value
	local now = os.time()
	conf.value.auditend.value = timestamp or os.date("%Y-%m-%d %H:%M:%S", now - now%86400 - 86400)
	conf = updateconfig(conf)
	local retval = cfe({ value="Audit completed", label="Complete Audit Result" })
	if conf.errtxt then
		retval.value = ""
		retval.errtxt = "Failed to complete audit\n"..conf.errtxt.."\n"..conf.value.auditend.errtxt
	end
	return retval
end

function getconfig()
	local result = {}
	result.auditstart = cfe({ value=config.auditstart or "", label="Audit Start Time" })
	result.auditend = cfe({ value=config.auditend or "", label="Audit End Time" })
	result.badyesno = cfe({ type="boolean", value=(config.badyesno == "1"), label="Display Suspect Records", descr="Show only records flagged as suspect on initial display" })
	result.minimumscore = cfe({ value=config.minimumscore or "0", label="Minimum Score", descr="Minimum Score to search for" })
	result.sortby = cfe({ type="select", value=config.sortby or "logdatetime", label="Sort By field", option={"logdatetime", "logdatetime DESC", "clientuserid", "clientuserid DESC", "clientip", "clientip DESC", "bytes", "bytes DESC", "score", "score DESC", "reason"} })
	result.window = cfe({ value=config.window or "5", label="Time Window", descr="Minutes of activity to display before and after selected block" })
	result.watchdays = cfe({ value=config.watchdays or "14", label="Days to Watch", descr="Number of additional days to keep history for users in watchlist" })
	result.purgedays = cfe({ value=config.purgedays or "30", label="Days before Purge", descr="Days to keep history, regardless of audit" })
	result.historydays = cfe({ value=config.historydays or "14", label="Days to keep History", descr="Days beyond Audit Start Time to keep complete log history" })
	result.groupby = cfe({ type="select", value=config.groupby or "clientuserid", label="Group results by", option={"clientuserid", "clientip"} })
	result.shorturi = cfe({ type="boolean", value=(config.shorturi == "true"), label="Truncate URLs", descr="You can limit the length of displayed URLs by enabling this option"})
	result.shortreason = cfe({ type="boolean", value=(config.shortreason == "true"), label="Short Reason", descr="Display a short reason (without objectional words)"})
	result.shortreason = cfe({ type="boolean", value=(config.shortreason == "true"), label="Short Reason", descr="Display a short reason (dansguardian only)"})
	result.stoponerror = cfe({ type="boolean", value=(config.stoponerror == "true"), label="Stop on Error", descr="Stop import of logs if an error is encountered"})
	return cfe({ type="group", value=result, label="Weblog Config" })
end

local function validateconfig(newconfig)
	local success = modelfunctions.validateselect(newconfig.value.groupby)
	local success = modelfunctions.validateselect(newconfig.value.sortby)
	if newconfig.value.window.value == "" then
		newconfig.value.window.errtxt = "Cannot be blank"
		success = false
@@ -1273,11 +1654,14 @@ function updateconfig(newconfig)
		configcontent = format.update_ini_file(configcontent, "", "watchdays", newconfig.value.watchdays.value)
		configcontent = format.update_ini_file(configcontent, "", "purgedays", newconfig.value.purgedays.value)
		configcontent = format.update_ini_file(configcontent, "", "historydays", newconfig.value.historydays.value)
		configcontent = format.update_ini_file(configcontent, "", "groupby", newconfig.value.groupby.value)
		--configcontent = format.update_ini_file(configcontent, "", "groupby", newconfig.value.groupby.value)
		configcontent = format.update_ini_file(configcontent, "", "shorturi", tostring(newconfig.value.shorturi.value))
		configcontent = format.update_ini_file(configcontent, "", "shortreason", tostring(newconfig.value.shortreason.value))
		configcontent = format.update_ini_file(configcontent, "", "stoponerror", tostring(newconfig.value.stoponerror.value))

		configcontent = format.update_ini_file(configcontent, "", "badyesno", tostring(newconfig.value.badyesno.value))
		configcontent = format.update_ini_file(configcontent, "", "minimumscore", tostring(newconfig.value.minimumscore.value))
		configcontent = format.update_ini_file(configcontent, "", "sortby", tostring(newconfig.value.sortby.value))
			
		fs.write_file(configfile, configcontent)
		config = format.parse_ini_file(configcontent, "") or {}
	else
@@ -1414,3 +1798,64 @@ function create_database(database)

	return database
end
function listfiles()
        local retval = cfe({ type="list", value={}, label="Weblog Files" })
        if not fs.is_dir(baseurl) then fs.create_directory(baseurl) end
        for file in posix.files(baseurl) do
                 file = baseurl..file
                 if fs.is_file(file) then
                         table.insert(retval.value, file)
                 end
        end
        table.sort(retval.value)
        return retval
end
function getnewfile()
        local filename = cfe({ label="File Name", descr="Must be in "..baseurl })
        return cfe({ type="group", value={filename=filename}, label="Weblog File" })
end
function readfile(filename)
        return modelfunctions.getfiledetails(filename, listfiles().value)
end
        
function updatefile(filedetails)
         return modelfunctions.setfiledetails(filedetails, listfiles().value)
end
                
function deletefile(filename)
        local retval = cfe({ label="Delete Weblog File result", errtxt = "Failed to delete Weblog File - invalid filename" })
        for i,file in ipairs(listfiles().value) do
	        if filename == file then
      	      	  retval.value = "Deleted File"
                  retval.errtxt = nil
                  os.remove(filename)
                  break
                end
        end
                                                                                                                                                                        
        return retval
end

-- Split a string to an array by delimiter or pattern
function split(str, pat)
   if string.find(str, pat) == nil then
      return str
   end
   local t = {}
   local fpat = "(.-)" .. pat
   local last_end = 1
   local s, e, cap = str:find(fpat, 1)
   while s do
     if s ~= 1 or cap ~= "" then
        table.insert(t,cap)
     end
     last_end = e+1
     s, e, cap = str:find(fpat, last_end)
   end
   if last_end <= #str then
      cap = str:sub(last_end)
      table.insert(t, cap)
   end
   return t
end
                                                                                               
diff --git a/weblog-summary-html.lsp b/weblog-summary-html.lsp
new file mode 100644
index 0000000..60040b5
--- /dev/null
+++ b/weblog-summary-html.lsp
@@ -0,0 +1,17 @@
<% local form, viewlibrary, page_info = ... 
require("viewfunctions")
%>

<style type="text/css">
  #content table { border-collapse: collapse; width: 100%; }
  #content table td { white-space: normal; padding-right:20px; border-bottom:1px solid #999; }
  #content table tr.mark { background: #E9E9E9; }
</style>

<H1>Summary</H1>
<H2>Last 24 Hours</H2>
<H2>Last 7 Days</H2>
<H2>Last 30 Days</
<% displayformstart(form, page_info) %>
<% displayformitem(form.value.query, "query") %>
<% displayformend(form) %>
diff --git a/weblog-viewwatchlist-html.lsp b/weblog-viewwatchlist-html.lsp
index 17bf1e0..1cf9a79 100644
--- a/weblog-viewwatchlist-html.lsp
+++ b/weblog-viewwatchlist-html.lsp
@@ -24,7 +24,7 @@
<% for i,watch in ipairs(data.value) do %>
	<TR>
		<TD><%= html.link{value = "deletewatchlistentry?clientuserid="..watch.clientuserid, label="Delete "} %></TD>
		<TD><%= html.link{value = "viewblocklog?clientuserid="..watch.clientuserid, label=watch.clientuserid} %></TD>
		<TD><%= html.link{value = "viewweblog?clientuserid="..watch.clientuserid, label=watch.clientuserid} %></TD>
		<TD><%= html.html_escape(watch.expiredatetime) %></TD>
	</TR>
<% end %>
diff --git a/weblog-viewweblog-html.lsp b/weblog-viewweblog-html.lsp
deleted file mode 120000
index 4ec32bc..0000000
--- a/weblog-viewweblog-html.lsp
@@ -1 +0,0 @@
weblog-viewblocklog-html.lsp
\ No newline at end of file
diff --git a/weblog-viewweblog-html.lsp b/weblog-viewweblog-html.lsp
new file mode 100644
index 0000000..b4c6083
--- /dev/null
+++ b/weblog-viewweblog-html.lsp
@@ -0,0 +1,300 @@
<% local data, viewlibrary, page_info, session = ... %>
<% require("viewfunctions")%>
<% require("newviewfunctions")%>
<% if data.value.focus.value ~= "" then %>
<script type="text/javascript" src="<%= html.html_escape(page_info.wwwprefix) %>/js/jquery-latest.js"></script>
<script type="text/javascript">
	$(function(){
	   	if ($("#focus").length) {
			var top = $("#focus").offset().top;
			$("html,body").scrollTop(top);
		}
	});
</script>
<% end %>

<script type="text/javascript" src="<%= html.html_escape(page_info.wwwprefix) %>/js/jquery.min.js"></script>
<script type="text/javascript" src="<%= html.html_escape(page_info.wwwprefix)%>/js/jquery.tablesorter.js"></script>
<script type="text/javascript">
        $(document).ready(function() {
                $("#loglist").tablesorter({headers: {0:{sorter: false},1:{sorter: false}, 2:{sorter: 'text'}, 6:{sorter: false}, 7:{sorter: false}, 8:{sorter: false}}});
        });
        function hideColumn(myCol) {
        myCol.style.display = "none";
        };
</script>
			
<% local subdata, pagedata = paginate(data.value.log.value, page_info.clientdata, 200) %>

<style type="text/css">
  #content table { border-collapse: collapse; width: 100%; }
  #content table td { border-bottom: none; white-space: normal; padding-right:20px; }
  #content table th { border-bottom: none; white-space: normal; vertical-align: middle; padding-right:15px }
  #content table tr.mark { background: #E9E9E9; }
  #content table tr.selected { background: #FC9A01; } 
</style>

<H1>Search Parameters</H1>
<DL>
<% if data.errtxt then %><p class="error"><%= html.html_escape(data.errtxt) %></p><% end %>
<form action="<%= html.html_escape(page_info.script .. page_info.prefix .. page_info.controller .. "/" .. page_info.action) %>" method="POST">
<DT>Active Weblog</DT>
<DD><select name="activelog">
<option value="pubweblog">Current</option>
<option value="pubweblog_history"<% if data.value.activelog.value == "pubweblog_history" then %> selected="selected" <% end %> >History</option>
</select>  
</DD>
<DT>Start Time</DT>
<DD><input class="text" type="text" name="starttime" value="<%= html.html_escape(data.value.starttime.value) %>" >
<p><%= html.html_escape(data.value.starttime.value) %></p>
<% if data.value.starttime.errtxt then %><p class="error"><%= html.html_escape(data.value.starttime.errtxt) %></p><% end %>
</DD>
<DT>User ID</DT>
<DD><input class="text" type="text"  name="clientuserid"  value="<%= html.html_escape(data.value.clientuserid.value) %>" >
<p><%= html.html_escape(data.value.clientuserid.value) %></p>
<% if data.value.clientuserid.errtxt then %><p class="error"><%= html.html_escape(data.value.clientuserid.errtxt) %></p><% end %>
</DD>
<DT>Client IP</DT>
<DD><input class="text" type="text"  name="clientip"  value="<%= html.html_escape(data.value.clientip.value) %>" >
<p><%= html.html_escape(data.value.clientip.value) %></p>
<% if data.value.clientip.errtxt then %><p class="error"><%= html.html_escape(data.value.clientip.errtxt) %></p><% end %>
</DD>
<DT>End Time</DT>
<DD><input class="text" type="text"  name="endtime"  value="<%= html.html_escape(data.value.endtime.value) %>" >
<p><%= html.html_escape(data.value.endtime.value) %></p>
<% if data.value.endtime.errtxt then %><p class="error"><%= html.html_escape(data.value.endtime.errtxt) %></p><% end %>
</DD>
<DT>URI Contains</DT>
<DD><input class="text" type="text"  name="urisearch"  value="<%= html.html_escape(data.value.urisearch.value) %>" >
<P CLASS="descr">Retrieve records where the URI contains this word</P>
<p><%= html.html_escape(data.value.urisearch.value) %></p>
<% if data.value.urisearch.errtxt then %><p class="error"><%= html.html_escape(data.value.urisearch.errtxt) %></p><% end %>
</DD>
<DT>Minimum Score</DT>
<DD><input class="text" type="text"  name="score"  value="<%= html.html_escape(data.value.score.value) %>" >
<P CLASS="descr">Minimum score to search on</P>
<% if data.value.score.errtxt then %><p class="error"><%= html.html_escape(data.value.score.errtxt) %></p><% end %>
</DD>
<DT>Sort By</DT>
<DD><select name="sortby">
<option value="logdatetime"<% if data.value.log.value == "sortby" then %> selected="selected" <% end %> >Timestamp</option>
<option value="logdatetime DESC"<% if data.value.sortby.value == "logdatetime DESC" then %> selected="selected" <% end %> >Timestamp DESC</option>
<option value="clientuserid"<% if data.value.sortby.value == "clientuserid" then %> selected="selected" <% end %> >User ID</option>
<option value="clientuserid DESC"<% if data.value.sortby.value == "clientuserid DESC" then %> selected="selected" <% end %> >User ID DESC</option>
<option value="bytes"<% if data.value.sortby.value == "bytes" then %> selected="selected" <% end %> >Size</option>
<option value="bytes DESC"<% if data.value.sortby.value == "bytes DESC" then %> selected="selected" <% end %> >Size DESC</option>
<option value="score"<% if data.value.sortby.value == "score" then %> selected="selected" <% end %> >Score</option>
<option value="score DESC"<% if data.value.sortby.value == "score DESC" then %> selected="selected" <% end %> >Score DESC</option>
<option value="reason"<% if data.value.sortby.value == "reason" then %> selected="selected" <% end %> >Reason</option>
<option value="reason DESC"<% if data.value.sortby.value == "reason DESC" then %> selected="selected" <% end %> >Reason DESC</option>
</select>  
</DD>
<DT>Show Suspect Records</DT>
<DD>
<input class="checkbox" type="checkbox"  name="badyesno"  value="1" <% if data.value.badyesno.value == "1" then %> checked <% end %>>
<P CLASS="descr">Show only URIs containing flagged words</P>
<% if data.value.badyesno.errtxt then %><p class="error"><%= html.html_escape(data.value.badyesno.errtxt) %></p><% end %>
</DD>
<DT>Show Denied URIs</DT>
<DD>
<input class="checkbox" type="checkbox" name="deniedyesno" value="1" <% if data.value.deniedyesno.value == "1" then %>checked<% end %>>
<% if data.value.deniedyesno.errtxt then %><p class="error"><%= html.html_escape(data.value.deniedyesno.errtxt) %></p><% end %>
<P CLASS="descr">Show only Denied URIs</P>
</DD>
<DT>Show Bypass Attempts</DT>
<DD>
<input class="checkbox" type="checkbox"  name="bypassyesno"  value="1" <% if data.value.bypassyesno.value == "1" then %>checked <% end %>>
<% if data.value.bypassyesno.errtxt then %><p class="error"><%= html.html_escape(data.value.bypassyesno.errtxt) %></p><% end %>
<P CLASS="descr">Show only Bypass attempts</P>
</DD>
<DT>Show Selected Records</DT>
<DD>
<input class="checkbox" type="checkbox" name="selected" value="true" <% if data.value.selected.value == "true" then %>checked <% end %>>
<% if data.value.selected.errtxt then %><p class="error"><%= html.html_escape(data.value.selected.errtxt) %></p><% end %>
<P CLASS="descr">Show only records that have been selected</P>
</DD>
<DT></DT><DD><input class="submit" type="submit" name="Update" value="Update"></DD>
</FORM>
</DL>

<%
local clientinfo = ""
if data.value.clientuserid.value ~= "" then
	clientinfo = clientinfo .. "clientuserid="..data.value.clientuserid.value.."&"
end
if data.value.clientip.value ~= "" then
	clientinfo = clientinfo .. "clientip="..data.value.clientip.value.."&"
end
%>

<% displaypagination(pagedata, page_info) %>
<H1><%= html.html_escape(data.label) %></H1>
<DL>
<TABLE id="loglist" class="tablesorter">
<THEAD>
<TR style=font-weight:bold;>
		<TH><input type="checkbox" id="chkHead" /></TH>
		<TH style="width:0%; display:none"></TH>
		<TH>Timestamp</TH>
		<TH>Client IP</TH>
		<TH>User ID</TH>
		<TH>Size</TH>
		<TH style=font-weight:bold >Sus</TH>
		<TH style=font-weight:bold >Den</TH>
		<TH style=font-weight:bold >Byp</TH>
		<TH>Score</TH>
		<TH>Reason</TH>
		<TH WIDTH="90%">URL</TH>
		<TH>Bad Words</TH>
	</TR>
</THEAD>
<TBODY>
<FORM action="<%= html.html_escape(page_info.script .. page_info.prefix .. page_info.controller .. "/checkselected") %>" name="markselected" onsubmit="return false" method="POST">
<input type="hidden" id="chkdata" name="chkdata" value="chkdata"></FORM>
<% for i,watch in ipairs(subdata) do
	local a,b = math.modf((i/2))
	local mark = ''
	if (b == 0) and watch.selected ~= "t" then mark=' class="mark"' end
	if watch.selected == "t" then mark=' class="selected"' end
	local time = {}
	time.year, time.month, time.day, time.hour, time.min, time.sec = 
		string.match(watch.logdatetime, "(%d+)%-(%d+)-(%d+)%s+(%d+):(%d+):(%d+)")
	time = os.time(time) %>
<TR<%= mark %>>
		<TD><input class="chktbl" type="checkbox" value="true" <% if watch.selected == "t" then %> checked <% end %>></TD>
		<TD style="width:0%; display:none"><%= html.html_escape(watch.id) %></TD>
		<TD <% if data.value.focus.value == watch.logdatetime then %> style="font-weight:bold;" id="focus" <% end %> ><%= html.link{value = "viewweblog?"..clientinfo..
			"starttime="..os.date("%Y-%m-%d %H:%M:%S", time - 60*(tonumber(data.value.window.value)))..
			"&endtime="..os.date("%Y-%m-%d %H:%M:%S", time + 60*(tonumber(data.value.window.value)))..
			"&focus="..watch.logdatetime,
			label=watch.logdatetime} %></TD>
		<TD <% if data.value.clientip.value == watch.clientip then %> style="font-weight:bold;" <% end %> ><%= html.html_escape(watch.clientip) %></TD>
		<TD <% if data.value.clientuserid.value == watch.clientuserid then %> style="font-weight:bold;" <% end %> ><%= html.html_escape(watch.clientuserid) %></TD>
		<TD><%= html.html_escape(watch.bytes) %></TD>
		<TD WIDTH="2%"><% if watch.badyesno == "1" then %><IMG SRC='<%= html.html_escape(page_info.wwwprefix..page_info.staticdir) %>/dodgy.png' width='13' height='13'><% end %></TD>
		<TD WIDTH="2%"><% if watch.deniedyesno ~= "0" then %> <IMG SRC='<%= html.html_escape(page_info.wwwprefix..page_info.staticdir) %>/denied.png' width='13' height='13'><% end %></TD>
		<TD WIDTH="2%"><% if watch.bypassyesno ~= "0" then %> <IMG SRC='<%= html.html_escape(page_info.wwwprefix..page_info.staticdir) %>/bypass.png' width='13' height='13'><% end %></TD>   
		<TD><%= html.html_escape(watch.score) %></TD>
		<TD><%= html.html_escape(watch.reason) %></TD>
		<TD style="word-wrap: break-word" width="500"><% highlight_uri=html.html_escape(watch.uri) 
		       if watch.wordloc ~= nil then 
		   	 if string.find(watch.wordloc,"|") then 
		   	   badwords = split(watch.wordloc,"|")
		   	   for key,wrd in pairs(badwords) do
		   	      highlight_uri = string.highlight(highlight_uri, wrd, "yellow","red")
		   	   end
		   	 else
		   	   highlight_uri = string.highlight(highlight_uri, watch.wordloc, "yellow","red")
		   	 end
		       end %> 
		    <%= highlight_uri %></TD>
		<TD><%= watch.wordloc %></TD>
</TR>
<% end %>
</TBODY>
</TABLE>
<% displaypagination(pagedata, page_info) %>

<% if data.errtxt then %>
<p class="error"><%= html.html_escape(data.errtxt) %></p>
<% end %>
<% if #data.value.log.value == 0 then %>
<p>No results, try adjusting search parameters</p>
<% end %>
<DT>Download Options</DT>
<% if page_info.action == "viewweblog" then %>
<form action="<%= html.html_escape(page_info.script .. page_info.prefix .. page_info.controller .. "/downloadlogview") %>" method="POST">
<input type="hidden"  name="activelog" value="<%= html.html_escape(data.value.activelog.value) %>" >
<input type="hidden"  name="starttime" value="<%= html.html_escape(data.value.starttime.value) %>" >
<input type="hidden"  name="clientuserid" value="<%= html.html_escape(data.value.clientuserid.value) %>" >
<input type="hidden"  name="clientip" value="<%= html.html_escape(data.value.clientip.value) %>" >
<input type="hidden"  name="endtime" value="<%= html.html_escape(data.value.endtime.value) %>" >
<input type="hidden"  name="badyesno" value="<%= html.html_escape(data.value.badyesno.value) %>" >
<input type="hidden"  name="deniedyesno" value="<%= html.html_escape(data.value.deniedyesno.value) %>" >
<input type="hidden"  name="bypassyesno" value="<%= html.html_escape(data.value.bypassyesno.value) %>" >
<input type="hidden"  name="score" value="<%= html.html_escape(data.value.score.value) %>" >
<input type="hidden"  name="sortby" value="<%= html.html_escape(data.value.sortby.value) %>" >
<input type="hidden"  name="urisearch" value="<%= html.html_escape(data.value.urisearch.value) %>" >
<input type="hidden"  name="selected" value="<%= html.html_escape(data.value.selected.value) %>" >
<DD><input class="submit" type="submit" name="Download" value="Export List"></DD>
</form>
<% end %>

<script type="text/javascript">
    	$('#chkHead').click(function () {
            if (this.checked == false) {
              $('.chktbl:checked').attr('checked', false);
            }
            else {
            	$('.chktbl:not(:checked)').attr('checked', true);
            }
            if ($(this).attr("checked")==true)
            {
               $("#loglist").find('tr:not(#chktbl)').css("background-color","#FC9A01");
            }
            else
            {
              $("#loglist").find('tr:not(#chktbl)').css("background-color","#FFF");
            } 
        });
        $('#chkHead').click(function(){
        });
        
        $('.chktbl').click(function () {
       	if($("chkHead").attr('checked') == true && this.checked == false)
        {
        	var csv_data = "";
        	var csv_cnt = 0;
        	$(".chktbl").attr('checked',false);
        	$(this).closest('tr').css("background-color","#ffffff");
        	$(this).closest('tr').each(function () {
        	  $(this).find('td').each(function () {
        	  	if(csv_cnt == 1)
        	  	 { document.viewweblog.chktbl.value = "false|" + $(this).text();
        	  	   return false;
        	  	}
        	  	csv_cnt +=1;
        	  	});
        	  });
        }
        if(this.checked == true)
        {	
        	$(this).closest('tr').css("background-color","#FC9A01");
         	var csv_list = "";
         	var csv_cnt = 0; 
        	$(this).closest('tr').each(function () {
        	  $(this).find('td').each(function () {
        	  	if(csv_cnt == 1)
        	  	 { document.markselected.chkdata.value = "true|" + $(this).text();
        	  	  //alert("this is: " + document.markselected.chkdata.value );
        	  	   return false;
        	  	}
        	  	csv_cnt +=1;
        	  	});
        	  });
        	document.forms["markselected"].submit();
        	//document.getElementById("subbutton").click();
        
        }
        if(this.checked == false)
        {
        	$(this).closest('tr').css("background-color","#ffffff");
         	var csv_list = "";
         	var csv_cnt = 0; 
        	$(this).closest('tr').each(function () {
        	  $(this).find('td').each(function () {
        	  	if(csv_cnt == 1)
        	  	 { document.markselected.chkdata.value = "false|" + $(this).text();
        	  	   return false;
        	  	}
        	  	csv_cnt +=1;
        	  	});
        	  });
        	document.forms["markselected"].submit();
        }
        });
        
</script>


</DL>
diff --git a/weblog.menu b/weblog.menu
index 9090b81..30638e5 100644
--- a/weblog.menu
+++ b/weblog.menu
@@ -1,7 +1,9 @@
#CAT  		GROUP/DESC		TAB		ACTION
Applications 	41Weblog		Status		status
Applications 	41Weblog		Audit		viewauditstats
#Applications 	41Weblog		Audit		viewauditstats
Applications	41Weblog		View_Log	viewweblog
Applications 	41Weblog		Config		config
Applications	41Weblog		File_List	listfiles
Applications 	41Weblog		Watch_List	viewwatchlist
Applications 	41Weblog		Sources		listsources
Applications 	41Weblog		Usage		viewusagestats
diff --git a/weblog.roles b/weblog.roles
index 5bce219..043506b 100644
--- a/weblog.roles
+++ b/weblog.roles
@@ -1,3 +1,3 @@
USER=weblog:viewauditstats,weblog:completeaudit,weblog:viewactivitylog,weblog:viewwatchlist,weblog:viewweblog,weblog:downloadweblog,weblog:viewblocklog,weblog:viewusagestats,weblog:deletewatchlistentry,weblog:createwatchlistentry,weblog:adhocquery,weblog:downloadadhocquery
EXPERT=weblog:config,weblog:listsources,weblog:createsource,weblog:deletesource,weblog:editsource,weblog:testsource,weblog:importlogs,weblog:status,weblog:createdatabase
ADMIN=weblog:config,weblog:viewauditstats,weblog:completeaudit,weblog:viewactivitylog,weblog:viewwatchlist,weblog:viewweblog,weblog:downloadweblog,weblog:viewblocklog,weblog:viewusagestats,weblog:listsources,weblog:createsource,weblog:deletesource,weblog:editsource,weblog:testsource,weblog:importlogs,weblog:deletewatchlistentry,weblog:createwatchlistentry,weblog:adhocquery,weblog:downloadadhocquery,weblog:status,weblog:createdatabase
EXPERT=weblog:config,weblog:viewweblog,weblog:listsources,weblog:createsource,weblog:deletesource,weblog:editsource,weblog:testsource,weblog:importlogs,weblog:status,weblog:createdatabase,weblog:listfile,weblog:editfile
ADMIN=weblog:config,weblog:viewauditstats,weblog:completeaudit,weblog:viewactivitylog,weblog:viewwatchlist,weblog:viewweblog,weblog:viewselected,weblog:downloadweblog,weblog:downloadlogview,weblog:downloadselected,weblog:checkselected,weblog:editselected,weblog:clearselected,weblog:viewblocklog,weblog:viewusagestats,weblog:listsources,weblog:createsource,weblog:deletesource,weblog:editsource,weblog:testsource,weblog:importlogs,weblog:deletewatchlistentry,weblog:createwatchlistentry,weblog:adhocquery,weblog:downloadadhocquery,weblog:status,weblog:createdatabase,weblog:listfiles,weblog:editfile
diff --git a/weblog_notify_daily b/weblog_notify_daily
new file mode 100755
index 0000000..3137c5b
--- /dev/null
+++ b/weblog_notify_daily
@@ -0,0 +1,36 @@
#!/bin/bash
echo "<html>" > /tmp/weblog_summary_daily.html
echo "<head>" >> /tmp/weblog_summary_daily.html
echo '<p><font weight="bold">DAILY SUMMARY WEBLOG REPORT FOR RESNET</font>'  >> /tmp/weblog_summary_daily.html
echo "</head>" >> /tmp/weblog_summary_daily.html
echo "" >> /tmp/weblog_summary_daily.html
echo "<body>" >> /tmp/weblog_summary_daily.html
echo "" >> /tmp/weblog_summary_daily.html
echo "<p>Total number of records imported:" >> /tmp/weblog_summary_daily.html
echo -e "`psql -t -U postgres -d webproxylog -c \"SELECT COUNT(*) FROM pubweblog WHERE logdatetime >= CURRENT_DATE - interval '$2 days';\"`</p>"  >> /tmp/weblog_summary_daily.html
echo "" >> /tmp/weblog_summary_daily.html
echo "<p>Total number of records with score > 0 imported:" >> /tmp/weblog_summary_daily.html
echo -e "`psql -t -U postgres -d webproxylog -c \"SELECT COUNT(*) FROM pubweblog WHERE score > 0 AND logdatetime >= CURRENT_DATE - interval '7 days' AND score > 0;\"`</p>" >> /tmp/weblog_summary_daily.html
echo "" >> /tmp/weblog_summary_daily.html
echo "<p>Top 10 users with the highest number of suspect records:</p>" >> /tmp/weblog_summary_daily.html
echo "" >> /tmp/weblog_summary_daily.html
psql -H -U postgres -d webproxylog -c "SELECT clientuserid as User_ID, SUM(badyesno) AS Total_Suspect, MAX(score) as Highest_Score FROM pubweblog WHERE score > 0 and logdatetime >= CURRENT_DATE - interval '$2 days' GROUP BY clientuserid ORDER BY SUM(badyesno) DESC limit 10;" >> /tmp/weblog_summary_daily.html
echo "" >> /tmp/weblog_summary_daily.html
echo "<p>Top 10 users with the highest scores per uri:</p>" >> /tmp/weblog_summary_daily.html
echo "" >> /tmp/weblog_summary_daily.html
psql -H -U postgres -d webproxylog -c "SELECT DISTINCT f.clientuserid AS User_ID, MAX(f.score) AS Score, t.uri AS Uri from pubweblog AS f INNER JOIN (SELECT clientuserid, score, id, uri FROM pubweblog where logdatetime >= CURRENT_DATE -interval '$2 days' AND score > 0) as t ON f.clientuserid = t.clientuserid and f.score = t.score and f.id = t.id WHERE f.logdatetime >= CURRENT_DATE - interval '$2 days' AND f.score > 0 GROUP BY f.clientuserid, t.uri ORDER BY MAX(f.score) DESC limit 10;" >> /tmp/weblog_summary_daily.html
echo "" >> /tmp/weblog_summary_daily.html
echo "<p>Top 10 users with the largest requests:</p>" >> /tmp/weblog_summary_daily.html
echo "" >> /tmp/weblog_summary_daily.html
psql -H -U postgres -d webproxylog -c "SELECT DISTINCT f.clientuserid as User_ID, ROUND((MAX(f.bytes)/1000000),2) AS Mbytes, t.uri AS Uri FROM pubweblog AS f INNER JOIN (SELECT clientuserid, bytes, id, uri FROM pubweblog where logdatetime >= CURRENT_DATE -interval '$2 days') as t ON f.clientuserid = t.clientuserid and f.bytes = t.bytes and f.id = t.id WHERE logdatetime >= CURRENT_DATE - interval '$2 days' GROUP BY f.clientuserid, t.uri ORDER BY Mbytes DESC limit 10;" >> /tmp/weblog_summary_daily.html
echo "" >> /tmp/weblog_summary_daily.html
echo "<p>Top 10 most prolific browsers:</p>" >> /tmp/weblog_summary_daily.html
echo "" >> /tmp/weblog_summary_daily.html
psql -H -U postgres -d webproxylog -c "SELECT clientuserid as User_ID, ROUND((SUM(bytes)/1000000),2) as Total_MB FROM pubweblog WHERE logdatetime >= CURRENT_DATE - interval '$2 days' GROUP BY clientuserid ORDER BY SUM(bytes) DESC limit 10;" >> /tmp/weblog_summary_daily.html
echo "" >> /tmp/weblog_summary_daily.html
echo "<br>For more information, visit the </br><a href='https://172.20.0.2/'>Resnet Weblog Viewer.</a>" >> /tmp/weblog_summary_daily.html
echo "" >> /tmp/weblog_summary_daily.html
echo "</body>" >> /tmp/weblog_summary_daily.html
echo "</html>" >> /tmp/weblog_summary_daily.html
echo "" >> /tmp/weblog_summary_daily.html
cat /tmp/weblog_summary_daily.html |grep -v "10 rows" | makemime -a "subject: Daily Resnet Weblog Summary - `date +\"%d.%m.%Y\"`" -c text/html | sendmail -S 10.78.64.4 -f "root@xzprxy01.resnet.zaf.wtbts.net" $1 
diff --git a/weblog_notify_weekly b/weblog_notify_weekly
new file mode 100755
index 0000000..49ab345
--- /dev/null
+++ b/weblog_notify_weekly
@@ -0,0 +1,36 @@
#!/bin/bash
echo "<html>" > /tmp/weblog_summary_weekly.html
echo "<head>" >> /tmp/weblog_summary_weekly.html
echo '<p><font weight="bold">WEEKLY SUMMARY WEBLOG REPORT FOR RESNET</font>'  >> /tmp/weblog_summary_weekly.html
echo "</head>" >> /tmp/weblog_summary_weekly.html
echo "" >> /tmp/weblog_summary_weekly.html
echo "<body>" >> /tmp/weblog_summary_weekly.html
echo "" >> /tmp/weblog_summary_weekly.html
echo "<p>Total number of records imported:" >> /tmp/weblog_summary_weekly.html
echo -e "`psql -t -U postgres -d webproxylog -c \"SELECT COUNT(*) FROM pubweblog WHERE logdatetime >= CURRENT_DATE - interval '$2 days';\"`</p>"  >> /tmp/weblog_summary_weekly.html
echo "" >> /tmp/weblog_summary_weekly.html
echo "<p>Total number of records with score > 0 imported:" >> /tmp/weblog_summary_weekly.html
echo -e "`psql -t -U postgres -d webproxylog -c \"SELECT COUNT(*) FROM pubweblog WHERE score > 0 AND logdatetime >= CURRENT_DATE - interval '$2 days' AND score > 0;\"`</p>" >> /tmp/weblog_summary_weekly.html
echo "" >> /tmp/weblog_summary_weekly.html
echo "<p>Top 10 users with the highest number of suspect records:</p>" >> /tmp/weblog_summary_weekly.html
echo "" >> /tmp/weblog_summary_weekly.html
psql -H -U postgres -d webproxylog -c "SELECT clientuserid as User_ID, SUM(badyesno) AS Total_Suspect, MAX(score) as Highest_Score FROM pubweblog WHERE score > 0 and logdatetime >= CURRENT_DATE - interval '$2 days' GROUP BY clientuserid ORDER BY SUM(badyesno) DESC limit 10;" >> /tmp/weblog_summary_weekly.html
echo "" >> /tmp/weblog_summary_weekly.html
echo "<p>Top 10 users with the highest scores per uri:</p>" >> /tmp/weblog_summary_weekly.html
echo "" >> /tmp/weblog_summary_weekly.html
psql -H -U postgres -d webproxylog -c "SELECT DISTINCT f.clientuserid AS User_ID, MAX(f.score) AS Score, t.uri AS Uri from pubweblog AS f INNER JOIN (SELECT clientuserid, score, id, uri FROM pubweblog where logdatetime >= CURRENT_DATE -interval '$2 days' AND score > 0) as t ON f.clientuserid = t.clientuserid and f.score = t.score and f.id = t.id WHERE f.logdatetime >= CURRENT_DATE - interval '$2 days' AND f.score > 0 GROUP BY f.clientuserid, t.uri ORDER BY MAX(f.score) DESC limit 10;" >> /tmp/weblog_summary_weekly.html
echo "" >> /tmp/weblog_summary_weekly.html
echo "<p>Top 10 users with the largest requests:</p>" >> /tmp/weblog_summary_weekly.html
echo "" >> /tmp/weblog_summary_weekly.html
psql -H -U postgres -d webproxylog -c "SELECT DISTINCT f.clientuserid as User_ID, ROUND((MAX(f.bytes)/1000000),2) AS Mbytes, t.uri AS Uri FROM pubweblog AS f INNER JOIN (SELECT clientuserid, bytes, id, uri FROM pubweblog where logdatetime >= CURRENT_DATE -interval '$2 days') as t ON f.clientuserid = t.clientuserid and f.bytes = t.bytes and f.id = t.id WHERE logdatetime >= CURRENT_DATE - interval '$2 days' GROUP BY f.clientuserid, t.uri ORDER BY Mbytes DESC limit 10;" >> /tmp/weblog_summary_weekly.html
echo "" >> /tmp/weblog_summary_weekly.html
echo "<p>Top 10 most prolific browsers:</p>" >> /tmp/weblog_summary_weekly.html
echo "" >> /tmp/weblog_summary_weekly.html
psql -H -U postgres -d webproxylog -c "SELECT clientuserid as User_ID, ROUND((SUM(bytes)/1000000),2) as Total_MB FROM pubweblog WHERE logdatetime >= CURRENT_DATE - interval '$2 days' GROUP BY clientuserid ORDER BY SUM(bytes) DESC limit 10;" >> /tmp/weblog_summary_weekly.html
echo "" >> /tmp/weblog_summary_weekly.html
echo "<br>For more information, visit the </br><a href='https://172.20.0.2/'>Resnet Weblog Viewer.</a>" >> /tmp/weblog_summary_weekly.html
echo "" >> /tmp/weblog_summary_weekly.html
echo "</body>" >> /tmp/weblog_summary_weekly.html
echo "</html>" >> /tmp/weblog_summary_weekly.html
echo "" >> /tmp/weblog_summary_weekly.html
cat /tmp/weblog_summary_weekly.html |grep -v "10 rows" | makemime -a "subject: Weekly Resnet Weblog Summary - `date +\"%d.%m.%Y\"`" -c text/html | sendmail -S 10.78.64.4 -f "root@xzprxy01.resnet.zaf.wtbts.net" $1 
-- 
1.7.4.1



---
Unsubscribe:  alpine-devel+unsubscribe@lists.alpinelinux.org
Help:         alpine-devel+help@lists.alpinelinux.org
---
Details
Message ID
<684692.17856.qm@web130110.mail.mud.yahoo.com>
In-Reply-To
<1298643294-15858-1-git-send-email-lukestu@gmail.com> (view parent)
Sender timestamp
1298643454
DKIM signature
missing
Download raw message
I'll take care of this. Luke, please e-mail me the source.

Ted



----- Original Message ----
From: Luke Stuart <lukestu@gmail.com>
To: alpine-devel@lists.alpinelinux.org
Cc: Luke Stuart <lukestu@gmail.com>
Sent: Fri, February 25, 2011 9:14:54 AM
Subject: [alpine-devel] [PATCH] Upgrade Weblog to Weblog 2.0

---
Makefile                      |   15 +-
bypass.png                    |  Bin 0 -> 1395 bytes
denied.png                    |  Bin 0 -> 1376 bytes
dodgy.png                     |  Bin 0 -> 1357 bytes
jquery.min.js                 |  154 ++++++++
newviewfunctions.lua          |   52 +++
template-silent.lsp           |    9 +
weblog-adhocquery-html.lsp    |    2 +-
weblog-config-html.lsp        |    5 +-
weblog-controller.lua         |   69 +++-
weblog-editfile-html.lsp      |    1 +
weblog-listfiles-html.lsp     |   42 ++
weblog-maintenance-html.lsp   |   17 +
weblog-model.lua              |  873 +++++++++++++++++++++++++++++++----------
weblog-summary-html.lsp       |   17 +
weblog-viewwatchlist-html.lsp |    2 +-
weblog-viewweblog-html.lsp    |  301 ++++++++++++++-
weblog.menu                   |    4 +-
weblog.roles                  |    4 +-
weblog_notify_daily           |   36 ++
weblog_notify_weekly          |   36 ++
21 files changed, 1405 insertions(+), 234 deletions(-)
create mode 100644 bypass.png
create mode 100644 denied.png
create mode 100644 dodgy.png
create mode 100644 jquery.min.js
create mode 100644 newviewfunctions.lua
create mode 100644 template-silent.lsp
create mode 120000 weblog-editfile-html.lsp
create mode 100644 weblog-listfiles-html.lsp
create mode 100644 weblog-maintenance-html.lsp
create mode 100644 weblog-summary-html.lsp
mode change 120000 => 100644 weblog-viewweblog-html.lsp
create mode 100755 weblog_notify_daily
create mode 100755 weblog_notify_weekly

diff --git a/Makefile b/Makefile
index 64962e6..b79753b 100644
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,11 @@
APP_NAME=weblog
PACKAGE=acf-$(APP_NAME)
-VERSION=0.5.9
+VERSION=0.9.1

CRON_FILE=weblogimport
+TEMPLATE_FILE=template-silent.lsp
+JAVA_FILE=jquery.min.js
+LIB_FILE=newviewfunctions.lua

APP_DIST=$(filter-out $(CRON_FILE), $(wildcard weblog*))

@@ -16,6 +19,9 @@ P=$(PACKAGE)-$(VERSION)
tarball=$(P).tar.bz2
install_dir=$(DESTDIR)/$(appdir)/$(APP_NAME)
cron_dir=$(DESTDIR)/etc/periodic/daily
+template_dir=$(DESTDIR)/$(appdir)
+java_dir=$(DESTDIR)/www/js/
+lib_dir=$(DESTDIR)/lib/

all:
clean:
@@ -24,10 +30,13 @@ clean:
dist: $(tarball)

install:
-    mkdir -p "$(install_dir)" "$(cron_dir)"
+    mkdir -p "$(install_dir)" "$(cron_dir)" "$(template_dir)" "$(java_dir)" 
"$(lib_dir)"
    cp -a $(APP_DIST) "$(install_dir)"
    cp -a $(CRON_FILE) "$(cron_dir)"
-
+    cp -a $(JAVA_FILE) "$(java_dir)"
+    cp -a $(TEMPLATE_FILE) "$(template_dir)"
+    cp -a $(LIB_FILE) "$(lib_dir)"
+    
$(tarball):    $(DISTFILES)
    rm -rf $(P)
    mkdir -p $(P)
diff --git a/bypass.png b/bypass.png
new file mode 100644
index 
0000000000000000000000000000000000000000..896070ebbcd862d47abd2f3f087e70b5e6054cae

GIT binary patch
literal 1395
zcmeAS@N?(olHy`uVBq!ia0vp^B0wy_!3-o7kFD1PQjEnx?oJHr&dIz4a#+$GeH|GX
zHuiJ>Nn~YUU}gyL32_CAr)e|HWB?-LnLvg%kW8By$}lt3_zVNX8EqgkJ`>7tCe-*p
zP$V?%e`wmwhO{#c#{V0P&ord{2clI#?#wf*X8v!O`G3{SGgpE7M!{$Z42=-z6nZTV
z%qI*bL4LviM>b#x{?4unj5W>zkH}&M2EM}}%y>M1MG8<*qQo_#Bsf2<q&%@Gl_4N8
zGp|I?&oxA$%vjIZY~}MuAdP1{T^vI+f^8=>79COGaN#{_<``c5!nOGC|My!il=Vr<
z)*NQaj*wH%<E;4iOzfbay4cKOhhNfs=U(XNR-H}x@a>deWVVVWixuy(ya`4DvB%Wk
z=mm$pc#ze9e9>|%=Yt%-(|>OG=%aUa@=`Mvt%TRFPepUz=P7vbF0wGw`;PeHKo2g<
zJ@2FzYz(uxEElI?7d<=DfbEIJA))yJ0Z(uLxw4n*_ouvMGusx6Ytz=QuioBkpno+p
xcmJOE@-cr8*q+s#{QsoANzazti>Gwz7~WY`_dk)Gy$h6#Jzf1=);T3K0RY8Tv2p+a

literal 0
HcmV?d00001

diff --git a/denied.png b/denied.png
new file mode 100644
index 
0000000000000000000000000000000000000000..0238f3d4149a144b94186f26102baf097b5fe665

GIT binary patch
literal 1376
zcmeAS@N?(olHy`uVBq!ia0vp^f<P?5!3-pizfZ{pQjEnx?oJHr&dIz4a#+$GeH|GX
zHuiJ>Nn~YUU}gyL32_CAr)e|HWB?-LnLvg%kW8By$}lt3_zVNX8EqgkJ`>7tCe-*p
zP$V?%e`wmwhO{#c#{V0P&ord{2clI#?#wf*X8v!O`G3{SGgpE7M!{$Z42=-z6nZTV
z%qI*bL4LviM>b#x{?4unj5W>zkH}&M2EM}}%y>M1MG8<*qQo_#Bsf2<q&%@Gl_4N8
zGp|I?&oxA$%vjIZY~}MuAdNdcT^vI+f_3{F^A0QUxOAp(J5n$~Qfkh(|NAG;ESshi
z>3{8V?2K%;J3=2S?jPJP+&zQW<Nt(%l7CnF>U)1zn!D+mM-j)BpmHb472XHbyH4`R
z#uz?-zocDEq-R6@^z~1bE>B)+#-f!_{_xr%b7q+x>sM!Z-%(#2=)q-Kz<Xha@w`la
z|0%1^I$JRm$s~4(hE!JG*%kh9szKys=Z@suo3X1|-vpV4|JAv^`(@+pJ*=1OFCU$-
dP4`#xd3onE-usi{4g`bJtf#A=%Q~loCIHSBsL%ia

literal 0
HcmV?d00001

diff --git a/dodgy.png b/dodgy.png
new file mode 100644
index 
0000000000000000000000000000000000000000..b035ba9218d6aa0caa4644ef3cdda37c4729ce60

GIT binary patch
literal 1357
zcmeAS@N?(olHy`uVBq!ia0vp^f*{Pn3?z9rZ$AN~7>k44ofy`glX(f`u%tWsIx;Y9
z?C1WI$jZRL%n;xc;tCWu);2a~NHf+>OJhh&1CpV}X`yMx3^UV!NE=9=Nz*=)7CLh#
z!_1l5K=RB??K3lh+|V;;LeI=>m^pLR%$W^mX0AGOreWrpRWr{toH+wzulj%H>X|cF
z|Np;w=0A}9{~u`4C>RZa!4?AXI<-E)e8Nx?<QEJ|rXv_I1b=5&1;!6&fk$L90|Vb-
z5N14{zaj-FC{f}XQ4*Y=R#Ki=l*$m0n3-3i=jR%tP-d)WY_{_GBap^ro-U3d8o{v_
z5`~)-c-S6vd6^ruW{Nmn`S-uxWZ9jkTl>%7OHOWox}Q(l=iJU)QLR-<MmN@~Jv#Aw
zVul0HY>TdmGlh8-Rw~_%QBXf8rROi`-v8xX%FJqA#fcXun@%*&u;@ydnSAz)J~xL~
z$|WfiquWA_ZYm4R%-?c)&0UsjHBGNR>cF=sa~BqmK&9_m3$4Yor%sxBJzmE<V@lR3
hY5SY;OX8B<<2RZ0KJ|U}UIdgBJzf1=);T3K0RRn0sU`pb

literal 0
HcmV?d00001

diff --git a/jquery.min.js b/jquery.min.js
new file mode 100644
index 0000000..7c24308
--- /dev/null
+++ b/jquery.min.js
@@ -0,0 +1,154 @@
+/*!
+ * jQuery JavaScript Library v1.4.2
+ * http://jquery.com/
+ *
+ * Copyright 2010, John Resig
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ * Copyright 2010, The Dojo Foundation
+ * Released under the MIT, BSD, and GPL Licenses.
+ *
+ * Date: Sat Feb 13 22:33:48 2010 -0500
+ */
+(function(A,w){function 
ma(){if(!c.isReady){try{s.documentElement.doScroll("left")}catch(a){setTimeout(ma,1);return}c.ready()}}function
Qa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function
n X(a,b,d,f,e,j){var i=a.length;if(typeof b==="object"){for(var o in 
b)X(a,o,b[o],f,e,d);return 
a}if(d!==w){f=!j&&f&&c.isFunction(d);for(o=0;o<i;o++)e(a[o],b,f?d.call(a[o],o,e(a[o],b)):d,j);return
 a}return i?
+e(a[0],b):w}function J(){return(new Date).getTime()}function Y(){return 
false}function Z(){return true}function na(a,b,d){d[0].type=a;return 
c.event.handle.apply(b,d)}function oa(a){var 
b,d=[],f=[],e=arguments,j,i,o,k,n,r;i=c.data(this,"events");if(!(a.liveFired===this||!i||!i.live||a.button&&a.type==="click")){a.liveFired=this;var
u=i.live.slice(0);for(k=0;k<u.length;k++){i=u[k];i.origType.replace(O,"")===a.type?f.push(i.selector):u.splice(k--,1)}j=c(a.target).closest(f,a.currentTarget);n=0;for(r=
=
+j.length;n<r;n++)for(k=0;k<u.length;k++){i=u[k];if(j[n].selector===i.selector){o=j[n].elem;f=null;if(i.preType==="mouseenter"||i.preType==="mouseleave")f=c(a.relatedTarget).closest(i.selector)[0];if(!f||f!==o)d.push({elem:o,handleObj:i})}}n=0;for(r=d.length;n<r;n++){j=d[n];a.currentTarget=j.elem;a.data=j.handleObj.data;a.handleObj=j.handleObj;if(j.handleObj.origHandler.apply(j.elem,e)===false){b=false;break}}return
 b}}function 
pa(a,b){return"live."+(a&&a!=="*"?a+".":"")+b.replace(/\./g,"`").replace(/ /g,
+"&")}function 
qa(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function ra(a,b){var 
d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var 
f=c.data(a[d++]),e=c.data(this,f);if(f=f&&f.events){delete 
e.handle;e.events={};for(var j in f)for(var i in 
f[j])c.event.add(this,j,f[j][i],f[j][i].data)}}})}function sa(a,b,d){var 
f,e,j;b=b&&b[0]?b[0].ownerDocument||b[0]:s;if(a.length===1&&typeof 
a[0]==="string"&&a[0].length<512&&b===s&&!ta.test(a[0])&&(c.support.checkClone||!ua.test(a[0]))){e=

+true;if(j=c.fragments[a[0]])if(j!==1)f=j}if(!f){f=b.createDocumentFragment();c.clean(a,b,f,d)}if(e)c.fragments[a[0]]=j?f:1;return{fragment:f,cacheable:e}}function
 K(a,b){var 
d={};c.each(va.concat.apply([],va.slice(0,b)),function(){d[this]=a});return 
d}function wa(a){return"scrollTo"in 
a&&a.document?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var 
c=function(a,b){return new 
c.fn.init(a,b)},Ra=A.jQuery,Sa=A.$,s=A.document,T,Ta=/^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/,

+Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var
 d,f;if(!a)return 
this;if(a.nodeType){this.context=this[0]=a;this.length=1;return 
this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return
 this}if(typeof a==="string")if((d=Ta.exec(a))&&
+(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else
a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return
n c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return 
T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return 
this}else 
if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return
 c.merge(this,
+a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else 
if(c.isFunction(a))return 
T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return
 c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return 
this.length},toArray:function(){return R.call(this,0)},get:function(a){return 
a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var
f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b===
=
+"find")f.selector=this.selector+(this.selector?" ":"")+d;else 
if(b)f.selector=this.selector+"."+b+"("+d+")";return 
f},each:function(a,b){return 
c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else 
Q&&Q.push(a);return this},eq:function(a){return 
a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return 
this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return 
this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return
 this.pushStack(c.map(this,
+function(b,d){return a.call(b,d,b)}))},end:function(){return 
this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var
 a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof 
a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof 
a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b<d;b++)if((e=arguments[b])!=null)for(j
 in 
e){i=a[j];o=e[j];if(a!==o)if(f&&o&&(c.isPlainObject(o)||c.isArray(o))){i=i&&(c.isPlainObject(i)||

+c.isArray(i))?i:c.isArray(o)?[]:{};a[j]=c.extend(f,i,o)}else 
if(o!==w)a[j]=o}return 
a};c.extend({noConflict:function(a){A.$=Sa;if(a)A.jQuery=Ra;return 
c},isReady:false,ready:function(){if(!c.isReady){if(!s.body)return 
setTimeout(c.ready,13);c.isReady=true;if(Q){for(var 
a,b=0;a=Q[b++];)a.call(s,c);Q=null}c.fn.triggerHandler&&c(s).triggerHandler("ready")}},bindReady:function(){if(!xa){xa=true;if(s.readyState==="complete")return
 c.ready();if(s.addEventListener){s.addEventListener("DOMContentLoaded",
+L,false);A.addEventListener("load",c.ready,false)}else 
if(s.attachEvent){s.attachEvent("onreadystatechange",L);A.attachEvent("onload",c.ready);var
a=false;try{a=A.frameElement==null}catch(b){}s.documentElement.doScroll&&a&&ma()}}},isFunction:function(a){return
n $.call(a)==="[object Function]"},isArray:function(a){return 
$.call(a)==="[object 
Array]"},isPlainObject:function(a){if(!a||$.call(a)!=="[object 
Object]"||a.nodeType||a.setInterval)return 
false;if(a.constructor&&!aa.call(a,"constructor")&&!aa.call(a.constructor.prototype,

+"isPrototypeOf"))return false;var b;for(b in a);return 
b===w||aa.call(a,b)},isEmptyObject:function(a){for(var b in a)return 
false;return true},error:function(a){throw a;},parseJSON:function(a){if(typeof 
a!=="string"||!a)return 
null;a=c.trim(a);if(/^[\],:{}\s]*$/.test(a.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return
 A.JSON&&A.JSON.parse?A.JSON.parse(a):(new Function("return "+
+a))();else c.error("Invalid JSON: 
"+a)},noop:function(){},globalEval:function(a){if(a&&Va.test(a)){var 
b=s.getElementsByTagName("head")[0]||s.documentElement,d=s.createElement("script");d.type="text/javascript";if(c.support.scriptEval)d.appendChild(s.createTextNode(a));else
d.text=a;b.insertBefore(d,b.firstChild);b.removeChild(d)}},nodeName:function(a,b){return
n 
a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,b,d){var 
f,e=0,j=a.length,i=j===w||c.isFunction(a);if(d)if(i)for(f in a){if(b.apply(a[f],
+d)===false)break}else for(;e<j;){if(b.apply(a[e++],d)===false)break}else 
if(i)for(f in a){if(b.call(a[f],f,a[f])===false)break}else 
for(d=a[0];e<j&&b.call(d,e,d)!==false;d=a[++e]);return 
a},trim:function(a){return(a||"").replace(Wa,"")},makeArray:function(a,b){b=b||[];if(a!=null)a.length==null||typeof
 a==="string"||c.isFunction(a)||typeof 
a!=="function"&&a.setInterval?ba.call(b,a):c.merge(b,a);return 
b},inArray:function(a,b){if(b.indexOf)return b.indexOf(a);for(var 
d=0,f=b.length;d<f;d++)if(b[d]===
+a)return d;return-1},merge:function(a,b){var d=a.length,f=0;if(typeof 
b.length==="number")for(var e=b.length;f<e;f++)a[d++]=b[f];else 
for(;b[f]!==w;)a[d++]=b[f++];a.length=d;return a},grep:function(a,b,d){for(var 
f=[],e=0,j=a.length;e<j;e++)!d!==!b(a[e],e)&&f.push(a[e]);return 
f},map:function(a,b,d){for(var 
f=[],e,j=0,i=a.length;j<i;j++){e=b(a[j],j,d);if(e!=null)f[f.length]=e}return 
f.concat.apply([],f)},guid:1,proxy:function(a,b,d){if(arguments.length===2)if(typeof
 b==="string"){d=a;a=d[b];b=w}else if(b&&
+!c.isFunction(b)){d=b;b=w}if(!b&&a)b=function(){return 
a.apply(d||this,arguments)};if(a)b.guid=a.guid=a.guid||b.guid||c.guid++;return 
b},uaMatch:function(a){a=a.toLowerCase();a=/(webkit)[ 
\/]([\w.]+)/.exec(a)||/(opera)(?:.*version)?[ \/]([\w.]+)/.exec(a)||/(msie) 
([\w.]+)/.exec(a)||!/compatible/.test(a)&&/(mozilla)(?:.*? 
rv:([\w.]+))?/.exec(a)||[];return{browser:a[1]||"",version:a[2]||"0"}},browser:{}});P=c.uaMatch(P);if(P.browser){c.browser[P.browser]=true;c.browser.version=P.version}if(c.browser.webkit)c.browser.safari=

+true;if(ya)c.inArray=function(a,b){return 
ya.call(b,a)};T=c(s);if(s.addEventListener)L=function(){s.removeEventListener("DOMContentLoaded",L,false);c.ready()};else
if(s.attachEvent)L=function(){if(s.readyState==="complete"){s.detachEvent("onreadystatechange",L);c.ready()}};(function(){c.support={};var
r 
a=s.documentElement,b=s.createElement("script"),d=s.createElement("div"),f="script"+J();d.style.display="none";d.innerHTML=" 
  <link/><table></table><a href='/a' 
style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
+var 
e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected,

+parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete
 A[f]}try{delete 
b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function
 k(){c.support.noCloneEvent=
+false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="<input
 type='radio' name='radiotest' 
checked='checked'/>";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var
k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var
r n=
+s.createElement("div");k="on"+k;var r=k in 
n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return 
r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var
G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true,
,
+applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var
 f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return 
null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else 
if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof 
b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var
 d=a[G],f=c.cache,e=f[d];if(b){if(e){delete 
e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete 
a[c.expando];
+else a.removeAttribute&&a.removeAttribute(c.expando);delete 
f[d]}}}});c.fn.extend({data:function(a,b){if(typeof 
a==="undefined"&&this.length)return c.data(this[0]);else if(typeof 
a==="object")return this.each(function(){c.data(this,a)});var 
d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var 
f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return
 f===w&&d[1]?this.data(d[0]):f}else return 
this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this,
+a,b)})},removeData:function(a){return 
this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var
 f=c.data(a,b);if(!d)return 
f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return 
f}},dequeue:function(a,b){b=b||"fx";var 
d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof
 a!=="string"){b=a;a="fx"}if(b===
+w)return c.queue(this[0],a);return this.each(function(){var 
d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return
this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return
n this.queue(b,function(){var 
d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return 
this.queue(a||"fx",[])}});var 
Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i,

+cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return 
X(this,a,b,true,c.attr)},removeAttr:function(a){return 
this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return
 this.each(function(n){var 
r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof 
a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var 
e=this[d];if(e.nodeType===1)if(e.className){for(var j=" "+e.className+" ",
+i=e.className,o=0,k=b.length;o<k;o++)if(j.indexOf(" "+b[o]+" ")<0)i+=" 
"+b[o];e.className=c.trim(i)}else e.className=a}return 
this},removeClass:function(a){if(c.isFunction(a))return 
this.each(function(k){var 
n=c(this);n.removeClass(a.call(this,k,n.attr("class")))});if(a&&typeof 
a==="string"||a===w)for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var 
e=this[d];if(e.nodeType===1&&e.className)if(a){for(var j=(" "+e.className+" 
").replace(Aa," "),i=0,o=b.length;i<o;i++)j=j.replace(" "+b[i]+" ",
+" ");e.className=c.trim(j)}else e.className=""}return 
this},toggleClass:function(a,b){var d=typeof a,f=typeof 
b==="boolean";if(c.isFunction(a))return this.each(function(e){var 
j=c(this);j.toggleClass(a.call(this,e,j.attr("class"),b),b)});return 
this.each(function(){if(d==="string")for(var 
e,j=0,i=c(this),o=b,k=a.split(ca);e=k[j++];){o=f?o:!i.hasClass(e);i[o?"addClass":"removeClass"](e)}else
if(d==="undefined"||d==="boolean"){this.className&&c.data(this,"__className__",this.className);this.className=
=
+this.className||a===false?"":c.data(this,"__className__")||""}})},hasClass:function(a){a="
 "+a+" ";for(var b=0,d=this.length;b<d;b++)if((" "+this[b].className+" 
").replace(Aa," ").indexOf(a)>-1)return true;return 
false},val:function(a){if(a===w){var 
b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var
 d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return 
null;var j=b?d:0;for(d=b?d+1:e.length;j<d;j++){var i=
+e[j];if(i.selected){a=c(i).val();if(b)return a;f.push(a)}}return 
f}if(Ba.test(b.type)&&!c.support.checkOn)return 
b.getAttribute("value")===null?"on":b.value;return(b.value||"").replace(Za,"")}return
 w}var o=c.isFunction(a);return this.each(function(k){var 
n=c(this),r=a;if(this.nodeType===1){if(o)r=a.call(this,k,n.val());if(typeof 
r==="number")r+="";if(c.isArray(r)&&Ba.test(this.type))this.checked=c.inArray(n.val(),r)>=0;else
 if(c.nodeName(this,"select")){var 
u=c.makeArray(r);c("option",this).each(function(){this.selected=
+c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else 
this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return
 w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var 
e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in 
a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type 
property can't be changed");
+a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return 
a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return
 a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return 
a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return
 a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return 
a.replace(/[^\w\s\.\|`]/g,
+function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var
e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var 
 i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof 
c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split("
 ");for(var 
k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split(".");

+k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var
u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else
e 
a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var
 e,j=0,i,o,k,n,r,u,z=c.data(a),
+C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof 
b==="string"&&b.charAt(0)==="."){b=b||"";for(e in 
C)c.event.remove(a,e+b)}else{for(b=b.split(" 
");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new
RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B<r.length;B++){u=r[B];if(d.guid===u.guid){if(i||k.test(u.namespace)){f==null&&r.splice(B--,1);n.remove&&n.remove.call(a,u)}if(f!=
=
+null)break}}if(r.length===0||f!=null&&r.length===1){if(!n.teardown||n.teardown.call(a,o)===false)Ca(a,e,z.handle);delete
 C[e]}}else for(var 
B=0;B<r.length;B++){u=r[B];if(i||k.test(u.namespace)){c.event.remove(a,n,u.handler,B);r.splice(B--,1)}}}if(c.isEmptyObject(C)){if(b=z.handle)b.elem=null;delete
 z.events;delete 
z.handle;c.isEmptyObject(z)&&c.removeData(a)}}}}},trigger:function(a,b,d,f){var 
e=a.type||a;if(!f){a=typeof 
a==="object"?a[G]?a:c.extend(c.Event(e),a):c.Event(e);if(e.indexOf("!")>=0){a.type=

+e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return
w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&&
&
+f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var 
i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var
b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive;
;
+if(!b){d=a.type.split(".");a.type=d.shift();f=new 
RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var
 j=d.length;e<j;e++){var 
i=d[e];if(b||f.test(i.namespace)){a.handler=i.handler;a.data=i.data;a.handleObj=i;i=i.handler.apply(this,arguments);if(i!==w){a.result=i;if(i===false){a.preventDefault();a.stopPropagation()}}if(a.isImmediatePropagationStopped())break}}}return
 a.result},props:"altKey attrChange attrName bubbles button cancelable charCode 
clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler 
keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX 
pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement 
target toElement view wheelDelta which".split(" "),
+fix:function(a){if(a[G])return a;var b=a;a=c.Event(b);for(var 
d=this.props.length,f;d;){f=this.props[--d];a[f]=b[f]}if(!a.target)a.target=a.srcElement||s;if(a.target.nodeType===3)a.target=a.target.parentNode;if(!a.relatedTarget&&a.fromElement)a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement;if(a.pageX==null&&a.clientX!=null){b=s.documentElement;d=s.body;a.pageX=a.clientX+(b&&b.scrollLeft||d&&d.scrollLeft||0)-(b&&b.clientLeft||d&&d.clientLeft||0);a.pageY=a.clientY+(b&&b.scrollTop||

+d&&d.scrollTop||0)-(b&&b.clientTop||d&&d.clientTop||0)}if(!a.which&&(a.charCode||a.charCode===0?a.charCode:a.keyCode))a.which=a.charCode||a.keyCode;if(!a.metaKey&&a.ctrlKey)a.metaKey=a.ctrlKey;if(!a.which&&a.button!==w)a.which=a.button&1?1:a.button&2?3:a.button&4?2:0;return
a},guid:1E8,proxy:c.proxy,special:{ready:{setup:c.bindReady,teardown:c.noop},live:{add:function(a){c.event.add(this,a.origType,c.extend({},a,{handler:oa}))},remove:function(a){var
r b=true,d=a.origType.replace(O,"");c.each(c.data(this,
+"events").live||[],function(){if(d===this.origType.replace(O,""))return 
b=false});b&&c.event.remove(this,a.origType,oa)}},beforeunload:{setup:function(a,b,d){if(this.setInterval)this.onbeforeunload=d;return
false},teardown:function(a,b){if(this.onbeforeunload===b)this.onbeforeunload=null}}}};var
r 
Ca=s.removeEventListener?function(a,b,d){a.removeEventListener(b,d,false)}:function(a,b,d){a.detachEvent("on"+b,d)};c.Event=function(a){if(!this.preventDefault)return
 new c.Event(a);if(a&&a.type){this.originalEvent=
+a;this.type=a.type}else 
this.type=a;this.timeStamp=J();this[G]=true};c.Event.prototype={preventDefault:function(){this.isDefaultPrevented=Z;var
a=this.originalEvent;if(a){a.preventDefault&&a.preventDefault();a.returnValue=false}},stopPropagation:function(){this.isPropagationStopped=Z;var
r 
a=this.originalEvent;if(a){a.stopPropagation&&a.stopPropagation();a.cancelBubble=true}},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=Z;this.stopPropagation()},isDefaultPrevented:Y,isPropagationStopped:Y,

+isImmediatePropagationStopped:Y};var Da=function(a){var 
b=a.relatedTarget;try{for(;b&&b!==this;)b=b.parentNode;if(b!==this){a.type=a.data;c.event.handle.apply(this,arguments)}}catch(d){}},Ea=function(a){a.type=a.data;c.event.handle.apply(this,arguments)};c.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){c.event.special[a]={setup:function(d){c.event.add(this,b,d&&d.selector?Ea:Da,a)},teardown:function(d){c.event.remove(this,b,d&&d.selector?Ea:Da)}}});if(!c.support.submitBubbles)c.event.special.submit=

+{setup:function(){if(this.nodeName.toLowerCase()!=="form"){c.event.add(this,"click.specialSubmit",function(a){var
b=a.target,d=b.type;if((d==="submit"||d==="image")&&c(b).closest("form").length)return
n 
na("submit",this,arguments)});c.event.add(this,"keypress.specialSubmit",function(a){var
b=a.target,d=b.type;if((d==="text"||d==="password")&&c(b).closest("form").length&&a.keyCode===13)return
n na("submit",this,arguments)})}else return 
false},teardown:function(){c.event.remove(this,".specialSubmit")}};
+if(!c.support.changeBubbles){var 
da=/textarea|input|select/i,ea,Fa=function(a){var 
b=a.type,d=a.value;if(b==="radio"||b==="checkbox")d=a.checked;else 
if(b==="select-multiple")d=a.selectedIndex>-1?c.map(a.options,function(f){return 
f.selected}).join("-"):"";else 
if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return 
d},fa=function(a,b){var 
d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data",

+e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return 
c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var
b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return
n fa.call(this,a)},keydown:function(a){var 
b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return
 fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a,
+"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return 
false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return 
da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return
da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function
n d(f){f=c.event.fix(f);f.type=b;return 
c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a,

+d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof
 d==="object"){for(var j in d)this[b](j,f,d[j],e);return 
this}if(c.isFunction(f)){e=f;f=w}var 
i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return 
e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var
 o=this.length;j<o;j++)c.event.add(this[j],d,i,f)}return 
this}});c.fn.extend({unbind:function(a,b){if(typeof a==="object"&&
+!a.preventDefault)for(var d in a)this.unbind(d,a[d]);else{d=0;for(var 
f=this.length;d<f;d++)c.event.remove(this[d],a,b)}return 
this},delegate:function(a,b,d,f){return 
this.live(b,d,f,a)},undelegate:function(a,b,d){return 
arguments.length===0?this.unbind("live"):this.die(b,null,d,a)},trigger:function(a,b){return
this.each(function(){c.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){a=c.Event(a);a.preventDefault();a.stopPropagation();c.event.trigger(a,b,this[0]);return
n a.result}},
+toggle:function(a){for(var b=arguments,d=1;d<b.length;)c.proxy(a,b[d++]);return 
this.click(c.proxy(a,function(f){var 
e=(c.data(this,"lastToggle"+a.guid)||0)%d;c.data(this,"lastToggle"+a.guid,e+1);f.preventDefault();return
 b[e].apply(this,arguments)||false}))},hover:function(a,b){return 
this.mouseenter(a).mouseleave(b||a)}});var 
Ga={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};c.each(["live","die"],function(a,b){c.fn[b]=function(d,f,e,j){var
 i,o=0,k,n,r=j||this.selector,
+u=j?this:c(this.context);if(c.isFunction(f)){e=f;f=w}for(d=(d||"").split(" 
");(i=d[o++])!=null;){j=O.exec(i);k="";if(j){k=j[0];i=i.replace(O,"")}if(i==="hover")d.push("mouseenter"+k,"mouseleave"+k);else{n=i;if(i==="focus"||i==="blur"){d.push(Ga[i]+k);i+=k}else
i=(Ga[i]||i)+k;b==="live"?u.each(function(){c.event.add(this,pa(i,r),{data:f,selector:r,handler:e,origType:i,origHandler:e,preType:n})}):u.unbind(pa(i,r),e)}}return
n this}});c.each("blur focus focusin focusout load resize scroll unload click 
dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave 
change select submit keydown keypress keyup error".split(" "),
+function(a,b){c.fn[b]=function(d){return 
d?this.bind(b,d):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});A.attachEvent&&!A.addEventListener&&A.attachEvent("onunload",function(){for(var
 a in 
c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}});(function(){function
 a(g){for(var 
h="",l,m=0;g[m];m++){l=g[m];if(l.nodeType===3||l.nodeType===4)h+=l.nodeValue;else
 if(l.nodeType!==8)h+=a(l.childNodes)}return h}function 
b(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];
+if(t){t=t[g];for(var 
y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1&&!p){t.sizcache=l;t.sizset=q}if(t.nodeName.toLowerCase()===h){y=t;break}t=t[g]}m[q]=y}}}function
 d(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];if(t){t=t[g];for(var 
y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1){if(!p){t.sizcache=l;t.sizset=q}if(typeof
 h!=="string"){if(t===h){y=true;break}}else 
if(k.filter(h,[t]).length>0){y=t;break}}t=t[g]}m[q]=y}}}var 
f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^
 >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
+e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return
 0});var k=function(g,h,l,m){l=l||[];var 
q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof 
g!=="string")return l;for(var 
p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else
for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift();
;
+t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else
 H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else 
D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D||
+g);if(j.call(y)==="[object 
Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else
 for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else 
l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return 
l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var 
h=1;h<g.length;h++)g[h]===g[h-1]&&g.splice(h--,1)}return 
g};k.matches=function(g,h){return k(g,null,null,h)};k.find=function(g,h,l){var 
m,q;if(!g)return[];
+for(var p=0,v=n.order.length;p<v;p++){var 
t=n.order[p];if(q=n.leftMatch[t].exec(g)){var 
y=q[1];q.splice(1,1);if(y.substr(y.length-1)!=="\\"){q[1]=(q[1]||"").replace(/\\/g,"");m=n.find[t](q,h,l);if(m!=null){g=g.replace(n.match[t],"");break}}}}m||(m=h.getElementsByTagName("*"));return{set:m,expr:g}};k.filter=function(g,h,l,m){for(var
 q=g,p=[],v=h,t,y,S=h&&h[0]&&x(h[0]);g&&h.length;){for(var H in 
n.filter)if((t=n.leftMatch[H].exec(g))!=null&&t[2]){var 
M=n.filter[H],I,D;D=t[1];y=false;t.splice(1,1);if(D.substr(D.length-
+1)!=="\\"){if(v===p)p=[];if(n.preFilter[H])if(t=n.preFilter[H](t,v,l,p,m,S)){if(t===true)continue}else
 y=I=true;if(t)for(var U=0;(D=v[U])!=null;U++)if(D){I=M(D,t,U,v);var 
Ha=m^!!I;if(l&&I!=null)if(Ha)y=true;else v[U]=false;else 
if(Ha){p.push(D);y=true}}if(I!==w){l||(v=p);g=g.replace(n.match[H],"");if(!y)return[];break}}}if(g===q)if(y==null)k.error(g);else
 break;q=g}return v};k.error=function(g){throw"Syntax error, unrecognized 
expression: "+g;};var 
n=k.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,

+CLASS:/\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(g){return
 g.getAttribute("href")}},
+relative:{"+":function(g,h){var l=typeof 
h==="string",m=l&&!/\W/.test(h);l=l&&!m;if(m)h=h.toLowerCase();m=0;for(var 
q=g.length,p;m<q;m++)if(p=g[m]){for(;(p=p.previousSibling)&&p.nodeType!==1;);g[m]=l||p&&p.nodeName.toLowerCase()===h?p||false:p===h}l&&k.filter(h,g,true)},">":function(g,h){var
 l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var 
m=0,q=g.length;m<q;m++){var 
p=g[m];if(p){l=p.parentNode;g[m]=l.nodeName.toLowerCase()===h?l:false}}}else{m=0;for(q=g.length;m<q;m++)if(p=g[m])g[m]=

+l?p.parentNode:p.parentNode===h;l&&k.filter(h,g,true)}},"":function(g,h,l){var 
m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var 
p=h=h.toLowerCase();q=b}q("parentNode",h,m,g,p,l)},"~":function(g,h,l){var 
m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var 
p=h=h.toLowerCase();q=b}q("previousSibling",h,m,g,p,l)}},find:{ID:function(g,h,l){if(typeof
h.getElementById!=="undefined"&&!l)return(g=h.getElementById(g[1]))?[g]:[]},NAME:function(g,h){if(typeof
f h.getElementsByName!=="undefined"){var l=[];
+h=h.getElementsByName(g[1]);for(var 
m=0,q=h.length;m<q;m++)h[m].getAttribute("name")===g[1]&&l.push(h[m]);return 
l.length===0?null:l}},TAG:function(g,h){return 
h.getElementsByTagName(g[1])}},preFilter:{CLASS:function(g,h,l,m,q,p){g=" 
"+g[1].replace(/\\/g,"")+" ";if(p)return g;p=0;for(var 
v;(v=h[p])!=null;p++)if(v)if(q^(v.className&&(" "+v.className+" 
").replace(/[\t\n]/g," ").indexOf(g)>=0))l||m.push(v);else 
if(l)h[p]=false;return false},ID:function(g){return 
g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},
+CHILD:function(g){if(g[1]==="nth"){var 
h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return
g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]="
" "+g[4]+" ";return 
g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m,

+g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return 
true;return g},POS:function(g){g.unshift(true);return 
g}},filters:{enabled:function(g){return 
g.disabled===false&&g.type!=="hidden"},disabled:function(g){return 
g.disabled===true},checked:function(g){return 
g.checked===true},selected:function(g){return 
g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},

+text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},

+setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return 
h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return 
h%2===1},lt:function(g,h,l){return h<l[3]-0},gt:function(g,h,l){return 
h>l[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return 
l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var 
q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else 
if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else
 if(q==="not"){h=
+h[3];l=0;for(m=h.length;l<m;l++)if(h[l]===g)return false;return true}else 
k.error("Syntax error, unrecognized expression: "+q)},CHILD:function(g,h){var 
l=h[1],m=g;switch(l){case "only":case 
"first":for(;m=m.previousSibling;)if(m.nodeType===1)return 
false;if(l==="first")return true;m=g;case 
"last":for(;m=m.nextSibling;)if(m.nodeType===1)return false;return true;case 
"nth":l=h[2];var q=h[3];if(l===1&&q===0)return true;h=h[0];var 
p=g.parentNode;if(p&&(p.sizcache!==h||!g.nodeIndex)){var 
v=0;for(m=p.firstChild;m;m=
+m.nextSibling)if(m.nodeType===1)m.nodeIndex=++v;p.sizcache=h}g=g.nodeIndex-q;return
 l===0?g===0:g%l===0&&g/l>=0}},ID:function(g,h){return 
g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return 
h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return("
 "+(g.className||g.getAttribute("class"))+" 
").indexOf(h)>-1},ATTR:function(g,h){var 
l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var
 m=h[2];h=h[4];return g==null?m==="!=":m===
+"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" 
").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var
 q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in 
n.match){n.match[u]=new 
RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new 
RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g,

+h){return"\\"+(h-0+1)}))}var 
z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return 
h}return 
g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object
 Array]")Array.prototype.push.apply(h,g);else if(typeof 
g.length==="number")for(var l=0,m=g.length;l<m;l++)h.push(g[l]);else 
for(l=0;g[l];l++)h.push(g[l]);return h}}var 
B;if(s.documentElement.compareDocumentPosition)B=function(g,h){if(!g.compareDocumentPosition||

+!h.compareDocumentPosition){if(g==h)i=true;return 
g.compareDocumentPosition?-1:1}g=g.compareDocumentPosition(h)&4?-1:g===h?0:1;if(g===0)i=true;return
 g};else if("sourceIndex"in 
s.documentElement)B=function(g,h){if(!g.sourceIndex||!h.sourceIndex){if(g==h)i=true;return
 g.sourceIndex?-1:1}g=g.sourceIndex-h.sourceIndex;if(g===0)i=true;return g};else 
if(s.createRange)B=function(g,h){if(!g.ownerDocument||!h.ownerDocument){if(g==h)i=true;return
 g.ownerDocument?-1:1}var l=g.ownerDocument.createRange(),m=
+h.ownerDocument.createRange();l.setStart(g,0);l.setEnd(g,0);m.setStart(h,0);m.setEnd(h,0);g=l.compareBoundaryPoints(Range.START_TO_END,m);if(g===0)i=true;return
 g};(function(){var g=s.createElement("div"),h="script"+(new 
Date).getTime();g.innerHTML="<a name='"+h+"'/>";var 
l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof
q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof
f q.getAttributeNode!=="undefined"&&
+q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var
 p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return 
m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var
g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var
r m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML="<a 
href='#'></a>";
+if(g.firstChild&&typeof 
g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return
 h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var 
g=k,h=s.createElement("div");h.innerHTML="<p 
class='TEST'></p>";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return
 z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in 
g)k[l]=g[l];h=null}}();
+(function(){var g=s.createElement("div");g.innerHTML="<div class='test 
e'></div><div 
class='test'></div>";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof
 l.getElementsByClassName!=="undefined"&&!m)return 
l.getElementsByClassName(h[1])};g=null}}})();var 
E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}:

+function(g,h){return 
g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var
l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var
r p=h.length;q<p;q++)k(g,h[q],l);return 
k.filter(m,l)};c.find=k;c.expr=k.selectors;c.expr[":"]=c.expr.filters;c.unique=k.uniqueSort;c.text=a;c.isXMLDoc=x;c.contains=E})();var
 eb=/Until$/,fb=/^(?:parents|prevUntil|prevAll)/,
+gb=/,/;R=Array.prototype.slice;var Ia=function(a,b,d){if(c.isFunction(b))return 
c.grep(a,function(e,j){return!!b.call(e,j,e)===d});else if(b.nodeType)return 
c.grep(a,function(e){return e===b===d});else if(typeof b==="string"){var 
f=c.grep(a,function(e){return e.nodeType===1});if(Ua.test(b))return 
c.filter(b,f,!d);else b=c.filter(b,f)}return c.grep(a,function(e){return 
c.inArray(e,b)>=0===d})};c.fn.extend({find:function(a){for(var 
b=this.pushStack("","find",a),d=0,f=0,e=this.length;f<e;f++){d=b.length;
+c.find(a,this[f],b);if(f>0)for(var j=d;j<b.length;j++)for(var 
i=0;i<d;i++)if(b[i]===b[j]){b.splice(j--,1);break}}return b},has:function(a){var 
b=c(a);return this.filter(function(){for(var 
d=0,f=b.length;d<f;d++)if(c.contains(this,b[d]))return 
true})},not:function(a){return 
this.pushStack(Ia(this,a,false),"not",a)},filter:function(a){return 
this.pushStack(Ia(this,a,true),"filter",a)},is:function(a){return!!a&&c.filter(a,this).length>0},closest:function(a,b){if(c.isArray(a)){var
 d=[],f=this[0],e,j=
+{},i;if(f&&a.length){e=0;for(var 
o=a.length;e<o;e++){i=a[e];j[i]||(j[i]=c.expr.match.POS.test(i)?c(i,b||this.context):i)}for(;f&&f.ownerDocument&&f!==b;){for(i
 in 
j){e=j[i];if(e.jquery?e.index(f)>-1:c(f).is(e)){d.push({selector:i,elem:f});delete
 j[i]}}f=f.parentNode}}return d}var 
k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return 
this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return
 r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a===
+"string")return c.inArray(this[0],a?c(a):this.parent().children());return 
c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof 
a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return 
this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return 
this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return
 c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return 
c.dir(a,"parentNode",
+d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return 
c.nth(a,2,"previousSibling")},nextAll:function(a){return 
c.dir(a,"nextSibling")},prevAll:function(a){return 
c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return 
c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return 
c.dir(a,"previousSibling",d)},siblings:function(a){return 
c.sibling(a.parentNode.firstChild,a)},children:function(a){return 
c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?
+a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var
 e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof 
f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return
this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return
n c.find.matches(a,b)},dir:function(a,b,d){var 
f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType===

+1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var 
f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return 
a},sibling:function(a,b){for(var 
d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ 
jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/<tbody/i,jb=/<|&#?\w+;/,ta=/<script|<object|<embed|<option|<style/i,ua=/checked\s*(?:[^=]|=\s*.checked.)/i,Ma=function(a,b,d){return
 hb.test(d)?
+a:b+"></"+d+">"},F={option:[1,"<select 
multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div<div>","</div>"];c.fn.extend({text:function(a){if(c.isFunction(a))return
 this.each(function(b){var d=
+c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return 
this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return
 c.text(this)},wrapAll:function(a){if(c.isFunction(a))return 
this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var 
b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var
 d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return 
d}).append(this)}return this},
+wrapInner:function(a){if(c.isFunction(a))return 
this.each(function(b){c(this).wrapInner(a.call(this,b))});return 
this.each(function(){var 
b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return
 this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return 
this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return
this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})},
,
+prepend:function(){return 
this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return
this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else
e if(arguments.length){var 
a=c(arguments[0]);a.push.apply(a,this.toArray());return 
this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return
 this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,
+this.nextSibling)});else if(arguments.length){var 
a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return
 a}},remove:function(a,b){for(var 
d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return
 this},empty:function(){for(var 
a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild);

+return this},clone:function(a){var 
b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var 
d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return
c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else
e return 
this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return
 b},html:function(a){if(a===w)return 
this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja,
+""):null;else if(typeof 
a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var
b=0,d=this.length;b<d;b++)if(this[b].nodeType===1){c.cleanData(this[b].getElementsByTagName("*"));this[b].innerHTML=a}}catch(f){this.empty().append(a)}}else
e c.isFunction(a)?this.each(function(e){var 
j=c(this),i=j.html();j.empty().append(function(){return 
a.call(this,e,i)})}):this.empty().append(a);return 
this},replaceWith:function(a){if(this[0]&&
+this[0].parentNode){if(c.isFunction(a))return this.each(function(b){var 
d=c(this),f=d.html();d.replaceWith(a.call(this,b,f))});if(typeof 
a!=="string")a=c(a).detach();return this.each(function(){var 
b=this.nextSibling,d=this.parentNode;c(this).remove();b?c(b).before(a):c(d).append(a)})}else
 return 
this.pushStack(c(c.isFunction(a)?a():a),"replaceWith",a)},detach:function(a){return
 this.remove(a,true)},domManip:function(a,b,d){function f(u){return 
c.nodeName(u,"table")?u.getElementsByTagName("tbody")[0]||
+u.appendChild(u.ownerDocument.createElement("tbody")):u}var 
e,j,i=a[0],o=[],k;if(!c.support.checkClone&&arguments.length===3&&typeof 
i==="string"&&ua.test(i))return 
this.each(function(){c(this).domManip(a,b,d,true)});if(c.isFunction(i))return 
this.each(function(u){var 
z=c(this);a[0]=i.call(this,u,b?z.html():w);z.domManip(a,b,d)});if(this[0]){e=i&&i.parentNode;e=c.support.parentNode&&e&&e.nodeType===11&&e.childNodes.length===this.length?{fragment:e}:sa(a,this,o);k=e.fragment;if(j=k.childNodes.length===

+1?(k=k.firstChild):k.firstChild){b=b&&c.nodeName(j,"tr");for(var 
n=0,r=this.length;n<r;n++)d.call(b?f(this[n],j):this[n],n>0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return
this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var
r f=[];d=c(d);var 
e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]);

+return this}else{e=0;for(var j=d.length;e<j;e++){var 
i=(e>0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return
this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof
f 
b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var
 e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof 
i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof 
i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["",
+""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]==="<table>"&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else
 e=
+c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return
 e},cleanData:function(a){for(var 
b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var
 k in b.events)e[k]?
+c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else 
o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var 
kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja=

+function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return 
X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof 
e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return
 w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var 
f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter=

+Na.test(a)?a.replace(Na,b):b}return 
f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return
 f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var 
e,j=b==="width"?pb:qb;function 
i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else
 e-=parseFloat(c.curCSS(a,
+"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return 
Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var 
f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return
 f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else 
if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return
 null;if(a=e.getComputedStyle(a,null))f=
+a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else 
if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var
j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return
n f},swap:function(a,b,d){var f={};for(var e in 
b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in 
b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var
 b=
+a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return 
b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var
sb=J(),tb=/<script(.|\s)*?\/script>/gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof
f a!==
+"string")return zb.call(this,a);else if(!this.length)return this;var 
f=a.indexOf(" ");if(f>=0){var 
e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else
 if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var 
j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("<div
/>").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return
n this},
+serialize:function(){return 
c.param(this.serializeArray())},serializeArray:function(){return 
this.map(function(){return 
this.elements?c.makeArray(this.elements):this}).filter(function(){return 
this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return
a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart
t ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),
+function(a,b){c.fn[b]=function(d){return 
this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return
c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return
n c.get(a,null,b,"script")},getJSON:function(a,b,d){return 
c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return
c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,
,
+global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return
 new A.XMLHttpRequest}:function(){try{return new 
A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, 
text/xml",html:"text/html",script:"text/javascript, 
application/javascript",json:"application/json, 
text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function
 b(){e.success&&
+e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function 
d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function
 f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var 
e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof
e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)?
?
+"&":"?")+(e.jsonp||"callback")+"=?");else 
if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete
A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache===
=
+false&&n==="GET"){var 
r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var
z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var
r B=
+false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return
 w}var 
E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since",

+c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+",
*/*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return
n false}e.global&&f("ajaxSend",[x,e]);var 
g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E||
+d();E=true;if(x)x.onreadystatechange=c.noop}else 
if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var
p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else
e 
c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var 
h=x.abort;x.abort=function(){x&&h.call(x);
+g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return
x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status===
=
+1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var 
d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return
 a.status===304||a.status===0},httpData:function(a,b,d){var 
f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof
 a==="string")if(b===
+"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else 
if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return 
a},param:function(a,b){function 
d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof
 n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof 
o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function 
f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var
 e=[];if(b===w)b=c.ajaxSettings.traditional;
+if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else 
for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var 
la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return
 this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a<b;a++){var 
d=c.data(this[a],"olddisplay");
+this[a].style.display=d||"";if(c.css(this[a],"display")==="none"){d=this[a].nodeName;var
 f;if(la[d])f=la[d];else{var e=c("<"+d+" 
/>").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a<b;a++)this[a].style.display=c.data(this[a],"olddisplay")||"";return
 this}},hide:function(a,b){if(a||a===0)return 
this.animate(K("hide",3),a,b);else{a=0;for(b=this.length;a<b;a++){var 
d=c.data(this[a],"olddisplay");!d&&d!=="none"&&c.data(this[a],
+"olddisplay",c.css(this[a],"display"))}a=0;for(b=this.length;a<b;a++)this[a].style.display="none";return
 this}},_toggle:c.fn.toggle,toggle:function(a,b){var d=typeof 
a==="boolean";if(c.isFunction(a)&&c.isFunction(b))this._toggle.apply(this,arguments);else
 a==null||d?this.each(function(){var 
f=d?a:c(this).is(":hidden");c(this)[f?"show":"hide"]()}):this.animate(K("toggle",3),a,b);return
 this},fadeTo:function(a,b,d){return 
this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,d)},
+animate:function(a,b,d,f){var e=c.speed(b,d,f);if(c.isEmptyObject(a))return 
this.each(e.complete);return this[e.queue===false?"each":"queue"](function(){var 
j=c.extend({},e),i,o=this.nodeType===1&&c(this).is(":hidden"),k=this;for(i in 
a){var n=i.replace(ia,ja);if(i!==n){a[n]=a[i];delete 
a[i];i=n}if(a[i]==="hide"&&o||a[i]==="show"&&!o)return 
j.complete.call(this);if((i==="height"||i==="width")&&this.style){j.display=c.css(this,"display");j.overflow=this.style.overflow}if(c.isArray(a[i])){(j.specialEasing=

+j.specialEasing||{})[i]=a[i][1];a[i]=a[i][0]}}if(j.overflow!=null)this.style.overflow="hidden";j.curAnim=c.extend({},a);c.each(a,function(r,u){var
 z=new c.fx(k,j,r);if(Ab.test(u))z[u==="toggle"?o?"show":"hide":u](a);else{var 
C=Bb.exec(u),B=z.cur(true)||0;if(C){u=parseFloat(C[2]);var 
E=C[3]||"px";if(E!=="px"){k.style[r]=(u||1)+E;B=(u||1)/z.cur(true)*B;k.style[r]=B+E}if(C[1])u=(C[1]==="-="?-1:1)*u+B;z.custom(B,u,E)}else
 z.custom(B,u,"")}});return true})},stop:function(a,b){var 
d=c.timers;a&&this.queue([]);
+this.each(function(){for(var 
f=d.length-1;f>=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return
this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return
n this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof 
a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof
 f.duration===
+"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return
 f},easing:{linear:function(a,b,d,f){return 
d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||

+c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return
this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function
n f(j){return 
e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;

+this.pos=this.state=0;var 
e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var
 b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=
+this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var
 f in 
this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var
 e in this.options.curAnim)c.style(this.elem,
+e,this.options.orig[e]);this.options.complete.call(this.elem)}return 
false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return
 true}};c.extend(c.fx,{tick:function(){for(var 
a=c.timers,b=0;b<a.length;b++)a[b]()||a.splice(b--,1);a.length||
+c.fx.stop()},stop:function(){clearInterval(W);W=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){c.style(a.elem,"opacity",a.now)},_default:function(a){if(a.elem.style&&a.elem.style[a.prop]!=null)a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit;else
a.elem[a.prop]=a.now}}});if(c.expr&&c.expr.filters)c.expr.filters.animated=function(a){return
n c.grep(c.timers,function(b){return 
a===b.elem}).length};c.fn.offset="getBoundingClientRect"in s.documentElement?
+function(a){var b=this[0];if(a)return 
this.each(function(e){c.offset.setOffset(this,a,e)});if(!b||!b.ownerDocument)return
 null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);var 
d=b.getBoundingClientRect(),f=b.ownerDocument;b=f.body;f=f.documentElement;return{top:d.top+(self.pageYOffset||c.support.boxModel&&f.scrollTop||b.scrollTop)-(f.clientTop||b.clientTop||0),left:d.left+(self.pageXOffset||c.support.boxModel&&f.scrollLeft||b.scrollLeft)-(f.clientLeft||b.clientLeft||0)}}:function(a){var
 b=
+this[0];if(a)return 
this.each(function(r){c.offset.setOffset(this,a,r)});if(!b||!b.ownerDocument)return
 null;if(b===b.ownerDocument.body)return 
c.offset.bodyOffset(b);c.offset.initialize();var 
d=b.offsetParent,f=b,e=b.ownerDocument,j,i=e.documentElement,o=e.body;f=(e=e.defaultView)?e.getComputedStyle(b,null):b.currentStyle;for(var
k=b.offsetTop,n=b.offsetLeft;(b=b.parentNode)&&b!==o&&b!==i;){if(c.offset.supportsFixedPosition&&f.position==="fixed")break;j=e?e.getComputedStyle(b,null):b.currentStyle;
;
+k-=b.scrollTop;n-=b.scrollLeft;if(b===d){k+=b.offsetTop;n+=b.offsetLeft;if(c.offset.doesNotAddBorder&&!(c.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(b.nodeName))){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=d;d=b.offsetParent}if(c.offset.subtractsBorderForOverflowNotVisible&&j.overflow!=="visible"){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=j}if(f.position==="relative"||f.position==="static"){k+=o.offsetTop;n+=o.offsetLeft}if(c.offset.supportsFixedPosition&&

+f.position==="fixed"){k+=Math.max(i.scrollTop,o.scrollTop);n+=Math.max(i.scrollLeft,o.scrollLeft)}return{top:k,left:n}};c.offset={initialize:function(){var
a=s.body,b=s.createElement("div"),d,f,e,j=parseFloat(c.curCSS(a,"marginTop",true))||0;c.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"});b.innerHTML="<div
v style='position:absolute;top:0;left:0;margin:0;border:5px solid 
#000;padding:0;width:1px;height:1px;'><div></div></div><table 
style='position:absolute;top:0;left:0;margin:0;border:5px solid 
#000;padding:0;width:1px;height:1px;' cellpadding='0' 
cellspacing='0'><tr><td></td></tr></table>";
+a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b);

+c.offset.initialize=c.noop},bodyOffset:function(a){var 
b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var
f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a,
,
+d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in 
b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return
 null;var 
a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top-

+f.top,left:d.left-f.left}},offsetParent:function(){return 
this.map(function(){for(var 
a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return
 a})}});c.each(["Left","Top"],function(a,b){var 
d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return 
null;if(f!==w)return 
this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else
 this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset":
+"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var
 d=b.toLowerCase();c.fn["inner"+b]=function(){return 
this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return
this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var 
 e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return 
this.each(function(j){var 
i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in
+e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof
 f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window);
diff --git a/newviewfunctions.lua b/newviewfunctions.lua
new file mode 100644
index 0000000..2695c6d
--- /dev/null
+++ b/newviewfunctions.lua
@@ -0,0 +1,52 @@
+require("html")
+require("session")
+
+-- Split a string to an array by delimiter or pattern
+function split(str, pat)
+   if string.find(str, pat) == nil then
+       return str
+   end
+   local t = {} 
+   local fpat = "(.-)" .. pat
+   local last_end = 1
+   local s, e, cap = str:find(fpat, 1)
+   while s do
+     if s ~= 1 or cap ~= "" then
+        table.insert(t,cap)
+     end
+     last_end = e+1
+     s, e, cap = str:find(fpat, last_end)
+   end
+   if last_end <= #str then
+      cap = str:sub(last_end)
+      table.insert(t, cap)
+   end
+   return t
+end
+
+-- Insert a string into another string
+function string.insert(value, insert, place)
+
+   if place == nil then
+       place = string.len(value)+1
+   end
+
+   return string.sub(value, 1,place-1) .. tostring(insert) .. string.sub(value, 
place, string.len(value))
+                    
+end
+
+--Highlight occurences of a word in a string
+function string.highlight(txtvalue, searchval, fcolour, bcolour)
+
+  if txtvalue ~=nil and searchval ~= nil then
+      sStart = string.find(string.lower(txtvalue),string.lower(searchval))
+      if sStart ~= nil then
+        sEnd = sStart + string.len(searchval)
+          txtvalue = string.insert(txtvalue,"</font>", sEnd)
+          txtvalue = string.insert(txtvalue,"<font style='color:"..fcolour.."; 
background-color:"..bcolour..";'>", sStart)
+     end
+    end 
+  
+  return txtvalue
+
+end
diff --git a/template-silent.lsp b/template-silent.lsp
new file mode 100644
index 0000000..45a8ad4
--- /dev/null
+++ b/template-silent.lsp
@@ -0,0 +1,9 @@
+<% local viewtable, viewlibrary, pageinfo, session = ... %>
+Status: 204 No content 
+Content-Type: <% print(viewtable.option or "application/octet-stream") %>
+<% if viewtable.length then %>
+Content-Length: <%= viewtable.length %>
+<% end %>
+<% if viewtable.label ~= "" then %>
+Content-Disposition: attachment; filename="<%= viewtable.label %>"
+<% end %>
diff --git a/weblog-adhocquery-html.lsp b/weblog-adhocquery-html.lsp
index 002dba3..49675cd 100644
--- a/weblog-adhocquery-html.lsp
+++ b/weblog-adhocquery-html.lsp
@@ -4,7 +4,7 @@ require("viewfunctions")

<style type="text/css">
   #content table { border-collapse: collapse; width: 100%; }
-  #content table td { white-space: nowrap; padding-right:20px; 
border-bottom:1px solid #999; }
+  #content table td { white-space: normal; padding-right:20px; 
border-bottom:1px solid #999; }
   #content table tr.mark { background: #E9E9E9; }
</style>

diff --git a/weblog-config-html.lsp b/weblog-config-html.lsp
index 35f3ca5..7107721 100644
--- a/weblog-config-html.lsp
+++ b/weblog-config-html.lsp
@@ -1,9 +1,8 @@
<% local form, viewlibrary, page_info = ... 
require("viewfunctions")
%>
-
<H1><%= html.html_escape(form.label) %></H1>
<%
-    local order = {"auditstart", "auditend", "historydays", "watchdays", 
"purgedays", "window", "shorturi", "shortreason", "groupby"}
-    displayform(form, order, nil, page_info)
+        local order = {"auditstart", "auditend", "badyesno", "sortby", 
"minimumscore", "window", "shorturi", "shortreason", "historydays", "watchdays", 
"purgedays" }
+        displayform(form, order, nil, page_info)
%>
diff --git a/weblog-controller.lua b/weblog-controller.lua
index 26a69ae..eb9ff8c 100644
--- a/weblog-controller.lua
+++ b/weblog-controller.lua
@@ -50,25 +50,63 @@ function deletewatchlistentry(self)
end

function viewweblog(self)
-    return self.model.getweblog(self.clientdata.clientuserid, 
self.clientdata.starttime, self.clientdata.endtime, self.clientdata.clientip, 
clientdata.focus)
+    return self.model.getweblog(self.clientdata.activelog, 
self.clientdata.clientuserid, self.clientdata.starttime, 
self.clientdata.endtime, self.clientdata.clientip, self.clientdata.badyesno, 
self.clientdata.deniedyesno, self.clientdata.bypassyesno, self.clientdata.score, 
self.clientdata.urisearch, self.clientdata.sortby, self.clientdata.selected, 
clientdata.focus)
end

function downloadweblog(self)
    self.conf.viewtype = "stream"
    local retval = viewweblog(self)
-    local file = cfe({ type="longtext", value="", 
label=retval.value.clientuserid.value .. ".log" })
-    local content = 
{"sourcename\tclientip\tclientuserid\tlogdatetime\turi\tbytes\treason\tscore"}
+    local file = cfe({ type="longtext", value="", 
label=retval.value.clientuserid.value .. ".csv" })
+    local content = 
{"clientuserid,clientip,logdatetime,uri,bytes,reason,score,reason,badyesno,deniedyesno,bypassyesno"}

    for i,log in ipairs(retval.value.log.value) do
-        content[#content+1] = string.format("%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t",
-            log.sourcename, log.clientip, log.clientuserid, log.logdatetime,
-            log.uri, log.bytes, log.reason or "", log.score or "0")
+        content[#content+1] = 
string.format("%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,",
+            log.clientuserid, log.clientip, log.logdatetime, log.uri, 
log.bytes, log.reason, log.score or "0", log.reason, log.badyesno, 
log.deniedyesno, log.bypassyesno )
+            
    end
    file.value = table.concat(content, "\n")
    return file
end

-function viewblocklog(self)
-    return self.model.getblocklog(self.clientdata.clientuserid, 
self.clientdata.starttime, self.clientdata.endtime, self.clientdata.clientip, 
clientdata.focus)
+function downloadlogview(self)
+    thisdate=os.date()
+    self.conf.viewtype = "stream"
+    local retval = viewweblog(self)
+    local file = cfe({ type="longtext", value="", 
label="Weblog-resnet-"..thisdate..".tab" })
+    local content = 
{"clientuserid\tclientip\tlogdatetime\turi\tbytes\treason\tscore\treason\tbadyesno\tdeniedyesno\tbypassyesno"}

+    for i,log in ipairs(retval.value.log.value) do
+        content[#content+1] = 
string.format("%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t",
+            log.clientuserid, log.clientip, log.logdatetime, log.uri, 
log.bytes, log.reason, log.score or "0", log.reason, log.badyesno, 
log.deniedyesno, log.bypassyesno )
+    end
+    file.value = table.concat(content, "\n")
+    return file
+end
+
+function downloadselected(self)
+    thisdate=os.date()
+    self.conf.viewtype = "stream"
+    local retval = viewselected(self)    
+    local file = cfe({ type="longtext", value="", 
label="Weblog-resnet-selected-"..thisdate..".tab" })
+    local content = 
{"clientuserid\tclientip\tlogdatetime\turi\tbytes\treason\tscore\treason\tbadyesno\tdeniedyesno\tbypassyesno"}

+    for i,log in ipairs(retval.value.log.value) do
+        content[#content+1] = 
string.format("%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t",
+        log.clientuserid, log.clientip, log.logdatetime, log.uri, log.bytes, 
log.reason, log.score or "0", log.reason, log.badyesno, log.deniedyesno, 
log.bypassyesno )
+    end    
+    file.value = table.concat(content, "\n") 
+    return file
+end
+
+function checkselected(self)
+    self.conf.viewtype = "silent"
+    return self.model.editselected(self.clientdata.chkdata)
+    --return file
+end    
+function clearselected(self)
+     return self:redirect_to_referrer(self.model.clearselected())
+end
+
+function viewselected(self)
+    --return self.model.getselected(self.clientdata.csvdata, 
self.clientdata.starttime, self.clientdata.endtime)
+    return self.model.getweblog(self.clientdata.activelog, 
self.clientdata.clientuserid, self.clientdata.starttime, 
self.clientdata.endtime, self.clientdata.clientip, self.clientdata.badyesno, 
self.clientdata.deniedyesno, self.clientdata.bypassyesno, self.clientdata.score, 
self.clientdata.urisearch, self.clientdata.sortby, self.clientdata.getselected, 
clientdata.focus)
end

function viewusagestats(self)
@@ -120,3 +158,18 @@ end
function createdatabase(self)
    return controllerfunctions.handle_form(self, self.model.getnewdatabase, 
self.model.create_database, self.clientdata, "Create", "Create New Database", 
"Database Created")
end
+
+function listfiles(self)
+    return self.model.listfiles(self)
+end
+function createfile(self)
+        return controllerfunctions.handle_form(self, self.model.getnewfile, 
self.model.createfile, self.clientdata, "Create", "Create New Weblog File", 
"Weblog File Created")
+end
+        
+function editfile(self)
+        return controllerfunctions.handle_form(self, function() return 
self.model.readfile(self.clientdata.filename) end, self.model.updatefile, 
self.clientdata, "Save", "Edit Weblog File", "Weblog File Saved" )
+end
+              
+function deletefile(self)
+        return 
self:redirect_to_referrer(self.model.deletefile(self.clientdata.filename))
+end
diff --git a/weblog-editfile-html.lsp b/weblog-editfile-html.lsp
new file mode 120000
index 0000000..15b1930
--- /dev/null
+++ b/weblog-editfile-html.lsp
@@ -0,0 +1 @@
+../filedetails-html.lsp
\ No newline at end of file
diff --git a/weblog-listfiles-html.lsp b/weblog-listfiles-html.lsp
new file mode 100644
index 0000000..c2fe301
--- /dev/null
+++ b/weblog-listfiles-html.lsp
@@ -0,0 +1,42 @@
+<% local view, viewlibrary, page_info, session = ... 
+require("viewfunctions")
+%>
+
+<% displaycommandresults({"editfile", "deletefile", "startstop"}, session) %>
+<% displaycommandresults({"createfile"}, session, true) %>
+
+
+<H1>File List</H1>
+<DL>
+<TABLE>
+    <TR style="background:#eee;font-weight:bold;">
+        <TD style="padding-right:20px;white-space:nowrap;text-align:left;" 
class="header">Action</TD>
+        <TD style="white-space:nowrap;text-align:left;" 
class="header">File</TD>
+    </TR>
+<% for i,file in ipairs(view.value) do %>
+    <TR>
+        <TD style="padding-right:20px;white-space:nowrap;">
+        <% if viewlibrary.check_permission("editfile") then %>    
+            <%= 
html.link{value=page_info.script..page_info.prefix..page_info.controller.."/editfile?filename="..file.."&redir="..page_info.orig_action,
 label="Edit "} %>
+        <% end %>
+        <% if viewlibrary.check_permission("deletefile") then %>    
+            <%= 
html.link{value=page_info.script..page_info.prefix..page_info.controller.."/deletefile?filename="..file,
 label="Delete "} %>
+        <% end %>
+        </TD>
+        <TD style="white-space:nowrap;"><%= html.html_escape(file) %></TD>
+    </TR>
+<% end %>
+</TABLE>
+</DL>
+
+<% if viewlibrary and viewlibrary.dispatch_component and 
viewlibrary.check_permission("createfile") then
+    local createform = viewlibrary.dispatch_component("createfile", nil, true) 
%>
+<H2><%= html.html_escape(createform.label) %></H2>
+<%
+    createform.action = page_info.script .. page_info.prefix .. 
page_info.controller .. "/createfile"
+    displayform(createform)
+end %>
+
+<% if viewlibrary and viewlibrary.dispatch_component and 
viewlibrary.check_permission("startstop") then
+    viewlibrary.dispatch_component("startstop")
+end %>
diff --git a/weblog-maintenance-html.lsp b/weblog-maintenance-html.lsp
new file mode 100644
index 0000000..2ca1dc7
--- /dev/null
+++ b/weblog-maintenance-html.lsp
@@ -0,0 +1,17 @@
+<% local form, viewlibrary, page_info = ... 
+require("viewfunctions")
+%>
+
+<style type="text/css">
+  #content table { border-collapse: collapse; width: 100%; }
+  #content table td { white-space: normal; padding-right:20px; 
border-bottom:1px solid #999; }
+  #content table tr.mark { background: #E9E9E9; }
+</style>
+
+<H1>Maintenance</H1>
+<% displayformstart(form, page_info) %>
+<% displayformitem(form.value.query, "query") %>
+<% displayformend(form) %>
+<H2>Purge Database Operations</H2>
+<H3>Analysis Operations</H3>
+<H4>Actions</H4>
diff --git a/weblog-model.lua b/weblog-model.lua
index 8db7490..4c5ae8f 100644
--- a/weblog-model.lua
+++ b/weblog-model.lua
@@ -6,44 +6,40 @@ require("fs")
require("format")
require("validator")
require("luasql.postgres")
+require("date")

-local DatabaseName = "webproxylog"
+local DatabaseName = "weblog"
local DatabaseOwner = "weblogowner"
local DatabaseUser = "webloguser"

local path = "PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin 
"
local env
local con
-local configfile = "/etc/weblog.conf"
+local configfile = "/etc/weblog/weblog.conf"
local configcontent = fs.read_file(configfile) or ""
local config = format.parse_ini_file(configcontent, "") or {}
+local goodwordslist = "/etc/weblog/goodwords"
+local badwordslist = "/etc/weblog/badwords"
+local baseurl = "/etc/weblog/"

local database_creation_script = {
    "CREATE TABLE dbhistlog (logdatetime timestamp(3) without time zone NOT 
NULL, msgtext text)",
-    "CREATE TABLE pubblocklog(sourcename character varying(40), clientip inet 
NOT NULL, clientuserid character varying(64) NOT NULL, logdatetime timestamp(3) 
without time zone NOT NULL, uri text NOT NULL, bytes bigint NOT NULL, reason 
text, score integer, shortreason text)",
-    "CREATE TABLE blocklog(sourcename character varying(40), clientip inet NOT 
NULL, clientuserid character varying(64) NOT NULL, logdatetime timestamp(0) 
without time zone NOT NULL, uri text NOT NULL, bytes bigint NOT NULL, reason 
text, score integer, shortreason text)",
-    "CREATE TABLE pubweblog(sourcename character varying(40), clientip inet NOT 
NULL, clientuserid character varying(64) NOT NULL, logdatetime timestamp(3) 
without time zone NOT NULL, uri text NOT NULL, bytes bigint NOT NULL, reason 
text, score integer, shortreason text)",
-    "CREATE TABLE weblog(sourcename character varying(40), clientip inet NOT 
NULL, clientuserid character varying(64) NOT NULL, logdatetime timestamp(3) 
without time zone NOT NULL, uri text NOT NULL, bytes bigint NOT NULL, reason 
text, score integer, shortreason text)",
+    "CREATE TABLE pubweblog(sourcename character varying(40), clientip inet NOT 
NULL, clientuserid character varying(64) NOT NULL, logdatetime timestamp(3) 
without time zone NOT NULL, uri text NOT NULL, bytes bigint NOT NULL, reason 
text, score integer, shortreason text, badyesno int, deniedyesno int, 
bypassyesno int, wordloc text, goodwordloc text, selected boolean, id serial)",
+    "CREATE TABLE pubweblog_history(sourcename character varying(40), clientip 
inet NOT NULL, clientuserid character varying(64) NOT NULL, logdatetime 
timestamp(3) without time zone NOT NULL, uri text NOT NULL, bytes bigint NOT 
NULL, reason text, score integer, shortreason text, badyesno int, deniedyesno 
int, bypassyesno int, wordloc text, goodwordloc text, selected boolean, id 
int)",
    "CREATE TABLE source (sourcename character varying(40) NOT NULL, method 
character varying(100) NOT NULL, userid character varying(32), passwd character 
varying(255), source character varying(255) NOT NULL, tzislocal boolean, enabled 
boolean)",
-    "CREATE TABLE usagestat (sourcename character varying(40) NOT NULL, date 
timestamp(0) without time zone NOT NULL, numrequest integer, numblock integer)",
-    "CREATE TABLE watchlist (clientuserid character varying(64) NOT NULL, 
expiredatetime timestamp(0) without time zone NOT NULL)",
+    "CREATE TABLE usagestat(sourcename character varying(40) NOT NULL, date 
timestamp(0) without time zone NOT NULL, numrequest integer, numblock integer)",
+    "CREATE TABLE watchlist(clientuserid character varying(64) NOT NULL, 
expiredatetime timestamp(0) without time zone NOT NULL)",
    "ALTER TABLE ONLY source ADD CONSTRAINT source_pkey PRIMARY KEY 
(sourcename)",
-    "CREATE INDEX blocklogclientididx ON blocklog USING btree (clientuserid)",
-    "CREATE INDEX blocklogclientidx ON blocklog USING btree (clientip, 
clientuserid)",
    "CREATE INDEX dbhistlogdatetimeidx ON dbhistlog USING btree (logdatetime)",
-    "CREATE INDEX pubblocklogclientididx ON pubblocklog USING btree 
(clientuserid)",
-    "CREATE INDEX pubblocklogclientidx ON pubblocklog USING btree (clientip, 
clientuserid)",
    "CREATE INDEX pubweblogclientdateidx ON pubweblog USING btree (logdatetime, 
clientuserid)",
-    "CREATE INDEX pubweblogclientidx ON pubweblog USING btree (clientip, 
clientuserid)",
-    "CREATE INDEX pubweblogclientipidx ON pubweblog USING btree (clientip)",
    "CREATE INDEX pubweblogclientuserididx ON pubweblog USING btree 
(clientuserid)",
    "CREATE INDEX pubwebloglogdatetimeidx ON pubweblog USING btree 
(logdatetime)",
-    "CREATE INDEX weblogclientidx ON weblog USING btree (clientip, 
clientuserid)",
-    "CREATE INDEX weblogclientipidx ON weblog USING btree (clientip)",
-    "CREATE INDEX weblogclientuserididx ON weblog USING btree (clientuserid)",
+    "CREATE INDEX pubweblog_historyclientdateidx ON pubweblog_history USING 
btree (logdatetime, clientuserid)",
+    "CREATE INDEX pubweblog_historyclientuserididx ON pubweblog_history USING 
btree (clientuserid)",
+    "CREATE INDEX pubweblog_historylogdatetimeidx ON pubweblog_history USING 
btree (logdatetime)",
    "GRANT SELECT ON dbhistlog TO "..DatabaseUser,
-    "GRANT SELECT ON pubblocklog TO "..DatabaseUser,
    "GRANT SELECT ON pubweblog TO "..DatabaseUser,
+    "GRANT SELECT ON pubweblog_history TO "..DatabaseUser,
    "GRANT SELECT, UPDATE, INSERT, DELETE ON source TO "..DatabaseUser,
    "GRANT SELECT ON usagestat TO "..DatabaseUser,
    "GRANT SELECT, UPDATE, INSERT, DELETE ON watchlist TO "..DatabaseUser,
@@ -137,7 +133,7 @@ local runSQLscript = function(filename)
end

-- Create the database and tables
--- pg_dump -U postgres -c webproxylog > makeweblog.postgres
+-- pg_dump -U postgres -c weblog > makeweblog.postgres
--runSQLscript("/root/work/weblog/makeweblog.postgres")

local databaseconnect = function(username, password)
@@ -181,21 +177,39 @@ end

local importsquidlog = function(entry, sourcename)
    if entry then
-        local sql = string.format("INSERT INTO weblog VALUES ('%s', '%s', '%s', 
'%s', '%s', '%s')",
+        local sql = string.format("INSERT INTO pubweblog VALUES ('%s', '%s', 
'%s', '%s', '%s', '%s','%s','%s','%s','%s','%s','%s','%s')",
            escape(sourcename), escape(entry.clientip), 
escape(entry.clientuserid, 64):lower(),
-            escape(entry.logdatetime), escape(entry.URL), escape(entry.bytes))
+            escape(entry.logdatetime), escape(entry.URL), escape(entry.bytes), 
escape(entry.reason), escape(entry.score), escape(entry.shortreason), 
escape(entry.badyesno), escape(entry.deniedyesno), escape(entry.bypassyesno), 
escape(entry.wordloc), escape(entry.goodwordloc))
+            
        local res = assert (con:execute(sql))
    end
end

+local importsquarklog = function(entry, sourcename)
+        if entry then
+           local sql = string.format("INSERT INTO pubweblog VALUES ('%s', '%s', 
'%s', '%s', '%s', '%s','%s','%s','%s','%s','%s','%s','%s')",
+              escape(sourcename), escape(entry.clientip), 
escape(entry.clientuserid, 64):lower(),
+                  escape(entry.logdatetime), escape(entry.URL), 
escape(entry.bytes), escape(entry.reason), escape(entry.score), 
escape(entry.shortreason), escape(entry.badyesno), escape(entry.deniedyesno), 
escape(entry.bypassyesno), escape(entry.wordloc), escape(entry.gwordloc))
+           local res = assert (con:execute(sql))
+        end
+end
+
local importdglog = function(entry, sourcename)
    if entry then
-        local sql = string.format("INSERT INTO blocklog VALUES ('%s', 
'0.0.0.0', '%s', '%s', '%s', '%s', '%s', '%s', '%s')",
-            escape(sourcename), escape(entry.clientuserid:lower(), 64), 
escape(entry.logdatetime), escape(entry.URL),
-            escape(entry.bytes), escape(entry.reason), escape(entry.score or 
"0"), escape(entry.shortreason))
-        local res = assert (con:execute(sql))
+           local sql = string.format("INSERT INTO pubweblog VALUES ('%s', '%s', 
'%s', '%s', '%s', '%s','%s','%s','%s','%s','%s','%s','%s')",
+              escape(sourcename), escape(entry.clientip), 
escape(entry.clientuserid, 64):lower(),
+                  escape(entry.logdatetime), escape(entry.URL), 
escape(entry.bytes), escape(entry.reason), escape(entry.score), 
escape(entry.shortreason), escape(entry.badyesno), escape(entry.deniedyesno), 
escape(entry.bypassyesno), escape(entry.wordloc), escape(entry.gwordloc))
+           local res = assert (con:execute(sql))
    end
-end
+end 
+local importdumplog = function(entry, sourcename)
+    if entry then
+           local sql = string.format("INSERT INTO pubweblog VALUES ('%s', '%s', 
'%s', '%s', '%s', '%s','%s','%s','%s','%s','%s','%s','%s')",
+              escape(sourcename), escape(entry.clientip), 
escape(entry.clientuserid, 64):lower(),
+                  escape(entry.logdatetime), escape(entry.URL), 
escape(entry.bytes), escape(entry.reason), escape(entry.score), 
escape(entry.shortreason), escape(entry.badyesno), escape(entry.deniedyesno), 
escape(entry.bypassyesno), escape(entry.wordloc), escape(entry.gwordloc))
+           local res = assert (con:execute(sql))
+    end
+end 

local listsourceentries = function(sourcename)
    local sources = {}
@@ -245,7 +259,7 @@ local addtowatchlist = function()
    local watchdays = config.watchdays or 14
    local sql = "insert into watchlist select clientuserid, " ..
        "(max(logdatetime) + INTERVAL '"..watchdays.." days') as expiredatetime 
" ..
-        "from blocklog group by clientuserid"
+        "from pubweblog where bypassyesno > '0' group by clientuserid"
    local res1 = assert (con:execute(sql))
    sql = "delete from watchlist where exists " ..
        "(select * from watchlist w where w.clientuserid = 
watchlist.clientuserid " ..
@@ -258,67 +272,11 @@ end
local updateusagestats = function()
    -- update the usagestat table from weblog
    -- (will result in multiple rows where logs rotated on partial hours)
-    local sql = "insert into usagestat select weblog.sourcename, " ..
-        "date_trunc('hour', weblog.logdatetime) as date, " ..
-        "count(*), 0 from weblog group by sourcename,date"
+    local sql = "insert into usagestat select pubweblog.sourcename, " ..
+        "date_trunc('hour', pubweblog.logdatetime) as date, " ..
+        "count(*), SUM(deniedyesno) from pubweblog group by sourcename,date"
    local res = assert (con:execute(sql))

-    -- update the usagestat table from blocklog
-    -- (will result in multiple rows where logs rotated on partial hours)
-    -- (also, numrequest and numblock end up in different rows)
-    sql= "insert into usagestat select blocklog.sourcename, " ..
-        "date_trunc('hour', blocklog.logdatetime) as date, " ..
-        "0, count(*) from blocklog group by sourcename,date"
-    res = assert (con:execute(sql))
-end
-
--- Process weblog and blocklog, combine into pubweblog and pubblocklog
--- empties weblog and blocklog
-local importpubweblog = function()
-    local sql = "ANALYZE"
-    res = assert (con:execute(sql))
-    -- Merge equal blocks into weblog
-    sql = "update weblog set reason=blocklog.reason, " ..
-        "score=blocklog.score, shortreason=blocklog.shortreason from blocklog 
where " ..
-        "blocklog.logdatetime >= date_trunc('second', weblog.logdatetime) and " 
..
-        "blocklog.logdatetime < (weblog.logdatetime + INTERVAL '45' second) and 
" ..
-        "blocklog.sourcename=weblog.sourcename and "..
-        "blocklog.clientuserid=weblog.clientuserid and "..
-        "weblog.uri like (blocklog.uri || '%')"
-    res = assert (con:execute(sql))
-    logme("importpubweblog merged " .. res .. " blocks with matching 
timestamps.")
-
-    sql = "insert into weblog select * from blocklog where " ..
-        " NOT EXISTS (select * from weblog where " ..
-        "blocklog.logdatetime >= date_trunc('second', weblog.logdatetime) and " 
..
-        "blocklog.logdatetime < (weblog.logdatetime + INTERVAL '45' second) and 
" ..
-        "blocklog.sourcename=weblog.sourcename and "..
-        "blocklog.clientuserid=weblog.clientuserid and "..
-        "weblog.uri like (blocklog.uri || '%') )"
-    res = assert (con:execute(sql))
-    if ( res > 0 ) then
-        logme("NOTE: importpubweblog found and merged " .. res .. " unmatched 
blocks (source IP will not match)")
-    end
-
-    -- Move weblog to pubweblog
-    sql= "insert into pubweblog select * from weblog"
-    res = assert (con:execute(sql))
-    logme("importpubweblog imported " .. res .. " new rows into database.")
-
-    -- update pubblocklog table
-    sql = "insert into pubblocklog select * from weblog where reason is not 
null"
-    res = assert (con:execute(sql))
-    logme("importpubweblog imported " .. res .. " new blocks into block 
table.")
-
-    -- grab the bypass info
-    sql = "insert into pubblocklog select * from weblog where uri like 
'%?GBYPASS%'"
-    res = assert (con:execute(sql))
-    logme("importpubweblog imported " .. res .. " dg bybass events into block 
table.")
-
-    -- Truncate the staging tables
-    assert (con:execute("truncate weblog"))
-    assert (con:execute("truncate blocklog"))
-    logme("truncated staging tables")
end

-- Delete people from the watchlist when they have expired out
@@ -344,41 +302,38 @@ end
-- Delete old junk from pub tables
local groompublogs = function()
    local purgedays = config.purgedays or 30
-    local watchdays = config.watchdays or 14
-    local historydays = config.historydays or 14
+    --local watchdays = config.watchdays or 14
+    --local historydays = config.historydays or 14
+    
    local now = os.time()

    local temp = os.date("%Y-%m-%d %H:%M:%S", now - purgedays*86400)
-    logme("Purgedate is " .. temp .. ". Nothing will exist beyond purgedate.")
+    logme("Purgedate is " .. temp .. ". Nothing will exist in pubweblog beyond 
purgedate.")

-    -- purge anything older than purgedate
-    sql = "delete from pubweblog where logdatetime < '" .. temp .."'"
+    -- Move flagged records to histoy and then purge anything older than 
purgedate
+    sql = "Insert into pubweblog_history select * from pubweblog where 
logdatetime < '" .. temp .."' and (badyesno > 0 or deniedyesno > 0 or 
bypassyesno > 0 or selected = 'true')"
    res = assert (con:execute(sql))
-    logme("Purged " .. res .. " old records from pubweblog")
-
-    sql = "delete from pubblocklog where logdatetime < '" .. temp .. "'"
+    logme("Moved " .. res .. " old records to history")
+    
+    sql = "Delete from pubweblog where logdatetime < '" .. temp .."'"
    res = assert (con:execute(sql))
-    logme("Purged " .. res .. " old records from pubblocklog")
+    logme("Deleted " .. res .. " old records to from pubweblog")

    -- purge anything older than startddate+historydays+watchdays
-    local temp = config.auditstart
-    if not temp or temp == "" then temp = os.date("%Y-%m-%d %H:%M:%S") end
-    logme("Purge date since last audit is " .. tostring(watchdays+historydays) 
.. " days before " .. temp .. ".")
-
-    sql = "delete from pubweblog where logdatetime < (timestamp '"..temp.."' - 
INTERVAL '"..tostring(watchdays+historydays).." days')"
-    res = assert (con:execute(sql))
-        logme("removed " .. res .. " old pubweblog records that are older than 
history+watchdays")
+    --local temp = config.auditstart
+    --if not temp or temp == "" then temp = os.date("%Y-%m-%d %H:%M:%S") end
+    --logme("Purge date since last audit is " .. 
tostring(watchdays+historydays) .. " days before " .. temp .. ".")

-    sql = "delete from pubblocklog where logdatetime < (timestamp '"..temp.."' 
- INTERVAL '"..tostring(watchdays+historydays).." days')"
-    res = assert (con:execute(sql))
-        logme("removed " .. res .. " old pubblocklog records that are older 
than history+watchdays")
+    --sql = "delete from pubweblog where logdatetime < (timestamp '"..temp.."' 
- INTERVAL '"..tostring(watchdays+historydays).." days')"
+    --res = assert (con:execute(sql))
+        --logme("removed " .. res .. " old pubweblog records that are older 
than history+watchdays")

    -- purge good people after historydays
-    logme("The delete date for non-watchlist users is " .. 
tostring(historydays) .. " days before " .. temp .. ".")
+    --logme("The delete date for non-watchlist users is " .. 
tostring(historydays) .. " days before " .. temp .. ".")

-    sql = "delete from pubweblog where logdatetime < (timestamp '".. temp.."' - 
INTERVAL '"..tostring(historydays).." days') and clientuserid NOT IN (select 
clientuserid from watchlist)"
-    res = assert (con:execute(sql))
-    logme("removed " .. res .. " records for users not on the watchlist.")
+    --sql = "delete from pubweblog where logdatetime < (timestamp '".. temp.."' 
- INTERVAL '"..tostring(historydays).." days') and clientuserid NOT IN (select 
clientuserid from watchlist)"
+    --res = assert (con:execute(sql))
+    --logme("removed " .. res .. " records for users not on the watchlist.")
end

local listwatchlistentries = function()
@@ -408,11 +363,11 @@ local deletewatchlistentry = function(clientuserid)
    return res
end

-local generatewhereclause = function(clientuserid, starttime, endtime, 
clientip)
+local generatewhereclause = function(clientuserid, starttime, endtime, 
clientip, badyesno, deniedyesno, bypassyesno, score, urisearch, selected)
    local sql = ""
    local where = {}
    if clientuserid and clientuserid ~= "" then
-        where[#where+1] = "clientuserid = '"..escape(clientuserid).."'"
+        where[#where+1] = "clientuserid LIKE '%"..escape(clientuserid).."%'"
    end
    if starttime and starttime ~= "" then
        where[#where+1] = "logdatetime >= '"..escape(starttime).."'"
@@ -423,25 +378,46 @@ local generatewhereclause = function(clientuserid, 
starttime, endtime, clientip)
    if clientip and clientip ~= "" then
        where[#where+1] = "clientip = '"..escape(clientip).."'"
    end
+    if badyesno and badyesno ~= "" then
+        where[#where+1] = "badyesno = '"..escape(badyesno).."'"
+    end
+    if deniedyesno and deniedyesno ~= "" then
+        where[#where+1] = "deniedyesno = '"..escape(deniedyesno).."'"
+    end
+    if bypassyesno and bypassyesno ~= "" then
+        where[#where+1] = "bypassyesno = '"..escape(bypassyesno).."'"
+    end
+    if score and score ~= "" then
+        where[#where+1] = "score >= '"..escape(score).."'"
+    end
+    if urisearch and urisearch ~= "" then 
+            where[#where+1] = "lower(uri) LIKE '%"..escape(urisearch).."%'"
+    end
+    
+    if selected and selected == "true" then
+        where[#where+1] = "selected = 'true'"
+    end
+    
    if #where > 0 then
        sql = " WHERE " .. table.concat(where, " AND ")
    end
+    
    return sql
end

-local listlogentries = function(logname, clientuserid, starttime, endtime, 
clientip)
+local listlogentries = function(activelog, clientuserid, starttime, endtime, 
clientip, badyesno, deniedyesno, bypassyesno, score, urisearch, sortby, 
selected)
    local entries = {}
    -- retrieve a cursor
-    local sql = "SELECT * from "..logname
-    sql = sql .. generatewhereclause(clientuserid, starttime, endtime, 
clientip)
-    sql = sql .. " ORDER BY logdatetime"
+    local sql = "SELECT * FROM "..activelog
+    sql = sql .. generatewhereclause(clientuserid, starttime, endtime, 
clientip, badyesno, deniedyesno, bypassyesno, score, urisearch, selected)
+    sql = sql .. " ORDER BY "..sortby
    cur = assert (con:execute(sql))
    row = cur:fetch ({}, "a")
    while row do
        if config.shorturi == "true" then
            shorturi=string.gsub(row.uri, "[;?].*", "...")
        end
-        entries[#entries+1] = {sourcename=row.sourcename, 
clientip=row.clientip, clientuserid=row.clientuserid, 
logdatetime=row.logdatetime, uri=row.uri, shorturi=shorturi, bytes=row.bytes, 
reason=row.reason, score=row.score, shortreason=row.shortreason}
+        entries[#entries+1] = {sourcename=row.sourcename, 
clientip=row.clientip, clientuserid=row.clientuserid, 
logdatetime=row.logdatetime, uri=row.uri, shorturi=shorturi, bytes=row.bytes, 
reason=row.reason, score=row.score, shortreason=row.shortreason, 
badyesno=row.badyesno, deniedyesno=row.deniedyesno, bypassyesno=row.bypassyesno, 
wordloc=row.wordloc, id=row.id, selected=row.selected }
        if (config.shortreason ~= "true") then
            entries[#entries].shortreason = nil
        end
@@ -452,31 +428,8 @@ local listlogentries = function(logname, clientuserid, 
starttime, endtime, clien
    return entries
end

-local listpubblocklogentries = function(...)
-    return listlogentries("pubblocklog", ...)
-end
-
local listpubweblogentries = function(...)
-    return listlogentries("pubweblog", ...)
-end
-
-local grouppubblocklogentries = function(starttime, endtime, groupby)
-    groupby = groupby or "clientuserid"
-    local entries = {}
-    -- retrieve a cursor
-    local sql = "SELECT "..groupby..", count(*) AS numblock, max(score) AS 
maxscore FROM pubblocklog"
-    sql = sql .. generatewhereclause(nil, starttime, endtime)
-    sql = sql .. " GROUP BY "..groupby.. " ORDER BY numblock DESC"
-    cur = assert (con:execute(sql))
-    row = cur:fetch ({}, "a")
-    while row do
-        entries[#entries+1] = {numblock=row.numblock, maxscore=row.maxscore}
-        entries[#entries][groupby] = row[groupby]
-        row = cur:fetch (row, "a")
-    end
-    -- close everything
-    cur:close()
-    return entries
+    return listlogentries(...)
end

local listusagestats = function()
@@ -561,9 +514,87 @@ local function parsesquidlog(line)
    -- Format of squid log (space separated):
    -- time elapsed remotehost code/status bytes method URL rfc931 
peerstatus/peerhost
    local words = {}
+    
    for word in string.gmatch(line, "%S+") do
        words[#words+1] = word
    end
+    
+    local goodwordloc=""
+    local badwordloc=""
+    -- logme("value of word7 is "..words[7])
+    local wrdcnt=0
+    local isbad=0
+    local isdenied=0
+    local isbypass=0
+    local ignoreme=false
+    
+    --check for ignored records first
+    for thisline in io.lines("/etc/weblog/ignorewords") do
+        if not thisline then
+            break
+        end
+        _,instcnt = string.lower(words[7]):gsub(thisline, " ")
+        if instcnt ~= 0 then
+           ignoreme = true
+           break
+        end
+    end
+
+    if ignoreme ~= true then
+     --proceed with record analysis
+      for thisline in io.lines("/etc/weblog/badwords") do
+        if not thisline then
+            break
+        end
+        
+        _,instcnt = string.lower(words[7]):gsub(thisline, " ")  
+        --if string.find(words[7],thisline) ~= nil then
+        if instcnt ~= 0 then
+         -- logme("instcnt =  "..instcnt)
+          isbad=1
+          wrdcnt= wrdcnt + instcnt 
+          if badwordloc ~= "" then 
+            badwordloc = badwordloc.."|"..thisline
+          else
+            badwordloc=thisline
+          end
+        
+            end
+        
+        if string.find(words[7],"*DENIED*") then
+           logme("*Denied*")
+           isdenied=1
+        elseif string.find(words[7],"GBYPASS") then
+           logme("GBYPASS")
+           isbypass=1
+        elseif string.find(words[7],"*OVERRIDE*") then
+           logme("*OVERRIDE*")
+           isbypass=1
+        end
+      end
+      for goodline in io.lines("/etc/weblog/goodwords") do
+        if not goodline then
+          break
+        end
+        _,instcnt = string.lower(words[7]):gsub(goodline, " ")
+        --if string.find(words[7],goodline) then
+        if instcnt ~= 0 then
+          if wrdcnt ~= 0 then
+             wrdcnt = wrdcnt - instcnt
+             if goodwordloc ~= "" then
+                goodwordloc = goodwordloc.."|"..goodline
+             else 
+                goodwordloc = goodline
+             end
+          end
+        end
+      end    
+    end
+    -- Reset bad to reduce number of bad hits if score is zero
+    -- if wrdcnt == 0 then
+    -- isbad=0
+    -- end
+        
    local logentry = {logdatetime=words[1],
        elapsed=words[2],
        clientip=words[3],
@@ -574,32 +605,334 @@ local function parsesquidlog(line)
        URL=words[7],
        clientuserid=words[8],
        peerstatus=string.match(words[9] or "", "^[^/]*"),
-        peerhost=string.match(words[9] or "", "[^/]*$")}
+        peerhost=string.match(words[9] or "", "[^/]*$"),
+        score=wrdcnt,
+        badyesno=isbad,
+        deniedyesno=isdenied,
+        bypassyesno=isbypass,        
+        wordloc=badwordloc,
+        gwordloc=goodwordloc}    

    -- Don't care about local requests (from DG) (this check also removes blank 
lines)
    if logentry.clientip and logentry.clientip ~= "127.0.0.1" then
+       if logentry.clientuserid and logentry.clientuserid ~= "-" then
        logentry.logdatetime = os.date("%Y-%m-%d %H:%M:%S", 
logentry.logdatetime)..string.match(logentry.logdatetime, "%..*")
        return logentry
+           end
+    end
+    return nil
+end
+
+local function parsesquarklog(line)
+    -- Format of squid log (space separated):
+    -- time elapsed remotehost code/status bytes method URL rfc931 
peerstatus/peerhost
+    local words = {}
+    
+    for word in string.gmatch(line, "%S+") do
+        words[#words+1] = word
+    end
+
+    local goodwordloc=""
+    local badwordloc=""
+    local wrdcnt=0
+    local isbad=0
+    local isdenied=0
+    local isbypass=0
+    local ignoreme=false
+    
+    --check for ignored records first
+    for thisline in io.lines("/etc/weblog/ignorewords") do
+        if not thisline then
+            break
+        end
+        _,instcnt = string.lower(words[5]):gsub(thisline, " ")
+        if instcnt ~= 0 then
+           ignoreme = true
+           break
+        end
+    end
+
+     if ignoreme ~= true then    
+      for thisline in io.lines(baseurl.."badwords") do
+        if not thisline then
+            -- logme("This line is apparently empty...")
+            break
+        end
+        
+        _,instcnt = string.lower(words[5]):gsub(thisline, " ")
+    --    if string.find(words[5],thisline) ~= nil then
+        --logme("checking "..thisline.." against "..words[5])
+        if instcnt ~= 0 then
+          isbad=1
+          wrdcnt = wrdcnt + instcnt
+        if badwordloc ~= "" then 
+            badwordloc = badwordloc.."|"..thisline
+        else
+            badwordloc=thisline
+        end
+        
+          -- logme("bad "..badwordloc)
+            end
+    
+        if string.find(words[6],"*DENIED*") then    
+           isdenied=1
+        end
+        if string.find(words[6],"*OVERRIDE*") then
+           isbypass=1
+        end
+    end
+    for goodline in io.lines(baseurl.."goodwords") do
+        if not goodline then
+          -- logme("This line is apparently empty...")
+          break
+        end
+        _,instcnt = string.lower(words[5]):gsub(goodline, " ")
+        --if string.find(words[4],goodline) then
+          if instcnt ~= 0 then
+           if wrdcnt ~= 0 then
+             wrdcnt = wrdcnt - instcnt
+             if goodwordloc ~= "" then
+                goodwordloc = goodwordloc.."|"..goodline
+             else 
+                goodwordloc = goodline
+             end
+          end
+        end
+      end
+    end
+    
+    local words = format.string_to_table(line, "\t")    
+    local logentry = {logdatetime=words[1],
+            clientuserid=words[2],
+            clientip=words[3],
+            URL=words[4],
+            reason=words[5],
+            method=words[6],
+            bytes=words[7],
+            shortreason=words[9],
+            score=wrdcnt,
+            badyesno=isbad,
+            deniedyesno=isdenied,
+            bypassyesno=isbypass,        
+            wordloc=badwordloc,
+            gwordloc=goodwordloc}    
+
+    if logentry.reason and logentry.reason ~= "" then
+               if logentry.shortreason == "" then
+                   logentry.shortreason = logentry.reason
+               end
+           return logentry
    end
    return nil
end

local function parsedglog(line)
-    local words = format.string_to_table(line, "\t")
-    local logentry = { logdatetime=words[1], clientuserid=words[2], 
clientip=words[3],
-        URL=words[4], reason=words[5], method=words[6], bytes=words[7],
-        shortreason=words[9]}
+    -- Format of squid log (space separated):
+    -- time elapsed remotehost code/status bytes method URL rfc931 
peerstatus/peerhost
+    local words = {}
+    
+    for word in string.gmatch(line, "%S+") do
+        words[#words+1] = word
+    end
+
+    local goodwordloc=""
+    local badwordloc=""
+    -- logme("value of word4 is "..words[4])
+    local wrdcnt=0
+    local isbad=0
+    local isdenied=0
+    local isbypass=0
+    local ignoreme=false
+
+    --check for ignored records first
+    for thisline in io.lines("/etc/weblog/ignorewords") do
+        if not thisline then
+            break
+        end
+        _,instcnt = string.lower(words[4]):gsub(thisline, " ")
+        if instcnt ~= 0 then
+           ignoreme = true
+           break
+        end
+    end
+
+    if ignoreme ~= true then
+      for thisline in io.lines("/etc/weblog/badwords") do
+        if not thisline then
+            -- logme("This line is apparently empty...")
+            break
+        end
+        
+        _,instcnt = string.lower(words[4]):gsub(thisline, " ")
+        --if string.find(words[4],thisline) ~= nil then
+          if instcnt ~= 0 then
+           if wrdcnt ~= 0 then
+             isbad=1
+             wrdcnt= wrdcnt + instcnt
+             if badwordloc ~= "" then 
+               badwordloc = badwordloc.."|"..thisline
+             else
+               badwordloc=thisline
+             end
+        
+          -- logme("bad "..badwordloc)
+            end
+        
+        if string.find(words[5],"*DENIED*") then
+           isdenied=1
+        elseif string.find(words[5],"GBYPASS") then
+           isdenied=1 
+        elseif string.find(words[5],"*OVERRIDE*") then
+           isbypass=1
+        end
+      end
+      for goodline in io.lines("/etc/weblog/goodwords") do
+        if not goodline then
+          -- logme("This line is apparently empty...")
+          break
+        end
+        _,instcnt = string.lower(words[4]):gsub(goodline, " ")
+        --if string.find(words[4],goodline) then
+          
+          if instcnt ~= 0 then
+             wrdcnt = wrdcnt - instcnt
+             if goodwordloc ~= "" then
+                goodwordloc = goodwordloc.."|"..goodline
+             else 
+                goodwordloc = goodline
+             end
+          end
+        end
+      end    
+    
+    end
+    
+    local words = format.string_to_table(line, "\t")    
+    local logentry = {logdatetime=words[1],
+            clientuserid=words[2],
+            clientip=words[3],
+            URL=words[4],
+            reason=words[5],
+            method=words[6],
+            bytes=words[7],
+            shortreason=words[9],
+            score=wrdcnt,
+            badyesno=isbad,
+            deniedyesno=isdenied,
+            bypassyesno=isbypass,        
+            wordloc=badwordloc,
+            gwordloc=goodwordloc}    
+
    if logentry.reason and logentry.reason ~= "" then
-        if logentry.shortreason == "" then
-            logentry.shortreason = logentry.reason
+               if logentry.shortreason == "" then
+                   logentry.shortreason = logentry.reason
+               end
+           return logentry
+    end
+    return nil
+end
+
+local function parsedumplog(line)
+    -- Format of squid log (space separated):
+    -- time elapsed remotehost code/status bytes method URL rfc931 
peerstatus/peerhost
+    local words = {}
+    
+    for word in string.gmatch(line, "%S+") do
+        words[#words+1] = word
+    end
+    goodwordloc=""
+    badwordloc=""
+    wrdcnt=0
+    isbad=0
+    isdenied=0
+    isbypass=0
+    for thisline in io.lines("/etc/weblog/badwords") do
+        if not thisline then
+             logme("This line is apparently empty...")
+            break
        end
-        logentry.score = string.match(logentry.reason, "^.*: ([0-9]+) ")
-        logentry.logdatetime = string.gsub(logentry.logdatetime, "%.", "-")
-        return logentry
+        _,instcnt = string.lower(words[5]):gsub(thisline, " ")
+        if instcnt ~= 0 then
+          isbad=1
+          wrdcnt = wrdcnt + instcnt
+          if badwordloc ~= "" then 
+            badwordloc = badwordloc.."|"..thisline
+          else
+            badwordloc=thisline
+          end
+        
+           -- logme("bad "..badwordloc)
+            end
+        if string.find(words[6],"*DENIED*") then    
+           isdenied=1
+        end
+        if string.find(words[5],"GBYPASS") then
+           isbypass=1
+        elseif string.find(words[6],"*OVERRIDE*") then
+           isbypass=1
+        end
+    end
+    for goodline in io.lines("/etc/weblog/goodwords") do
+        if not goodline then
+          -- logme("This line is apparently empty...")
+          break
+        end
+        _,instcnt = string.lower(words[4]):gsub(goodline, " ")
+        --if string.find(words[4],goodline) then
+          if instcnt ~= 0 then
+           if wrdcnt ~= 0 then
+             wrdcnt = wrdcnt - instcnt
+             if goodwordloc ~= "" then
+                goodwordloc = goodwordloc.."|"..goodline
+             else 
+                goodwordloc = goodline
+             end
+          end
+        end
+    end    
+    
+    local words = format.string_to_table(line, "\t")    
+    local logentry = {logdatetime=words[1],
+            clientuserid=words[2],
+            clientip=words[3],
+            URL=words[4],
+            reason=words[6],
+            method=words[5],
+            bytes=words[7],
+            shortreason=words[9],
+            score=wrdcnt,
+            badyesno=isbad,
+            deniedyesno=isdenied,
+            bypassyesno=isbypass,        
+            wordloc=badwordloc,
+            gwordloc=goodwordloc}    
+
+    if logentry.reason and logentry.reason ~= "" then
+               if logentry.shortreason == "" then
+                   logentry.shortreason = logentry.reason
+               end
+           return logentry
    end
    return nil
end

+--local function parsedglog(line)
+--    local words = format.string_to_table(line, "\t")
+--    local logentry = { logdatetime=words[1], clientuserid=words[2], 
clientip=words[3],
+--        URL=words[4], reason=words[5], method=words[6], bytes=words[7],
+--        shortreason=words[9]}
+--    if logentry.reason and logentry.reason ~= "" then
+--        if logentry.shortreason == "" then
+--            logentry.shortreason = logentry.reason
+--        end
+--        logentry.score = string.match(logentry.reason, "^.*: ([0-9]+) ")
+--        logentry.logdatetime = string.gsub(logentry.logdatetime, "%.", "-")
+--        return logentry
+--    end
+--    return nil
+--end
+
+
-- 
################################################################################
-- DOWNLOAD FILE FUNCTIONS

@@ -880,7 +1213,7 @@ local function importlogfile(source, cookiesfile, file, 
parselog_func, importlog
                end
                pcall(function() logme("Exception on line:"..line) end)
                if err2 then
-                    pcall(function() logme(err2) end)
+                    pcall(function() logme("err2 "..err2) end)
                end
                if (config.stoponerror == "true") then
                    assert(res2, "Import halted on exception")
@@ -914,10 +1247,16 @@ function importlogs()

    local res, err = pcall(function()
        databaseconnect(DatabaseOwner, config.password)
-        -- Determine sources
-        local sources = listsourceentries(sourcename)

        -- Download, parse, and import the logs
+        logme("Executing importlogs")
+        logme("Analyzing...")
+        local sql = "ANALYZE"
+        res = assert (con:execute(sql))
+        
+        -- Determine sources
+        local sources = listsourceentries(sourcename)
+        
        for i,source in ipairs(sources) do
            if source.enabled then
                logme("Getting logs from source " .. source.sourcename)
@@ -928,10 +1267,19 @@ function importlogs()
                        if string.match(file, "dansguardian/access%.log[%.%-]") 
then
                            count = count + 1
                            success = importlogfile(source, cookiesfile, file, 
parsedglog, importdglog) and success
-                        elseif string.match(file, "squid/access%.log[%.%-]") 
then
+                        end
+                        if string.match(file, "squark/access%.log[%.%-]") then
+                            count = count + 1
+                            success = importlogfile(source, cookiesfile, file, 
parsesquarklog, importsquarklog) and success
+                        end
+                        if string.match(file, "squid/access%.log[%.%-]") then
                            count = count + 1
                            success = importlogfile(source, cookiesfile, file, 
parsesquidlog, importsquidlog) and success
                        end
+                        if string.match(file, "dump/access%.log[%.%-]") then
+                            count = count + 1
+                            success = importlogfile(source, cookiesfile, file, 
parsedumplog, importdumplog) and success
+                        end
                    end
                end
                os.remove(cookiesfile)
@@ -942,7 +1290,6 @@ function importlogs()
        if success then
            addtowatchlist()
            updateusagestats()
-            importpubweblog()
            groomwatchlist()
        end
        -- Purge old database entries
@@ -1112,55 +1459,116 @@ local validateparameters = function(params)
    return success
end

-local handleparameters = function(clientuserid, starttime, endtime, clientip, 
focus)
+local handleparameters = function(activelog, clientuserid, starttime, endtime, 
clientip, badyesno, deniedyesno, bypassyesno, score, urisearch, sortby, 
selected, focus)
    local result = {}
+    result.activelog = cfe({ value=activelog or "pubweblog", label="Active 
Weblog" })
    result.clientuserid = cfe({ value=clientuserid or "", label="User ID" })
    result.starttime = cfe({ value=starttime or "", label="Start Time" })
    result.endtime = cfe({ value=endtime or "", label="End Time" })
    result.clientip = cfe({ value=clientip or "", label="Client IP" })
+    result.badyesno = cfe({ value=badyesno, label="Show Dodgy Records", 
descr="Limit search to Dodgy records"})
+    result.deniedyesno = cfe({ value=deniedyesno, label="Show Denied Records", 
descr="Limit search to Denied uri"})
+    result.bypassyesno = cfe({ value=bypassyesno, label="Show Bypass Actions", 
descr="Limit search to Bypass attempts"})
+    result.score = cfe({ value=score, label="Minimum Score", descr="Minimum 
score to search on"})
+    result.urisearch = cfe({ value=urisearch or "", label="URI Contains", 
descr="Retrieve records where the URI contains this word"})
+    result.sortby = cfe({ value=sortby, label="Sort By field", descr="Sort by 
this field when displaying records"})
+    result.selected = cfe({ value=selected, label="Show Selected Records", 
descr="Show only records that have been selected"})
    result.window = cfe({ value=config.window or "5", label="Time Window" })
    result.focus = cfe({ value=focus or "", label="Focus Time" })
    return result
end

-function getweblog(clientuserid, starttime, endtime, clientip, focus)
+function getselected(csvdata)
+    local result = {}
+    result.id = cfe({ value=csvdata or "", label="Record ID", descr="Id of 
Record"})
+        result.log = cfe({ type="list", value={}, label="Weblog Access Log" })
+        local res, err = pcall(function()
+         databaseconnect(DatabaseUser)
+        local entries = {}
+        -- retrieve a cursor
+        local sql = "SELECT * FROM pubweblog where selected = true and 
logdatetime >= '" .. starttime .. "' and logdatetime <= '" .. endtime .. "'" 

+        local idcnt = 0
+        sql = sql .. " ORDER BY logdatetime;"
+        cur = assert (con:execute(sql))
+        row = cur:fetch ({}, "a")
+        while row do
+            entries[#entries+1] = {sourcename=row.sourcename, 
clientip=row.clientip, clientuserid=row.clientuserid, 
logdatetime=row.logdatetime, uri=row.uri, shorturi=shorturi, bytes=row.bytes, 
reason=row.reason, core=row.score, shortreason=row.shortreason, 
badyesno=row.badyesno, deniedyesno=row.deniedyesno, bypassyesno=row.bypassyesno, 
wordloc=row.wordloc, selected=row.selected }
+            row = cur:fetch (row, "a")
+        end
+        -- close everything
+        cur:close()
+        result.log.value = entries or {} 
+        --result.log.value = sql
+        databasedisconnect()
+     end)
+    return cfe({ type="group", value=result, errtxt=err, label="Weblog 
Selected" })    

+end
+
+function editselected(chkdata)
+    keycnt = 0
+    sql = "UPDATE pubweblog SET selected = "
+    databaseconnect(DatabaseOwner)
+    idarray = split(chkdata,"|")
+      for key,x in pairs(idarray) do
+        keycnt = keycnt + 1
+        if keycnt == 1 then 
+          sql = sql..x.." WHERE id = "
+        else 
+          sql = sql..x
+        end
+      end
+    assert (con:execute(sql))
+    databasedisconnect()
+end
+
+function clearselected()
+        local retval = cfe({ label="Clear selected records", errtxt = "Failed 
to clear selected records - who knows why" })
+    sql = "UPDATE pubweblog SET selected = false WHERE selected = true"
+    databaseconnect(DatabaseOwner)
+    assert (con:execute(sql))
+    databasedisconnect()
+    retval.value = "Cleared"
+    retval.errtxt = nil
+    return retval 
+end
+
+function getweblog(activelog, clientuserid, starttime, endtime, clientip, 
badyesno, deniedyesno, bypassyesno, score, urisearch, sortby, selected, focus )
+
+    if (not activelog or activelog=="") then
+        activelog = "pubweblog"
+    end
+    
    if (not starttime or starttime=="") and (not endtime or endtime=="") and 
config.auditstart~="" and config.auditend~="" then
-        starttime = config.auditstart
-        endtime = config.auditend
+        
+         starttime = config.auditstart
+         endtime = config.auditend
+    
+        if config.badyesno=="true" then
+           badyesno = '1'
+        end
    end
-    local result = handleparameters(clientuserid, starttime, endtime, clientip, 
focus)
+    if (not score or score=="") and config.minimumscore~="" then
+      score = config.minimumscore
+    end
+    
+    if (not sortby or sortby=="") and config.sortby~="" then
+       sortby = config.sortby
+    end
+    
+    local result = handleparameters(activelog, clientuserid, starttime, 
endtime, clientip, badyesno, deniedyesno, bypassyesno, score, urisearch, sortby, 
selected, focus)
    result.log = cfe({ type="list", value={}, label="Weblog Access Log" })
    local success = validateparameters(result)
    if success then
        local res, err = pcall(function()
            databaseconnect(DatabaseUser)
-            result.log.value = listpubweblogentries(clientuserid, starttime, 
endtime, clientip) or {}
+            result.log.value = listpubweblogentries(activelog, clientuserid, 
starttime, endtime, clientip, badyesno, deniedyesno, bypassyesno, score, 
urisearch, sortby, selected ) or {}
            databasedisconnect()
        end)
    else
        err = "Invalid search parameters"
    end
    return cfe({ type="group", value=result, errtxt=err, label="Weblog Access 
Log" })
-end

-function getblocklog(clientuserid, starttime, endtime, clientip, focus)
-    if (not starttime or starttime=="") and (not endtime or endtime=="") and 
config.auditstart~="" and config.auditend~="" then
-        starttime = config.auditstart
-        endtime = config.auditend
-    end
-    local result = handleparameters(clientuserid, starttime, endtime, clientip, 
focus)
-    result.log = cfe({ type="list", value={}, label="Weblog Block Log" })
-    local success = validateparameters(result)
-    if success then
-        local res, err = pcall(function()
-            databaseconnect(DatabaseUser)
-            result.log.value = listpubblocklogentries(clientuserid, starttime, 
endtime, clientip) or {}
-            databasedisconnect()
-        end)
-    else
-        err = "Invalid search parameters"
-    end
-    return cfe({ type="group", value=result, errtxt=err, label="Weblog Block 
Log" })
end

function getusagestats()
@@ -1177,53 +1585,26 @@ function getusagestats()
    return retval
end

-function getauditstats()
-    local result = {}
-    result.auditstart = cfe({ value=config.auditstart or "", label="Audit Start 
Time" })
-    result.auditend = cfe({ value=config.auditend or "", label="Audit End Time" 
})
-    result.groupby = cfe({ value=config.groupby or "clientuserid", label="Group 
By" })
-    result.stats = cfe({ type="list", value={}, label="Audit Block Statistics" 
})
-    local res, err = pcall(function()
-        if config.auditstart ~= "" and config.auditend ~= "" then
-            databaseconnect(DatabaseUser)
-            result.stats.value = grouppubblocklogentries(config.auditstart, 
config.auditend, result.groupby.value) or {}
-            databasedisconnect()
-        end
-    end)
-    return cfe({ type="group", value=result, errtxt=err, label="Weblog Audit 
Statistics" })
-end
-
-function completeaudit(timestamp)
-    local conf = getconfig()
-    conf.value.auditstart.value = conf.value.auditend.value
-    local now = os.time()
-    conf.value.auditend.value = timestamp or os.date("%Y-%m-%d %H:%M:%S", now - 
now%86400 - 86400)
-    conf = updateconfig(conf)
-    local retval = cfe({ value="Audit completed", label="Complete Audit Result" 
})
-    if conf.errtxt then
-        retval.value = ""
-        retval.errtxt = "Failed to complete 
audit\n"..conf.errtxt.."\n"..conf.value.auditend.errtxt
-    end
-    return retval
-end

function getconfig()
    local result = {}
    result.auditstart = cfe({ value=config.auditstart or "", label="Audit Start 
Time" })
    result.auditend = cfe({ value=config.auditend or "", label="Audit End Time" 
})
+    result.badyesno = cfe({ type="boolean", value=(config.badyesno == "1"), 
label="Display Suspect Records", descr="Show only records flagged as suspect on 
initial display" })
+    result.minimumscore = cfe({ value=config.minimumscore or "0", 
label="Minimum Score", descr="Minimum Score to search for" })
+    result.sortby = cfe({ type="select", value=config.sortby or "logdatetime", 
label="Sort By field", option={"logdatetime", "logdatetime DESC", 
"clientuserid", "clientuserid DESC", "clientip", "clientip DESC", "bytes", 
"bytes DESC", "score", "score DESC", "reason"} })
    result.window = cfe({ value=config.window or "5", label="Time Window", 
descr="Minutes of activity to display before and after selected block" })
    result.watchdays = cfe({ value=config.watchdays or "14", label="Days to 
Watch", descr="Number of additional days to keep history for users in watchlist" 
})
    result.purgedays = cfe({ value=config.purgedays or "30", label="Days before 
Purge", descr="Days to keep history, regardless of audit" })
    result.historydays = cfe({ value=config.historydays or "14", label="Days to 
keep History", descr="Days beyond Audit Start Time to keep complete log history" 
})
-    result.groupby = cfe({ type="select", value=config.groupby or 
"clientuserid", label="Group results by", option={"clientuserid", "clientip"} })
    result.shorturi = cfe({ type="boolean", value=(config.shorturi == "true"), 
label="Truncate URLs", descr="You can limit the length of displayed URLs by 
enabling this option"})
-    result.shortreason = cfe({ type="boolean", value=(config.shortreason == 
"true"), label="Short Reason", descr="Display a short reason (without 
objectional words)"})
+    result.shortreason = cfe({ type="boolean", value=(config.shortreason == 
"true"), label="Short Reason", descr="Display a short reason (dansguardian 
only)"})
    result.stoponerror = cfe({ type="boolean", value=(config.stoponerror == 
"true"), label="Stop on Error", descr="Stop import of logs if an error is 
encountered"})
    return cfe({ type="group", value=result, label="Weblog Config" })
end

local function validateconfig(newconfig)
-    local success = modelfunctions.validateselect(newconfig.value.groupby)
+    local success = modelfunctions.validateselect(newconfig.value.sortby)
    if newconfig.value.window.value == "" then
        newconfig.value.window.errtxt = "Cannot be blank"
        success = false
@@ -1273,11 +1654,14 @@ function updateconfig(newconfig)
        configcontent = format.update_ini_file(configcontent, "", "watchdays", 
newconfig.value.watchdays.value)
        configcontent = format.update_ini_file(configcontent, "", "purgedays", 
newconfig.value.purgedays.value)
        configcontent = format.update_ini_file(configcontent, "", "historydays", 
newconfig.value.historydays.value)
-        configcontent = format.update_ini_file(configcontent, "", "groupby", 
newconfig.value.groupby.value)
+        --configcontent = format.update_ini_file(configcontent, "", "groupby", 
newconfig.value.groupby.value)
        configcontent = format.update_ini_file(configcontent, "", "shorturi", 
tostring(newconfig.value.shorturi.value))
        configcontent = format.update_ini_file(configcontent, "", "shortreason", 
tostring(newconfig.value.shortreason.value))
        configcontent = format.update_ini_file(configcontent, "", "stoponerror", 
tostring(newconfig.value.stoponerror.value))
-
+        configcontent = format.update_ini_file(configcontent, "", "badyesno", 
tostring(newconfig.value.badyesno.value))
+        configcontent = format.update_ini_file(configcontent, "", 
"minimumscore", tostring(newconfig.value.minimumscore.value))
+        configcontent = format.update_ini_file(configcontent, "", "sortby", 
tostring(newconfig.value.sortby.value))
+            
        fs.write_file(configfile, configcontent)
        config = format.parse_ini_file(configcontent, "") or {}
    else
@@ -1414,3 +1798,64 @@ function create_database(database)

    return database
end
+function listfiles()
+        local retval = cfe({ type="list", value={}, label="Weblog Files" })
+        if not fs.is_dir(baseurl) then fs.create_directory(baseurl) end
+        for file in posix.files(baseurl) do
+                 file = baseurl..file
+                 if fs.is_file(file) then
+                         table.insert(retval.value, file)
+                 end
+        end
+        table.sort(retval.value)
+        return retval
+end
+function getnewfile()
+        local filename = cfe({ label="File Name", descr="Must be in "..baseurl 
})
+        return cfe({ type="group", value={filename=filename}, label="Weblog 
File" })
+end
+function readfile(filename)
+        return modelfunctions.getfiledetails(filename, listfiles().value)
+end
+        
+function updatefile(filedetails)
+         return modelfunctions.setfiledetails(filedetails, listfiles().value)
+end
+                
+function deletefile(filename)
+        local retval = cfe({ label="Delete Weblog File result", errtxt = 
"Failed to delete Weblog File - invalid filename" })
+        for i,file in ipairs(listfiles().value) do
+            if filename == file then
+                      retval.value = "Deleted File"
+                  retval.errtxt = nil
+                  os.remove(filename)
+                  break
+                end
+        end
+                                                                                
                                                                                
        

+        return retval
+end
+
+-- Split a string to an array by delimiter or pattern
+function split(str, pat)
+   if string.find(str, pat) == nil then
+      return str
+   end
+   local t = {}
+   local fpat = "(.-)" .. pat
+   local last_end = 1
+   local s, e, cap = str:find(fpat, 1)
+   while s do
+     if s ~= 1 or cap ~= "" then
+        table.insert(t,cap)
+     end
+     last_end = e+1
+     s, e, cap = str:find(fpat, last_end)
+   end
+   if last_end <= #str then
+      cap = str:sub(last_end)
+      table.insert(t, cap)
+   end
+   return t
+end
+                                                                                
              

diff --git a/weblog-summary-html.lsp b/weblog-summary-html.lsp
new file mode 100644
index 0000000..60040b5
--- /dev/null
+++ b/weblog-summary-html.lsp
@@ -0,0 +1,17 @@
+<% local form, viewlibrary, page_info = ... 
+require("viewfunctions")
+%>
+
+<style type="text/css">
+  #content table { border-collapse: collapse; width: 100%; }
+  #content table td { white-space: normal; padding-right:20px; 
border-bottom:1px solid #999; }
+  #content table tr.mark { background: #E9E9E9; }
+</style>
+
+<H1>Summary</H1>
+<H2>Last 24 Hours</H2>
+<H2>Last 7 Days</H2>
+<H2>Last 30 Days</
+<% displayformstart(form, page_info) %>
+<% displayformitem(form.value.query, "query") %>
+<% displayformend(form) %>
diff --git a/weblog-viewwatchlist-html.lsp b/weblog-viewwatchlist-html.lsp
index 17bf1e0..1cf9a79 100644
--- a/weblog-viewwatchlist-html.lsp
+++ b/weblog-viewwatchlist-html.lsp
@@ -24,7 +24,7 @@
<% for i,watch in ipairs(data.value) do %>
    <TR>
        <TD><%= html.link{value = 
"deletewatchlistentry?clientuserid="..watch.clientuserid, label="Delete "} 
%></TD>
-        <TD><%= html.link{value = 
"viewblocklog?clientuserid="..watch.clientuserid, label=watch.clientuserid} 
%></TD>
+        <TD><%= html.link{value = 
"viewweblog?clientuserid="..watch.clientuserid, label=watch.clientuserid} 
%></TD>
        <TD><%= html.html_escape(watch.expiredatetime) %></TD>
    </TR>
<% end %>
diff --git a/weblog-viewweblog-html.lsp b/weblog-viewweblog-html.lsp
deleted file mode 120000
index 4ec32bc..0000000
--- a/weblog-viewweblog-html.lsp
+++ /dev/null
@@ -1 +0,0 @@
-weblog-viewblocklog-html.lsp
\ No newline at end of file
diff --git a/weblog-viewweblog-html.lsp b/weblog-viewweblog-html.lsp
new file mode 100644
index 0000000..b4c6083
--- /dev/null
+++ b/weblog-viewweblog-html.lsp
@@ -0,0 +1,300 @@
+<% local data, viewlibrary, page_info, session = ... %>
+<% require("viewfunctions")%>
+<% require("newviewfunctions")%>
+<% if data.value.focus.value ~= "" then %>
+<script type="text/javascript" src="<%= html.html_escape(page_info.wwwprefix) 
%>/js/jquery-latest.js"></script>
+<script type="text/javascript">
+    $(function(){
+           if ($("#focus").length) {
+            var top = $("#focus").offset().top;
+            $("html,body").scrollTop(top);
+        }
+    });
+</script>
+<% end %>
+
+<script type="text/javascript" src="<%= html.html_escape(page_info.wwwprefix) 
%>/js/jquery.min.js"></script>
+<script type="text/javascript" src="<%= 
html.html_escape(page_info.wwwprefix)%>/js/jquery.tablesorter.js"></script>
+<script type="text/javascript">
+        $(document).ready(function() {
+                $("#loglist").tablesorter({headers: {0:{sorter: 
false},1:{sorter: false}, 2:{sorter: 'text'}, 6:{sorter: false}, 7:{sorter: 
false}, 8:{sorter: false}}});
+        });
+        function hideColumn(myCol) {
+        myCol.style.display = "none";
+        };
+</script>
+            
+<% local subdata, pagedata = paginate(data.value.log.value, 
page_info.clientdata, 200) %>
+
+<style type="text/css">
+  #content table { border-collapse: collapse; width: 100%; }
+  #content table td { border-bottom: none; white-space: normal; 
padding-right:20px; }
+  #content table th { border-bottom: none; white-space: normal; vertical-align: 
middle; padding-right:15px }
+  #content table tr.mark { background: #E9E9E9; }
+  #content table tr.selected { background: #FC9A01; } 
+</style>
+
+<H1>Search Parameters</H1>
+<DL>
+<% if data.errtxt then %><p class="error"><%= html.html_escape(data.errtxt) 
%></p><% end %>
+<form action="<%= html.html_escape(page_info.script .. page_info.prefix .. 
page_info.controller .. "/" .. page_info.action) %>" method="POST">
+<DT>Active Weblog</DT>
+<DD><select name="activelog">
+<option value="pubweblog">Current</option>
+<option value="pubweblog_history"<% if data.value.activelog.value == 
"pubweblog_history" then %> selected="selected" <% end %> >History</option>
+</select>  
+</DD>
+<DT>Start Time</DT>
+<DD><input class="text" type="text" name="starttime" value="<%= 
html.html_escape(data.value.starttime.value) %>" >
+<p><%= html.html_escape(data.value.starttime.value) %></p>
+<% if data.value.starttime.errtxt then %><p class="error"><%= 
html.html_escape(data.value.starttime.errtxt) %></p><% end %>
+</DD>
+<DT>User ID</DT>
+<DD><input class="text" type="text"  name="clientuserid"  value="<%= 
html.html_escape(data.value.clientuserid.value) %>" >
+<p><%= html.html_escape(data.value.clientuserid.value) %></p>
+<% if data.value.clientuserid.errtxt then %><p class="error"><%= 
html.html_escape(data.value.clientuserid.errtxt) %></p><% end %>
+</DD>
+<DT>Client IP</DT>
+<DD><input class="text" type="text"  name="clientip"  value="<%= 
html.html_escape(data.value.clientip.value) %>" >
+<p><%= html.html_escape(data.value.clientip.value) %></p>
+<% if data.value.clientip.errtxt then %><p class="error"><%= 
html.html_escape(data.value.clientip.errtxt) %></p><% end %>
+</DD>
+<DT>End Time</DT>
+<DD><input class="text" type="text"  name="endtime"  value="<%= 
html.html_escape(data.value.endtime.value) %>" >
+<p><%= html.html_escape(data.value.endtime.value) %></p>
+<% if data.value.endtime.errtxt then %><p class="error"><%= 
html.html_escape(data.value.endtime.errtxt) %></p><% end %>
+</DD>
+<DT>URI Contains</DT>
+<DD><input class="text" type="text"  name="urisearch"  value="<%= 
html.html_escape(data.value.urisearch.value) %>" >
+<P CLASS="descr">Retrieve records where the URI contains this word</P>
+<p><%= html.html_escape(data.value.urisearch.value) %></p>
+<% if data.value.urisearch.errtxt then %><p class="error"><%= 
html.html_escape(data.value.urisearch.errtxt) %></p><% end %>
+</DD>
+<DT>Minimum Score</DT>
+<DD><input class="text" type="text"  name="score"  value="<%= 
html.html_escape(data.value.score.value) %>" >
+<P CLASS="descr">Minimum score to search on</P>
+<% if data.value.score.errtxt then %><p class="error"><%= 
html.html_escape(data.value.score.errtxt) %></p><% end %>
+</DD>
+<DT>Sort By</DT>
+<DD><select name="sortby">
+<option value="logdatetime"<% if data.value.log.value == "sortby" then %> 
selected="selected" <% end %> >Timestamp</option>
+<option value="logdatetime DESC"<% if data.value.sortby.value == "logdatetime 
DESC" then %> selected="selected" <% end %> >Timestamp DESC</option>
+<option value="clientuserid"<% if data.value.sortby.value == "clientuserid" 
then %> selected="selected" <% end %> >User ID</option>
+<option value="clientuserid DESC"<% if data.value.sortby.value == "clientuserid 
DESC" then %> selected="selected" <% end %> >User ID DESC</option>
+<option value="bytes"<% if data.value.sortby.value == "bytes" then %> 
selected="selected" <% end %> >Size</option>
+<option value="bytes DESC"<% if data.value.sortby.value == "bytes DESC" then %> 
selected="selected" <% end %> >Size DESC</option>
+<option value="score"<% if data.value.sortby.value == "score" then %> 
selected="selected" <% end %> >Score</option>
+<option value="score DESC"<% if data.value.sortby.value == "score DESC" then %> 
selected="selected" <% end %> >Score DESC</option>
+<option value="reason"<% if data.value.sortby.value == "reason" then %> 
selected="selected" <% end %> >Reason</option>
+<option value="reason DESC"<% if data.value.sortby.value == "reason DESC" then 
%> selected="selected" <% end %> >Reason DESC</option>
+</select>  
+</DD>
+<DT>Show Suspect Records</DT>
+<DD>
+<input class="checkbox" type="checkbox"  name="badyesno"  value="1" <% if 
data.value.badyesno.value == "1" then %> checked <% end %>>
+<P CLASS="descr">Show only URIs containing flagged words</P>
+<% if data.value.badyesno.errtxt then %><p class="error"><%= 
html.html_escape(data.value.badyesno.errtxt) %></p><% end %>
+</DD>
+<DT>Show Denied URIs</DT>
+<DD>
+<input class="checkbox" type="checkbox" name="deniedyesno" value="1" <% if 
data.value.deniedyesno.value == "1" then %>checked<% end %>>
+<% if data.value.deniedyesno.errtxt then %><p class="error"><%= 
html.html_escape(data.value.deniedyesno.errtxt) %></p><% end %>
+<P CLASS="descr">Show only Denied URIs</P>
+</DD>
+<DT>Show Bypass Attempts</DT>
+<DD>
+<input class="checkbox" type="checkbox"  name="bypassyesno"  value="1" <% if 
data.value.bypassyesno.value == "1" then %>checked <% end %>>
+<% if data.value.bypassyesno.errtxt then %><p class="error"><%= 
html.html_escape(data.value.bypassyesno.errtxt) %></p><% end %>
+<P CLASS="descr">Show only Bypass attempts</P>
+</DD>
+<DT>Show Selected Records</DT>
+<DD>
+<input class="checkbox" type="checkbox" name="selected" value="true" <% if 
data.value.selected.value == "true" then %>checked <% end %>>
+<% if data.value.selected.errtxt then %><p class="error"><%= 
html.html_escape(data.value.selected.errtxt) %></p><% end %>
+<P CLASS="descr">Show only records that have been selected</P>
+</DD>
+<DT></DT><DD><input class="submit" type="submit" name="Update" 
value="Update"></DD>
+</FORM>
+</DL>
+
+<%
+local clientinfo = ""
+if data.value.clientuserid.value ~= "" then
+    clientinfo = clientinfo .. 
"clientuserid="..data.value.clientuserid.value.."&"
+end
+if data.value.clientip.value ~= "" then
+    clientinfo = clientinfo .. "clientip="..data.value.clientip.value.."&"
+end
+%>
+
+<% displaypagination(pagedata, page_info) %>
+<H1><%= html.html_escape(data.label) %></H1>
+<DL>
+<TABLE id="loglist" class="tablesorter">
+<THEAD>
+<TR style=font-weight:bold;>
+        <TH><input type="checkbox" id="chkHead" /></TH>
+        <TH style="width:0%; display:none"></TH>
+        <TH>Timestamp</TH>
+        <TH>Client IP</TH>
+        <TH>User ID</TH>
+        <TH>Size</TH>
+        <TH style=font-weight:bold >Sus</TH>
+        <TH style=font-weight:bold >Den</TH>
+        <TH style=font-weight:bold >Byp</TH>
+        <TH>Score</TH>
+        <TH>Reason</TH>
+        <TH WIDTH="90%">URL</TH>
+        <TH>Bad Words</TH>
+    </TR>
+</THEAD>
+<TBODY>
+<FORM action="<%= html.html_escape(page_info.script .. page_info.prefix .. 
page_info.controller .. "/checkselected") %>" name="markselected" 
onsubmit="return false" method="POST">
+<input type="hidden" id="chkdata" name="chkdata" value="chkdata"></FORM>
+<% for i,watch in ipairs(subdata) do
+    local a,b = math.modf((i/2))
+    local mark = ''
+    if (b == 0) and watch.selected ~= "t" then mark=' class="mark"' end
+    if watch.selected == "t" then mark=' class="selected"' end
+    local time = {}
+    time.year, time.month, time.day, time.hour, time.min, time.sec = 
+        string.match(watch.logdatetime, 
"(%d+)%-(%d+)-(%d+)%s+(%d+):(%d+):(%d+)")
+    time = os.time(time) %>
+<TR<%= mark %>>
+        <TD><input class="chktbl" type="checkbox" value="true" <% if 
watch.selected == "t" then %> checked <% end %>></TD>
+        <TD style="width:0%; display:none"><%= html.html_escape(watch.id) 
%></TD>
+        <TD <% if data.value.focus.value == watch.logdatetime then %> 
style="font-weight:bold;" id="focus" <% end %> ><%= html.link{value = 
"viewweblog?"..clientinfo..
+            "starttime="..os.date("%Y-%m-%d %H:%M:%S", time - 
60*(tonumber(data.value.window.value)))..
+            "&endtime="..os.date("%Y-%m-%d %H:%M:%S", time + 
60*(tonumber(data.value.window.value)))..
+            "&focus="..watch.logdatetime,
+            label=watch.logdatetime} %></TD>
+        <TD <% if data.value.clientip.value == watch.clientip then %> 
style="font-weight:bold;" <% end %> ><%= html.html_escape(watch.clientip) 
%></TD>
+        <TD <% if data.value.clientuserid.value == watch.clientuserid then %> 
style="font-weight:bold;" <% end %> ><%= html.html_escape(watch.clientuserid) 
%></TD>
+        <TD><%= html.html_escape(watch.bytes) %></TD>
+        <TD WIDTH="2%"><% if watch.badyesno == "1" then %><IMG SRC='<%= 
html.html_escape(page_info.wwwprefix..page_info.staticdir) %>/dodgy.png' 
width='13' height='13'><% end %></TD>
+        <TD WIDTH="2%"><% if watch.deniedyesno ~= "0" then %> <IMG SRC='<%= 
html.html_escape(page_info.wwwprefix..page_info.staticdir) %>/denied.png' 
width='13' height='13'><% end %></TD>
+        <TD WIDTH="2%"><% if watch.bypassyesno ~= "0" then %> <IMG SRC='<%= 
html.html_escape(page_info.wwwprefix..page_info.staticdir) %>/bypass.png' 
width='13' height='13'><% end %></TD>  

+        <TD><%= html.html_escape(watch.score) %></TD>
+        <TD><%= html.html_escape(watch.reason) %></TD>
+        <TD style="word-wrap: break-word" width="500"><% 
highlight_uri=html.html_escape(watch.uri) 

+               if watch.wordloc ~= nil then 
+                if string.find(watch.wordloc,"|") then 
+                  badwords = split(watch.wordloc,"|")
+                  for key,wrd in pairs(badwords) do
+                     highlight_uri = string.highlight(highlight_uri, wrd, 
"yellow","red")
+                  end
+                else
+                  highlight_uri = string.highlight(highlight_uri, 
watch.wordloc, "yellow","red")
+                end
+               end %> 
+            <%= highlight_uri %></TD>
+        <TD><%= watch.wordloc %></TD>
+</TR>
+<% end %>
+</TBODY>
+</TABLE>
+<% displaypagination(pagedata, page_info) %>
+
+<% if data.errtxt then %>
+<p class="error"><%= html.html_escape(data.errtxt) %></p>
+<% end %>
+<% if #data.value.log.value == 0 then %>
+<p>No results, try adjusting search parameters</p>
+<% end %>
+<DT>Download Options</DT>
+<% if page_info.action == "viewweblog" then %>
+<form action="<%= html.html_escape(page_info.script .. page_info.prefix .. 
page_info.controller .. "/downloadlogview") %>" method="POST">
+<input type="hidden"  name="activelog" value="<%= 
html.html_escape(data.value.activelog.value) %>" >
+<input type="hidden"  name="starttime" value="<%= 
html.html_escape(data.value.starttime.value) %>" >
+<input type="hidden"  name="clientuserid" value="<%= 
html.html_escape(data.value.clientuserid.value) %>" >
+<input type="hidden"  name="clientip" value="<%= 
html.html_escape(data.value.clientip.value) %>" >
+<input type="hidden"  name="endtime" value="<%= 
html.html_escape(data.value.endtime.value) %>" >
+<input type="hidden"  name="badyesno" value="<%= 
html.html_escape(data.value.badyesno.value) %>" >
+<input type="hidden"  name="deniedyesno" value="<%= 
html.html_escape(data.value.deniedyesno.value) %>" >
+<input type="hidden"  name="bypassyesno" value="<%= 
html.html_escape(data.value.bypassyesno.value) %>" >
+<input type="hidden"  name="score" value="<%= 
html.html_escape(data.value.score.value) %>" >
+<input type="hidden"  name="sortby" value="<%= 
html.html_escape(data.value.sortby.value) %>" >
+<input type="hidden"  name="urisearch" value="<%= 
html.html_escape(data.value.urisearch.value) %>" >
+<input type="hidden"  name="selected" value="<%= 
html.html_escape(data.value.selected.value) %>" >
+<DD><input class="submit" type="submit" name="Download" value="Export 
List"></DD>
+</form>
+<% end %>
+
+<script type="text/javascript">
+        $('#chkHead').click(function () {
+            if (this.checked == false) {
+              $('.chktbl:checked').attr('checked', false);
+            }
+            else {
+                $('.chktbl:not(:checked)').attr('checked', true);
+            }
+            if ($(this).attr("checked")==true)
+            {
+               
$("#loglist").find('tr:not(#chktbl)').css("background-color","#FC9A01");
+            }
+            else
+            {
+              
$("#loglist").find('tr:not(#chktbl)').css("background-color","#FFF");
+            } 
+        });
+        $('#chkHead').click(function(){
+        });
+        
+        $('.chktbl').click(function () {
+           if($("chkHead").attr('checked') == true && this.checked == false)
+        {
+            var csv_data = "";
+            var csv_cnt = 0;
+            $(".chktbl").attr('checked',false);
+            $(this).closest('tr').css("background-color","#ffffff");
+            $(this).closest('tr').each(function () {
+              $(this).find('td').each(function () {
+                  if(csv_cnt == 1)
+                   { document.viewweblog.chktbl.value = "false|" + 
$(this).text();
+                     return false;
+                  }
+                  csv_cnt +=1;
+                  });
+              });
+        }
+        if(this.checked == true)
+        {    
+            $(this).closest('tr').css("background-color","#FC9A01");
+             var csv_list = "";
+             var csv_cnt = 0; 
+            $(this).closest('tr').each(function () {
+              $(this).find('td').each(function () {
+                  if(csv_cnt == 1)
+                   { document.markselected.chkdata.value = "true|" + 
$(this).text();
+                    //alert("this is: " + document.markselected.chkdata.value 
);
+                     return false;
+                  }
+                  csv_cnt +=1;
+                  });
+              });
+            document.forms["markselected"].submit();
+            //document.getElementById("subbutton").click();
+        
+        }
+        if(this.checked == false)
+        {
+            $(this).closest('tr').css("background-color","#ffffff");
+             var csv_list = "";
+             var csv_cnt = 0; 
+            $(this).closest('tr').each(function () {
+              $(this).find('td').each(function () {
+                  if(csv_cnt == 1)
+                   { document.markselected.chkdata.value = "false|" + 
$(this).text();
+                     return false;
+                  }
+                  csv_cnt +=1;
+                  });
+              });
+            document.forms["markselected"].submit();
+        }
+        });
+        
+</script>
+
+
+</DL>
diff --git a/weblog.menu b/weblog.menu
index 9090b81..30638e5 100644
--- a/weblog.menu
+++ b/weblog.menu
@@ -1,7 +1,9 @@
#CAT          GROUP/DESC        TAB        ACTION
Applications     41Weblog        Status        status
-Applications     41Weblog        Audit        viewauditstats
+#Applications     41Weblog        Audit        viewauditstats
+Applications    41Weblog        View_Log    viewweblog
Applications     41Weblog        Config        config
+Applications    41Weblog        File_List    listfiles
Applications     41Weblog        Watch_List    viewwatchlist
Applications     41Weblog        Sources        listsources
Applications     41Weblog        Usage        viewusagestats
diff --git a/weblog.roles b/weblog.roles
index 5bce219..043506b 100644
--- a/weblog.roles
+++ b/weblog.roles
@@ -1,3 +1,3 @@
USER=weblog:viewauditstats,weblog:completeaudit,weblog:viewactivitylog,weblog:viewwatchlist,weblog:viewweblog,weblog:downloadweblog,weblog:viewblocklog,weblog:viewusagestats,weblog:deletewatchlistentry,weblog:createwatchlistentry,weblog:adhocquery,weblog:downloadadhocquery

-EXPERT=weblog:config,weblog:listsources,weblog:createsource,weblog:deletesource,weblog:editsource,weblog:testsource,weblog:importlogs,weblog:status,weblog:createdatabase

-ADMIN=weblog:config,weblog:viewauditstats,weblog:completeaudit,weblog:viewactivitylog,weblog:viewwatchlist,weblog:viewweblog,weblog:downloadweblog,weblog:viewblocklog,weblog:viewusagestats,weblog:listsources,weblog:createsource,weblog:deletesource,weblog:editsource,weblog:testsource,weblog:importlogs,weblog:deletewatchlistentry,weblog:createwatchlistentry,weblog:adhocquery,weblog:downloadadhocquery,weblog:status,weblog:createdatabase

+EXPERT=weblog:config,weblog:viewweblog,weblog:listsources,weblog:createsource,weblog:deletesource,weblog:editsource,weblog:testsource,weblog:importlogs,weblog:status,weblog:createdatabase,weblog:listfile,weblog:editfile

+ADMIN=weblog:config,weblog:viewauditstats,weblog:completeaudit,weblog:viewactivitylog,weblog:viewwatchlist,weblog:viewweblog,weblog:viewselected,weblog:downloadweblog,weblog:downloadlogview,weblog:downloadselected,weblog:checkselected,weblog:editselected,weblog:clearselected,weblog:viewblocklog,weblog:viewusagestats,weblog:listsources,weblog:createsource,weblog:deletesource,weblog:editsource,weblog:testsource,weblog:importlogs,weblog:deletewatchlistentry,weblog:createwatchlistentry,weblog:adhocquery,weblog:downloadadhocquery,weblog:status,weblog:createdatabase,weblog:listfiles,weblog:editfile

diff --git a/weblog_notify_daily b/weblog_notify_daily
new file mode 100755
index 0000000..3137c5b
--- /dev/null
+++ b/weblog_notify_daily
@@ -0,0 +1,36 @@
+#!/bin/bash
+echo "<html>" > /tmp/weblog_summary_daily.html
+echo "<head>" >> /tmp/weblog_summary_daily.html
+echo '<p><font weight="bold">DAILY SUMMARY WEBLOG REPORT FOR RESNET</font>'  >> 
/tmp/weblog_summary_daily.html
+echo "</head>" >> /tmp/weblog_summary_daily.html
+echo "" >> /tmp/weblog_summary_daily.html
+echo "<body>" >> /tmp/weblog_summary_daily.html
+echo "" >> /tmp/weblog_summary_daily.html
+echo "<p>Total number of records imported:" >> /tmp/weblog_summary_daily.html
+echo -e "`psql -t -U postgres -d webproxylog -c \"SELECT COUNT(*) FROM 
pubweblog WHERE logdatetime >= CURRENT_DATE - interval '$2 days';\"`</p>"  >> 
/tmp/weblog_summary_daily.html
+echo "" >> /tmp/weblog_summary_daily.html
+echo "<p>Total number of records with score > 0 imported:" >> 
/tmp/weblog_summary_daily.html
+echo -e "`psql -t -U postgres -d webproxylog -c \"SELECT COUNT(*) FROM 
pubweblog WHERE score > 0 AND logdatetime >= CURRENT_DATE - interval '7 days' 
AND score > 0;\"`</p>" >> /tmp/weblog_summary_daily.html
+echo "" >> /tmp/weblog_summary_daily.html
+echo "<p>Top 10 users with the highest number of suspect records:</p>" >> 
/tmp/weblog_summary_daily.html
+echo "" >> /tmp/weblog_summary_daily.html
+psql -H -U postgres -d webproxylog -c "SELECT clientuserid as User_ID, 
SUM(badyesno) AS Total_Suspect, MAX(score) as Highest_Score FROM pubweblog WHERE 
score > 0 and logdatetime >= CURRENT_DATE - interval '$2 days' GROUP BY 
clientuserid ORDER BY SUM(badyesno) DESC limit 10;" >> 
/tmp/weblog_summary_daily.html
+echo "" >> /tmp/weblog_summary_daily.html
+echo "<p>Top 10 users with the highest scores per uri:</p>" >> 
/tmp/weblog_summary_daily.html
+echo "" >> /tmp/weblog_summary_daily.html
+psql -H -U postgres -d webproxylog -c "SELECT DISTINCT f.clientuserid AS 
User_ID, MAX(f.score) AS Score, t.uri AS Uri from pubweblog AS f INNER JOIN 
(SELECT clientuserid, score, id, uri FROM pubweblog where logdatetime >= 
CURRENT_DATE -interval '$2 days' AND score > 0) as t ON f.clientuserid = 
t.clientuserid and f.score = t.score and f.id = t.id WHERE f.logdatetime >= 
CURRENT_DATE - interval '$2 days' AND f.score > 0 GROUP BY f.clientuserid, t.uri 
ORDER BY MAX(f.score) DESC limit 10;" >> /tmp/weblog_summary_daily.html
+echo "" >> /tmp/weblog_summary_daily.html
+echo "<p>Top 10 users with the largest requests:</p>" >> 
/tmp/weblog_summary_daily.html
+echo "" >> /tmp/weblog_summary_daily.html
+psql -H -U postgres -d webproxylog -c "SELECT DISTINCT f.clientuserid as 
User_ID, ROUND((MAX(f.bytes)/1000000),2) AS Mbytes, t.uri AS Uri FROM pubweblog 
AS f INNER JOIN (SELECT clientuserid, bytes, id, uri FROM pubweblog where 
logdatetime >= CURRENT_DATE -interval '$2 days') as t ON f.clientuserid = 
t.clientuserid and f.bytes = t.bytes and f.id = t.id WHERE logdatetime >= 
CURRENT_DATE - interval '$2 days' GROUP BY f.clientuserid, t.uri ORDER BY Mbytes 
DESC limit 10;" >> /tmp/weblog_summary_daily.html
+echo "" >> /tmp/weblog_summary_daily.html
+echo "<p>Top 10 most prolific browsers:</p>" >> /tmp/weblog_summary_daily.html
+echo "" >> /tmp/weblog_summary_daily.html
+psql -H -U postgres -d webproxylog -c "SELECT clientuserid as User_ID, 
ROUND((SUM(bytes)/1000000),2) as Total_MB FROM pubweblog WHERE logdatetime >= 
CURRENT_DATE - interval '$2 days' GROUP BY clientuserid ORDER BY SUM(bytes) DESC 
limit 10;" >> /tmp/weblog_summary_daily.html
+echo "" >> /tmp/weblog_summary_daily.html
+echo "<br>For more information, visit the </br><a 
href='https://172.20.0.2/'>Resnet Weblog Viewer.</a>" >> 
/tmp/weblog_summary_daily.html
+echo "" >> /tmp/weblog_summary_daily.html
+echo "</body>" >> /tmp/weblog_summary_daily.html
+echo "</html>" >> /tmp/weblog_summary_daily.html
+echo "" >> /tmp/weblog_summary_daily.html
+cat /tmp/weblog_summary_daily.html |grep -v "10 rows" | makemime -a "subject: 
Daily Resnet Weblog Summary - `date +\"%d.%m.%Y\"`" -c text/html | sendmail -S 
10.78.64.4 -f "root@xzprxy01.resnet.zaf.wtbts.net" $1 

diff --git a/weblog_notify_weekly b/weblog_notify_weekly
new file mode 100755
index 0000000..49ab345
--- /dev/null
+++ b/weblog_notify_weekly
@@ -0,0 +1,36 @@
+#!/bin/bash
+echo "<html>" > /tmp/weblog_summary_weekly.html
+echo "<head>" >> /tmp/weblog_summary_weekly.html
+echo '<p><font weight="bold">WEEKLY SUMMARY WEBLOG REPORT FOR RESNET</font>'  
>> /tmp/weblog_summary_weekly.html
+echo "</head>" >> /tmp/weblog_summary_weekly.html
+echo "" >> /tmp/weblog_summary_weekly.html
+echo "<body>" >> /tmp/weblog_summary_weekly.html
+echo "" >> /tmp/weblog_summary_weekly.html
+echo "<p>Total number of records imported:" >> /tmp/weblog_summary_weekly.html
+echo -e "`psql -t -U postgres -d webproxylog -c \"SELECT COUNT(*) FROM 
pubweblog WHERE logdatetime >= CURRENT_DATE - interval '$2 days';\"`</p>"  >> 
/tmp/weblog_summary_weekly.html
+echo "" >> /tmp/weblog_summary_weekly.html
+echo "<p>Total number of records with score > 0 imported:" >> 
/tmp/weblog_summary_weekly.html
+echo -e "`psql -t -U postgres -d webproxylog -c \"SELECT COUNT(*) FROM 
pubweblog WHERE score > 0 AND logdatetime >= CURRENT_DATE - interval '$2 days' 
AND score > 0;\"`</p>" >> /tmp/weblog_summary_weekly.html
+echo "" >> /tmp/weblog_summary_weekly.html
+echo "<p>Top 10 users with the highest number of suspect records:</p>" >> 
/tmp/weblog_summary_weekly.html
+echo "" >> /tmp/weblog_summary_weekly.html
+psql -H -U postgres -d webproxylog -c "SELECT clientuserid as User_ID, 
SUM(badyesno) AS Total_Suspect, MAX(score) as Highest_Score FROM pubweblog WHERE 
score > 0 and logdatetime >= CURRENT_DATE - interval '$2 days' GROUP BY 
clientuserid ORDER BY SUM(badyesno) DESC limit 10;" >> 
/tmp/weblog_summary_weekly.html
+echo "" >> /tmp/weblog_summary_weekly.html
+echo "<p>Top 10 users with the highest scores per uri:</p>" >> 
/tmp/weblog_summary_weekly.html
+echo "" >> /tmp/weblog_summary_weekly.html
+psql -H -U postgres -d webproxylog -c "SELECT DISTINCT f.clientuserid AS 
User_ID, MAX(f.score) AS Score, t.uri AS Uri from pubweblog AS f INNER JOIN 
(SELECT clientuserid, score, id, uri FROM pubweblog where logdatetime >= 
CURRENT_DATE -interval '$2 days' AND score > 0) as t ON f.clientuserid = 
t.clientuserid and f.score = t.score and f.id = t.id WHERE f.logdatetime >= 
CURRENT_DATE - interval '$2 days' AND f.score > 0 GROUP BY f.clientuserid, t.uri 
ORDER BY MAX(f.score) DESC limit 10;" >> /tmp/weblog_summary_weekly.html
+echo "" >> /tmp/weblog_summary_weekly.html
+echo "<p>Top 10 users with the largest requests:</p>" >> 
/tmp/weblog_summary_weekly.html
+echo "" >> /tmp/weblog_summary_weekly.html
+psql -H -U postgres -d webproxylog -c "SELECT DISTINCT f.clientuserid as 
User_ID, ROUND((MAX(f.bytes)/1000000),2) AS Mbytes, t.uri AS Uri FROM pubweblog 
AS f INNER JOIN (SELECT clientuserid, bytes, id, uri FROM pubweblog where 
logdatetime >= CURRENT_DATE -interval '$2 days') as t ON f.clientuserid = 
t.clientuserid and f.bytes = t.bytes and f.id = t.id WHERE logdatetime >= 
CURRENT_DATE - interval '$2 days' GROUP BY f.clientuserid, t.uri ORDER BY Mbytes 
DESC limit 10;" >> /tmp/weblog_summary_weekly.html
+echo "" >> /tmp/weblog_summary_weekly.html
+echo "<p>Top 10 most prolific browsers:</p>" >> /tmp/weblog_summary_weekly.html
+echo "" >> /tmp/weblog_summary_weekly.html
+psql -H -U postgres -d webproxylog -c "SELECT clientuserid as User_ID, 
ROUND((SUM(bytes)/1000000),2) as Total_MB FROM pubweblog WHERE logdatetime >= 
CURRENT_DATE - interval '$2 days' GROUP BY clientuserid ORDER BY SUM(bytes) DESC 
limit 10;" >> /tmp/weblog_summary_weekly.html
+echo "" >> /tmp/weblog_summary_weekly.html
+echo "<br>For more information, visit the </br><a 
href='https://172.20.0.2/'>Resnet Weblog Viewer.</a>" >> 
/tmp/weblog_summary_weekly.html
+echo "" >> /tmp/weblog_summary_weekly.html
+echo "</body>" >> /tmp/weblog_summary_weekly.html
+echo "</html>" >> /tmp/weblog_summary_weekly.html
+echo "" >> /tmp/weblog_summary_weekly.html
+cat /tmp/weblog_summary_weekly.html |grep -v "10 rows" | makemime -a "subject: 
Weekly Resnet Weblog Summary - `date +\"%d.%m.%Y\"`" -c text/html | sendmail -S 
10.78.64.4 -f "root@xzprxy01.resnet.zaf.wtbts.net" $1 

-- 
1.7.4.1



---
Unsubscribe:  alpine-devel+unsubscribe@lists.alpinelinux.org
Help:         alpine-devel+help@lists.alpinelinux.org
---


      


---
Unsubscribe:  alpine-devel+unsubscribe@lists.alpinelinux.org
Help:         alpine-devel+help@lists.alpinelinux.org
---
Reply to thread Export thread (mbox)