]> _ Git - cubeextranet.git/commitdiff
(no commit message)
authorvincent@cubedesigners.com <vincent@cubedesigners.com@f5622870-0f3c-0410-866d-9cb505b7a8ef>
Wed, 3 Sep 2014 14:27:33 +0000 (14:27 +0000)
committervincent@cubedesigners.com <vincent@cubedesigners.com@f5622870-0f3c-0410-866d-9cb505b7a8ef>
Wed, 3 Sep 2014 14:27:33 +0000 (14:27 +0000)
fluidbook/compile/_js/esapi.js [new file with mode: 0644]
fluidbook/compile/_js/fluidbook.js
fluidbook/compile/_js/log4js-lib.js [new file with mode: 0644]
fluidbook/compile/_js/log4js.js [new file with mode: 0644]
fluidbook/compile/_js/resources/Base.esapi.properties.js [new file with mode: 0644]
fluidbook/compile/_js/swfaddress.js
inc/ws/Util/packager/class.ws.packager.html.php
inc/ws/Util/packager/class.ws.packager.php

diff --git a/fluidbook/compile/_js/esapi.js b/fluidbook/compile/_js/esapi.js
new file mode 100644 (file)
index 0000000..3447881
--- /dev/null
@@ -0,0 +1,2953 @@
+/*
+ * OWASP Enterprise Security API (ESAPI)
+ *
+ * This file is part of the Open Web Application Security Project (OWASP)
+ * Enterprise Security API (ESAPI) project. For details, please see
+ * <a href="http://www.owasp.org/index.php/ESAPI">http://www.owasp.org/index.php/ESAPI</a>.
+ *
+ * Copyright (c) 2008 - The OWASP Foundation
+ *
+ * The ESAPI is published by OWASP under the BSD license. You should read and accept the
+ * LICENSE before you use, modify, and/or redistribute this software.
+ */
+
+
+// Utility and Core API Methods
+var $namespace = function(name, separator, container){
+  var ns = name.split(separator || '.'),
+    o = container || window,
+    i,
+    len;
+  for(i = 0, len = ns.length; i < len; i++){
+    o = o[ns[i]] = o[ns[i]] || {};
+  }
+  return o;
+};
+
+var $type = function( oVar, oType ) {
+    if ( !oVar instanceof oType ) {
+        throw new SyntaxError();
+    }
+};
+
+if (!$) {
+    var $ = function( sElementID ) {
+        return document.getElementById( sElementID );
+    };
+}
+
+if (!Array.prototype.each) {
+    Array.prototype.each = function(fIterator) {
+        if (typeof fIterator != 'function') {
+            throw 'Illegal Argument for Array.each';
+        }
+
+        for (var i = 0; i < this.length; i ++) {
+            fIterator(this[i]);
+        }
+    };
+}
+
+if (!Array.prototype.contains) {
+    Array.prototype.contains = function(srch) {
+        var found = false;
+        this.each(function(e) {
+            if ( ( srch.equals && srch.equals(e) ) || e == srch) {
+                found = true;
+                return;
+            }
+        });
+        return found;
+    };
+}
+
+if (!Array.prototype.containsKey) {
+    Array.prototype.containsKey = function(srch) {
+        for ( var key in this ) {
+            if ( key.toLowerCase() == srch.toLowerCase() ) {
+                return true;
+            }
+        }
+        return false;
+    };
+}
+
+if (!Array.prototype.getCaseInsensitive) {
+    Array.prototype.getCaseInsensitive = function(key) {
+        for (var k in this) {
+            if (k.toLowerCase() == key.toLowerCase()) {
+                return this[k];
+            }
+        }
+        return null;
+    };
+}
+
+if (!String.prototype.charCodeAt) {
+    String.prototype.charCodeAt = function( idx ) {
+        var c = this.charAt(idx);
+        for ( var i=0;i<65536;i++) {
+            var s = String.fromCharCode(i);
+            if ( s == c ) { return i; }
+        }
+        return 0;
+    };
+}
+             
+if (!String.prototype.endsWith) {
+    String.prototype.endsWith = function( test ) {
+        return this.substr( ( this.length - test.length ), test.length ) == test;
+    };
+}
+
+// Declare Core Exceptions
+if ( !Exception ) {
+    var Exception = function( sMsg, oException ) {
+        this.cause = oException;
+        this.errorMessage = sMsg;
+    };
+
+    Exception.prototype = Error.prototype;
+
+    Exception.prototype.getCause = function() { return this.cause; };
+
+    Exception.prototype.getMessage = function() { return this.message; };
+
+    /**
+     * This method creates the stacktrace for the Exception only when it is called the first time and
+     * caches it for access after that. Since building a stacktrace is a fairly expensive process, we
+     * only want to do it if it is called.
+     */
+    Exception.prototype.getStackTrace = function() {
+        if ( this.callstack ) {
+            return this.callstack;
+        }
+
+        if ( this.stack ) { // Mozilla
+            var lines = stack.split("\n");
+            for ( var i=0, len=lines.length; i<len; i ++ ) {
+                if ( lines[i].match( /^\s*[A-Za-z0-9\=+\$]+\(/ ) ) {
+                    this.callstack.push(lines[i]);
+                }
+            }
+            this.callstack.shift();
+            return this.callstack;
+        }
+        else if ( window.opera && this.message ) { // Opera
+            var lines = this.message.split('\n');
+            for ( var i=0, len=lines.length; i<len; i++ ) {
+                if ( lines[i].match( /^\s*[A-Za-z0-9\=+\$]+\(/ ) ) {
+                    var entry = lines[i];
+                    if ( lines[i+1] ) {
+                        entry += " at " + lines[i+1];
+                        i++;
+                    }
+                    this.callstack.push(entry);
+                }
+            }
+            this.callstack.shift();
+            return this.callstack;
+        }
+        else { // IE and Safari
+            var currentFunction = arguments.callee.caller;
+            while ( currentFunction ) {
+                var fn = currentFunction.toString();
+                var fname = fn.substring(fn.indexOf("function")+8,fn.indexOf("(")) || "anonymous";
+                this.callstack.push(fname);
+                currentFunction = currentFunction.caller;
+            }
+            return this.callstack;
+        }
+    };
+
+    Exception.prototype.printStackTrace = function( writer ) {
+        var out = this.getMessage() + "|||" + this.getStackTrace().join( "|||" );
+
+        if ( this.cause ) {
+            if ( this.cause.printStackTrace ) {
+                out += "||||||Caused by " + this.cause.printStackTrace().replace( "\n", "|||" );
+            }
+        }
+
+        if ( !writer ) {
+            return writer.replace( "|||", "\n" );
+        } else if ( writer.value ) {
+            writer.value = out.replace( "|||", "\n" );
+        } else if ( writer.writeln ) {
+            writer.writeln( out.replace( "|||", "\n" ) );
+        } else if ( writer.innerHTML ) {
+            writer.innerHTML = out.replace( "|||", "<br/>" );
+        } else if ( writer.innerText ) {
+            writer.innerText = out.replace( "|||", "<br/>" );
+        } else if ( writer.append ) {
+            writer.append( out.replace( "|||", "\n" ) );
+        } else if ( writer instanceof Function ) {
+            writer(out.replace( "|||", "\n" ) );
+        }
+    };
+}
+
+if ( !RuntimeException ) {
+    var RuntimeException = Exception;
+}
+
+if ( !IllegalArgumentException ) {
+    var IllegalArgumentException = Exception;
+}
+
+if ( !DateFormat ) {
+    // Based on http://jacwright.com/projects/javascript/date_format
+    var DateFormat = function( sFmt ) {
+
+        var fmt = sFmt;
+
+        var replaceChars = {
+            longMonths: [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ],
+            shortMonths: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ],
+            longDays: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ],
+            shortDays: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ],
+
+            // Day
+            d: function(date) { return (date.getDate() < 10 ? '0' : '') + date.getDate(); },
+            D: function(date) { return replaceChars.shortDays[date.getDay()]; },
+            j: function(date) { return date.getDate(); },
+            l: function(date) { return replaceChars.longDays[date.getDay()]; },
+            N: function(date) { return date.getDay() + 1; },
+            S: function(date) { return (date.getDate() % 10 == 1 && date.getDate() != 11 ? 'st' : (date.getDate() % 10 == 2 && date.getDate() != 12 ? 'nd' : (date.getDate() % 10 == 3 && date.getDate() != 13 ? 'rd' : 'th'))); },
+            w: function(date) { return date.getDay(); },
+            z: function(date) { return "Not Yet Supported"; },
+            // Week
+            W: function(date) { return "Not Yet Supported"; },
+            // Month
+            F: function(date) { return replaceChars.longMonths[date.getMonth()]; },
+            m: function(date) { return (date.getMonth() < 9 ? '0' : '') + (date.getMonth() + 1); },
+            M: function(date) { return replaceChars.shortMonths[date.getMonth()]; },
+            n: function(date) { return date.getMonth() + 1; },
+            t: function(date) { return "Not Yet Supported"; },
+            // Year
+            L: function(date) { return (((date.getFullYear()%4==0)&&(date.getFullYear()%100 != 0)) || (date.getFullYear()%400==0)) ? '1' : '0'; },
+            o: function(date) { return "Not Supported"; },
+            Y: function(date) { return date.getFullYear(); },
+            y: function(date) { return ('' + date.getFullYear()).substr(2); },
+            // Time
+            a: function(date) { return date.getHours() < 12 ? 'am' : 'pm'; },
+            A: function(date) { return date.getHours() < 12 ? 'AM' : 'PM'; },
+            B: function(date) { return "Not Yet Supported"; },
+            g: function(date) { return date.getHours() % 12 || 12; },
+            G: function(date) { return date.getHours(); },
+            h: function(date) { return ((date.getHours() % 12 || 12) < 10 ? '0' : '') + (date.getHours() % 12 || 12); },
+            H: function(date) { return (date.getHours() < 10 ? '0' : '') + date.getHours(); },
+            i: function(date) { return (date.getMinutes() < 10 ? '0' : '') + date.getMinutes(); },
+            s: function(date) { return (date.getSeconds() < 10 ? '0' : '') + date.getSeconds(); },
+            // Timezone
+            e: function(date) { return "Not Yet Supported"; },
+            I: function(date) { return "Not Supported"; },
+            O: function(date) { return (-date.getTimezoneOffset() < 0 ? '-' : '+') + (Math.abs(date.getTimezoneOffset() / 60) < 10 ? '0' : '') + (Math.abs(date.getTimezoneOffset() / 60)) + '00'; },
+            P: function(date) { return (-date.getTimezoneOffset() < 0 ? '-' : '+') + (Math.abs(date.getTimezoneOffset() / 60) < 10 ? '0' : '') + (Math.abs(date.getTimezoneOffset() / 60)) + ':' + (Math.abs(date.getTimezoneOffset() % 60) < 10 ? '0' : '') + (Math.abs(date.getTimezoneOffset() % 60)); },
+            T: function(date) { var m = date.getMonth(); date.setMonth(0); var result = date.toTimeString().replace(/^.+ \(?([^\)]+)\)?$/, '$1'); date.setMonth(m); return result;},
+            Z: function(date) { return -date.getTimezoneOffset() * 60; },
+            // Full Date/Time
+            c: function(date) { return date.format("Y-m-d") + "T" + date.format("H:i:sP"); },
+            r: function(date) { return date.toString(); },
+            U: function(date) { return date.getTime() / 1000; }
+        };
+
+
+        return {
+            format: function(oDate) {
+                var out = '';
+                for(var i=0;i<fmt.length;i++) {
+                    var c = fmt.charAt(i);
+                    if ( replaceChars[c] ) {
+                        out += replaceChars[c].call(oDate);
+                    } else {
+                        out += c;
+                    }
+                }
+                return out;
+            }
+        };
+    };
+
+    DateFormat.getDateInstance = function() {
+        return new DateFormat("M/d/y h:i a");
+    };
+}
+
+$namespace('org.owasp.esapi');
+
+org.owasp.esapi.ESAPI = function( oProperties ) {
+    var _properties = oProperties;
+
+    if ( !_properties ) throw new RuntimeException("Configuration Error - Unable to load $ESAPI_Properties Object");
+
+    var _encoder = null;
+    var _validator = null;
+    var _logFactory = null;
+    var _resourceBundle = null;
+    var _httputilities = null;
+
+    return {
+        properties: _properties,
+
+        encoder: function() {
+            if (!_encoder) {
+                if (!_properties.encoder.Implementation) throw new RuntimeException('Configuration Error - $ESAPI.properties.encoder.Implementation object not found.');
+                _encoder = new _properties.encoder.Implementation();
+            }
+            return _encoder;
+        },
+
+        logFactory: function() {
+            if ( !_logFactory ) {
+                if (!_properties.logging.Implementation) throw new RuntimeException('Configuration Error - $ESAPI.properties.logging.Implementation object not found.');
+                _logFactory = new _properties.logging.Implementation();
+            }
+            return _logFactory;
+        },
+
+        logger: function(sModuleName) {
+            return this.logFactory().getLogger(sModuleName);
+        },
+
+        locale: function() {
+            return org.owasp.esapi.i18n.Locale.getLocale( _properties.localization.DefaultLocale );
+        },
+
+        resourceBundle: function() {
+            if (!_resourceBundle) {
+                if(!_properties.localization.StandardResourceBundle) throw new RuntimeException("Configuration Error - $ESAPI.properties.localization.StandardResourceBundle not found.");
+                _resourceBundle = new org.owasp.esapi.i18n.ObjectResourceBundle( _properties.localization.StandardResourceBundle );
+            }
+            return _resourceBundle;
+        },
+
+        validator: function() {
+            if (!_validator) {
+                if (!_properties.validation.Implementation) throw new RuntimeException('Configuration Error - $ESAPI.properties.validation.Implementation object not found.');
+                _validator = new _properties.validation.Implementation();
+            }
+            return _validator;
+        },
+
+        httpUtilities: function() {
+            if (!_httputilities) _httputilities = new org.owasp.esapi.HTTPUtilities();
+            return _httputilities;
+        }
+    };
+};
+
+var $ESAPI = null;
+
+org.owasp.esapi.ESAPI.initialize = function() {
+    $ESAPI = new org.owasp.esapi.ESAPI( Base.esapi.properties );
+};
+
+$namespace('org.owasp.esapi');
+
+org.owasp.esapi.Encoder = function() {
+
+}
+
+$namespace('org.owasp.esapi');
+
+org.owasp.esapi.EncoderConstants = {
+    CHAR_LOWERS: [ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' ],
+    CHAR_UPPERS: [ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' ],
+    CHAR_DIGITS: [ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' ],
+    CHAR_SPECIALS: [ '!', '$', '*', '+', '-', '.', '=', '?', '@', '^', '_', '|', '~' ],
+    CHAR_LETTERS: [ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' ],
+    CHAR_ALNUM: [ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' ]
+};
+
+$namespace('org.owasp.esapi');
+
+org.owasp.esapi.EnterpriseSecurityException = function(sUserMessage, sLogMessage, oException) {
+    var _logMessage = sLogMessage;
+    var _super = new Exception(sUserMessage, oException);
+
+    return {
+        getMessage: _super.getMessage,
+        getUserMessage: _super.getMessage,
+        getLogMessage: function() {
+            return _logMessage;
+        },
+        getStackTrace: _super.getStackTrace,
+        printStackTrace: _super.printStackTrace
+    };
+};
+
+$namespace('org.owasp.esapi');
+
+org.owasp.esapi.HTTPUtilities = function() {
+    var log = $ESAPI.logger("HTTPUtilities");
+    var resourceBundle = $ESAPI.resourceBundle();
+    var EventType = org.owasp.esapi.Logger.EventType;
+
+    return {
+        addCookie: function( oCookie ) {
+            $type(oCookie,org.owasp.esapi.net.Cookie);
+
+            if ( window.top.location.protocol != 'http:' || window.top.location.protocol != 'https:' )
+                throw new RuntimeException(resourceBundle.getString( "HTTPUtilities.Cookie.Protocol", {"protocol":window.top.location.protocol}));
+
+            var name = oCookie.getName(),
+                value = oCookie.getValue(),
+                maxAge = oCookie.getMaxAge(),
+                domain = oCookie.getDomain(),
+                path = oCookie.getPath(),
+                secure = oCookie.getSecure();
+
+            var validationErrors = new org.owasp.esapi.ValidationErrorList();
+            var cookieName = $ESAPI.validator().getValidInput("cookie name", name, "HttpCookieName", 50, false, validationErrors );
+            var cookieValue = $ESAPI.validator().getValidInput("cookie value", value, "HttpCookieValue", 5000, false, validationErrors );
+
+            if (validationErrors.size() == 0) {
+                var header = name+'='+escape(value);
+                header += maxAge?";expires=" + ( new Date( ( new Date() ).getTime() + ( 1000 * maxAge ) ).toGMTString() ) : "";
+                header += path?";path="+path:"";
+                header += domain?";domain="+domain:"";
+                header += secure||$ESAPI.properties.httputilities.cookies.ForceSecure?";secure":"";
+                document.cookie=header;
+            }
+            else
+            {
+                log.warning(EventType.SECURITY_FAILURE, resourceBundle.getString("HTTPUtilities.Cookie.UnsafeData", { 'name':name, 'value':value } ) );
+            }
+        },
+
+        /**
+         * Returns a {@link org.owasp.esapi.net.Cookie} containing the name and value of the requested cookie.
+         *
+         * IMPORTANT: The value of the cookie is not sanitized at this level. It is the responsibility of the calling
+         * code to sanitize the value for proper output encoding prior to using it.
+         *
+         * @param sName {String} The name of the cookie to retrieve
+         * @return {org.owasp.esapi.net.Cookie}
+         */
+        getCookie: function(sName) {
+            var cookieJar = document.cookie.split("; ");
+            for(var i=0,len=cookieJar.length;i<len;i++) {
+                var cookie = cookieJar[i].split("=");
+                if (cookie[0] == escape(sName)) {
+                    return new org.owasp.esapi.net.Cookie( sName, cookie[1]?unescape(cookie[1]):'' );
+                }
+            }
+            return null;
+        },
+
+        /**
+         * Will attempt to kill any cookies associated with the current request (domain,path,secure). If a cookie cannot
+         * be deleted, a RuntimeException will be thrown.
+         *
+         * @throws RuntimeException if one of the cookies cannot be deleted.
+         */
+        killAllCookies: function() {
+            var cookieJar = document.cookie.split("; ");
+            for(var i=0,len=cookieJar.length;i<len;i++) {
+                var cookie = cookieJar[i].split("=");
+                var name = unescape(cookie[0]);
+                // RuntimeException will bubble through if the cookie cannot be deleted
+                if (!this.killCookie(name)) {
+                    // Something is wrong - cookieJar contains a cookie that is inaccesible using getCookie
+                    throw new RuntimeException(resourceBundle.getString("HTTPUtilities.Cookie.CantKill", {"name":name}));
+                }
+            }
+        },
+
+        /**
+         * Will kill a single cookie. If that cookie cannot be deleted a RuntimeException will be thrown
+         * @param sName {String} The name of the cookie
+         */
+        killCookie: function(sName) {
+            var c = this.getCookie(sName);
+            if ( c ) {
+                c.setMaxAge( -10 );
+                this.addCookie(c);
+                if (this.getCookie(sName)) {
+                    throw new RuntimeException(resourceBundle.getString("HTTPUtilities.Cookie.CantKill", {"name":sName}));
+                }
+                return true;
+            }
+            return false;
+        },
+
+        /**
+         * This only works for GET parameters and is meerly a convenience method for accessing that information if need be
+         * @param sName {String} The name of the parameter to retrieve
+         */
+        getRequestParameter: function( sName ) {
+            var url = window.top.location.search.substring(1);
+            var pIndex = url.indexOf(sName);
+            if (pIndex<0) return null;
+            pIndex=pIndex+sName.length;
+            var lastIndex=url.indexOf("&",pIndex);
+            if (lastIndex<0) lastIndex=url.length;
+            return unescape(url.substring(pIndex,lastIndex));
+        }
+    };
+};
+
+$namespace('org.owasp.esapi');
+
+org.owasp.esapi.IntrusionException = function(sUserMessage, sLogMessage, oCause) {
+    var _super = new org.owasp.esapi.EnterpriseSecurityException(sUserMessage, sLogMessage, oCause);
+
+    return {
+        getMessage: _super.getMessage,
+        getUserMessage: _super.getMessage,
+        getLogMessage: _super.getLogMessage,
+        getStackTrace: _super.getStackTrace,
+        printStackTrace: _super.printStackTrace
+    };
+};
+
+$namespace('org.owasp.esapi');
+
+org.owasp.esapi.LogFactory = function() {
+    return {
+        getLogger: false
+    };
+}
+
+$namespace('org.owasp.esapi');
+
+org.owasp.esapi.Logger = function() {
+    return {
+        setLevel: false,
+        fatal: false,
+        error: false,
+        isErrorEnabled: false,
+        warning: false,
+        isWarningEnabled: false,
+        info: false,
+        isInfoEnabled: false,
+        debug: false,
+        isDebugEnabled: false,
+        trace: false,
+        isTraceEnabled: false
+    };
+};
+
+org.owasp.esapi.Logger.EventType = function( sName, bNewSuccess ) {
+    var type = sName;
+    var success = bNewSuccess;
+
+    return {
+        isSuccess: function() {
+            return success;
+        },
+
+        toString: function() {
+            return type;
+        }
+    };
+};
+
+with(org.owasp.esapi.Logger) {
+
+    EventType.SECURITY_SUCCESS = new EventType( "SECURITY SUCCESS", true );
+    EventType.SECURITY_FAILURE = new EventType( "SECURITY FAILURE", false );
+    EventType.EVENT_SUCCESS    = new EventType( "EVENT SUCCESS", true );
+    EventType.EVENT_FAILURE    = new EventType( "EVENT FAILURE", false );
+
+    OFF = Number.MAX_VALUE;
+    FATAL = 1000;
+    ERROR = 800;
+    WARNING = 600;
+    INFO = 400;
+    DEBUG = 200;
+    TRACE = 100;
+    ALL = Number.MIN_VALUE;
+}
+
+$namespace('org.owasp.esapi');
+
+org.owasp.esapi.PreparedString = function(sTemplate, oCodec, sParameterCharacter) {
+    // Private Scope
+    var parts = [];
+    var parameters = [];
+
+    function split(s) {
+        var idx = 0, pcount = 0;
+        for (var i = 0; i < s.length; i ++) {
+            if (s.charAt(i) == sParameterCharacter) {
+                pcount ++;
+                parts.push(s.substr(idx, i));
+                idx = i + 1;
+            }
+        }
+        parts.push(s.substr(idx));
+        parameters = new Array(pcount);
+    }
+
+    ;
+
+    if (!sParameterCharacter) {
+        sParameterCharacter = '?';
+    }
+
+    split(sTemplate);
+
+    return {
+        set: function(iIndex, sValue, codec) {
+            if (iIndex < 1 || iIndex > parameters.length) {
+                throw new IllegalArgumentException("Attempt to set parameter: " + iIndex + " on a PreparedString with only " + parameters.length + " placeholders");
+            }
+            if (!codec) {
+                codec = oCodec;
+            }
+            parameters[iIndex - 1] = codec.encode([], sValue);
+        },
+
+        toString: function() {
+            for (var ix = 0; ix < parameters.length; ix ++) {
+                if (parameters[ix] == null) {
+                    throw new RuntimeException("Attempt to render PreparedString without setting parameter " + (ix + 1));
+                }
+            }
+            var out = '', i = 0;
+            for (var p = 0; p < parts.length; p ++) {
+                out += parts[p];
+                if (i < parameters.length) {
+                    out += parameters[i++];
+                }
+            }
+            return out;
+        }
+    };
+};
+
+
+$namespace('org.owasp.esapi');
+
+org.owasp.esapi.ValidationErrorList = function() {
+    var errorList = Array();
+
+    return {
+        addError: function( sContext, oValidationException ) {
+            if ( sContext == null ) throw new RuntimeException( "Context cannot be null: " + oValidationException.getLogMessage(), oValidationException );
+            if ( oValidationException == null ) throw new RuntimeException( "Context (" + sContext + ") - Error cannot be null" );
+            if ( errorList[sContext] ) throw new RuntimeException( "Context (" + sContext + ") already exists. must be unique." );
+            errorList[sContext] = oValidationException;
+        },
+
+        errors: function() {
+            return errorList;
+        },
+
+        isEmpty: function() {
+            return errorList.length == 0;
+        },
+
+        size: function() {
+            return errorList.length;
+        }
+    };
+};
+
+
+$namespace('org.owasp.esapi');
+
+org.owasp.esapi.ValidationRule = function() {
+    return {
+        getValid: false,
+        setAllowNull: false,
+        getTypeName: false,
+        setTypeName: false,
+        setEncoder: false,
+        assertValid: false,
+        getSafe: false,
+        isValid: false,
+        whitelist: false
+    };
+};
+
+
+$namespace('org.owasp.esapi');
+
+org.owasp.esapi.Validator = function() {
+    return {
+        addRule: false,
+        getRule: false,
+        getValidInput: false,
+        isValidDate: false,
+        getValidDate: false,
+        isValidSafeHTML: false,
+        getValidSafeHTML: false,
+        isValidCreditCard: false,
+        getValidCreditCard: false,
+        isValidFilename: false,
+        getValidFilename: false,
+        isValidNumber: false,
+        getValidNumber: false,
+        isValidPrintable: false,
+        getValidPrintable: false
+    };
+};
+
+
+$namespace('org.owasp.esapi.codecs.Base64');
+
+org.owasp.esapi.codecs.Base64 = {
+    _keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
+
+    encode: function(sInput) {
+        if (!sInput) {
+            return null;
+        }
+
+        var out = '';
+        var ch1,ch2,ch3,enc1,enc2,enc3,enc4;
+        var i = 0;
+
+        var input = org.owasp.esapi.codecs.UTF8.encode(sInput);
+
+        while (i < input.length) {
+            ch1 = input.charCodeAt(i++);
+            ch2 = input.charCodeAt(i++);
+            ch3 = input.charCodeAt(i++);
+
+            enc1 = ch1 >> 2;
+            enc2 = ((ch1 & 3) << 4) | (ch2 >> 4);
+            enc3 = ((ch2 & 15) << 2) | (ch3 >> 6);
+            enc4 = ch3 & 63;
+
+            if (isNaN(ch2)) {
+                enc3 = enc4 = 64;
+            }
+            else if (isNaN(ch3)) {
+                enc4 = 64;
+            }
+
+            out += this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) + this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
+        }
+
+        return out;
+    },
+
+    decode: function(sInput) {
+        if (!sInput) {
+            return null;
+        }
+
+        var out = '';
+        var ch1, ch2, ch3, enc1, enc2, enc3, enc4;
+        var i = 0;
+
+        var input = sInput.replace(/[^A-Za-z0-9\+\/\=]/g, "");
+
+        while (i < input.length) {
+            enc1 = this._keyStr.indexOf(input.charAt(i++));
+            enc2 = this._keyStr.indexOf(input.charAt(i++));
+            enc3 = this._keyStr.indexOf(input.charAt(i++));
+            enc4 = this._keyStr.indexOf(input.charAt(i++));
+
+            ch1 = (enc1 << 2) | (enc2 >> 4);
+            ch2 = ((enc2 & 15) << 4) | (enc3 >> 2);
+            ch3 = ((enc3 & 3) << 6) | enc4;
+
+            out += String.fromCharCode(ch1);
+            if (enc3 != 64) {
+                out += String.fromCharCode(ch2);
+            }
+            if (enc4 != 64) {
+                out += String.fromCharCode(ch3);
+            }
+        }
+
+        out = org.owasp.esapi.codecs.UTF8.decode(out);
+        return out;
+    }
+};
+
+
+$namespace('org.owasp.esapi.codecs');
+
+org.owasp.esapi.codecs.CSSCodec = function() {
+    var _super = new org.owasp.esapi.codecs.Codec();
+
+    return {
+        encode: _super.encode,
+
+        decode: _super.decode,
+
+        encodeCharacter: function(aImmune, c) {
+            if (aImmune.contains(c)) {
+                return c;
+            }
+
+            var hex = org.owasp.esapi.codecs.Codec.getHexForNonAlphanumeric(c);
+            if (hex == null) {
+                return c;
+            }
+
+            return "\\" + hex + " ";
+        },
+
+        decodeCharacter: function(oPushbackString) {
+            oPushbackString.mark();
+            var first = oPushbackString.next();
+            if (first == null) {
+                oPushbackString.reset();
+                return null;
+            }
+
+            if (first != '\\') {
+                oPushbackString.reset();
+                return null;
+            }
+
+            var second = oPushbackString.next();
+            if (second == null) {
+                oPushbackString.reset();
+                return null;
+            }
+
+            if (oPushbackString.isHexDigit(second)) {
+                var out = second;
+                for (var i = 0; i < 6; i ++) {
+                    var c = oPushbackString.next();
+                    if (c == null || c.charCodeAt(0) == 0x20) {
+                        break;
+                    }
+                    if (oPushbackString.isHexDigit(c)) {
+                        out += c;
+                    } else {
+                        input.pushback(c);
+                        break;
+                    }
+                }
+
+                try {
+                    var n = parseInt(out, 16);
+                    return String.fromCharCode(n);
+                } catch (e) {
+                    oPushbackString.reset();
+                    return null;
+                }
+            }
+
+            return second;
+        }
+    };
+};
+
+
+$namespace('org.owasp.esapi.codecs');
+
+org.owasp.esapi.codecs.Codec = function() {
+    return {
+        /**
+         * Encode a String so that it can be safely used in a specific context.
+         *
+         * @param aImmune
+         *              array of immune characters
+         * @param sInput
+         *              the String to encode
+         * @return the encoded String
+         */
+        encode: function(aImmune, sInput) {
+            var out = '';
+            for (var i = 0; i < sInput.length; i ++) {
+                var c = sInput.charAt(i);
+                out += this.encodeCharacter(aImmune, c);
+            }
+            return out;
+        },
+
+        /**
+         * Default implementation that should be overridden in specific codecs.
+         *
+         * @param aImmune
+         *              array of immune characters
+         * @param c
+         *              the Character to encode
+         * @return
+         *              the encoded Character
+         */
+        encodeCharacter: function(aImmune, c) {
+            return c;
+        },
+
+        /**
+         * Decode a String that was encoded using the encode method in this Class
+         *
+         * @param sInput
+         *              the String to decode
+         * @return
+         *              the decoded String
+         */
+        decode: function(sInput) {
+            var out = '';
+            var pbs = new org.owasp.esapi.codecs.PushbackString(sInput);
+            while (pbs.hasNext()) {
+                var c = this.decodeCharacter(pbs);
+                if (c != null) {
+                    out += c;
+                } else {
+                    out += pbs.next();
+                }
+            }
+            return out;
+        },
+
+        /**
+         * Returns the decoded version of the next character from the input string and advances the
+         * current character in the PushbackString.  If the current character is not encoded, this
+         * method MUST reset the PushbackString.
+         *
+         * @param oPushbackString the Character to decode
+         * @return the decoded Character
+         */
+        decodeCharacter: function(oPushbackString) {
+            return oPushbackString.next();
+        }
+    };
+};
+
+org.owasp.esapi.codecs.Codec.getHexForNonAlphanumeric = function(c) {
+    if (c.charCodeAt(0) < 256) {
+        return org.owasp.esapi.codecs.Codec.hex[c.charCodeAt(0)];
+    }
+    return c.charCodeAt(0).toString(16);
+};
+
+org.owasp.esapi.codecs.Codec.hex = [];
+for ( var c = 0; c < 0xFF; c ++ ) {
+    if ( c >= 0x30 && c <= 0x39 || c>= 0x41 && c <= 0x5A || c >= 0x61 && c <= 0x7A ) {
+        org.owasp.esapi.codecs.Codec.hex[c] = null;
+    } else {
+        org.owasp.esapi.codecs.Codec.hex[c] = c.toString(16);
+    }
+};
+
+var entityToCharacterMap = [];
+entityToCharacterMap["&quot"]        = "34";      /* 34 : quotation mark */
+entityToCharacterMap["&amp"]         = "38";      /* 38 : ampersand */
+entityToCharacterMap["&lt"]          = "60";        /* 60 : less-than sign */
+entityToCharacterMap["&gt"]          = "62";        /* 62 : greater-than sign */
+entityToCharacterMap["&nbsp"]        = "160";      /* 160 : no-break space */
+entityToCharacterMap["&iexcl"]       = "161";     /* 161 : inverted exclamation mark */
+entityToCharacterMap["&cent"]                  = "162";        /* 162  : cent sign */
+entityToCharacterMap["&pound"]                 = "163";        /* 163  : pound sign */
+entityToCharacterMap["&curren"]                        = "164";        /* 164  : currency sign */
+entityToCharacterMap["&yen"]                   = "165";        /* 165  : yen sign */
+entityToCharacterMap["&brvbar"]                        = "166";        /* 166  : broken bar */
+entityToCharacterMap["&sect"]                  = "167";        /* 167  : section sign */
+entityToCharacterMap["&uml"]                   = "168";        /* 168  : diaeresis */
+entityToCharacterMap["&copy"]                  = "169";        /* 169  : copyright sign */
+entityToCharacterMap["&ordf"]                  = "170";        /* 170  : feminine ordinal indicator */
+entityToCharacterMap["&laquo"]          = "171";    /* 171 : left-pointing double angle quotation mark */
+entityToCharacterMap["&not"]                   = "172";        /* 172  : not sign */
+entityToCharacterMap["&shy"]                   = "173";        /* 173  : soft hyphen */
+entityToCharacterMap["&reg"]                   = "174";        /* 174  : registered sign */
+entityToCharacterMap["&macr"]                  = "175";        /* 175  : macron */
+entityToCharacterMap["&deg"]                   = "176";        /* 176  : degree sign */
+entityToCharacterMap["&plusmn"]         = "177";    /* 177 : plus-minus sign */
+entityToCharacterMap["&sup2"]                  = "178";        /* 178  : superscript two */
+entityToCharacterMap["&sup3"]                  = "179";        /* 179  : superscript three */
+entityToCharacterMap["&acute"]                 = "180";        /* 180  : acute accent */
+entityToCharacterMap["&micro"]                 = "181";        /* 181  : micro sign */
+entityToCharacterMap["&para"]                  = "182";        /* 182  : pilcrow sign */
+entityToCharacterMap["&middot"]                        = "183";        /* 183  : middle dot */
+entityToCharacterMap["&cedil"]                 = "184";        /* 184  : cedilla */
+entityToCharacterMap["&sup1"]                  = "185";        /* 185  : superscript one */
+entityToCharacterMap["&ordm"]                  = "186";        /* 186  : masculine ordinal indicator */
+entityToCharacterMap["&raquo"]          = "187";    /* 187 : right-pointing double angle quotation mark */
+entityToCharacterMap["&frac14"]                        = "188";        /* 188  : vulgar fraction one quarter */
+entityToCharacterMap["&frac12"]                        = "189";        /* 189  : vulgar fraction one half */
+entityToCharacterMap["&frac34"]                        = "190";        /* 190  : vulgar fraction three quarters */
+entityToCharacterMap["&iquest"]                        = "191";        /* 191  : inverted question mark */
+entityToCharacterMap["&Agrave"]                        = "192";        /* 192  : Latin capital letter a with grave */
+entityToCharacterMap["&Aacute"]                        = "193";        /* 193  : Latin capital letter a with acute */
+entityToCharacterMap["&Acirc"]                 = "194";        /* 194  : Latin capital letter a with circumflex */
+entityToCharacterMap["&Atilde"]                        = "195";        /* 195  : Latin capital letter a with tilde */
+entityToCharacterMap["&Auml"]                  = "196";        /* 196  : Latin capital letter a with diaeresis */
+entityToCharacterMap["&Aring"]                 = "197";        /* 197  : Latin capital letter a with ring above */
+entityToCharacterMap["&AElig"]                 = "198";        /* 198  : Latin capital letter ae */
+entityToCharacterMap["&Ccedil"]                        = "199";        /* 199  : Latin capital letter c with cedilla */
+entityToCharacterMap["&Egrave"]                        = "200";        /* 200  : Latin capital letter e with grave */
+entityToCharacterMap["&Eacute"]                        = "201";        /* 201  : Latin capital letter e with acute */
+entityToCharacterMap["&Ecirc"]                 = "202";        /* 202  : Latin capital letter e with circumflex */
+entityToCharacterMap["&Euml"]                  = "203";        /* 203  : Latin capital letter e with diaeresis */
+entityToCharacterMap["&Igrave"]                        = "204";        /* 204  : Latin capital letter i with grave */
+entityToCharacterMap["&Iacute"]                        = "205";        /* 205  : Latin capital letter i with acute */
+entityToCharacterMap["&Icirc"]                 = "206";        /* 206  : Latin capital letter i with circumflex */
+entityToCharacterMap["&Iuml"]                  = "207";        /* 207  : Latin capital letter i with diaeresis */
+entityToCharacterMap["&ETH"]                       = "208";    /* 208  : Latin capital letter eth */
+entityToCharacterMap["&Ntilde"]                        = "209";        /* 209  : Latin capital letter n with tilde */
+entityToCharacterMap["&Ograve"]                        = "210";        /* 210  : Latin capital letter o with grave */
+entityToCharacterMap["&Oacute"]                        = "211";        /* 211  : Latin capital letter o with acute */
+entityToCharacterMap["&Ocirc"]           = "212";  /* 212 : Latin capital letter o with circumflex */
+entityToCharacterMap["&Otilde"]                        = "213";         /* 213 : Latin capital letter o with tilde */
+entityToCharacterMap["&Ouml"]                  = "214";         /* 214 : Latin capital letter o with diaeresis */
+entityToCharacterMap["&times"]                 = "215";         /* 215 : multiplication sign */
+entityToCharacterMap["&Oslash"]                        = "216";         /* 216 : Latin capital letter o with stroke */
+entityToCharacterMap["&Ugrave"]                        = "217";         /* 217 : Latin capital letter u with grave */
+entityToCharacterMap["&Uacute"]                        = "218";         /* 218 : Latin capital letter u with acute */
+entityToCharacterMap["&Ucirc"]                 = "219";         /* 219 : Latin capital letter u with circumflex */
+entityToCharacterMap["&Uuml"]                  = "220";         /* 220 : Latin capital letter u with diaeresis */
+entityToCharacterMap["&Yacute"]                        = "221";         /* 221 : Latin capital letter y with acute */
+entityToCharacterMap["&THORN"]                 = "222";         /* 222 : Latin capital letter thorn */
+entityToCharacterMap["&szlig"]           = "223";   /* 223 : Latin small letter sharp s, German Eszett */
+entityToCharacterMap["&agrave"]                        = "224";         /* 224 : Latin small letter a with grave */
+entityToCharacterMap["&aacute"]                        = "225";         /* 225 : Latin small letter a with acute */
+entityToCharacterMap["&acirc"]                 = "226";         /* 226 : Latin small letter a with circumflex */
+entityToCharacterMap["&atilde"]                        = "227";         /* 227 : Latin small letter a with tilde */
+entityToCharacterMap["&auml"]                  = "228";         /* 228 : Latin small letter a with diaeresis */
+entityToCharacterMap["&aring"]                 = "229";         /* 229 : Latin small letter a with ring above */
+entityToCharacterMap["&aelig"]                 = "230";         /* 230 : Latin lowercase ligature ae */
+entityToCharacterMap["&ccedil"]                        = "231";         /* 231 : Latin small letter c with cedilla */
+entityToCharacterMap["&egrave"]                        = "232";         /* 232 : Latin small letter e with grave */
+entityToCharacterMap["&eacute"]                        = "233";         /* 233 : Latin small letter e with acute */
+entityToCharacterMap["&ecirc"]                 = "234";         /* 234 : Latin small letter e with circumflex */
+entityToCharacterMap["&euml"]                  = "235";         /* 235 : Latin small letter e with diaeresis */
+entityToCharacterMap["&igrave"]                        = "236";         /* 236 : Latin small letter i with grave */
+entityToCharacterMap["&iacute"]                        = "237";         /* 237 : Latin small letter i with acute */
+entityToCharacterMap["&icirc"]                 = "238";         /* 238 : Latin small letter i with circumflex */
+entityToCharacterMap["&iuml"]                  = "239";         /* 239 : Latin small letter i with diaeresis */
+entityToCharacterMap["&eth"]                       = "240";     /* 240 : Latin small letter eth */
+entityToCharacterMap["&ntilde"]                        = "241";         /* 241 : Latin small letter n with tilde */
+entityToCharacterMap["&ograve"]                        = "242";         /* 242 : Latin small letter o with grave */
+entityToCharacterMap["&oacute"]                        = "243";         /* 243 : Latin small letter o with acute */
+entityToCharacterMap["&ocirc"]                 = "244";         /* 244 : Latin small letter o with circumflex */
+entityToCharacterMap["&otilde"]                        = "245";         /* 245 : Latin small letter o with tilde */
+entityToCharacterMap["&ouml"]                  = "246";         /* 246 : Latin small letter o with diaeresis */
+entityToCharacterMap["&divide"]                        = "247";         /* 247 : division sign */
+entityToCharacterMap["&oslash"]                        = "248";         /* 248 : Latin small letter o with stroke */
+entityToCharacterMap["&ugrave"]                        = "249";         /* 249 : Latin small letter u with grave */
+entityToCharacterMap["&uacute"]                        = "250";         /* 250 : Latin small letter u with acute */
+entityToCharacterMap["&ucirc"]                 = "251";         /* 251 : Latin small letter u with circumflex */
+entityToCharacterMap["&uuml"]                  = "252";         /* 252 : Latin small letter u with diaeresis */
+entityToCharacterMap["&yacute"]                        = "253";         /* 253 : Latin small letter y with acute */
+entityToCharacterMap["&thorn"]                 = "254";         /* 254 : Latin small letter thorn */
+entityToCharacterMap["&yuml"]                  = "255";         /* 255 : Latin small letter y with diaeresis */
+entityToCharacterMap["&OElig"]                 = "338";         /* 338 : Latin capital ligature oe */
+entityToCharacterMap["&oelig"]                 = "339";         /* 339 : Latin small ligature oe */
+entityToCharacterMap["&Scaron"]                        = "352";         /* 352 : Latin capital letter s with caron */
+entityToCharacterMap["&scaron"]                        = "353";         /* 353 : Latin small letter s with caron */
+entityToCharacterMap["&Yuml"]                  = "376";         /* 376 : Latin capital letter y with diaeresis */
+entityToCharacterMap["&fnof"]                  = "402";         /* 402 : Latin small letter f with hook */
+entityToCharacterMap["&circ"]                  = "710";         /* 710 : modifier letter circumflex accent */
+entityToCharacterMap["&tilde"]                 = "732";         /* 732 : small tilde */
+entityToCharacterMap["&Alpha"]                 = "913";         /* 913 : Greek capital letter alpha */
+entityToCharacterMap["&Beta"]                  = "914";         /* 914 : Greek capital letter beta */
+entityToCharacterMap["&Gamma"]                 = "915";         /* 915 : Greek capital letter gamma */
+entityToCharacterMap["&Delta"]                 = "916";         /* 916 : Greek capital letter delta */
+entityToCharacterMap["&Epsilon"]                       = "917";         /* 917 : Greek capital letter epsilon */
+entityToCharacterMap["&Zeta"]                  = "918";         /* 918 : Greek capital letter zeta */
+entityToCharacterMap["&Eta"]                       = "919";     /* 919 : Greek capital letter eta */
+entityToCharacterMap["&Theta"]                 = "920";         /* 920 : Greek capital letter theta */
+entityToCharacterMap["&Iota"]                  = "921";         /* 921 : Greek capital letter iota */
+entityToCharacterMap["&Kappa"]                 = "922";         /* 922 : Greek capital letter kappa */
+entityToCharacterMap["&Lambda"]                        = "923";         /* 923 : Greek capital letter lambda */
+entityToCharacterMap["&Mu"]                    = "924";         /* 924 : Greek capital letter mu */
+entityToCharacterMap["&Nu"]                    = "925";         /* 925 : Greek capital letter nu */
+entityToCharacterMap["&Xi"]                    = "926";         /* 926 : Greek capital letter xi */
+entityToCharacterMap["&Omicron"]                       = "927";         /* 927 : Greek capital letter omicron */
+entityToCharacterMap["&Pi"]                    = "928";         /* 928 : Greek capital letter pi */
+entityToCharacterMap["&Rho"]                   = "929";         /* 929 : Greek capital letter rho */
+entityToCharacterMap["&Sigma"]                 = "931";         /* 931 : Greek capital letter sigma */
+entityToCharacterMap["&Tau"]                   = "932";         /* 932 : Greek capital letter tau */
+entityToCharacterMap["&Upsilon"]                       = "933";         /* 933 : Greek capital letter upsilon */
+entityToCharacterMap["&Phi"]                   = "934";         /* 934 : Greek capital letter phi */
+entityToCharacterMap["&Chi"]                   = "935";         /* 935 : Greek capital letter chi */
+entityToCharacterMap["&Psi"]                   = "936";         /* 936 : Greek capital letter psi */
+entityToCharacterMap["&Omega"]                 = "937";         /* 937 : Greek capital letter omega */
+entityToCharacterMap["&alpha"]                 = "945";         /* 945 : Greek small letter alpha */
+entityToCharacterMap["&beta"]                  = "946";         /* 946 : Greek small letter beta */
+entityToCharacterMap["&gamma"]                 = "947";         /* 947 : Greek small letter gamma */
+entityToCharacterMap["&delta"]                 = "948";         /* 948 : Greek small letter delta */
+entityToCharacterMap["&epsilon"]                       = "949";         /* 949 : Greek small letter epsilon */
+entityToCharacterMap["&zeta"]                  = "950";         /* 950 : Greek small letter zeta */
+entityToCharacterMap["&eta"]                   = "951";         /* 951 : Greek small letter eta */
+entityToCharacterMap["&theta"]                 = "952";         /* 952 : Greek small letter theta */
+entityToCharacterMap["&iota"]                  = "953";         /* 953 : Greek small letter iota */
+entityToCharacterMap["&kappa"]                 = "954";         /* 954 : Greek small letter kappa */
+entityToCharacterMap["&lambda"]                        = "955";         /* 955 : Greek small letter lambda */
+entityToCharacterMap["&mu"]                    = "956";         /* 956 : Greek small letter mu */
+entityToCharacterMap["&nu"]                    = "957";         /* 957 : Greek small letter nu */
+entityToCharacterMap["&xi"]                    = "958";         /* 958 : Greek small letter xi */
+entityToCharacterMap["&omicron"]                       = "959";         /* 959 : Greek small letter omicron */
+entityToCharacterMap["&pi"]                    = "960";         /* 960 : Greek small letter pi */
+entityToCharacterMap["&rho"]                   = "961";         /* 961 : Greek small letter rho */
+entityToCharacterMap["&sigmaf"]                        = "962";         /* 962 : Greek small letter final sigma */
+entityToCharacterMap["&sigma"]                 = "963";         /* 963 : Greek small letter sigma */
+entityToCharacterMap["&tau"]                   = "964";         /* 964 : Greek small letter tau */
+entityToCharacterMap["&upsilon"]                       = "965";         /* 965 : Greek small letter upsilon */
+entityToCharacterMap["&phi"]                   = "966";         /* 966 : Greek small letter phi */
+entityToCharacterMap["&chi"]                   = "967";         /* 967 : Greek small letter chi */
+entityToCharacterMap["&psi"]                   = "968";         /* 968 : Greek small letter psi */
+entityToCharacterMap["&omega"]                 = "969";         /* 969 : Greek small letter omega */
+entityToCharacterMap["&thetasym"]                      = "977";         /* 977 : Greek theta symbol */
+entityToCharacterMap["&upsih"]                 = "978";         /* 978 : Greek upsilon with hook symbol */
+entityToCharacterMap["&piv"]                   = "982";         /* 982 : Greek pi symbol */
+entityToCharacterMap["&ensp"]                  = "8194";        /* 8194 : en space */
+entityToCharacterMap["&emsp"]                  = "8195";        /* 8195 : em space */
+entityToCharacterMap["&thinsp"]                        = "8201";        /* 8201 : thin space */
+entityToCharacterMap["&zwnj"]            = "8204"; /* 8204 : zero width non-joiner */
+entityToCharacterMap["&zwj"]                   = "8205";        /* 8205 : zero width joiner */
+entityToCharacterMap["&lrm"]             = "8206"; /* 8206 : left-to-right mark */
+entityToCharacterMap["&rlm"]             = "8207"; /* 8207 : right-to-left mark */
+entityToCharacterMap["&ndash"]                 = "8211";        /* 8211 : en dash */
+entityToCharacterMap["&mdash"]                 = "8212";        /* 8212 : em dash */
+entityToCharacterMap["&lsquo"]                 = "8216";        /* 8216 : left single quotation mark */
+entityToCharacterMap["&rsquo"]                 = "8217";        /* 8217 : right single quotation mark */
+entityToCharacterMap["&sbquo"]           = "8218";  /* 8218 : single low-9 quotation mark */
+entityToCharacterMap["&ldquo"]                 = "8220";        /* 8220 : left double quotation mark */
+entityToCharacterMap["&rdquo"]                 = "8221";        /* 8221 : right double quotation mark */
+entityToCharacterMap["&bdquo"]           = "8222";  /* 8222 : double low-9 quotation mark */
+entityToCharacterMap["&dagger"]                        = "8224";        /* 8224 : dagger */
+entityToCharacterMap["&Dagger"]                        = "8225";        /* 8225 : double dagger */
+entityToCharacterMap["&bull"]                  = "8226";        /* 8226 : bullet */
+entityToCharacterMap["&hellip"]                        = "8230";        /* 8230 : horizontal ellipsis */
+entityToCharacterMap["&permil"]                        = "8240";        /* 8240 : per mille sign */
+entityToCharacterMap["&prime"]                 = "8242";        /* 8242 : prime */
+entityToCharacterMap["&Prime"]                 = "8243";        /* 8243 : double prime */
+entityToCharacterMap["&lsaquo"]          = "8249";  /* 8249 : single left-pointing angle quotation mark */
+entityToCharacterMap["&rsaquo"]          = "8250";  /* 8250 : single right-pointing angle quotation mark */
+entityToCharacterMap["&oline"]                 = "8254";        /* 8254 : overline */
+entityToCharacterMap["&frasl"]                 = "8260";        /* 8260 : fraction slash */
+entityToCharacterMap["&euro"]                  = "8364";        /* 8364 : euro sign */
+entityToCharacterMap["&image"]           = "8365";  /* 8465 : black-letter capital i */
+entityToCharacterMap["&weierp"]          = "8472";  /* 8472 : script capital p, Weierstrass p */
+entityToCharacterMap["&real"]            = "8476";  /* 8476 : black-letter capital r */
+entityToCharacterMap["&trade"]                 = "8482";        /* 8482 : trademark sign */
+entityToCharacterMap["&alefsym"]                       = "8501";        /* 8501 : alef symbol */
+entityToCharacterMap["&larr"]                  = "8592";        /* 8592 : leftwards arrow */
+entityToCharacterMap["&uarr"]                  = "8593";        /* 8593 : upwards arrow */
+entityToCharacterMap["&rarr"]                  = "8594";        /* 8594 : rightwards arrow */
+entityToCharacterMap["&darr"]                  = "8595";        /* 8595 : downwards arrow */
+entityToCharacterMap["&harr"]                  = "8596";        /* 8596 : left right arrow */
+entityToCharacterMap["&crarr"]                 = "8629";        /* 8629 : downwards arrow with corner leftwards */
+entityToCharacterMap["&lArr"]                  = "8656";        /* 8656 : leftwards double arrow */
+entityToCharacterMap["&uArr"]                  = "8657";        /* 8657 : upwards double arrow */
+entityToCharacterMap["&rArr"]                  = "8658";        /* 8658 : rightwards double arrow */
+entityToCharacterMap["&dArr"]                  = "8659";        /* 8659 : downwards double arrow */
+entityToCharacterMap["&hArr"]                  = "8660";        /* 8660 : left right double arrow */
+entityToCharacterMap["&forall"]                        = "8704";        /* 8704 : for all */
+entityToCharacterMap["&part"]                  = "8706";        /* 8706 : partial differential */
+entityToCharacterMap["&exist"]                 = "8707";        /* 8707 : there exists */
+entityToCharacterMap["&empty"]                 = "8709";        /* 8709 : empty set */
+entityToCharacterMap["&nabla"]                 = "8711";        /* 8711 : nabla */
+entityToCharacterMap["&isin"]                  = "8712";        /* 8712 : element of */
+entityToCharacterMap["&notin"]                 = "8713";        /* 8713 : not an element of */
+entityToCharacterMap["&ni"]                        = "8715";    /* 8715 : contains as member */
+entityToCharacterMap["&prod"]            = "8719";  /* 8719 : n-ary product */
+entityToCharacterMap["&sum"]             = "8721";  /* 8721 : n-ary summation */
+entityToCharacterMap["&minus"]                 = "8722";        /* 8722 : minus sign */
+entityToCharacterMap["&lowast"]                        = "8727";        /* 8727 : asterisk operator */
+entityToCharacterMap["&radic"]                 = "8730";        /* 8730 : square root */
+entityToCharacterMap["&prop"]                  = "8733";        /* 8733 : proportional to */
+entityToCharacterMap["&infin"]                 = "8734";        /* 8734 : infinity */
+entityToCharacterMap["&ang"]                   = "8736";        /* 8736 : angle */
+entityToCharacterMap["&and"]                   = "8743";        /* 8743 : logical and */
+entityToCharacterMap["&or"]                    = "8744";        /* 8744 : logical or */
+entityToCharacterMap["&cap"]                   = "8745";        /* 8745 : intersection */
+entityToCharacterMap["&cup"]                   = "8746";        /* 8746 : union */
+entityToCharacterMap["&int"]                   = "8747";        /* 8747 : integral */
+entityToCharacterMap["&there4"]                        = "8756";        /* 8756 : therefore */
+entityToCharacterMap["&sim"]                   = "8764";        /* 8764 : tilde operator */
+entityToCharacterMap["&cong"]                  = "8773";        /* 8773 : congruent to */
+entityToCharacterMap["&asymp"]                 = "8776";        /* 8776 : almost equal to */
+entityToCharacterMap["&ne"]                    = "8800";        /* 8800 : not equal to */
+entityToCharacterMap["&equiv"]           = "8801";   /* 8801 : identical to, equivalent to */
+entityToCharacterMap["&le"]              = "8804"; /* 8804 : less-than or equal to */
+entityToCharacterMap["&ge"]              = "8805"; /* 8805 : greater-than or equal to */
+entityToCharacterMap["&sub"]                   = "8834";        /* 8834 : subset of */
+entityToCharacterMap["&sup"]                   = "8835";        /* 8835 : superset of */
+entityToCharacterMap["&nsub"]                  = "8836";        /* 8836 : not a subset of */
+entityToCharacterMap["&sube"]                  = "8838";        /* 8838 : subset of or equal to */
+entityToCharacterMap["&supe"]                  = "8839";        /* 8839 : superset of or equal to */
+entityToCharacterMap["&oplus"]                 = "8853";        /* 8853 : circled plus */
+entityToCharacterMap["&otimes"]                        = "8855";        /* 8855 : circled times */
+entityToCharacterMap["&perp"]                  = "8869";        /* 8869 : up tack */
+entityToCharacterMap["&sdot"]                  = "8901";        /* 8901 : dot operator */
+entityToCharacterMap["&lceil"]                 = "8968";        /* 8968 : left ceiling */
+entityToCharacterMap["&rceil"]                 = "8969";        /* 8969 : right ceiling */
+entityToCharacterMap["&lfloor"]                        = "8970";        /* 8970 : left floor */
+entityToCharacterMap["&rfloor"]                        = "8971";        /* 8971 : right floor */
+entityToCharacterMap["&lang"]            = "9001";  /* 9001 : left-pointing angle bracket */
+entityToCharacterMap["&rang"]            = "9002";  /* 9002 : right-pointing angle bracket */
+entityToCharacterMap["&loz"]                   = "9674";        /* 9674 : lozenge */
+entityToCharacterMap["&spades"]                        = "9824";        /* 9824 : black spade suit */
+entityToCharacterMap["&clubs"]                 = "9827";        /* 9827 : black club suit */
+entityToCharacterMap["&hearts"]                        = "9829";        /* 9829 : black heart suit */
+entityToCharacterMap["&diams"]                 = "9830";        /* 9830 : black diamond suit */
+
+var characterToEntityMap = [];
+
+for ( var entity in entityToCharacterMap ) {
+    characterToEntityMap[entityToCharacterMap[entity]] = entity;
+}
+
+$namespace('org.owasp.esapi.codecs');
+
+org.owasp.esapi.codecs.HTMLEntityCodec = function() {
+    var _super = new org.owasp.esapi.codecs.Codec();
+
+    var getNumericEntity = function(input) {
+        var first = input.peek();
+        if (first == null) {
+            return null;
+        }
+
+        if (first == 'x' || first == 'X') {
+            input.next();
+            return parseHex(input);
+        }
+        return parseNumber(input);
+    };
+
+    var parseNumber = function(input) {
+        var out = '';
+        while (input.hasNext()) {
+            var c = input.peek();
+            if (c.match(/[0-9]/)) {
+                out += c;
+                input.next();
+            } else if (c == ';') {
+                input.next();
+                break;
+            } else {
+                break;
+            }
+        }
+
+        try {
+            return parseInt(out);
+        } catch (e) {
+            return null;
+        }
+    };
+
+    var parseHex = function(input) {
+        var out = '';
+        while (input.hasNext()) {
+            var c = input.peek();
+            if (c.match(/[0-9A-Fa-f]/)) {
+                out += c;
+                input.next();
+            } else if (c == ';') {
+                input.next();
+                break;
+            } else {
+                break;
+            }
+        }
+        try {
+            return parseInt(out, 16);
+        } catch (e) {
+            return null;
+        }
+    };
+
+    var getNamedEntity = function(input) {
+        var entity = '';
+        while (input.hasNext()) {
+            var c = input.peek();
+            if (c.match(/[A-Za-z]/)) {
+                entity += c;
+                input.next();
+                if (entityToCharacterMap.containsKey('&' + entity)) {
+                    if (input.peek(';')) input.next();
+                    break;
+                }
+            } else if (c == ';') {
+                input.next();
+            } else {
+                break;
+            }
+        }
+
+        return String.fromCharCode(entityToCharacterMap.getCaseInsensitive('&' + entity));
+    };
+
+    return {
+        encode: _super.encode,
+
+        decode: _super.decode,
+
+        encodeCharacter: function(aImmune, c) {
+            if (aImmune.contains(c)) {
+                return c;
+            }
+
+            var hex = org.owasp.esapi.codecs.Codec.getHexForNonAlphanumeric(c);
+            if (hex == null) {
+                return c;
+            }
+
+            var cc = c.charCodeAt(0);
+            if (( cc <= 0x1f && c != '\t' && c != '\n' && c != '\r' ) || ( cc >= 0x7f && cc <= 0x9f ) || c == ' ') {
+                return " ";
+            }
+
+            var entityName = characterToEntityMap[cc];
+            if (entityName != null) {
+                return entityName + ";";
+            }
+
+            return "&#x" + hex + ";";
+        },
+
+        decodeCharacter: function(oPushbackString) {
+            //noinspection UnnecessaryLocalVariableJS
+            var input = oPushbackString;
+            input.mark();
+            var first = input.next();
+            if (first == null || first != '&') {
+                input.reset();
+                return null;
+            }
+
+            var second = input.next();
+            if (second == null) {
+                input.reset();
+                return null;
+            }
+
+            if (second == '#') {
+                var c = getNumericEntity(input);
+                if (c != null) {
+                    return c;
+                }
+            } else if (second.match(/[A-Za-z]/)) {
+                input.pushback(second);
+                c = getNamedEntity(input);
+                if (c != null) {
+                    return c;
+                }
+            }
+            input.reset();
+            return null;
+        }
+    };
+};
+
+
+$namespace('org.owasp.esapi.codecs');
+
+org.owasp.esapi.codecs.JavascriptCodec = function() {
+    var _super = new org.owasp.esapi.codecs.Codec();
+
+    return {
+        encode: function(aImmune, sInput) {
+            var out = '';
+            for (var idx = 0; idx < sInput.length; idx ++) {
+                var ch = sInput.charAt(idx);
+                if (aImmune.contains(ch)) {
+                    out += ch;
+                }
+                else {
+                    var hex = org.owasp.esapi.codecs.Codec.getHexForNonAlphanumeric(ch);
+                    if (hex == null) {
+                        out += ch;
+                    }
+                    else {
+                        var tmp = ch.charCodeAt(0).toString(16);
+                        if (ch.charCodeAt(0) < 256) {
+                            var pad = "00".substr(tmp.length);
+                            out += "\\x" + pad + tmp.toUpperCase();
+                        }
+                        else {
+                            pad = "0000".substr(tmp.length);
+                            out += "\\u" + pad + tmp.toUpperCase();
+                        }
+                    }
+                }
+            }
+            return out;
+        },
+
+        decode: _super.decode,
+
+        decodeCharacter: function(oPushbackString) {
+            oPushbackString.mark();
+            var first = oPushbackString.next();
+            if (first == null) {
+                oPushbackString.reset();
+                return null;
+            }
+
+            if (first != '\\') {
+                oPushbackString.reset();
+                return null;
+            }
+
+            var second = oPushbackString.next();
+            if (second == null) {
+                oPushbackString.reset();
+                return null;
+            }
+
+            // \0 collides with the octal decoder and is non-standard
+            // if ( second.charValue() == '0' ) {
+            //      return Character.valueOf( (char)0x00 );
+            if (second == 'b') {
+                return 0x08;
+            } else if (second == 't') {
+                return 0x09;
+            } else if (second == 'n') {
+                return 0x0a;
+            } else if (second == 'v') {
+                return 0x0b;
+            } else if (second == 'f') {
+                return 0x0c;
+            } else if (second == 'r') {
+                return 0x0d;
+            } else if (second == '\"') {
+                return 0x22;
+            } else if (second == '\'') {
+                return 0x27;
+            } else if (second == '\\') {
+                return 0x5c;
+            } else if (second.toLowerCase() == 'x') {
+                out = '';
+                for (var i = 0; i < 2; i++) {
+                    var c = oPushbackString.nextHex();
+                    if (c != null) {
+                        out += c;
+                    } else {
+                        input.reset();
+                        return null;
+                    }
+                }
+                try {
+                    n = parseInt(out, 16);
+                    return String.fromCharCode(n);
+                } catch (e) {
+                    oPushbackString.reset();
+                    return null;
+                }
+            } else if (second.toLowerCase() == 'u') {
+                out = '';
+                for (i = 0; i < 4; i++) {
+                    c = oPushbackString.nextHex();
+                    if (c != null) {
+                        out += c;
+                    } else {
+                        input.reset();
+                        return null;
+                    }
+                }
+                try {
+                    var n = parseInt(out, 16);
+                    return String.fromCharCode(n);
+                } catch (e) {
+                    oPushbackString.reset();
+                    return null;
+                }
+            } else if (oPushbackString.isOctalDigit(second)) {
+                var out = second;
+                var c2 = oPushbackString.next();
+                if (!oPushbackString.isOctalDigit(c2)) {
+                    oPushbackString.pushback(c2);
+                } else {
+                    out += c2;
+                    var c3 = oPushbackString.next();
+                    if (!oPushbackString.isOctalDigit(c3)) {
+                        oPushbackString.pushback(c3);
+                    } else {
+                        out += c3;
+                    }
+                }
+
+                try {
+                    n = parseInt(out, 8);
+                    return String.fromCharCode(n);
+                } catch (e) {
+                    oPushbackString.reset();
+                    return null;
+                }
+            }
+            return second;
+        }
+    };
+};
+
+
+$namespace('org.owasp.esapi.codecs');
+
+org.owasp.esapi.codecs.PercentCodec = function() {
+    var _super = new org.owasp.esapi.codecs.Codec();
+
+    var ALPHA_NUMERIC_STR = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+    var RFC_NON_ALPHANUMERIC_UNRESERVED_STR = "-._~";
+    var ENCODED_NON_ALPHA_NUMERIC_UNRESERVED = true;
+    var UNENCODED_STR = ALPHA_NUMERIC_STR + (ENCODED_NON_ALPHA_NUMERIC_UNRESERVED ? "" : RFC_NON_ALPHANUMERIC_UNRESERVED_STR);
+
+    var getTwoUpperBytes = function(b) {
+        var out = '';
+        if (b < -128 || b > 127) {
+            throw new IllegalArgumentException("b is not a byte (was " + b + ")");
+        }
+        b &= 0xFF;
+        if (b < 0x10) {
+            out += '0';
+        }
+        return out + b.toString(16).toUpperCase();
+    };
+
+    return {
+        encode: _super.encode,
+
+        decode: _super.decode,
+
+        encodeCharacter: function(aImmune, c) {
+            if (UNENCODED_STR.indexOf(c) > -1) {
+                return c;
+            }
+
+            var bytes = org.owasp.esapi.codecs.UTF8.encode(c);
+            var out = '';
+            for (var b = 0; b < bytes.length; b++) {
+                out += '%' + getTwoUpperBytes(bytes.charCodeAt(b));
+            }
+            return out;
+        },
+
+        decodeCharacter: function(oPushbackString) {
+            oPushbackString.mark();
+            var first = oPushbackString.next();
+            if (first == null || first != '%') {
+                oPushbackString.reset();
+                return null;
+            }
+
+            var out = '';
+            for (var i = 0; i < 2; i++) {
+                var c = oPushbackString.nextHex();
+                if (c != null) {
+                    out += c;
+                }
+            }
+            if (out.length == 2) {
+                try {
+                    var n = parseInt(out, 16);
+                    return String.fromCharCode(n);
+                } catch (e) {
+                }
+            }
+            oPushbackString.reset();
+            return null;
+        }
+    };
+};
+
+
+$namespace('org.owasp.esapi.codecs');
+
+org.owasp.esapi.codecs.PushbackString = function(sInput) {
+    var _input = sInput,
+            _pushback = '',
+            _temp = '',
+            _index = 0,
+            _mark = 0;
+
+    return {
+        pushback: function(c) {
+            _pushback = c;
+        },
+
+        index: function() {
+            return _index;
+        },
+
+        hasNext: function() {
+            if (_pushback != null) return true;
+            return !(_input == null || _input.length == 0 || _index >= _input.length);
+
+        },
+
+        next: function() {
+            if (_pushback != null) {
+                var save = _pushback;
+                _pushback = null;
+                return save;
+            }
+            if (_input == null || _input.length == 0 || _index >= _input.length) {
+                return null;
+            }
+            return _input.charAt(_index++);
+        },
+
+        nextHex: function() {
+            var c = this.next();
+            if (this.isHexDigit(c)) return c;
+            return null;
+        },
+
+        nextOctal: function() {
+            var c = this.next();
+            if (this.isOctalDigit(c)) return c;
+            return null;
+        },
+
+        isHexDigit: function(c) {
+            return c != null && ( ( c >= '0' && c <= '9' ) || ( c >= 'a' && c <= 'f' ) || ( c >= 'A' && c <= 'F' ) );
+        },
+
+        isOctalDigit: function(c) {
+            return c != null && ( c >= '0' && c <= '7' );
+        },
+
+        peek: function(c) {
+            if (!c) {
+                if (_pushback != null) return _pushback;
+                if (_input == null || _input.length == 0 || _index >= _input.length) return null;
+                return _input.charAt(_index);
+            } else {
+                if (_pushback != null && _pushback == c) return true;
+                if (_input == null || _input.length == 0 || _index >= _input.length) return false;
+                return _input.charAt(_index) == c;
+            }
+        },
+
+        mark: function() {
+            _temp = _pushback;
+            _mark = _index;
+        },
+
+        reset: function() {
+            _pushback = _temp;
+            _index = _mark;
+        },
+
+        remainder: function() {
+            var out = _input.substr(_index);
+            if (_pushback != null) {
+                out = _pushback + out;
+            }
+            return out;
+        }
+    };
+};
+
+
+$namespace('org.owasp.esapi.codecs');
+
+org.owasp.esapi.codecs.UTF8 = {
+    encode: function(sInput) {
+        var input = sInput.replace(/\r\n/g, "\n");
+        var utftext = '';
+
+        for (var n = 0; n < input.length; n ++) {
+            var c = input.charCodeAt(n);
+
+            if (c < 128) {
+                utftext += String.fromCharCode(c);
+            }
+            else if (( c > 127) && (c < 2048)) {
+                utftext += String.fromCharCode((c >> 6) | 192);
+                utftext += String.fromCharCode((c & 63) | 128);
+            }
+            else {
+                utftext += String.fromCharCode((c >> 12) | 224);
+                utftext += String.fromCharCode(((c >> 6) & 63) | 128);
+                utftext += String.fromCharCode((c & 63) | 128);
+            }
+        }
+
+        return utftext;
+    }
+    ,
+
+    decode: function(sInput) {
+        var out = '';
+        var i = c = c1 = c2 = 0;
+
+        while (i < sInput.length) {
+            c = sInput.charCodeAt(i);
+
+            if (c < 128) {
+                out += String.fromCharCode(c);
+                i ++;
+            }
+            else if ((c > 191) && (c < 224)) {
+                c2 = sInput.charCodeAt(i + 1);
+                out += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
+                i += 2;
+            }
+            else {
+                c2 = utftext.charCodeAt(i + 1);
+                c3 = utftext.charCodeAt(i + 2);
+                string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
+                i += 3;
+            }
+        }
+
+        return out;
+    }
+};
+
+
+$namespace('org.owasp.esapi.i18n');
+
+org.owasp.esapi.i18n.ArrayResourceBundle = function( sName, oLocale, aMessages, oParent ) {
+    with(org.owasp.esapi.i18n) var _super = new ResourceBundle( sName, oLocale, oParent );
+
+    var messages = aMessages;
+
+    return {
+        getParent: _super.getParent,
+        getLocale: _super.getLocale,
+        getName: _super.getName,
+        getString: _super.getString,
+        getMessage: function(sKey) {
+            return messages[sKey];
+        }
+    };
+};
+
+
+$namespace('org.owasp.esapi.i18n');
+
+org.owasp.esapi.i18n.Locale = function( sLanguage, sCountry, sVariant ) {
+    var language = sLanguage, country = sCountry, variant = sVariant;
+
+    return {
+        getLanguage: function() { return language; },
+        getCountry: function() { return country; },
+        getVariant: function() { return variant; },
+        toString: function() { return language + ( country ? "-" + country + ( variant ? "-" + variant : "" ) : "" ); }
+    };
+};
+
+org.owasp.esapi.i18n.Locale.US = new org.owasp.esapi.i18n.Locale("en","US");
+org.owasp.esapi.i18n.Locale.GB = new org.owasp.esapi.i18n.Locale("en","GB");
+
+org.owasp.esapi.i18n.Locale.getLocale = function(sLocale) {
+    var l = sLocale.split("-");
+    return new org.owasp.esapi.i18n.Locale( l[0], (l.length>1?l[1]:""), (l.length>2?l.length[2]:""));
+};
+
+org.owasp.esapi.i18n.Locale.getDefault = function() {
+    var l = (navigator['language']?navigator['language']:(navigator['userLanguage']?navigator['userLanguage']:'en-US')).split("-");
+    return new org.owasp.esapi.i18n.Locale( l[0], (l.length>1?l[1]:""), (l.length>2?l.length[2]:""));
+};
+
+
+$namespace('org.owasp.esapi.i18n');
+
+org.owasp.esapi.i18n.ObjectResourceBundle = function( oResource, oParent ) {
+    var _super = new org.owasp.esapi.i18n.ResourceBundle( oResource.name, org.owasp.esapi.i18n.Locale.getLocale(oResource.locale), oParent );
+
+    var messages = oResource.messages;
+
+    return {
+        getParent: _super.getParent,
+        getLocale: _super.getLocale,
+        getName: _super.getName,
+        getString: _super.getString,
+        getMessage: function(sKey) {
+            return messages[sKey];
+        }
+    };
+};
+
+
+$namespace('org.owasp.esapi.i18n');
+
+org.owasp.esapi.i18n.ResourceBundle = function( sName, oLocale, oParentResourceBundle ) {
+    var parent = oParentResourceBundle;
+    var locale = oLocale;
+    var name = sName;
+
+    if ( !name ) throw new SyntaxError("Name required for implementations of org.owasp.esapi.i18n.ResourceBundle");
+    if ( !locale ) throw new SyntaxError("Locale required for implementations of org.owasp.esapi.i18n.ResourceBundle");
+
+    return {
+        getParent: function() { return parent; },
+        getLocale: function() { return locale; },
+        getName: function() { return name; },
+        getMessage: function(sKey) { return sKey; },
+        getString: function( sKey, oContextMap ) {
+            if ( arguments.length < 1 ) {
+                throw new IllegalArgumentException("No key passed to getString");
+            }
+
+            var msg = this.getMessage(sKey);
+            if ( !msg ) {
+                if ( parent ) {
+                    return parent.getString( sKey, oContextMap );
+                } else {
+                    return sKey;
+                }
+            }
+
+            if ( !msg.match( /\{([A-Za-z]+)\}/ ) || !oContextMap ) {
+                return msg;
+            }
+
+            var out = '', lastIndex = 0;
+            while (true) {
+                var nextVarIdx = msg.indexOf( "{", lastIndex );
+                var endIndex = msg.indexOf( "}", nextVarIdx );
+
+                if ( nextVarIdx < 0 ) {
+                    out += msg.substr( lastIndex, msg.length-lastIndex );
+                    break;
+                }
+
+                if ( nextVarIdx >= 0 && endIndex < -1 ) {
+                    throw new SyntaxError("Invalid Message - Unclosed Context Reference: " + msg );
+                }
+
+                out += msg.substring( lastIndex, nextVarIdx );
+                var contextKey = msg.substring( nextVarIdx+1, endIndex );
+                if ( oContextMap[contextKey] ) {
+                    out += oContextMap[contextKey];
+                } else {
+                    out += msg.substring( nextVarIdx, endIndex+1 );
+                }
+
+                lastIndex = endIndex + 1;
+            }
+
+            return out;
+        }
+    };
+};
+
+org.owasp.esapi.i18n.ResourceBundle.getResourceBundle = function(sResource, oLocale) {
+    var classname = sResource + "_" + oLocale.toString().replace("-","_");
+
+    with( org.owasp.esapi.i18n ) {
+        if ( ResourceBundle[classname] instanceof Object ) {
+            return ResourceBundle[classname];
+        } else {
+            return new ResourceBundle[classname]();
+        }
+    }
+};
+
+$namespace('org.owasp.esapi.net');
+
+/**
+ * Constructs a cookie with a specified name and value.
+ * <p/>
+ * The name must conform to RFC 2109. That means it can contain only ASCII alphanumeric characters and cannot contain
+ * commas, semicolons, or white space or begin with a $ character. The cookie's name cannot be changed after creation.
+ * <p/>
+ * The value can be anything the server chooses to send. Its value is probably of interest only to the server. The
+ * cookie's value can be changed after creation with the setValue method.
+ * <p/>
+ * By default, cookies are created according to the Netscape cookie specification. The version can be changed with the
+ * {@link #setVersion} method.
+ *
+ * @constructor
+ * @param sName {String} a <code>String</code> specifying the name of the cookie
+ * @param sValue {String} a <code>String</code> specifying the value of the cookie
+ * @throws  IllegalArgumentException
+ *          if the cookie name contains illegal characters (for example, a comma, space, or semicolon) or it is one of
+ *          the tokens reserved for use by the cookie protocol
+ */
+org.owasp.esapi.net.Cookie = function( sName, sValue ) {
+    var name;       // NAME= ... "$Name" style is reserved
+    var value;      // value of NAME
+
+    var comment;    // ;Comment=VALUE ... describes the cookies use
+    var domain;     // ;Domain=VALUE ... domain that sees the cookie
+    var maxAge;     // ;Max-Age=VALUE ... cookies auto-expire
+    var path;       // ;Path=VALUE ... URLs that see the cookie
+    var secure;     // ;Secure ... e.g. use SSL
+    var version;    // ;Version=1 ... means RFC-2109++ style
+
+    var _resourceBundle = $ESAPI.resourceBundle();
+
+    var tSpecials = ",; ";
+
+    var isToken = function(sValue) {
+        for(var i=0,len=sValue.length;i<len;i++) {
+            var cc = sValue.charCodeAt(i),c=sValue.charAt(i);
+            if (cc<0x20||cc>=0x7F||tSpecials.indexOf(c)!=-1) {
+                return false;
+            }
+        }
+        return true;
+    };
+
+    if ( !isToken(sName)
+            || sName.toLowerCase() == 'comment'
+            || sName.toLowerCase() == 'discard'
+            || sName.toLowerCase() == 'domain'
+            || sName.toLowerCase() == 'expires'
+            || sName.toLowerCase() == 'max-age'
+            || sName.toLowerCase() == 'path'
+            || sName.toLowerCase() == 'secure'
+            || sName.toLowerCase() == 'version'
+            || sName.charAt(0) == '$' ) {
+        var errMsg = _resourceBundle.getString( "Cookie.Name", { 'name':sName } );
+        throw new IllegalArgumentException(errMsg);
+    }
+
+    name = sName;
+    value = sValue;
+
+    return {
+        setComment: function(purpose) { comment = purpose; },
+        getComment: function() { return comment; },
+        setDomain: function(sDomain) { domain = sDomain.toLowerCase(); },
+        getDomain: function() { return domain; },
+        setMaxAge: function(nExpirey) { maxAge = nExpirey; },
+        getMaxAge: function() { return maxAge; },
+        setPath: function(sPath) { path = sPath; },
+        getPath: function() { return path; },
+        setSecure: function(bSecure) { secure = bSecure; },
+        getSecure: function() { return secure; },
+        getName: function() { return name; },
+        setValue: function(sValue) { value = sValue; },
+        getValue: function() { return value; },
+        setVersion: function(nVersion) {
+            if(nVersion<0||nVersion>1)throw new IllegalArgumentException(_resourceBundle.getString("Cookie.Version", { 'version':nVersion } ) );
+            version = nVersion;
+        },
+        getVersion: function() { return version; }
+    };
+};
+
+$namespace('org.owasp.esapi.reference.encoding');
+
+org.owasp.esapi.reference.encoding.DefaultEncoder = function(aCodecs) {
+    var _codecs = [],
+            _htmlCodec = new org.owasp.esapi.codecs.HTMLEntityCodec(),
+            _javascriptCodec = new org.owasp.esapi.codecs.JavascriptCodec(),
+            _cssCodec = new org.owasp.esapi.codecs.CSSCodec(),
+            _percentCodec = new org.owasp.esapi.codecs.PercentCodec();
+
+    if (!aCodecs) {
+        _codecs.push(_htmlCodec);
+        _codecs.push(_javascriptCodec);
+        _codecs.push(_cssCodec);
+        _codecs.push(_percentCodec);
+    } else {
+        _codecs = aCodecs;
+    }
+
+    var IMMUNE_HTML = new Array(',', '.', '-', '_', ' ');
+    var IMMUNE_HTMLATTR = new Array(',', '.', '-', '_');
+    var IMMUNE_CSS = new Array();
+    var IMMUNE_JAVASCRIPT = new Array(',', '.', '_');
+
+    return {
+        cananicalize: function(sInput, bStrict) {
+            if (!sInput) {
+                return null;
+            }
+            var working = sInput, codecFound = null, mixedCount = 1, foundCount = 0, clean = false;
+            while (!clean) {
+                clean = true;
+
+                _codecs.each(function(codec) {
+                    var old = working;
+                    working = codec.decode(working);
+
+                    if (old != working) {
+                        if (codecFound != null && codecFound != codec) {
+                            mixedCount ++;
+                        }
+                        codecFound = codec;
+                        if (clean) {
+                            foundCount ++;
+                        }
+                        clean = false;
+                    }
+                });
+            }
+
+            if (foundCount >= 2 && mixedCount > 1) {
+                if (bStrict) {
+                    throw new org.owasp.esapi.IntrusionException("Input validation failure", "Multiple (" + foundCount + "x) and mixed encoding (" + mixedCount + "x) detected in " + sInput);
+                }
+            }
+            else if (foundCount >= 2) {
+                if (bStrict) {
+                    throw new org.owasp.esapi.IntrusionException("Input validation failure", "Multiple (" + foundCount + "x) encoding detected in " + sInput);
+                }
+            }
+            else if (mixedCount > 1) {
+                    if (bStrict) {
+                        throw new org.owasp.esapi.IntrusionException("Input validation failure", "Mixed (" + mixedCount + "x) encoding detected in " + sInput);
+                    }
+                }
+            return working;
+        },
+
+        normalize: function(sInput) {
+            return sInput.replace(/[^\x00-\x7F]/g, '');
+        },
+
+        encodeForHTML: function(sInput) {
+            return !sInput ? null : _htmlCodec.encode(IMMUNE_HTML, sInput);
+        },
+
+        decodeForHTML: function(sInput) {
+            return !sInput ? null : _htmlCodec.decode(sInput);
+        },
+
+        encodeForHTMLAttribute: function(sInput) {
+            return !sInput ? null : _htmlCodec.encode(IMMUNE_HTMLATTR, sInput);
+        },
+
+        encodeForCSS: function(sInput) {
+            return !sInput ? null : _cssCodec.encode(IMMUNE_CSS, sInput);
+        },
+
+        encodeForJavaScript: function(sInput) {
+            return !sInput ? null : _javascriptCodec.encode(IMMUNE_JAVASCRIPT, sInput);
+        },
+
+        encodeForJavascript: this.encodeForJavaScript,
+
+        encodeForURL: function(sInput) {
+            return !sInput ? null : escape(sInput);
+        },
+
+        decodeFromURL: function(sInput) {
+            return !sInput ? null : unescape(sInput);
+        },
+
+        encodeForBase64: function(sInput) {
+            return !sInput ? null : org.owasp.esapi.codecs.Base64.encode(sInput);
+        },
+
+        decodeFromBase64: function(sInput) {
+            return !sInput ? null : org.owasp.esapi.codecs.Base64.decode(sInput);
+        }
+    };
+};
+
+
+$namespace('org.owasp.esapi.reference.logging');
+
+org.owasp.esapi.reference.logging.Log4JSLogFactory = function() {
+    var loggersMap = Array();
+
+    var Log4JSLogger = function( sModuleName ) {
+        var jsLogger = null;
+        var moduleName = sModuleName?sModuleName:null;
+        var Level = Log4js.Level;
+
+        var logUrl = false, logApplicationName = false, encodingRequired = false, encodingFunction = $ESAPI.encoder().encodeForHTML;
+
+        jsLogger = Log4js.getLogger( moduleName );
+
+        var convertESAPILevel = function( nLevel ) {
+            var Logger = org.owasp.esapi.Logger;
+            switch (nLevel) {
+                case Logger.OFF:        return Log4js.Level.OFF;
+                case Logger.FATAL:      return Log4js.Level.FATAL;
+                case Logger.ERROR:      return Log4js.Level.ERROR;
+                case Logger.WARNING:    return Log4js.Level.WARN;
+                case Logger.INFO:       return Log4js.Level.INFO;
+                case Logger.DEBUG:      return Log4js.Level.DEBUG;
+                case Logger.TRACE:      return Log4js.Level.TRACE;
+                case Logger.ALL:        return Log4js.Level.ALL;
+            }
+        };
+
+        return {
+            setLevel: function( nLevel ) {
+                try {
+                    jsLogger.setLevel( convertESAPILevel( nLevel ) );
+                } catch (e) {
+                    this.error( org.owasp.esapi.Logger.SECURITY_FAILURE, "", e );
+                }
+            },
+
+            trace: function( oEventType, sMessage, oException ) {
+                this.log( Level.TRACE, oEventType, sMessage, oException );
+            },
+
+            debug: function( oEventType, sMessage, oException ) {
+                this.log( Level.DEBUG, oEventType, sMessage, oException );
+            },
+
+            info: function( oEventType, sMessage, oException ) {
+                this.log( Level.INFO, oEventType, sMessage, oException );
+            },
+
+            warning: function( oEventType, sMessage, oException ) {
+                this.log( Level.WARN, oEventType, sMessage, oException );
+            },
+
+            error: function( oEventType, sMessage, oException ) {
+                this.log( Level.ERROR, oEventType, sMessage, oException );
+            },
+
+            fatal: function( oEventType, sMessage, oException ) {
+                this.log( Level.FATAL, oEventType, sMessage, oException );
+            },
+
+            log: function( oLevel, oEventType, sMessage, oException ) {
+                switch(oLevel) {
+                    case Level.TRACE:       if ( !jsLogger.isTraceEnabled() ) { return; } break;
+                    case Level.DEBUG:       if ( !jsLogger.isDebugEnabled() ) { return; } break;
+                    case Level.INFO:        if ( !jsLogger.isInfoEnabled()  ) { return; } break;
+                    case Level.WARNING:     if ( !jsLogger.isWarnEnabled()  ) { return; } break;
+                    case Level.ERROR:       if ( !jsLogger.isErrorEnabled() ) { return; } break;
+                    case Level.FATAL:       if ( !jsLogger.isFatalEnabled() ) { return; } break;
+                }
+
+                if ( !sMessage ) {
+                    sMessage = "";
+                }
+
+                sMessage = '[' + oEventType.toString() + '] - ' + sMessage;
+
+                var clean = sMessage.replace("\n","_").replace("\r","_");
+                if ( encodingRequired ) {
+                    clean = encodingFunction(clean);
+                    if ( clean != sMessage) {
+                        clean += " [Encoded]";
+                    }
+                }
+
+                var appInfo =   ( logUrl ? window.location.href : "" ) +
+                                ( logApplicationName ? "/" + $ESAPI.properties.application.Name : "" );
+
+                jsLogger.log( oLevel, ( appInfo != "" ? "[" + appInfo + "] " : "" ) + clean, oException );
+            },
+
+            addAppender: function( oAppender ) {
+                jsLogger.addAppender( oAppender );
+            },
+
+            isLogUrl: function()                { return logUrl; },
+            setLogUrl: function(b)              { logUrl = b; },
+            isLogApplicationName: function()    { return logApplicationName; },
+            setLogApplicationName: function(b)  { logApplicationName = b; },
+            isEncodingRequired: function()      { return encodingRequired; },
+            setEncodingRequired: function(b)    { encodingRequired = b; },
+            setEncodingFunction: function(f)    { encodingFunction = f; },
+            isDebugEnabled: function()          { return jsLogger.isDebugEnabled(); },
+            isErrorEnabled: function()          { return jsLogger.isErrorEnabled(); },
+            isFatalEnabled: function()          { return jsLogger.isFatalEnabled(); },
+            isInfoEnabled: function()           { return jsLogger.isInfoEnabled(); },
+            isTraceEnabled: function()          { return jsLogger.isTraceEnabled(); },
+            isWarningEnabled: function()        { return jsLogger.isWarnEnabled(); }
+        };
+    };
+
+    var getLoggerConfig = function( moduleName ) {
+        var logConfig = $ESAPI.properties.logging;
+        if ( logConfig[moduleName] ) {
+            logConfig = logConfig[moduleName];
+        }
+        return logConfig;
+    };
+
+    return {
+        getLogger: function ( moduleName ) {
+            var key = ( typeof moduleName == 'string' ) ? moduleName : moduleName.constructor.toString();
+            var logger = loggersMap[key];
+            if ( !logger ) {
+                logger = new Log4JSLogger(key);
+
+                var logConfig = getLoggerConfig(moduleName);
+
+                logger.setLevel( logConfig.Level );
+                logger.setLogUrl( logConfig.LogUrl );
+                logger.setLogApplicationName( logConfig.LogApplicationName );
+                logger.setEncodingRequired( logConfig.EncodingRequired );
+
+                if ( logConfig.EncodingFunction ) {
+                    logger.setEncodingFunction( logConfig.EncodingFunction );
+                }
+
+                logConfig.Appenders.each(function(e){
+                    if ( logConfig.Layout ) {
+                        e.setLayout( logConfig.Layout );
+                    }
+                    logger.addAppender(e);
+                });
+
+                loggersMap[key] = logger;
+            }
+            return logger;
+        }
+    };
+};
+
+
+$namespace('org.owasp.esapi.reference.validation');
+
+org.owasp.esapi.reference.validation.BaseValidationRule = function( sTypeName, oEncoder, oLocale ) {
+    var log = $ESAPI.logger( "Validation" );
+    var EventType = org.owasp.esapi.Logger.EventType;
+
+    var typename = sTypeName;
+    var encoder = oEncoder?oEncoder:$ESAPI.encoder();
+    var allowNull = false;
+
+    var ResourceBundle = org.owasp.esapi.i18n.ResourceBundle;
+
+    var locale = oLocale?oLocale:$ESAPI.locale();
+    var resourceBundle;
+
+    if ( $ESAPI.properties.validation.ResourceBundle ) {
+        resourceBundle = ResourceBundle.getResourceBundle( $ESAPI.properties.validation.ResourceBundle, locale );
+    }
+
+    if ( !resourceBundle ) {
+        resourceBundle = $ESAPI.resourceBundle();
+        log.info( EventType.EVENT_FAILURE, "No Validation ResourceBundle - Defaulting to " + resourceBundle.getName() + "(" + resourceBundle.getLocale().toString() + ")" );
+    }
+
+    log.info( EventType.EVENT_SUCCESS, "Validation Rule Initialized with ResourceBundle: " + resourceBundle.getName() );
+
+    return {
+        setAllowNull: function(b) { allowNull = b; },
+
+        isAllowNull: function() { return allowNull; },
+
+        getTypeName: function() { return typename; },
+
+        setTypeName: function(s) { typename = s; },
+
+        setEncoder: function(oEncoder) { encoder = oEncoder; },
+
+        getEncoder: function() { return encoder; },
+
+        assertValid: function( sContext, sInput ) {
+            this.getValid( sContext, sInput );
+        },
+
+        getValid: function( sContext, sInput, oValidationErrorList ) {
+            var valid = null;
+            try {
+                valid = this.getValidInput( sContext, sInput );
+            } catch (oValidationException) {
+                return this.sanitize( sContext, sInput );
+            }
+            return valid;
+        },
+
+        getValidInput: function( sContext, sInput ) {
+            return sInput;
+        },
+
+        getSafe: function( sContext, sInput ) {
+            var valid = null;
+            try {
+                valid = this.getValidInput( sContext, sInput );
+            } catch (oValidationException) {
+                return this.sanitize( sContext, sInput );
+            }
+            return valid;
+        },
+
+        /**
+     * The method is similar to ValidationRuile.getSafe except that it returns a
+     * harmless object that <b>may or may not have any similarity to the original
+     * input (in some cases you may not care)</b>. In most cases this should be the
+     * same as the getSafe method only instead of throwing an exception, return
+     * some default value.
+     *
+     * @param context
+     * @param input
+     * @return a parsed version of the input or a default value.
+     */
+        sanitize: function( sContext, sInput ) {
+            return sInput;
+        },
+
+        isValid: function( sContext, sInput ) {
+            var valid = false;
+            try {
+                this.getValidInput( sContext, sInput );
+                valid = true;
+            } catch (oValidationException) {
+                return false;
+            }
+            return valid;
+        },
+
+        /**
+         * Removes characters that aren't in the whitelist from the input String.
+         * O(input.length) whitelist performance
+         * @param input String to be sanitized
+         * @param whitelist allowed characters
+         * @return input stripped of all chars that aren't in the whitelist
+         */
+        whitelist: function( sInput, aWhitelist ) {
+            var stripped = '';
+            for ( var i=0;i<sInput.length;i++ ) {
+                var c = sInput.charAt(i);
+                if ( aWhitelist.contains(c) ) {
+                    stripped += c;
+                }
+            }
+            return stripped;
+        },
+
+        getUserMessage: function( sContext, sDefault, oContextValues ) {
+            return this.getMessage( sContext+".Usr", sDefault+".Usr", oContextValues );
+        },
+
+        getLogMessage: function( sContext, sDefault, oContextValues ) {
+            return this.getMessage( sContext+".Log", sDefault+".Log", oContextValues );
+        },
+
+        getMessage: function( sContext, sDefault, oContextValues ) {
+            return resourceBundle.getString( sContext, oContextValues ) ? resourceBundle.getString( sContext, oContextValues ) : resourceBundle.getString( sDefault, oContextValues );
+        },
+
+        validationException: function( sContext, sDefault, sValidation, oContextValues ) {
+            throw new org.owasp.esapi.reference.validation.ValidationException(
+                    this.getUserMessage( sContext+"."+sValidation, sDefault+"."+sValidation, oContextValues ),
+                    this.getLogMessage( sContext+"."+sValidation, sDefault+"."+sValidation, oContextValues ),
+                    sContext
+            );
+        }
+    };
+};
+
+
+$namespace('org.owasp.esapi.reference.validation');
+
+org.owasp.esapi.reference.validation.CreditCardValidationRule = function( sTypeName, oEncoder, oLocale ) {
+    var _super = new org.owasp.esapi.reference.validation.BaseValidationRule( sTypeName, oEncoder, oLocale );
+    var _validationType = "CreditCard";
+
+    var maxCardLength = 19;
+    var ccrule;
+
+    var readDefaultCreditCardRule = function() {
+        var p = new RegExp( $ESAPI.properties.validation.CreditCard );
+        var ccr = new org.owasp.esapi.reference.validation.StringValidationRule( "ccrule", _super.getEncoder(), oLocale, p );
+        ccr.setMaxLength( maxCardLength );
+        ccr.setAllowNull( false );
+        return ccr;
+    };
+
+    ccRule = readDefaultCreditCardRule();
+
+    var validCreditCardFormat = function( ccNum ) {
+        var digitsonly = '';
+        var c;
+        for (var i=0;o<ccNum.length;i++) {
+            c = ccNum.charAt(i);
+            if ( c.match( /[0-9]/ ) ) digitsonly += c;
+        }
+
+        var sum = 0, digit = 0, addend = 0, timesTwo = false;
+
+        for (var j=digitsonly.length-1; j>=0; j--) {
+            digit = parseInt(digitsonly.substring(j,i+1));
+            if ( timesTwo ) {
+                addend = digit * 2;
+                if ( addend > 9 ) addend -= 9;
+            } else {
+                addend = digit;
+            }
+            sum += addend;
+            timesTwo = !timesTwo;
+        }
+        return sum % 10 == 0;
+    };
+
+    return {
+        getMaxCardLength: function() { return maxCardLength; },
+
+        setMaxCardLength: function(n) { maxCardLength = n; },
+
+        setAllowNull: _super.setAllowNull,
+
+        isAllowNull: _super.isAllowNull,
+
+        getTypeName: _super.getTypeName,
+
+        setTypeName: _super.setTypeName,
+
+        setEncoder: _super.setEncoder,
+
+        getEncoder: _super.getEncoder,
+
+        assertValid: _super.assertValid,
+
+        getValid: _super.getValid,
+
+        getValidInput: function( sContext, sInput ) {
+            if ( !sInput || sInput.trim() == '' ) {
+                if ( this.isAllowNull() ) {
+                    return null;
+                }
+                _super.validationException( sContext, _validationType, "Required", { "context":sContext, "input":sInput } );
+            }
+
+            var canonical = ccrule.getValid( sContext, sInput );
+
+            if ( !validCreditCardFormat(canonical) ) {
+                _super.validationException( sContext, _validationType, "Invalid", { "context":sContext, "input":sInput } );
+            }
+
+            return canonical;
+        },
+
+        getSafe: _super.getSafe,
+
+        sanitize: function( sContext, sInput ) {
+            return this.whitelist( sInput, org.owasp.esapi.EncoderConstants.CHAR_DIGITS );
+        },
+
+        isValid: _super.isValid,
+
+        whitelist: _super.whitelist
+    };
+};
+
+
+$namespace('org.owasp.esapi.reference.validation');
+
+org.owasp.esapi.reference.validation.DateValidationRule = function( sTypeName, oEncoder, oLocale ) {
+    var _super = new org.owasp.esapi.reference.validation.BaseValidationRule( sTypeName, oEncoder, oLocale );
+    var _validationTarget = "Date";
+
+    var format = DateFormat.getDateInstance();
+
+    var safelyParse = function(sContext,sInput) {
+        if ( !sContext || sContext.trim() == '' ) {
+            if ( _super.isAllowNull() ) {
+                return null;
+            }
+            _super.validationException( sContext, _validationTarget, "Required", { "context":sContext, "input":sInput, "format":format } );
+        }
+
+        var canonical = _super.getEncoder().cananicalize(sInput);
+
+        try {
+            return format.parse(canonical);
+        } catch (e) {
+            _super.validationException( sContext, _validationTarget, "Invalid", { "context":sContext, "input":sInput, "format":format } );
+        }
+    };
+
+    return {
+        setDateFormat: function(fmt) {
+            if ( !fmt ) {
+                throw new IllegalArgumentException("DateValidationRule.setDateFormat requires a non-null DateFormat");
+            }
+            format = fmt;
+        },
+
+        setAllowNull: _super.setAllowNull,
+
+        isAllowNull: _super.isAllowNull,
+
+        getTypeName: _super.getTypeName,
+
+        setTypeName: _super.setTypeName,
+
+        setEncoder: _super.setEncoder,
+
+        getEncoder: _super.getEncoder,
+
+        assertValid: _super.assertValid,
+
+        getValid: _super.getValid,
+
+        getValidInput: function( sContext, sInput ) {
+            return safelyParse(sContext,sInput);
+        },
+
+        getSafe: _super.getSafe,
+
+        sanitize: function( sContext, sInput ) {
+            var date = new Date(0);
+            try {
+                date = safelyParse(sContext,sInput);
+            } catch (e) { }
+            return date;
+        },
+
+        isValid: _super.isValid,
+
+        whitelist: _super.whitelist
+    };
+};
+
+
+$namespace('org.owasp.esapi.reference.validation');
+
+org.owasp.esapi.reference.validation.DefaultValidator = function( oEncoder, oLocale ) {
+    var rules = Array();
+    var encoder = oEncoder?oEncoder:$ESAPI.encoder();
+    var locale = oLocale?oLocale:org.owasp.esapi.i18n.Locale.getDefault();
+
+    var p = org.owasp.esapi.reference.validation;
+
+    return {
+        addRule: function( oValidationRule ) {
+            rules[oValidationRule.getName()] = oValidationRule;
+        },
+
+        getRule: function( sName ) {
+            return rules[sName];
+        },
+
+        isValidInput: function( sContext, sInput, sType, nMaxLength, bAllowNull ) {
+            try {
+                this.getValidInput( sContext, sInput, sType, nMaxLength, bAllowNull );
+                return true;
+            } catch (e) {
+                return false;
+            }
+        },
+
+        getValidInput: function( sContext, sInput, sType, nMaxLength, bAllowNull, oValidationErrorList ) {
+            var rvr = new org.owasp.esapi.reference.validation.StringValidationRule( sType, encoder, locale );
+            var p = new RegExp($ESAPI.properties.validation[sType]);
+            if ( p && p instanceof RegExp ) {
+                rvr.addWhitelistPattern( p );
+            } else {
+                throw new IllegalArgumentException("Invalid Type: " + sType + " not found.");
+            }
+            rvr.setMaxLength( nMaxLength );
+            rvr.setAllowNull( bAllowNull );
+
+            try {
+                return rvr.getValid(sContext,sInput);
+            } catch (e) {
+                if ( e instanceof p.ValidationErrorList && oValidationErrorList ) {
+                    oValidationErrorList.addError( sContext, e );
+                }
+                throw e;
+            }
+        },
+
+        isValidDate: function( sContext, sInput, oDateFormat, bAllowNull ) {
+            try {
+                this.getValidDate( sContext, sInput, oDateFormat, bAllowNull );
+                return true;
+            } catch (e) {
+                return false;
+            }
+        },
+
+        getValidDate: function( sContext, sInput, oDateFormat, bAllowNull, oValidationErrorList ) {
+            var dvr = new p.DateValidationRule( sContext, encoder, locale );
+            dvr.setAllowNull( bAllowNull );
+            dvr.setDateFormat(oDateFormat);
+            try {
+                return dvr.getValid( sContext, sInput );
+            } catch (e) {
+                if ( e instanceof p.ValidationErrorList && oValidationErrorList ) {
+                    oValidationErrorList.addError( sContext, e );
+                }
+                throw e;
+            }
+        },
+
+        getValidCreditCard: function( sContext, sInput, bAllowNull, oValidationErrorList ) {
+            var ccr = new p.CreditCardValidationRule( sContext, encoder, locale );
+            ccr.setAllowNull(bAllowNull);
+
+            try {
+                return ccr.getValid(sContext,sInput);
+            } catch (e) {
+                if ( e instanceof p.ValidationErrorList && oValidationErrorList ) {
+                    oValidationErrorList.addError( sContext, e );
+                }
+                throw e;
+            }
+        },
+
+        isValidCreditCard: function( sContext, sInput, bAllowNull ) {
+            try {
+                this.getValidCreditCard( sContext,sInput,bAllowNull );
+                return true;
+            } catch (e) {
+                return false;
+            }
+        },
+
+        getValidNumber: function( sContext, sInput, bAllowNull, nMinValue, nMaxValue, oValidationErrorList ) {
+            var nvr = new p.NumberValidationRule( sContext, encoder, locale, nMinValue, nMaxValue );
+            nvr.setAllowNull(bAllowNull);
+
+            try {
+                return nvr.getValid(sContext, sInput);
+            } catch(e) {
+                if ( e instanceof p.ValidationErrorList && oValidationErrorList ) {
+                    oValidationErrorList.addError( sContext, e );
+                }
+                throw e;
+            }
+        },
+
+        isValidNumber: function( sContext, sInput, bAllowNull, nMinValue, nMaxValue ) {
+            try {
+                this.getValidNumber(sContext,sInput,bAllowNull,nMinValue,nMaxValue);
+                return true;
+            } catch (e) {
+                return false;
+            }
+        },
+
+        getValidInteger: function( sContext, sInput, bAllowNull, nMinValue, nMaxValue, oValidationErrorList ) {
+            var nvr = new p.IntegerValidationRule( sContext, encoder, locale, nMinValue, nMaxValue );
+            nvr.setAllowNull(bAllowNull);
+
+            try {
+                return nvr.getValid(sContext, sInput);
+            } catch(e) {
+                if ( e instanceof p.ValidationErrorList && oValidationErrorList ) {
+                    oValidationErrorList.addError( sContext, e );
+                }
+                throw e;
+            }
+        },
+
+        isValidInteger: function( sContext, sInput, bAllowNull, nMinValue, nMaxValue ) {
+            try {
+                this.getValidInteger(sContext,sInput,bAllowNull,nMinValue,nMaxValue);
+                return true;
+            } catch (e) {
+                return false;
+            }
+        }
+    };
+};
+
+
+$namespace('org.owasp.esapi.reference.validation');
+
+org.owasp.esapi.reference.validation.IntegerValidationRule = function( sTypeName, oEncoder, oLocale, nMinValue, nMaxValue ) {
+    var _super = new org.owasp.esapi.reference.validation.BaseValidationRule( sTypeName, oEncoder, oLocale );
+    var _validationTarget = "Integer";
+
+    var minValue = nMinValue?nMinValue:Number.MIN_VALUE;
+    var maxValue = nMaxValue?nMaxValue:Number.MAX_VALUE;
+
+    if ( minValue >= maxValue ) {
+        throw new IllegalArgumentException( "minValue must be less than maxValue" );
+    }
+
+    var safelyParse = function(sContext,sInput) {
+        if ( !sInput || sInput.trim() == '' ) {
+            if ( _super.allowNull() ) {
+                return null;
+            }
+            _super.validationException( sContext, _validationTarget, "Required", { "context":sContext, "input":sInput, "minValue":minValue, "maxValue":maxValue } );
+        }
+
+        var canonical = _super.getEncoder().cananicalize(sInput);
+
+        var n = parseInt(canonical);
+        if ( n == 'NaN' ) {
+            _super.validationException( sContext, _validationTarget, "NaN", { "context":sContext, "input":sInput, "minValue":minValue, "maxValue":maxValue } );
+        }
+        if ( n < minValue ) {
+            _super.validationException( sContext, _validationTarget, "MinValue", { "context":sContext, "input":sInput, "minValue":minValue, "maxValue":maxValue } );
+        }
+        if ( n > maxValue ) {
+            _super.validationException( sContext, _validationTarget, "MaxValue", { "context":sContext, "input":sInput, "minValue":minValue, "maxValue":maxValue } );
+        }
+        return n;
+    };
+
+    return {
+        setMinValue: function(n) { minValue = n; },
+
+        getMinValue: function() { return minValue; },
+
+        setMaxValue: function(n) { maxValue = n; },
+
+        getMaxValue: function() { return maxValue; },
+
+        setAllowNull: _super.setAllowNull,
+
+        isAllowNull: _super.isAllowNull,
+
+        getTypeName: _super.getTypeName,
+
+        setTypeName: _super.setTypeName,
+
+        setEncoder: _super.setEncoder,
+
+        getEncoder: _super.getEncoder,
+
+        assertValid: _super.assertValid,
+
+        getValid: _super.getValid,
+
+        getValidInput: function( sContext, sInput ) {
+            return safelyParse(sContext,sInput);
+        },
+
+        getSafe: _super.getSafe,
+
+        sanitize: function( sContext, sInput ) {
+            var n = 0;
+            try {
+                n = safelyParse(sContext,sInput);
+            } catch (e) { }
+            return n;
+        },
+
+        isValid: _super.isValid,
+
+        whitelist: _super.whitelist
+    };
+};
+
+
+$namespace('org.owasp.esapi.reference.validation');
+
+org.owasp.esapi.reference.validation.NumberValidationRule = function( sTypeName, oEncoder, oLocale, fMinValue, fMaxValue ) {
+    var _super = new org.owasp.esapi.reference.validation.BaseValidationRule( sTypeName, oEncoder, oLocale );
+    var _validationTarget = 'Number';
+
+    var minValue = fMinValue?fMinValue:Number.MIN_VALUE;
+    var maxValue = fMaxValue?fMaxValue:Number.MAX_VALUE;
+
+    if ( minValue >= maxValue ) throw new IllegalArgumentException("MinValue must be less that MaxValue");
+
+    var safelyParse = function( sContext, sInput ) {
+        if ( !sInput || sInput.trim() == '' ) {
+            if ( _super.isAllowNull() ) {
+                return null;
+            }
+            _super.validationException( sContext, _validationTarget, "Required", { "context":sContext, "input":sInput, "minValue":minValue, "maxValue":maxValue } );
+        }
+
+        var canonical = _super.getEncoder().cananicalize( sInput );
+
+        var f = 0.0;
+        try {
+            f = parseFloat( canonical );
+        } catch (e) {
+            _super.validationException( sContext, _validationTarget, "Invalid", { "context":sContext, "input":sInput, "minValue":minValue, "maxValue":maxValue } );
+        }
+
+        if ( f == 'NaN' ) {
+            _super.validationException( sContext, _validationTarget, "NaN", { "context":sContext, "input":sInput, "minValue":minValue, "maxValue":maxValue } );
+        }
+        if ( f < minValue ) {
+            _super.validationException( sContext, _validationTarget, "MinValue", { "context":sContext, "input":sInput, "minValue":minValue, "maxValue":maxValue } );
+        }
+        if ( f > maxValue ) {
+            _super.validationException( sContext, _validationTarget, "MaxValue", { "context":sContext, "input":sInput, "minValue":minValue, "maxValue":maxValue } );
+        }
+        return f;
+    };
+
+    return {
+        setMinValue: function(n) { minValue = n; },
+
+        getMinValue: function() { return minValue; },
+
+        setMaxValue: function(n) { maxValue = n; },
+
+        getMaxValue: function() { return maxValue; },
+
+        setAllowNull: _super.setAllowNull,
+
+        isAllowNull: _super.isAllowNull,
+
+        getTypeName: _super.getTypeName,
+
+        setTypeName: _super.setTypeName,
+
+        setEncoder: _super.setEncoder,
+
+        getEncoder: _super.getEncoder,
+
+        assertValid: _super.assertValid,
+
+        getValid: _super.getValid,
+
+        getValidInput: function( sContext, sInput ) {
+            return safelyParse(sContext,sInput);
+        },
+
+        getSafe: _super.getSafe,
+
+        sanitize: function( sContext, sInput ) {
+            var n = 0;
+            try {
+                n = safelyParse(sContext,sInput);
+            } catch (e) { }
+            return n;
+        },
+
+        isValid: _super.isValid,
+
+        whitelist: _super.whitelist
+    };
+};
+
+
+$namespace('org.owasp.esapi.reference.validation');
+
+org.owasp.esapi.reference.validation.StringValidationRule = function( sTypeName, oEncoder, oLocale, sWhiteListPattern ) {
+    var _super = new org.owasp.esapi.reference.validation.BaseValidationRule( sTypeName, oEncoder, oLocale );
+    var _validationTarget = 'String';
+
+    var whitelistPatterns = Array();
+    var blacklistPatterns = Array();
+    var minLength = 0;
+    var maxLength = Number.MAX_VALUE;
+    var validateInputAndCanonical = true;
+
+    if ( sWhiteListPattern ) {
+        if ( sWhiteListPattern instanceof String ) {
+            whitelistPatterns.push( new RegExp(sWhiteListPattern) );
+        } else if ( sWhiteListPattern instanceof RegExp ) {
+            whitelistPatterns.push( sWhiteListPattern );
+        } else {
+            throw new IllegalArgumentException("sWhiteListPattern must be a string containing RegExp or a RegExp Object");
+        }
+    }
+
+    var checkWhitelist = function( sContext, sInput, sOrig ) {
+        whitelistPatterns.each(function(p){
+            if ( sInput.match(p) ) {
+                _super.validationException( sContext, _validationTarget, "Whitelist", { "context":sContext, "input":sInput, "orig":sOrig, "pattern":p.toString(), "minLength":minLength, "maxLength":maxLength, "validateInputAndCanonical":validateInputAndCanonical } );
+            }
+        });
+    };
+
+    var checkBlacklist = function( sContext, sInput, sOrig ) {
+        blacklistPatterns.each(function(p){
+            if ( sInput.match(p) ) {
+                _super.validationException( sContext, _validationTarget, "Blacklist", { "context":sContext, "input":sInput, "orig":sOrig, "pattern":p.toString(), "minLength":minLength, "maxLength":maxLength, "validateInputAndCanonical":validateInputAndCanonical } );
+            }
+        });
+    };
+
+    var checkLength = function( sContext, sInput, sOrig ) {
+        if ( sInput.length < minLength ) {
+            _super.validationException( sContext, _validationTarget, "MinLength", { "context":sContext, "input":sInput, "orig":sOrig, "minLength":minLength, "maxLength":maxLength, "validateInputAndCanonical":validateInputAndCanonical } );
+        }
+        if ( sInput.length > maxLength ) {
+            _super.validationException( sContext, _validationTarget, "MaxLength", { "context":sContext, "input":sInput, "orig":sOrig, "minLength":minLength, "maxLength":maxLength, "validateInputAndCanonical":validateInputAndCanonical } );
+        }
+        return sInput;
+    };
+
+    var checkEmpty = function( sContext, sInput, sOrig ) {
+        if ( !sInput || sInput.trim() == '' ) {
+            if ( _super.isAllowNull() ) {
+                return null;
+            }
+            _super.validationException( sContext, _validationTarget, "Required", { "context":sContext, "input":sInput, "orig":sOrig, "minLength":minLength, "maxLength":maxLength, "validateInputAndCanonical":validateInputAndCanonical } );
+        }
+    };
+
+    return {
+        addWhitelistPattern: function(p) {
+            if ( p instanceof String ) {
+                whitelistPatterns.push( new RegExp(p) );
+            } else if ( p instanceof RegExp ) {
+                whitelistPatterns.push(p);
+            } else {
+                throw new IllegalArgumentException("p must be a string containing RegExp or a RegExp Object");
+            }
+        },
+
+        addBlacklistPattern: function(p) {
+            if ( p instanceof String ) {
+                blacklistPatterns.push( new RegExp(p) );
+            } else if ( p instanceof RegExp ) {
+                blacklistPatterns.push(p);
+            } else {
+                throw new IllegalArgumentException("p must be a string containing RegExp or a RegExp Object");
+            }
+        },
+
+        setMinLength: function(n) { minLength = n; },
+
+        getMinLength: function() { return minLength; },
+
+        setMaxLength: function(n) { maxLength = n; },
+
+        getMaxLength: function() { return maxLength; },
+
+        setValidateInputAndCanonical: function(b) { validateInputAndCanonical = b; },
+
+        isValidateInputAndCanonical: function() { return validateInputAndCanonical; },
+
+        setAllowNull: _super.setAllowNull,
+
+        isAllowNull: _super.isAllowNull,
+
+        getTypeName: _super.getTypeName,
+
+        setTypeName: _super.setTypeName,
+
+        setEncoder: _super.setEncoder,
+
+        getEncoder: _super.getEncoder,
+
+        assertValid: _super.assertValid,
+
+        getValid: _super.getValid,
+
+        getValidInput: function( sContext, sInput ) {
+            var canonical = null;
+
+            if ( checkEmpty( sContext, sInput ) == null ) {
+                return null;
+            }
+
+            if ( validateInputAndCanonical ) {
+                checkLength(sContext, sInput);
+                checkWhitelist(sContext,sInput);
+                checkBlacklist(sContext,sInput);
+            }
+
+            canonical = this.getEncoder().cananicalize(sInput);
+
+            if ( checkEmpty( sContext, canonical, sInput ) == null ) {
+                return null;
+            }
+
+            checkLength( sContext, canonical, sInput );
+            checkWhitelist( sContext, canonical, sInput );
+            checkBlacklist( sContext, canonical, sInput );
+
+            return canonical;
+        },
+
+        getSafe: _super.getSafe,
+
+        sanitize: function( sContext, sInput ) {
+            return this.whitelist( sInput, org.owasp.esapi.EncoderConstants.CHAR_ALNUM );
+        },
+
+        isValid: _super.isValid,
+
+        whitelist: _super.whitelist
+    };
+};
+
+
+$namespace('org.owasp.esapi.reference.validation');
+
+org.owasp.esapi.reference.validation.ValidationException = function( sUserMessage, sLogMessage ) {
+    var oException, sContext;
+    if ( arguments[2] && arguments[2] instanceof Exception ) {
+        oException = arguments[2];
+        if ( arguments[3] && arguments[3] instanceof String ) {
+            sContext = arguments[3];
+        }
+    } else if ( arguments[2] && arguments[2] instanceof String ) {
+        sContext = arguments[2];
+    }
+
+    var _super = new org.owasp.esapi.EnterpriseSecurityException( sUserMessage, sLogMessage, oException );
+
+    return {
+        setContext: function(s) { sContext = s; },
+        getContext: function() { return sContext; },
+        getMessage: _super.getMessage,
+        getUserMessage: _super.getMessage,
+        getLogMessage: _super.getLogMessage,
+        getStackTrace: _super.getStackTrace,
+        printStackTrace: _super.printStackTrace
+    };
+};
index 7dd30868a12e8da395785d16326622aa6fde87ee..eb3141b99ff99e6fd30d58663b9104aab17f0174 100644 (file)
-var _GET = parseGet();\r
-var _openedWindows = {};\r
-\r
-function getWmode() {\r
-       if (_GET['wmode'] != undefined) {\r
-               return _GET['wmode'];\r
-       }\r
-\r
-       var ua = navigator.userAgent;\r
-       if (ua.search(/mac/i) > -1 && ua.search(/opera/i) > -1) {\r
-               return 'normal';\r
-       } else {\r
-               return 'direct';\r
-       }\r
-}\r
-\r
-function getLocation() {\r
-       return window.location.toString();\r
-}\r
-\r
-function getPath() {\r
-       var l = window.location;\r
-\r
-       var res = l.toString();\r
-       var origin = l.protocol + '//' + l.host\r
-       return res.replace(origin, '');\r
-}\r
-\r
-function getFlashvars(junk, fv) {\r
-       var res = {};\r
-       if (fv != undefined) {\r
-               res = fv;\r
-       }\r
-\r
-       res = parseGet(res);\r
-\r
-       res['junk'] = junk;\r
-       return res;\r
-}\r
-\r
-function parseGet(res) {\r
-       if (res == undefined) {\r
-               res = {};\r
-       }\r
-       var couples = window.location.search.substr(1).split('&');\r
-       var couple = new Array();\r
-       for (var i = 0; i < couples.length; i++) {\r
-               couple = couples[i].split('=');\r
-               res[couple[0]] = couple[1];\r
-       }\r
-       return res;\r
-}\r
-\r
-function getLang() {\r
-       if (_GET.lang == undefined || _GET.lang == null || _GET.lang == '') {\r
-               return FB_DEFAULT_LANG;\r
-       }\r
-       return _GET.lang;\r
-}\r
-\r
-function mailto(adresse) {\r
-       window.location = 'mailto:' + adresse;\r
-}\r
-function getBookmarks(id) {\r
-       return getCookie('fb_bookmarks_' + id);\r
-}\r
-function setBookmarks(data, id) {\r
-       date = new Date;\r
-       date.setFullYear(date.getFullYear() + 10);\r
-       setCookie('fb_bookmarks_' + id, data, date, '/');\r
-}\r
-\r
-function popupFS(page) {\r
-       if (page == undefined) {\r
-               page = 0;\r
-       }\r
-       var date = new Date().getTime();\r
-       window.open('index.html#/' + page, 'fbpopupfs_' + date, 'width=' + screen.width + ',height=' + screen.height + ',resizable=yes');\r
-}\r
-\r
-function popupFocus(url, target) {\r
-       var openedw;\r
-       if (target.substr(0, 1) == '_') {\r
-               openedw = window.open(url, target, 'width=' + screen.width + ',height=' + screen.height + ',resizable=yes');\r
-       } else {\r
-               if (_openedWindows[target] != undefined && _openedWindows[target] != null) {\r
-                       openedw = _openedWindows[target];\r
-                       openedw.location = url;\r
-               } else {\r
-                       openedw = window.open(url, target, 'width=' + screen.width + ',height=' + screen.height + ',resizable=yes');\r
-                       _openedWindows[target] = openedw;\r
-               }\r
-       }\r
-\r
-\r
-\r
-\r
-       openedw.focus();\r
-}\r
-\r
-function getCookieVal(offset)\r
-{\r
-       var endstr = document.cookie.indexOf(";", offset);\r
-       if (endstr == -1) {\r
-               endstr = document.cookie.length;\r
-       }\r
-       return unescape(document.cookie.substring(offset, endstr));\r
-}\r
-function getCookie(nom)\r
-{\r
-       var arg = nom + "=";\r
-       var alen = arg.length;\r
-       var clen = document.cookie.length;\r
-       var i = 0;\r
-       while (i < clen) {\r
-               var j = i + alen;\r
-               if (document.cookie.substring(i, j) == arg) {\r
-                       return getCookieVal(j);\r
-               }\r
-               i = document.cookie.indexOf(" ", i) + 1;\r
-               if (i == 0) {\r
-                       break;\r
-               }\r
-       }\r
-       return null;\r
-}\r
-function setCookie(nom, valeur)\r
-{\r
-       date = new Date;\r
-       date.setFullYear(date.getFullYear() + 10);\r
-\r
-       var argv = setCookie.arguments;\r
-       var argc = setCookie.arguments.length;\r
-       var expires = (argc > 2) ? argv[2] : date;\r
-       var path = (argc > 3) ? argv[3] : '/';\r
-       var domain = (argc > 4) ? argv[4] : null;\r
-       var secure = (argc > 5) ? argv[5] : false;\r
-       document.cookie = nom + "=" + escape(valeur) +\r
-                       ((expires == null) ? "" : ("; expires=" + expires.toGMTString())) +\r
-                       ((path == null) ? "" : ("; path=/")) +\r
-                       ((domain == null) ? "" : ("; domain=" + domain)) +\r
-                       ((secure == true) ? "; secure" : "");\r
-}\r
-function addThis(x) {\r
-       addthis_offset_left = parseFloat(x);\r
-       addthis_open(document.getElementById('addThisBt'), '', '[URL]', '[TITLE]');\r
-}\r
-function handleWheel(delta) {\r
-       try {\r
-               fb(delta);\r
-               document.getElementById('fluidbook').mouseWheel(delta);\r
-       } catch (e) {\r
-\r
-       }\r
-}\r
-\r
-function isMobile() {\r
-       var devices = ['iphone', 'ipad', 'ipod', 'droid', 'blackberry', 'mobile', 'htc', 'samsung', 'nokia', 'archos', 'galaxy', 'motorola', 'pad', 'slate', 'symbian', 'phone', 'nintendo', 'playstation', 'touch', 'webos', 'ericsson', 'metro'];\r
-       return _isMobile(devices);\r
-}\r
-\r
-function isBadMobile() {\r
-       var devices = ['kindle'];\r
-       return _isMobile(devices);\r
-}\r
-\r
-function _isMobile(devices) {\r
-       var ua = navigator.userAgent;\r
-       var pattern;\r
-\r
-       for (i = 0; i < devices.length; i++) {\r
-               pattern = new RegExp(devices[i], 'i');\r
-               if (ua.search(pattern) > -1) {\r
-                       return true;\r
-               }\r
-       }\r
-       return false;\r
-}\r
-\r
-function redirectPDF() {\r
-       window.location = 'data/document.pdf';\r
-}\r
-\r
-function redirectMobile() {\r
-       var page = '';\r
-       var get = parseGet();\r
-       console.log(get);\r
-       var html = 'index.html';\r
-       if (get['widget'] != undefined && get['widget'] == '1') {\r
-               html = 'widget.html';\r
-               page = '?widget=1&';\r
-               if (get['background'] != undefined) {\r
-                       page += "background=" + get['background'];\r
-               }\r
-       }\r
-       var pageNr = 0;\r
-       if (get.page != undefined) {\r
-               pageNr = parseInt(get.page);\r
-       }\r
-       if (window.location.hash != '') {\r
-               var e = window.location.hash.split('/');\r
-               var pnr = parseInt(e[1]);\r
-               if (!isNaN(pnr)) {\r
-                       pageNr = pnr;\r
-               }\r
-       }\r
-\r
-\r
-       if (page == '' && pageNr > 0) {\r
-               page = '#/page/' + pageNr;\r
-       }\r
-\r
-       window.location = 'm/' + html + page;\r
-}\r
-\r
-function fb(e) {\r
-       try {\r
-               console.log(e);\r
-       } catch (err) {\r
-\r
-       }\r
-}\r
-\r
-\r
-function wheel(event) {\r
-       var delta = 0;\r
-       if (!event) /* For IE. */\r
-               event = window.event;\r
-       if (event.wheelDelta) { /* IE/Opera. */\r
-               delta = event.wheelDelta / 120;\r
-               /** In Opera 9, delta differs in sign as compared to IE.\r
-                */\r
-               if (window.opera)\r
-                       delta = -delta;\r
-       } else if (event.detail) { /** Mozilla case. */\r
-               /** In Mozilla, sign of delta is different than in IE.\r
-                * Also, delta is multiple of 3.\r
-                */\r
-               delta = -event.detail / 3;\r
-       }\r
-       /** If delta is nonzero, handle it.\r
-        * Basically, delta is now positive if wheel was scrolled up,\r
-        * and negative, if wheel was scrolled down.\r
-        */\r
-       if (delta) {\r
-               handleWheel(delta);\r
-       }\r
-       /** Prevent default actions caused by mouse wheel.\r
-        * That might be ugly, but we handle scrolls somehow\r
-        * anyway, so don't bother here..\r
-        */\r
-       if (event.preventDefault) {\r
-               event.preventDefault();\r
-       }\r
-       event.returnValue = false;\r
-}\r
-\r
-function ready() {\r
-       document.body.style.backgroundColor = '#' + getBackgroundColor();\r
-}\r
-\r
-function getBackgroundColor() {\r
-       if (_GET['background'] != undefined) {\r
-               return _GET['background'];\r
-       } else {\r
-               return backgroundColor;\r
-       }\r
-}\r
-\r
-/** Initialization code.\r
- * If you use your own event management code, change it as required.\r
- */\r
-if (window.addEventListener) {\r
-       /** DOMMouseScroll is for mozilla. */\r
-       window.addEventListener('DOMMouseScroll', wheel, false);\r
-}\r
-/** IE/Opera. */\r
-window.onmousewheel = document.onmousewheel = wheel;\r
-\r
-window.onkeydown = key;\r
-window.onkeypress = key;\r
-window.onkeydown = key;\r
-\r
-function key(e) {\r
-       if (e.ctrlKey && (e.keyCode == 80 || e.keyCode == 112)) {\r
-               return false;\r
-       }\r
-\r
-       return true;\r
+// Initialize the api
+org.owasp.esapi.ESAPI.initialize();
+
+var _GET = parseGet();
+var _openedWindows = {};
+
+function getWmode() {
+       if (_GET['wmode'] != undefined) {
+               return _GET['wmode'];
+       }
+
+       var ua = navigator.userAgent;
+       if (ua.search(/mac/i) > -1 && ua.search(/opera/i) > -1) {
+               return 'normal';
+       } else {
+               return 'direct';
+       }
+}
+
+function getLocation() {
+       return window.location.toString();
+}
+
+function getPath() {
+       var l = window.location;
+
+       var res = l.toString();
+       var origin = l.protocol + '//' + l.host
+       return res.replace(origin, '');
+}
+
+function getFlashvars(junk, fv) {
+       var res = {};
+       if (fv != undefined) {
+               res = fv;
+       }
+
+       res = parseGet(res);
+       res['junk'] = $ESAPI.encoder().encodeForJavaScript(junk);
+       return res;
+}
+
+function parseGet(res) {
+       if (res == undefined) {
+               res = {};
+       }
+       var couples = window.location.search.substr(1).split('&');
+       var couple = new Array();
+       for (var i = 0; i < couples.length; i++) {
+               couple = couples[i].split('=');
+               res[couple[0]] = $ESAPI.httpUtilities().getRequestParameter(couple[0]);
+       }
+       return res;
+}
+
+function getLang() {
+       if (_GET.lang == undefined || _GET.lang == null || _GET.lang == '') {
+               return FB_DEFAULT_LANG;
+       }
+       return _GET.lang;
+}
+
+function mailto(adresse) {
+       window.location = 'mailto:' + adresse;
+}
+function getBookmarks(id) {
+       return getCookie('fb_bookmarks_' + id);
+}
+function setBookmarks(data, id) {
+       date = new Date;
+       date.setFullYear(date.getFullYear() + 10);
+       setCookie('fb_bookmarks_' + id, data, date, '/');
+}
+
+function popupFS(page) {
+       if (page == undefined) {
+               page = 0;
+       }
+       var date = new Date().getTime();
+       window.open('index.html#/' + page, 'fbpopupfs_' + date, 'width=' + screen.width + ',height=' + screen.height + ',resizable=yes');
+}
+
+function popupFocus(url, target) {
+       var openedw;
+       if (target.substr(0, 1) == '_') {
+               openedw = window.open(url, target, 'width=' + screen.width + ',height=' + screen.height + ',resizable=yes');
+       } else {
+               if (_openedWindows[target] != undefined && _openedWindows[target] != null) {
+                       openedw = _openedWindows[target];
+                       openedw.location = url;
+               } else {
+                       openedw = window.open(url, target, 'width=' + screen.width + ',height=' + screen.height + ',resizable=yes');
+                       _openedWindows[target] = openedw;
+               }
+       }
+
+
+
+
+       openedw.focus();
+}
+
+function getCookieVal(offset)
+{
+       var endstr = document.cookie.indexOf(";", offset);
+       if (endstr == -1) {
+               endstr = document.cookie.length;
+       }
+       return unescape(document.cookie.substring(offset, endstr));
+}
+function getCookie(nom)
+{
+       return $ESAPI.httpUtilities().getCookie(nom);
+
+       /*var arg = nom + "=";
+        var alen = arg.length;
+        var clen = document.cookie.length;
+        var i = 0;
+        while (i < clen) {
+        var j = i + alen;
+        if (document.cookie.substring(i, j) == arg) {
+        return getCookieVal(j);
+        }
+        i = document.cookie.indexOf(" ", i) + 1;
+        if (i == 0) {
+        break;
+        }
+        }
+        return null;*/
+}
+function setCookie(nom, valeur)
+{
+       var cookie = new org.owasp.esapi.net.Cookie(nom, valeur);
+       cookie.setMaxAge(10 * 365 * 24 * 3600);
+       return $ESAPI.httpUtilities().addCookie(cookie);
+
+
+       /*date = new Date;
+        date.setFullYear(date.getFullYear() + 10);
+
+        var argv = setCookie.arguments;
+        var argc = setCookie.arguments.length;
+        var expires = (argc > 2) ? argv[2] : date;
+        var path = (argc > 3) ? argv[3] : '/';
+        var domain = (argc > 4) ? argv[4] : null;
+        var secure = (argc > 5) ? argv[5] : false;
+        document.cookie = nom + "=" + escape(valeur) +
+        ((expires == null) ? "" : ("; expires=" + expires.toGMTString())) +
+        ((path == null) ? "" : ("; path=/")) +
+        ((domain == null) ? "" : ("; domain=" + domain)) +
+        ((secure == true) ? "; secure" : "");*/
+}
+function addThis(x) {
+       addthis_offset_left = parseFloat(x);
+       addthis_open(document.getElementById('addThisBt'), '', '[URL]', '[TITLE]');
+}
+function handleWheel(delta) {
+       try {
+               fb(delta);
+               document.getElementById('fluidbook').mouseWheel(delta);
+       } catch (e) {
+
+       }
+}
+
+function isMobile() {
+       var devices = ['iphone', 'ipad', 'ipod', 'droid', 'blackberry', 'mobile', 'htc', 'samsung', 'nokia', 'archos', 'galaxy', 'motorola', 'pad', 'slate', 'symbian', 'phone', 'nintendo', 'playstation', 'touch', 'webos', 'ericsson', 'metro'];
+       return _isMobile(devices);
+}
+
+function isBadMobile() {
+       var devices = ['kindle'];
+       return _isMobile(devices);
+}
+
+function _isMobile(devices) {
+       var ua = navigator.userAgent;
+       var pattern;
+
+       for (i = 0; i < devices.length; i++) {
+               pattern = new RegExp(devices[i], 'i');
+               if (ua.search(pattern) > -1) {
+                       return true;
+               }
+       }
+       return false;
+}
+
+function redirectPDF() {
+       window.location = 'data/document.pdf';
+}
+
+function redirectMobile() {
+       var page = '';
+       var get = parseGet();
+       console.log(get);
+       var html = 'index.html';
+       if (get['widget'] != undefined && get['widget'] == '1') {
+               html = 'widget.html';
+               page = '?widget=1&';
+               if (get['background'] != undefined) {
+                       page += "background=" + get['background'];
+               }
+       }
+       var pageNr = 0;
+       if (get.page != undefined) {
+               pageNr = parseInt(get.page);
+       }
+       if (window.location.hash != '') {
+               var e = window.location.hash.split('/');
+               var pnr = parseInt(e[1]);
+               if (!isNaN(pnr)) {
+                       pageNr = pnr;
+               }
+       }
+
+
+       if (page == '' && pageNr > 0) {
+               page = '#/page/' + pageNr;
+       }
+
+       window.location = 'm/' + html + page;
+}
+
+function fb(e) {
+       try {
+               console.log(e);
+       } catch (err) {
+
+       }
+}
+
+
+function wheel(event) {
+       var delta = 0;
+       if (!event) /* For IE. */
+               event = window.event;
+       if (event.wheelDelta) { /* IE/Opera. */
+               delta = event.wheelDelta / 120;
+               /** In Opera 9, delta differs in sign as compared to IE.
+                */
+               if (window.opera)
+                       delta = -delta;
+       } else if (event.detail) { /** Mozilla case. */
+               /** In Mozilla, sign of delta is different than in IE.
+                * Also, delta is multiple of 3.
+                */
+               delta = -event.detail / 3;
+       }
+       /** If delta is nonzero, handle it.
+        * Basically, delta is now positive if wheel was scrolled up,
+        * and negative, if wheel was scrolled down.
+        */
+       if (delta) {
+               handleWheel(delta);
+       }
+       /** Prevent default actions caused by mouse wheel.
+        * That might be ugly, but we handle scrolls somehow
+        * anyway, so don't bother here..
+        */
+       if (event.preventDefault) {
+               event.preventDefault();
+       }
+       event.returnValue = false;
+}
+
+function ready() {
+       document.body.style.backgroundColor = '#' + getBackgroundColor();
+}
+
+function getBackgroundColor() {
+       if (_GET['background'] != undefined) {
+               return _GET['background'];
+       } else {
+               return backgroundColor;
+       }
+}
+
+/** Initialization code.
+ * If you use your own event management code, change it as required.
+ */
+if (window.addEventListener) {
+       /** DOMMouseScroll is for mozilla. */
+       window.addEventListener('DOMMouseScroll', wheel, false);
+}
+/** IE/Opera. */
+window.onmousewheel = document.onmousewheel = wheel;
+
+window.onkeydown = key;
+window.onkeypress = key;
+window.onkeydown = key;
+
+function key(e) {
+       if (e.ctrlKey && (e.keyCode == 80 || e.keyCode == 112)) {
+               return false;
+       }
+
+       return true;
 }
\ No newline at end of file
diff --git a/fluidbook/compile/_js/log4js-lib.js b/fluidbook/compile/_js/log4js-lib.js
new file mode 100644 (file)
index 0000000..86a6697
--- /dev/null
@@ -0,0 +1 @@
+var Log4js={version:"1.0",applicationStartDate:new Date(),loggers:{},getLogger:function(categoryName){if(!(typeof categoryName=="string")){categoryName="[default]";}if(!Log4js.loggers[categoryName]){Log4js.loggers[categoryName]=new Log4js.Logger(categoryName);}return Log4js.loggers[categoryName];},getDefaultLogger:function(){return Log4js.getLogger("[default]");},attachEvent:function(element,name,observer){if(element.addEventListener){element.addEventListener(name,observer,false);}else if(element.attachEvent){element.attachEvent('on'+name,observer);}}};Log4js.extend=function(destination,source){for(property in source){destination[property]=source[property];}return destination;}Log4js.bind=function(fn,object){return function(){return fn.apply(object,arguments);};};Log4js.Level=function(level,levelStr){this.level=level;this.levelStr=levelStr;};Log4js.Level.prototype={toLevel:function(sArg,defaultLevel){if(sArg===null){return defaultLevel;}if(typeof sArg=="string"){var s=sArg.toUpperCase();if(s=="ALL"){return Log4js.Level.ALL;}if(s=="DEBUG"){return Log4js.Level.DEBUG;}if(s=="INFO"){return Log4js.Level.INFO;}if(s=="WARN"){return Log4js.Level.WARN;}if(s=="ERROR"){return Log4js.Level.ERROR;}if(s=="FATAL"){return Log4js.Level.FATAL;}if(s=="OFF"){return Log4js.Level.OFF;}if(s=="TRACE"){return Log4js.Level.TRACE;}return defaultLevel;}else if(typeof sArg=="number"){switch(sArg){case ALL_INT:return Log4js.Level.ALL;case DEBUG_INT:return Log4js.Level.DEBUG;case INFO_INT:return Log4js.Level.INFO;case WARN_INT:return Log4js.Level.WARN;case ERROR_INT:return Log4js.Level.ERROR;case FATAL_INT:return Log4js.Level.FATAL;case OFF_INT:return Log4js.Level.OFF;case TRACE_INT:return Log4js.Level.TRACE;default:return defaultLevel;}}else{return defaultLevel;}},toString:function(){return this.levelStr;},valueOf:function(){return this.level;}};Log4js.Level.OFF_INT=Number.MAX_VALUE;Log4js.Level.FATAL_INT=50000;Log4js.Level.ERROR_INT=40000;Log4js.Level.WARN_INT=30000;Log4js.Level.INFO_INT=20000;Log4js.Level.DEBUG_INT=10000;Log4js.Level.TRACE_INT=5000;Log4js.Level.ALL_INT=Number.MIN_VALUE;Log4js.Level.OFF=new Log4js.Level(Log4js.Level.OFF_INT,"OFF");Log4js.Level.FATAL=new Log4js.Level(Log4js.Level.FATAL_INT,"FATAL");Log4js.Level.ERROR=new Log4js.Level(Log4js.Level.ERROR_INT,"ERROR");Log4js.Level.WARN=new Log4js.Level(Log4js.Level.WARN_INT,"WARN");Log4js.Level.INFO=new Log4js.Level(Log4js.Level.INFO_INT,"INFO");Log4js.Level.DEBUG=new Log4js.Level(Log4js.Level.DEBUG_INT,"DEBUG");Log4js.Level.TRACE=new Log4js.Level(Log4js.Level.TRACE_INT,"TRACE");Log4js.Level.ALL=new Log4js.Level(Log4js.Level.ALL_INT,"ALL");Log4js.CustomEvent=function(){this.listeners=[];};Log4js.CustomEvent.prototype={addListener:function(method){this.listeners.push(method);},removeListener:function(method){var foundIndexes=this.findListenerIndexes(method);for(var i=0;i<foundIndexes.length;i++){this.listeners.splice(foundIndexes[i],1);}},dispatch:function(handler){for(var i=0;i<this.listeners.length;i++){try{this.listeners[i](handler);}catch(e){log4jsLogger.warn("Could not run the listener "+this.listeners[i]+". \n"+e);}}},findListenerIndexes:function(method){var indexes=[];for(var i=0;i<this.listeners.length;i++){if(this.listeners[i]==method){indexes.push(i);}}return indexes;}};Log4js.LoggingEvent=function(categoryName,level,message,exception,logger){this.startTime=new Date();this.categoryName=categoryName;this.message=message;this.exception=exception;this.level=level;this.logger=logger;};Log4js.LoggingEvent.prototype={getFormattedTimestamp:function(){if(this.logger){return this.logger.getFormattedTimestamp(this.startTime);}else{return this.startTime.toGMTString();}}};Log4js.Logger=function(name){this.loggingEvents=[];this.appenders=[];this.category=name||"";this.level=Log4js.Level.FATAL;this.dateformat=Log4js.DateFormatter.DEFAULT_DATE_FORMAT;this.dateformatter=new Log4js.DateFormatter();this.onlog=new Log4js.CustomEvent();this.onclear=new Log4js.CustomEvent();this.appenders.push(new Log4js.Appender(this));try{window.onerror=this.windowError.bind(this);}catch(e){}};Log4js.Logger.prototype={addAppender:function(appender){if(appender instanceof Log4js.Appender){appender.setLogger(this);this.appenders.push(appender);}else{throw "Not instance of an Appender: "+appender;}},setAppenders:function(appenders){for(var i=0;i<this.appenders.length;i++){this.appenders[i].doClear();}this.appenders=appenders;for(var j=0;j<this.appenders.length;j++){this.appenders[j].setLogger(this);}},setLevel:function(level){this.level=level;},log:function(logLevel,message,exception){var loggingEvent=new Log4js.LoggingEvent(this.category,logLevel,message,exception,this);this.loggingEvents.push(loggingEvent);this.onlog.dispatch(loggingEvent);},clear:function(){try{this.loggingEvents=[];this.onclear.dispatch();}catch(e){}},isTraceEnabled:function(){if(this.level.valueOf()<=Log4js.Level.TRACE.valueOf()){return true;}return false;},trace:function(message){if(this.isTraceEnabled()){this.log(Log4js.Level.TRACE,message,null);}},isDebugEnabled:function(){if(this.level.valueOf()<=Log4js.Level.DEBUG.valueOf()){return true;}return false;},debug:function(message){if(this.isDebugEnabled()){this.log(Log4js.Level.DEBUG,message,null);}},debug:function(message,throwable){if(this.isDebugEnabled()){this.log(Log4js.Level.DEBUG,message,throwable);}},isInfoEnabled:function(){if(this.level.valueOf()<=Log4js.Level.INFO.valueOf()){return true;}return false;},info:function(message){if(this.isInfoEnabled()){this.log(Log4js.Level.INFO,message,null);}},info:function(message,throwable){if(this.isInfoEnabled()){this.log(Log4js.Level.INFO,message,throwable);}},isWarnEnabled:function(){if(this.level.valueOf()<=Log4js.Level.WARN.valueOf()){return true;}return false;},warn:function(message){if(this.isWarnEnabled()){this.log(Log4js.Level.WARN,message,null);}},warn:function(message,throwable){if(this.isWarnEnabled()){this.log(Log4js.Level.WARN,message,throwable);}},isErrorEnabled:function(){if(this.level.valueOf()<=Log4js.Level.ERROR.valueOf()){return true;}return false;},error:function(message){if(this.isErrorEnabled()){this.log(Log4js.Level.ERROR,message,null);}},error:function(message,throwable){if(this.isErrorEnabled()){this.log(Log4js.Level.ERROR,message,throwable);}},isFatalEnabled:function(){if(this.level.valueOf()<=Log4js.Level.FATAL.valueOf()){return true;}return false;},fatal:function(message){if(this.isFatalEnabled()){this.log(Log4js.Level.FATAL,message,null);}},fatal:function(message,throwable){if(this.isFatalEnabled()){this.log(Log4js.Level.FATAL,message,throwable);}},windowError:function(msg,url,line){var message="Error in ("+(url||window.location)+") on line "+line+" with message ("+msg+")";this.log(Log4js.Level.FATAL,message,null);},setDateFormat:function(format){this.dateformat=format;},getFormattedTimestamp:function(date){return this.dateformatter.formatDate(date,this.dateformat);}};Log4js.Appender=function(){this.logger=null;};Log4js.Appender.prototype={doAppend:function(loggingEvent){return;},doClear:function(){return;},setLayout:function(layout){this.layout=layout;},setLogger:function(logger){logger.onlog.addListener(Log4js.bind(this.doAppend,this));logger.onclear.addListener(Log4js.bind(this.doClear,this));this.logger=logger;}};Log4js.Layout=function(){return;};Log4js.Layout.prototype={format:function(loggingEvent){return "";},getContentType:function(){return "text/plain";},getHeader:function(){return null;},getFooter:function(){return null;},getSeparator:function(){return "";}};Log4js.ConsoleAppender=function(isInline){this.layout=new Log4js.PatternLayout(Log4js.PatternLayout.TTCC_CONVERSION_PATTERN);this.inline=isInline;this.accesskey="d";this.tagPattern=null;this.commandHistory=[];this.commandIndex=0;this.popupBlocker=false;this.outputElement=null;this.docReference=null;this.winReference=null;if(this.inline){Log4js.attachEvent(window,'load',Log4js.bind(this.initialize,this));}};Log4js.ConsoleAppender.prototype=Log4js.extend(new Log4js.Appender(),{setAccessKey:function(key){this.accesskey=key;},initialize:function(){if(!this.inline){var doc=null;var win=null;window.top.consoleWindow=window.open("",this.logger.category,"left=0,top=0,width=700,height=700,scrollbars=no,status=no,resizable=yes;toolbar=no");window.top.consoleWindow.opener=self;win=window.top.consoleWindow;if(!win){this.popupBlocker=true;alert("Popup window manager blocking the Log4js popup window to bedisplayed.\n\n"+"Please disabled this to properly see logged events.");}else{doc=win.document;doc.open();doc.write("<!DOCTYPE html PUBLIC -//W3C//DTD XHTML 1.0 Transitional//EN ");doc.write("  http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd>\n\n");doc.write("<html><head><title>Log4js - "+this.logger.category+"</title>\n");doc.write("</head><body style=\"background-color:darkgray\"></body>\n");win.blur();win.focus();}this.docReference=doc;this.winReference=win;}else{this.docReference=document;this.winReference=window;}this.outputCount=0;this.tagPattern=".*";this.logElement=this.docReference.createElement('div');this.docReference.body.appendChild(this.logElement);this.logElement.style.display='none';this.logElement.style.position="absolute";this.logElement.style.left='0px';this.logElement.style.width='100%';this.logElement.style.textAlign="left";this.logElement.style.fontFamily="lucida console";this.logElement.style.fontSize="100%";this.logElement.style.backgroundColor='darkgray';this.logElement.style.opacity=0.9;this.logElement.style.zIndex=2000;this.toolbarElement=this.docReference.createElement('div');this.logElement.appendChild(this.toolbarElement);this.toolbarElement.style.padding="0 0 0 2px";this.buttonsContainerElement=this.docReference.createElement('span');this.toolbarElement.appendChild(this.buttonsContainerElement);if(this.inline){var closeButton=this.docReference.createElement('button');closeButton.style.cssFloat="right";closeButton.style.styleFloat="right";closeButton.style.color="black";closeButton.innerHTML="close";closeButton.onclick=Log4js.bind(this.toggle,this);this.buttonsContainerElement.appendChild(closeButton);}var clearButton=this.docReference.createElement('button');clearButton.style.cssFloat="right";clearButton.style.styleFloat="right";clearButton.style.color="black";clearButton.innerHTML="clear";clearButton.onclick=Log4js.bind(this.logger.clear,this.logger);this.buttonsContainerElement.appendChild(clearButton);this.tagFilterContainerElement=this.docReference.createElement('span');this.toolbarElement.appendChild(this.tagFilterContainerElement);this.tagFilterContainerElement.style.cssFloat='left';this.tagFilterContainerElement.appendChild(this.docReference.createTextNode("Log4js - "+this.logger.category));this.tagFilterContainerElement.appendChild(this.docReference.createTextNode(" | Level Filter: "));this.tagFilterElement=this.docReference.createElement('input');this.tagFilterContainerElement.appendChild(this.tagFilterElement);this.tagFilterElement.style.width='200px';this.tagFilterElement.value=this.tagPattern;this.tagFilterElement.setAttribute('autocomplete','off');Log4js.attachEvent(this.tagFilterElement,'keyup',Log4js.bind(this.updateTags,this));Log4js.attachEvent(this.tagFilterElement,'click',Log4js.bind(function(){this.tagFilterElement.select();},this));this.outputElement=this.docReference.createElement('div');this.logElement.appendChild(this.outputElement);this.outputElement.style.overflow="auto";this.outputElement.style.clear="both";this.outputElement.style.height=(this.inline)?("200px"):("650px");this.outputElement.style.width="100%";this.outputElement.style.backgroundColor='black';this.inputContainerElement=this.docReference.createElement('div');this.inputContainerElement.style.width="100%";this.logElement.appendChild(this.inputContainerElement);this.inputElement=this.docReference.createElement('input');this.inputContainerElement.appendChild(this.inputElement);this.inputElement.style.width='100%';this.inputElement.style.borderWidth='0px';this.inputElement.style.margin='0px';this.inputElement.style.padding='0px';this.inputElement.value='Type command here';this.inputElement.setAttribute('autocomplete','off');Log4js.attachEvent(this.inputElement,'keyup',Log4js.bind(this.handleInput,this));Log4js.attachEvent(this.inputElement,'click',Log4js.bind(function(){this.inputElement.select();},this));if(this.inline){window.setInterval(Log4js.bind(this.repositionWindow,this),500);this.repositionWindow();var accessElement=this.docReference.createElement('button');accessElement.style.position="absolute";accessElement.style.top="-100px";accessElement.accessKey=this.accesskey;accessElement.onclick=Log4js.bind(this.toggle,this);this.docReference.body.appendChild(accessElement);}else{this.show();}},toggle:function(){if(this.logElement.style.display=='none'){this.show();return true;}else{this.hide();return false;}},show:function(){this.logElement.style.display='';this.outputElement.scrollTop=this.outputElement.scrollHeight;this.inputElement.select();},hide:function(){this.logElement.style.display='none';},output:function(message,style){var shouldScroll=(this.outputElement.scrollTop+(2*this.outputElement.clientHeight))>=this.outputElement.scrollHeight;this.outputCount++;style=(style?style+=';':'');style+='padding:1px;margin:0 0 5px 0';if(this.outputCount%2===0){style+=";background-color:#101010";}message=message||"undefined";message=message.toString();this.outputElement.innerHTML+="<pre style='"+style+"'>"+message+"</pre>";if(shouldScroll){this.outputElement.scrollTop=this.outputElement.scrollHeight;}},updateTags:function(){var pattern=this.tagFilterElement.value;if(this.tagPattern==pattern){return;}try{new RegExp(pattern);}catch(e){return;}this.tagPattern=pattern;this.outputElement.innerHTML="";this.outputCount=0;for(var i=0;i<this.logger.loggingEvents.length;i++){this.doAppend(this.logger.loggingEvents[i]);}},repositionWindow:function(){var offset=window.pageYOffset||this.docReference.documentElement.scrollTop||this.docReference.body.scrollTop;var pageHeight=self.innerHeight||this.docReference.documentElement.clientHeight||this.docReference.body.clientHeight;this.logElement.style.top=(offset+pageHeight-this.logElement.offsetHeight)+"px";},doAppend:function(loggingEvent){if(this.popupBlocker){return;}if((!this.inline)&&(!this.winReference||this.winReference.closed)){this.initialize();}if(this.tagPattern!==null&&loggingEvent.level.toString().search(new RegExp(this.tagPattern,'igm'))==-1){return;}var style='';if(loggingEvent.level.toString().search(/ERROR/)!=-1){style+='color:red';}else if(loggingEvent.level.toString().search(/FATAL/)!=-1){style+='color:red';}else if(loggingEvent.level.toString().search(/WARN/)!=-1){style+='color:orange';}else if(loggingEvent.level.toString().search(/DEBUG/)!=-1){style+='color:green';}else if(loggingEvent.level.toString().search(/INFO/)!=-1){style+='color:white';}else{style+='color:yellow';}this.output(this.layout.format(loggingEvent),style);},doClear:function(){this.outputElement.innerHTML="";},handleInput:function(e){if(e.keyCode==13){var command=this.inputElement.value;switch(command){case "clear":this.logger.clear();break;default:var consoleOutput="";try{consoleOutput=eval(this.inputElement.value);}catch(e){this.logger.error("Problem parsing input <"+command+">"+e.message);break;}this.logger.trace(consoleOutput);break;}if(this.inputElement.value!==""&&this.inputElement.value!==this.commandHistory[0]){this.commandHistory.unshift(this.inputElement.value);}this.commandIndex=0;this.inputElement.value="";}else if(e.keyCode==38&&this.commandHistory.length>0){this.inputElement.value=this.commandHistory[this.commandIndex];if(this.commandIndex<this.commandHistory.length-1){this.commandIndex+=1;}}else if(e.keyCode==40&&this.commandHistory.length>0){if(this.commandIndex>0){this.commandIndex-=1;}this.inputElement.value=this.commandHistory[this.commandIndex];}else{this.commandIndex=0;}},toString:function(){return "Log4js.ConsoleAppender[inline="+this.inline+"]";}});Log4js.MetatagAppender=function(){this.currentLine=0;};Log4js.MetatagAppender.prototype=Log4js.extend(new Log4js.Appender(),{doAppend:function(loggingEvent){var now=new Date();var lines=loggingEvent.message.split("\n");var headTag=document.getElementsByTagName("head")[0];for(var i=1;i<=lines.length;i++){var value=lines[i-1];if(i==1){value=loggingEvent.level.toString()+": "+value;}else{value="> "+value;}var metaTag=document.createElement("meta");metaTag.setAttribute("name","X-log4js:"+this.currentLine);metaTag.setAttribute("content",value);headTag.appendChild(metaTag);this.currentLine+=1;}},toString:function(){return "Log4js.MetatagAppender";}});Log4js.AjaxAppender=function(loggingUrl){this.isInProgress=false;this.loggingUrl=loggingUrl||"logging.log4js";this.threshold=1;this.timeout=2000;this.loggingEventMap=new Log4js.FifoBuffer();this.layout=new Log4js.XMLLayout();this.httpRequest=null;};Log4js.AjaxAppender.prototype=Log4js.extend(new Log4js.Appender(),{doAppend:function(loggingEvent){log4jsLogger.trace("> AjaxAppender.append");if(this.loggingEventMap.length()<=this.threshold||this.isInProgress===true){this.loggingEventMap.push(loggingEvent);}if(this.loggingEventMap.length()>=this.threshold&&this.isInProgress===false){this.send();}log4jsLogger.trace("< AjaxAppender.append");},doClear:function(){log4jsLogger.trace("> AjaxAppender.doClear");if(this.loggingEventMap.length()>0){this.send();}log4jsLogger.trace("< AjaxAppender.doClear");},setThreshold:function(threshold){log4jsLogger.trace("> AjaxAppender.setThreshold: "+threshold);this.threshold=threshold;log4jsLogger.trace("< AjaxAppender.setThreshold");},setTimeout:function(milliseconds){this.timeout=milliseconds;},send:function(){if(this.loggingEventMap.length()>0){log4jsLogger.trace("> AjaxAppender.send");this.isInProgress=true;var a=[];for(var i=0;i<this.loggingEventMap.length()&&i<this.threshold;i++){a.push(this.layout.format(this.loggingEventMap.pull()));}var content=this.layout.getHeader();content+=a.join(this.layout.getSeparator());content+=this.layout.getFooter();var appender=this;if(this.httpRequest===null){this.httpRequest=this.getXmlHttpRequest();}this.httpRequest.onreadystatechange=function(){appender.onReadyStateChanged.call(appender);};this.httpRequest.open("POST",this.loggingUrl,true);this.httpRequest.setRequestHeader("Content-type",this.layout.getContentType());this.httpRequest.setRequestHeader("REFERER",location.href);this.httpRequest.setRequestHeader("Content-length",content.length);this.httpRequest.setRequestHeader("Connection","close");this.httpRequest.send(content);appender=this;try{window.setTimeout(function(){log4jsLogger.trace("> AjaxAppender.timeout");appender.httpRequest.onreadystatechange=function(){return;};appender.httpRequest.abort();appender.isInProgress=false;if(appender.loggingEventMap.length()>0){appender.send();}log4jsLogger.trace("< AjaxAppender.timeout");},this.timeout);}catch(e){log4jsLogger.fatal(e);}log4jsLogger.trace("> AjaxAppender.send");}},onReadyStateChanged:function(){log4jsLogger.trace("> AjaxAppender.onReadyStateChanged");var req=this.httpRequest;if(this.httpRequest.readyState!=4){log4jsLogger.trace("< AjaxAppender.onReadyStateChanged: readyState "+req.readyState+" != 4");return;}var success=((typeof req.status==="undefined")||req.status===0||(req.status>=200&&req.status<300));if(success){log4jsLogger.trace("  AjaxAppender.onReadyStateChanged: success");this.isInProgress=false;}else{var msg="  AjaxAppender.onReadyStateChanged: XMLHttpRequest request to URL "+this.loggingUrl+" returned status code "+this.httpRequest.status;log4jsLogger.error(msg);}log4jsLogger.trace("< AjaxAppender.onReadyStateChanged: readyState == 4");},getXmlHttpRequest:function(){log4jsLogger.trace("> AjaxAppender.getXmlHttpRequest");var httpRequest=false;try{if(window.XMLHttpRequest){httpRequest=new XMLHttpRequest();if(httpRequest.overrideMimeType){httpRequest.overrideMimeType(this.layout.getContentType());}}else if(window.ActiveXObject){try{httpRequest=new ActiveXObject("Msxml2.XMLHTTP");}catch(e){httpRequest=new ActiveXObject("Microsoft.XMLHTTP");}}}catch(e){httpRequest=false;}if(!httpRequest){log4jsLogger.fatal("Unfortunatelly your browser does not support AjaxAppender for log4js!");}log4jsLogger.trace("< AjaxAppender.getXmlHttpRequest");return httpRequest;},toString:function(){return "Log4js.AjaxAppender[loggingUrl="+this.loggingUrl+", threshold="+this.threshold+"]";}});Log4js.FileAppender=function(file){this.layout=new Log4js.SimpleLayout();this.isIE='undefined';this.file=file||"log4js.log";try{this.fso=new ActiveXObject("Scripting.FileSystemObject");this.isIE=true;}catch(e){try{netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");this.fso=Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);this.isIE=false;}catch(e){log4jsLogger.error(e);}}};Log4js.FileAppender.prototype=Log4js.extend(new Log4js.Appender(),{doAppend:function(loggingEvent){try{var fileHandle=null;if(this.isIE==='undefined'){log4jsLogger.error("Unsupported ")}else if(this.isIE){fileHandle=this.fso.OpenTextFile(this.file,8,true);fileHandle.WriteLine(this.layout.format(loggingEvent));fileHandle.close();}else{netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");this.fso.initWithPath(this.file);if(!this.fso.exists()){this.fso.create(0x00,0600);}fileHandle=Components.classes["@mozilla.org/network/file-output-stream;1"].createInstance(Components.interfaces.nsIFileOutputStream);fileHandle.init(this.fso,0x04|0x08|0x10,064,0);var line=this.layout.format(loggingEvent);fileHandle.write(line,line.length);fileHandle.close();}}catch(e){log4jsLogger.error(e);}},doClear:function(){try{if(this.isIE){var fileHandle=this.fso.GetFile(this.file);fileHandle.Delete();}else{netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");this.fso.initWithPath(this.file);if(this.fso.exists()){this.fso.remove(false);}}}catch(e){log4jsLogger.error(e);}},toString:function(){return "Log4js.FileAppender[file="+this.file+"]";}});Log4js.WindowsEventAppender=function(){this.layout=new Log4js.SimpleLayout();try{this.shell=new ActiveXObject("WScript.Shell");}catch(e){log4jsLogger.error(e);}};Log4js.WindowsEventAppender.prototype=Log4js.extend(new Log4js.Appender(),{doAppend:function(loggingEvent){var winLevel=4;switch(loggingEvent.level){case Log4js.Level.FATAL:winLevel=1;break;case Log4js.Level.ERROR:winLevel=1;break;case Log4js.Level.WARN:winLevel=2;break;default:winLevel=4;break;}try{this.shell.LogEvent(winLevel,this.level.format(loggingEvent));}catch(e){log4jsLogger.error(e);}},toString:function(){return "Log4js.WindowsEventAppender";}});Log4js.JSAlertAppender=function(){this.layout=new Log4js.SimpleLayout();};Log4js.JSAlertAppender.prototype=Log4js.extend(new Log4js.Appender(),{doAppend:function(loggingEvent){alert(this.layout.getHeader()+this.layout.format(loggingEvent)+this.layout.getFooter());},toString:function(){return "Log4js.JSAlertAppender";}});Log4js.MozillaJSConsoleAppender=function(){this.layout=new Log4js.SimpleLayout();try{netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");this.jsConsole=Components.classes["@mozilla.org/consoleservice;1"].getService(Components.interfaces.nsIConsoleService);this.scriptError=Components.classes["@mozilla.org/scripterror;1"].createInstance(Components.interfaces.nsIScriptError);}catch(e){log4jsLogger.error(e);}};Log4js.MozillaJSConsoleAppender.prototype=Log4js.extend(new Log4js.Appender(),{doAppend:function(loggingEvent){try{netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");this.scriptError.init(this.layout.format(loggingEvent),null,null,null,null,this.getFlag(loggingEvent),loggingEvent.categoryName);this.jsConsole.logMessage(this.scriptError);}catch(e){log4jsLogger.error(e);}},toString:function(){return "Log4js.MozillaJSConsoleAppender";},getFlag:function(loggingEvent){var retval;switch(loggingEvent.level){case Log4js.Level.FATAL:retval=2;break;case Log4js.Level.ERROR:retval=0;break;case Log4js.Level.WARN:retval=1;break;default:retval=1;break;}return retval;}});Log4js.OperaJSConsoleAppender=function(){this.layout=new Log4js.SimpleLayout();};Log4js.OperaJSConsoleAppender.prototype=Log4js.extend(new Log4js.Appender(),{doAppend:function(loggingEvent){opera.postError(this.layout.format(loggingEvent));},toString:function(){return "Log4js.OperaJSConsoleAppender";}});Log4js.SafariJSConsoleAppender=function(){this.layout=new Log4js.SimpleLayout();};Log4js.SafariJSConsoleAppender.prototype=Log4js.extend(new Log4js.Appender(),{doAppend:function(loggingEvent){window.console.log(this.layout.format(loggingEvent));},toString:function(){return "Log4js.SafariJSConsoleAppender";}});Log4js.BrowserConsoleAppender=function(){this.consoleDelegate=null;if(window.console){this.consoleDelegate=new Log4js.SafariJSConsoleAppender();}else if(window.opera){this.consoleDelegate=new Log4js.OperaJSConsoleAppender();}else if(netscape){this.consoleDelegate=new Log4js.MozJSConsoleAppender();}else{log4jsLogger.error("Unsupported Browser");}};Log4js.BrowserConsoleAppender.prototype=Log4js.extend(new Log4js.Appender(),{doAppend:function(loggingEvent){this.consoleDelegate.doAppend(loggingEvent);},doClear:function(){this.consoleDelegate.doClear();},setLayout:function(layout){this.consoleDelegate.setLayout(layout);},toString:function(){return "Log4js.BrowserConsoleAppender: "+this.consoleDelegate.toString();}});Log4js.SimpleLayout=function(){this.LINE_SEP="\n";this.LINE_SEP_LEN=1;};Log4js.SimpleLayout.prototype=Log4js.extend(new Log4js.Layout(),{format:function(loggingEvent){return loggingEvent.level.toString()+" - "+loggingEvent.message+this.LINE_SEP;},getContentType:function(){return "text/plain";},getHeader:function(){return "";},getFooter:function(){return "";}});Log4js.BasicLayout=function(){this.LINE_SEP="\n";};Log4js.BasicLayout.prototype=Log4js.extend(new Log4js.Layout(),{format:function(loggingEvent){return loggingEvent.categoryName+"~"+loggingEvent.startTime.toLocaleString()+" ["+loggingEvent.level.toString()+"] "+loggingEvent.message+this.LINE_SEP;},getContentType:function(){return "text/plain";},getHeader:function(){return "";},getFooter:function(){return "";}});Log4js.HtmlLayout=function(){return;};Log4js.HtmlLayout.prototype=Log4js.extend(new Log4js.Layout(),{format:function(loggingEvent){return "<div style=\""+this.getStyle(loggingEvent)+"\">"+loggingEvent.getFormattedTimestamp()+" - "+loggingEvent.level.toString()+" - "+loggingEvent.message+"</div>\n";},getContentType:function(){return "text/html";},getHeader:function(){return "<html><head><title>log4js</head><body>";},getFooter:function(){return "</body></html>";},getStyle:function(loggingEvent){var style;if(loggingEvent.level.toString().search(/ERROR/)!=-1){style='color:red';}else if(loggingEvent.level.toString().search(/FATAL/)!=-1){style='color:red';}else if(loggingEvent.level.toString().search(/WARN/)!=-1){style='color:orange';}else if(loggingEvent.level.toString().search(/DEBUG/)!=-1){style='color:green';}else if(loggingEvent.level.toString().search(/INFO/)!=-1){style='color:white';}else{style='color:yellow';}return style;}});Log4js.XMLLayout=function(){return;};Log4js.XMLLayout.prototype=Log4js.extend(new Log4js.Layout(),{format:function(loggingEvent){var useragent="unknown";try{useragent=navigator.userAgent;}catch(e){useragent="unknown";}var referer="unknown";try{referer=location.href;}catch(e){referer="unknown";}var content="<log4js:event logger=\"";content+=loggingEvent.categoryName+"\" level=\"";content+=loggingEvent.level.toString()+"\" useragent=\"";content+=useragent+"\" referer=\"";content+=referer.replace(/&/g,"&amp;")+"\" timestamp=\"";content+=loggingEvent.getFormattedTimestamp()+"\">\n";content+="\t<log4js:message><![CDATA["+this.escapeCdata(loggingEvent.message)+"]]></log4js:message>\n";if(loggingEvent.exception){content+=this.formatException(loggingEvent.exception);}content+="</log4js:event>\n";return content;},getContentType:function(){return "text/xml";},getHeader:function(){return "<log4js:eventSet version=\""+Log4js.version+"\" xmlns:log4js=\"http://log4js.berlios.de/2007/log4js/\">\n";},getFooter:function(){return "</log4js:eventSet>\n";},getSeparator:function(){return "\n";},formatException:function(ex){if(ex){var exStr="\t<log4js:throwable>";if(ex.message){exStr+="\t\t<log4js:message><![CDATA["+this.escapeCdata(ex.message)+"]]></log4js:message>\n";}if(ex.description){exStr+="\t\t<log4js:description><![CDATA["+this.escapeCdata(ex.description)+"]]></log4js:description>\n";}exStr+="\t\t<log4js:stacktrace>";exStr+="\t\t\t<log4js:location fileName=\""+ex.fileName+"\" lineNumber=\""+ex.lineNumber+"\" />";exStr+="\t\t</log4js:stacktrace>";exStr="\t</log4js:throwable>";return exStr;}return null;},escapeCdata:function(str){return str.replace(/\]\]>/,"]]>]]&gt;<![CDATA[");}});Log4js.JSONLayout=function(){this.df=new Log4js.DateFormatter();};Log4js.JSONLayout.prototype=Log4js.extend(new Log4js.Layout(),{format:function(loggingEvent){var useragent="unknown";try{useragent=navigator.userAgent;}catch(e){useragent="unknown";}var referer="unknown";try{referer=location.href;}catch(e){referer="unknown";}var jsonString="{\n \"LoggingEvent\": {\n";jsonString+="\t\"logger\": \""+loggingEvent.categoryName+"\",\n";jsonString+="\t\"level\": \""+loggingEvent.level.toString()+"\",\n";jsonString+="\t\"message\": \""+loggingEvent.message+"\",\n";jsonString+="\t\"referer\": \""+referer+"\",\n";jsonString+="\t\"useragent\": \""+useragent+"\",\n";jsonString+="\t\"timestamp\": \""+this.df.formatDate(loggingEvent.startTime,"yyyy-MM-ddThh:mm:ssZ")+"\",\n";jsonString+="\t\"exception\": \""+loggingEvent.exception+"\"\n";jsonString+="}}";return jsonString;},getContentType:function(){return "text/json";},getHeader:function(){return "{\"Log4js\": [\n";},getFooter:function(){return "\n]}";},getSeparator:function(){return ",\n";}});Log4js.PatternLayout=function(pattern){if(pattern){this.pattern=pattern;}else{this.pattern=Log4js.PatternLayout.DEFAULT_CONVERSION_PATTERN;}};Log4js.PatternLayout.TTCC_CONVERSION_PATTERN="%r %p %c - %m%n";Log4js.PatternLayout.DEFAULT_CONVERSION_PATTERN="%m%n";Log4js.PatternLayout.ISO8601_DATEFORMAT="yyyy-MM-dd HH:mm:ss,SSS";Log4js.PatternLayout.DATETIME_DATEFORMAT="dd MMM YYYY HH:mm:ss,SSS";Log4js.PatternLayout.ABSOLUTETIME_DATEFORMAT="HH:mm:ss,SSS";Log4js.PatternLayout.prototype=Log4js.extend(new Log4js.Layout(),{getContentType:function(){return "text/plain";},getHeader:function(){return null;},getFooter:function(){return null;},format:function(loggingEvent){var regex= /%(-?[0-9]+)?(\.?[0-9]+)?([cdmnpr%])(\{([^\}]+)\})?|([^%]+)/;var formattedString="";var result;var searchString=this.pattern;while((result=regex.exec(searchString))){var matchedString=result[0];var padding=result[1];var truncation=result[2];var conversionCharacter=result[3];var specifier=result[5];var text=result[6];if(text){formattedString+=""+text;}else{var replacement="";switch(conversionCharacter){case "c":var loggerName=loggingEvent.categoryName;if(specifier){var precision=parseInt(specifier,10);var loggerNameBits=loggingEvent.categoryName.split(".");if(precision>=loggerNameBits.length){replacement=loggerName;}else{replacement=loggerNameBits.slice(loggerNameBits.length-precision).join(".");}}else{replacement=loggerName;}break;case "d":var dateFormat=Log4js.PatternLayout.ISO8601_DATEFORMAT;if(specifier){dateFormat=specifier;if(dateFormat=="ISO8601"){dateFormat=Log4js.PatternLayout.ISO8601_DATEFORMAT;}else if(dateFormat=="ABSOLUTE"){dateFormat=Log4js.PatternLayout.ABSOLUTETIME_DATEFORMAT;}else if(dateFormat=="DATE"){dateFormat=Log4js.PatternLayout.DATETIME_DATEFORMAT;}}replacement=(new Log4js.SimpleDateFormat(dateFormat)).format(loggingEvent.startTime);break;case "m":replacement=loggingEvent.message;break;case "n":replacement="\n";break;case "p":replacement=loggingEvent.level.toString();break;case "r":replacement=""+loggingEvent.startTime.toLocaleTimeString();break;case "%":replacement="%";break;default:replacement=matchedString;break;}var len;if(truncation){len=parseInt(truncation.substr(1),10);replacement=replacement.substring(0,len);}if(padding){if(padding.charAt(0)=="-"){len=parseInt(padding.substr(1),10);while(replacement.length<len){replacement+=" ";}}else{len=parseInt(padding,10);while(replacement.length<len){replacement=" "+replacement;}}}formattedString+=replacement;}searchString=searchString.substr(result.index+result[0].length);}return formattedString;}});if(!Array.prototype.push){Array.prototype.push=function(){var startLength=this.length;for(var i=0;i<arguments.length;i++){this[startLength+i]=arguments[i];}return this.length;};}Log4js.FifoBuffer=function(){this.array=new Array();};Log4js.FifoBuffer.prototype={push:function(obj){this.array[this.array.length]=obj;return this.array.length;},pull:function(){if(this.array.length>0){var firstItem=this.array[0];for(var i=0;i<this.array.length-1;i++){this.array[i]=this.array[i+1];}this.array.length=this.array.length-1;return firstItem;}return null;},length:function(){return this.array.length;}};Log4js.DateFormatter=function(){return;};Log4js.DateFormatter.DEFAULT_DATE_FORMAT="yyyy-MM-ddThh:mm:ssO";Log4js.DateFormatter.prototype={formatDate:function(vDate,vFormat){var vDay=this.addZero(vDate.getDate());var vMonth=this.addZero(vDate.getMonth()+1);var vYearLong=this.addZero(vDate.getFullYear());var vYearShort=this.addZero(vDate.getFullYear().toString().substring(3,4));var vYear=(vFormat.indexOf("yyyy")>-1?vYearLong:vYearShort);var vHour=this.addZero(vDate.getHours());var vMinute=this.addZero(vDate.getMinutes());var vSecond=this.addZero(vDate.getSeconds());var vTimeZone=this.O(vDate);var vDateString=vFormat.replace(/dd/g,vDay).replace(/MM/g,vMonth).replace(/y{1,4}/g,vYear);vDateString=vDateString.replace(/hh/g,vHour).replace(/mm/g,vMinute).replace(/ss/g,vSecond);vDateString=vDateString.replace(/O/g,vTimeZone);return vDateString;},addZero:function(vNumber){return((vNumber<10)?"0":"")+vNumber;},O:function(date){var os=Math.abs(date.getTimezoneOffset());var h=String(Math.floor(os/60));var m=String(os%60);h.length==1?h="0"+h:1;m.length==1?m="0"+m:1;return date.getTimezoneOffset()<0?"+"+h+m:"-"+h+m;}};var log4jsLogger=Log4js.getLogger("Log4js");log4jsLogger.addAppender(new Log4js.ConsoleAppender());log4jsLogger.setLevel(Log4js.Level.ALL);\r
diff --git a/fluidbook/compile/_js/log4js.js b/fluidbook/compile/_js/log4js.js
new file mode 100644 (file)
index 0000000..d2c9dd6
--- /dev/null
@@ -0,0 +1,2501 @@
+/*\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *      http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+/*jsl:option explicit*/\r
+\r
+/**\r
+ * @fileoverview log4js is a library to log in JavaScript in similar manner \r
+ * than in log4j for Java. The API should be nearly the same.\r
+ * \r
+ * This file contains all log4js code and is the only file required for logging.\r
+ * \r
+ * <h3>Example:</h3>\r
+ * <pre>\r
+ *  var log = new Log4js.getLogger("some-category-name"); //create logger instance\r
+ *  log.setLevel(Log4js.Level.TRACE); //set the Level\r
+ *  log.addAppender(new ConsoleAppender(log, false)); // console that launches in new window\r
\r
+ *  // if multiple appenders are set all will log\r
+ *  log.addAppender(new ConsoleAppender(log, true)); // console that is in-line in the page\r
+ *  log.addAppender(new FileAppender("C:\\somefile.log")); // file appender logs to C:\\somefile.log\r
+ * \r
+ *  ...\r
+ * \r
+ *  //call the log\r
+ *  log.trace("trace me" );\r
+ * </pre>\r
+ *\r
+ * @version 0.3\r
+ * @author Stephan Strittmatter - http://jroller.com/page/stritti\r
+ * @author Seth Chisamore - http://www.chisamore.com\r
+ * @since 2005-05-20\r
+ * Website: http://log4js.berlios.de\r
+ */\r
+var Log4js = {\r
+       \r
+       /** \r
+        * Current version of log4js. \r
+        * @static\r
+        * @final\r
+        */\r
+       version: "1.0",\r
+\r
+       /**  \r
+        * Date of logger initialized.\r
+        * @static\r
+        * @final\r
+        */\r
+       applicationStartDate: new Date(),\r
+               \r
+       /**  \r
+        * Hashtable of loggers.\r
+        * @static\r
+        * @final\r
+        * @private  \r
+        */\r
+       loggers: {},\r
+       \r
+       /**\r
+        * Get a logger instance. Instance is cached on categoryName level.\r
+        * @param  {String} categoryName name of category to log to.\r
+        * @return {Logger} instance of logger for the category\r
+        * @static\r
+        */\r
+       getLogger: function(categoryName) {\r
+               \r
+               // Use default logger if categoryName is not specified or invalid\r
+               if (!(typeof categoryName == "string")) {\r
+                       categoryName = "[default]";\r
+               }\r
+\r
+               if (!Log4js.loggers[categoryName]) {\r
+                       // Create the logger for this name if it doesn't already exist\r
+                       Log4js.loggers[categoryName] = new Log4js.Logger(categoryName);\r
+               }\r
+               \r
+               return Log4js.loggers[categoryName];\r
+       },\r
+       \r
+       /**\r
+        * Get the default logger instance.\r
+        * @return {Logger} instance of default logger\r
+        * @static\r
+        */\r
+       getDefaultLogger: function() {\r
+               return Log4js.getLogger("[default]"); \r
+       },\r
+       \r
+       /**\r
+        * Atatch an observer function to an elements event browser independent.\r
+        * \r
+        * @param element element to attach event\r
+        * @param name name of event\r
+        * @param observer observer method to be called\r
+        * @private\r
+        */\r
+       attachEvent: function (element, name, observer) {\r
+               if (element.addEventListener) { //DOM event model\r
+                       element.addEventListener(name, observer, false);\r
+       } else if (element.attachEvent) { //M$ event model\r
+                       element.attachEvent('on' + name, observer);\r
+       }\r
+       }\r
+       \r
+       /**\r
+        * Load a JS-script dynamically.\r
+        * @param {String} src\r
+        */\r
+/*     $import: function (src) {\r
+               var documentScripts = document.getElementsByTagName("script");\r
+       \r
+               for (index = 0; index < documentScripts.length; ++index)\r
+               {\r
+                       var documentScript = documentScripts[index];\r
+                       if (documentScript.src == src) {\r
+                               return false;\r
+                       }\r
+               }\r
+               \r
+               var script = document.createElement('script');\r
+               script.type = 'text/javascript';\r
+               script.src = src;\r
+               document.getElementsByTagName('head')[0].appendChild(script); \r
+               \r
+               return true;\r
+       }\r
+       */\r
+};\r
+\r
+/**\r
+ * Internal object extension (OO) methods.\r
+ * \r
+ * @private\r
+ * @ignore\r
+ */\r
+Log4js.extend = function(destination, source) {\r
+  for (property in source) {\r
+    destination[property] = source[property];\r
+  }\r
+  return destination;\r
+}\r
+    \r
+/**\r
+ * Functions taken from Prototype library,  \r
+ * didn't want to require for just few functions.\r
+ * More info at {@link http://prototype.conio.net/}\r
+ * @private\r
+ */    \r
+Log4js.bind = function(fn, object) {\r
+  return function() {\r
+        return fn.apply(object, arguments);\r
+  };\r
+};\r
+\r
+/**\r
+ * Log4js.Level Enumeration. Do not use directly. Use static objects instead.\r
+ * @constructor\r
+ * @param {Number} level number of level\r
+ * @param {String} levelString String representation of level\r
+ * @private\r
+ */\r
+Log4js.Level = function(level, levelStr) {\r
+       this.level = level;\r
+       this.levelStr = levelStr;\r
+};\r
+\r
+Log4js.Level.prototype =  {\r
+       /** \r
+        * converts given String to corresponding Level\r
+        * @param {String} sArg String value of Level\r
+        * @param {Log4js.Level} defaultLevel default Level, if no String representation\r
+        * @return Level object\r
+        * @type Log4js.Level\r
+        */\r
+       toLevel: function(sArg, defaultLevel) {                  \r
+                               \r
+               if(sArg === null) {\r
+                       return defaultLevel;\r
+               }\r
+               \r
+               if(typeof sArg == "string") { \r
+                       var s = sArg.toUpperCase();\r
+                       if(s == "ALL") {return Log4js.Level.ALL;}\r
+                       if(s == "DEBUG") {return Log4js.Level.DEBUG;}\r
+                       if(s == "INFO") {return Log4js.Level.INFO;}\r
+                       if(s == "WARN") {return Log4js.Level.WARN;}\r
+                       if(s == "ERROR") {return Log4js.Level.ERROR;}\r
+                       if(s == "FATAL") {return Log4js.Level.FATAL;}\r
+                       if(s == "OFF") {return Log4js.Level.OFF;}\r
+                       if(s == "TRACE") {return Log4js.Level.TRACE;}\r
+                       return defaultLevel;\r
+               } else if(typeof sArg == "number") {\r
+                       switch(sArg) {\r
+                               case ALL_INT: return Log4js.Level.ALL;\r
+                               case DEBUG_INT: return Log4js.Level.DEBUG;\r
+                               case INFO_INT: return Log4js.Level.INFO;\r
+                               case WARN_INT: return Log4js.Level.WARN;\r
+                               case ERROR_INT: return Log4js.Level.ERROR;\r
+                               case FATAL_INT: return Log4js.Level.FATAL;\r
+                               case OFF_INT: return Log4js.Level.OFF;\r
+                               case TRACE_INT: return Log4js.Level.TRACE;\r
+                               default: return defaultLevel;\r
+                       }\r
+               } else {\r
+                       return defaultLevel;    \r
+               }\r
+       },      \r
+       /** \r
+        * @return  converted Level to String\r
+        * @type String\r
+        */             \r
+       toString: function() {\r
+               return this.levelStr;   \r
+       },\r
+       /** \r
+        * @return internal Number value of Level\r
+        * @type Number\r
+        */                     \r
+       valueOf: function() {\r
+               return this.level;\r
+       }\r
+};\r
+\r
+// Static variables\r
+/** \r
+ * @private\r
+ */\r
+Log4js.Level.OFF_INT = Number.MAX_VALUE;\r
+/** \r
+ * @private\r
+ */\r
+Log4js.Level.FATAL_INT = 50000;\r
+/** \r
+ * @private\r
+ */\r
+Log4js.Level.ERROR_INT = 40000;\r
+/** \r
+ * @private\r
+ */\r
+Log4js.Level.WARN_INT = 30000;\r
+/** \r
+ * @private\r
+ */\r
+Log4js.Level.INFO_INT = 20000;\r
+/** \r
+ * @private\r
+ */\r
+Log4js.Level.DEBUG_INT = 10000;\r
+/** \r
+ * @private\r
+ */\r
+Log4js.Level.TRACE_INT = 5000;\r
+/** \r
+ * @private\r
+ */\r
+Log4js.Level.ALL_INT = Number.MIN_VALUE;\r
+\r
+/** \r
+ * Logging Level OFF - all disabled\r
+ * @type Log4js.Level\r
+ * @static\r
+ */\r
+Log4js.Level.OFF = new Log4js.Level(Log4js.Level.OFF_INT, "OFF");\r
+/** \r
+ * Logging Level Fatal\r
+ * @type Log4js.Level\r
+ * @static\r
+ */\r
+Log4js.Level.FATAL = new Log4js.Level(Log4js.Level.FATAL_INT, "FATAL");\r
+/** \r
+ * Logging Level Error\r
+ * @type Log4js.Level\r
+ * @static\r
+ */\r
+Log4js.Level.ERROR = new Log4js.Level(Log4js.Level.ERROR_INT, "ERROR"); \r
+/** \r
+ * Logging Level Warn\r
+ * @type Log4js.Level\r
+ * @static\r
+ */\r
+Log4js.Level.WARN = new Log4js.Level(Log4js.Level.WARN_INT, "WARN"); \r
+/** \r
+ * Logging Level Info\r
+ * @type Log4js.Level\r
+ * @static\r
+ */\r
+Log4js.Level.INFO = new Log4js.Level(Log4js.Level.INFO_INT, "INFO");     \r
+/** \r
+ * Logging Level Debug\r
+ * @type Log4js.Level\r
+ * @static\r
+ */\r
+Log4js.Level.DEBUG = new Log4js.Level(Log4js.Level.DEBUG_INT, "DEBUG");  \r
+/** \r
+ * Logging Level Trace\r
+ * @type Log4js.Level\r
+ * @static\r
+ */\r
+Log4js.Level.TRACE = new Log4js.Level(Log4js.Level.TRACE_INT, "TRACE");  \r
+/** \r
+ * Logging Level All - All traces are enabled\r
+ * @type Log4js.Level\r
+ * @static\r
+ */\r
+Log4js.Level.ALL = new Log4js.Level(Log4js.Level.ALL_INT, "ALL"); \r
+\r
+/**\r
+ * Log4js CustomEvent\r
+ * @constructor\r
+ * @author Corey Johnson - original code in Lumberjack (http://gleepglop.com/javascripts/logger/)\r
+ * @author Seth Chisamore - adapted for Log4js\r
+ * @private\r
+ */\r
+Log4js.CustomEvent = function() {\r
+       this.listeners = [];\r
+};\r
+\r
+Log4js.CustomEvent.prototype = {\r
\r
+       /**\r
+        * @param method method to be added\r
+        */ \r
+       addListener : function(method) {\r
+               this.listeners.push(method);\r
+       },\r
+\r
+       /**\r
+        * @param method method to be removed\r
+        */ \r
+       removeListener : function(method) {\r
+               var foundIndexes = this.findListenerIndexes(method);\r
+\r
+               for(var i = 0; i < foundIndexes.length; i++) {\r
+                       this.listeners.splice(foundIndexes[i], 1);\r
+               }\r
+       },\r
+\r
+       /**\r
+        * @param handler\r
+        */ \r
+       dispatch : function(handler) {\r
+               for(var i = 0; i < this.listeners.length; i++) {\r
+                       try {\r
+                               this.listeners[i](handler);\r
+                       }\r
+                       catch (e) {\r
+                               log4jsLogger.warn("Could not run the listener " + this.listeners[i] + ". \n" + e);\r
+                       }\r
+               }\r
+       },\r
+\r
+       /**\r
+        * @private\r
+        * @param method\r
+        */\r
+       findListenerIndexes : function(method) {\r
+               var indexes = [];\r
+               for(var i = 0; i < this.listeners.length; i++) {                        \r
+                       if (this.listeners[i] == method) {\r
+                               indexes.push(i);\r
+                       }\r
+               }\r
+\r
+               return indexes;\r
+       }\r
+};\r
+\r
+/**\r
+ * Models a logging event.\r
+ * @constructor\r
+ * @param {String} categoryName name of category\r
+ * @param {Log4js.Level} level level of message\r
+ * @param {String} message message to log\r
+ * @param {Log4js.Logger} logger the associated logger\r
+ * @author Seth Chisamore\r
+ */\r
+Log4js.LoggingEvent = function(categoryName, level, message, exception, logger) {\r
+       /**\r
+        * the timestamp of the Logging Event\r
+        * @type Date\r
+        * @private\r
+        */\r
+       this.startTime = new Date();\r
+       /**\r
+        * category of event\r
+        * @type String\r
+        * @private\r
+        */\r
+       this.categoryName = categoryName;\r
+       /**\r
+        * the logging message\r
+        * @type String\r
+        * @private\r
+        */\r
+       this.message = message;\r
+       /**\r
+        * the logging exception\r
+        * @type Exception\r
+        * @private\r
+        */\r
+       this.exception = exception;\r
+       /**\r
+        * level of log\r
+        * @type Log4js.Level\r
+        * @private\r
+        */\r
+       this.level = level;\r
+       /**\r
+        * reference to logger\r
+        * @type Log4js.Logger\r
+        * @private\r
+        */\r
+       this.logger = logger;\r
+};\r
+\r
+Log4js.LoggingEvent.prototype = {      \r
+       /**\r
+        * get the timestamp formatted as String.\r
+        * @return {String} formatted timestamp\r
+        * @see Log4js#setDateFormat()\r
+        */\r
+       getFormattedTimestamp: function() {\r
+               if(this.logger) {\r
+                       return this.logger.getFormattedTimestamp(this.startTime);\r
+               } else {\r
+                       return this.startTime.toGMTString();\r
+               }\r
+       }\r
+};\r
+\r
+/**\r
+ * Logger to log messages to the defined appender.</p>\r
+ * Default appender is Appender, which is ignoring all messages. Please\r
+ * use setAppender() to set a specific appender (e.g. WindowAppender).\r
+ * use {@see Log4js#getLogger(String)} to get an instance.\r
+ * @constructor\r
+ * @param name name of category to log to\r
+ * @author Stephan Strittmatter\r
+ */\r
+Log4js.Logger = function(name) {\r
+       this.loggingEvents = [];\r
+       this.appenders = [];\r
+       /** category of logger */\r
+       this.category = name || "";\r
+       /** level to be logged */\r
+       this.level = Log4js.Level.FATAL;\r
+       \r
+       this.dateformat = Log4js.DateFormatter.DEFAULT_DATE_FORMAT;\r
+       this.dateformatter = new Log4js.DateFormatter();\r
+       \r
+       this.onlog = new Log4js.CustomEvent();\r
+       this.onclear = new Log4js.CustomEvent();\r
+       \r
+       /** appender to write in */\r
+       this.appenders.push(new Log4js.Appender(this));\r
+       \r
+       // if multiple log objects are instantiated this will only log to the log \r
+       // object that is declared last can't seem to get the attachEvent method to \r
+       // work correctly\r
+       try {\r
+               window.onerror = this.windowError.bind(this);\r
+       } catch (e) {\r
+               //log4jsLogger.fatal(e);\r
+       }\r
+};\r
+\r
+Log4js.Logger.prototype = {\r
+\r
+       /**\r
+        * add additional appender. DefaultAppender always is there.\r
+        * @param appender additional wanted appender\r
+        */\r
+       addAppender: function(appender) {\r
+               if (appender instanceof Log4js.Appender) {\r
+                       appender.setLogger(this);\r
+                       this.appenders.push(appender);                  \r
+               } else {\r
+                       throw "Not instance of an Appender: " + appender;\r
+               }\r
+       },\r
+\r
+       /**\r
+        * set Array of appenders. Previous Appenders are cleared and removed.\r
+        * @param {Array} appenders Array of Appenders\r
+        */\r
+       setAppenders: function(appenders) {\r
+               //clear first all existing appenders\r
+               for(var i = 0; i < this.appenders.length; i++) {\r
+                       this.appenders[i].doClear();\r
+               }\r
+               \r
+               this.appenders = appenders;\r
+               \r
+               for(var j = 0; j < this.appenders.length; j++) {\r
+                       this.appenders[j].setLogger(this);\r
+               }\r
+       },\r
+       \r
+       /**\r
+        * Set the Loglevel default is LogLEvel.TRACE\r
+        * @param level wanted logging level\r
+        */\r
+       setLevel: function(level) {\r
+               this.level = level;\r
+       },\r
+       \r
+       /** \r
+        * main log method logging to all available appenders \r
+        * @private\r
+        */\r
+       log: function(logLevel, message, exception) {\r
+               var loggingEvent = new Log4js.LoggingEvent(this.category, logLevel, \r
+                       message, exception, this);\r
+               this.loggingEvents.push(loggingEvent);\r
+               this.onlog.dispatch(loggingEvent);\r
+       },\r
+       \r
+       /** clear logging */\r
+       clear : function () {\r
+               try{\r
+                       this.loggingEvents = [];\r
+                       this.onclear.dispatch();\r
+               } catch(e){}\r
+       },\r
+       /** checks if Level Trace is enabled */\r
+       isTraceEnabled: function() {\r
+               if (this.level.valueOf() <= Log4js.Level.TRACE.valueOf()) {\r
+                       return true;\r
+               }\r
+               return false;\r
+       },\r
+       /** \r
+        * Trace messages \r
+        * @param message {Object} message to be logged\r
+        */\r
+       trace: function(message) {\r
+               if (this.isTraceEnabled()) {\r
+                       this.log(Log4js.Level.TRACE, message, null);\r
+               }\r
+       },\r
+       /** checks if Level Debug is enabled */\r
+       isDebugEnabled: function() {\r
+               if (this.level.valueOf() <= Log4js.Level.DEBUG.valueOf()) {\r
+                       return true;\r
+               }\r
+               return false;\r
+       },\r
+       /** \r
+        * Debug messages \r
+        * @param message {Object} message to be logged\r
+        */\r
+       debug: function(message) {\r
+               if (this.isDebugEnabled()) {\r
+                       this.log(Log4js.Level.DEBUG, message, null);\r
+               }\r
+       },\r
+       /**\r
+        * Debug messages \r
+        * @param {Object} message  message to be logged\r
+        * @param {Throwable} throwable \r
+        */\r
+       debug: function(message, throwable) {\r
+               if (this.isDebugEnabled()) {\r
+                       this.log(Log4js.Level.DEBUG, message, throwable);\r
+               }\r
+       },      \r
+       /** checks if Level Info is enabled */\r
+       isInfoEnabled: function() {\r
+               if (this.level.valueOf() <= Log4js.Level.INFO.valueOf()) {\r
+                       return true;\r
+               }\r
+               return false;\r
+       },\r
+       /** \r
+        * logging info messages \r
+        * @param {Object} message  message to be logged\r
+        */\r
+       info: function(message) {\r
+               if (this.isInfoEnabled()) {\r
+                       this.log(Log4js.Level.INFO, message, null);\r
+               }\r
+       },\r
+       /** \r
+        * logging info messages \r
+        * @param {Object} message  message to be logged\r
+        * @param {Throwable} throwable  \r
+        */\r
+       info: function(message, throwable) {\r
+               if (this.isInfoEnabled()) {\r
+                       this.log(Log4js.Level.INFO, message, throwable);\r
+               }\r
+       },\r
+       /** checks if Level Warn is enabled */\r
+       isWarnEnabled: function() {\r
+               if (this.level.valueOf() <= Log4js.Level.WARN.valueOf()) {\r
+                       return true;\r
+               }\r
+               return false;\r
+       },\r
+\r
+       /** logging warn messages */\r
+       warn: function(message) {\r
+               if (this.isWarnEnabled()) {\r
+                       this.log(Log4js.Level.WARN, message, null);\r
+               }\r
+       },\r
+       /** logging warn messages */\r
+       warn: function(message, throwable) {\r
+               if (this.isWarnEnabled()) {\r
+                       this.log(Log4js.Level.WARN, message, throwable);\r
+               }\r
+       },\r
+       /** checks if Level Error is enabled */\r
+       isErrorEnabled: function() {\r
+               if (this.level.valueOf() <= Log4js.Level.ERROR.valueOf()) {\r
+                       return true;\r
+               }\r
+               return false;\r
+       },\r
+       /** logging error messages */\r
+       error: function(message) {\r
+               if (this.isErrorEnabled()) {\r
+                       this.log(Log4js.Level.ERROR, message, null);\r
+               }\r
+       },\r
+       /** logging error messages */\r
+       error: function(message, throwable) {\r
+               if (this.isErrorEnabled()) {\r
+                       this.log(Log4js.Level.ERROR, message, throwable);\r
+               }\r
+       },\r
+       /** checks if Level Fatal is enabled */\r
+       isFatalEnabled: function() {\r
+               if (this.level.valueOf() <= Log4js.Level.FATAL.valueOf()) {\r
+                       return true;\r
+               }\r
+               return false;\r
+       },\r
+       /** logging fatal messages */\r
+       fatal: function(message) {\r
+               if (this.isFatalEnabled()) {\r
+                       this.log(Log4js.Level.FATAL, message, null);\r
+               }\r
+       },\r
+       /** logging fatal messages */\r
+       fatal: function(message, throwable) {\r
+               if (this.isFatalEnabled()) {\r
+                       this.log(Log4js.Level.FATAL, message, throwable);\r
+               }\r
+       },      \r
+       /** \r
+        * Capture main window errors and log as fatal.\r
+        * @private\r
+        */\r
+       windowError: function(msg, url, line){\r
+               var message = "Error in (" + (url || window.location) + ") on line "+ line +" with message (" + msg + ")";\r
+               this.log(Log4js.Level.FATAL, message, null);    \r
+       },\r
+       \r
+       /**\r
+        * Set the date format of logger. Following switches are supported:\r
+        * <ul>\r
+        * <li>yyyy - The year</li>\r
+        * <li>MM - the month</li>\r
+        * <li>dd - the day of month<li>\r
+        * <li>hh - the hour<li>\r
+        * <li>mm - minutes</li>\r
+        * <li>O - timezone offset</li>\r
+        * </ul>\r
+        * @param {String} format format String for the date\r
+        * @see #getTimestamp\r
+        */\r
+       setDateFormat: function(format) {\r
+               this.dateformat = format;\r
+       },\r
+        \r
+       /**\r
+        * Generates a timestamp using the format set in {Log4js.setDateFormat}.\r
+        * @param {Date} date the date to format\r
+        * @see #setDateFormat\r
+        * @return A formatted timestamp with the current date and time.\r
+        */\r
+       getFormattedTimestamp: function(date) {\r
+         return this.dateformatter.formatDate(date, this.dateformat);\r
+       }\r
+};\r
+\r
+/**\r
+ * Abstract base class for other appenders. \r
+ * It is doing nothing.\r
+ *\r
+ * @constructor\r
+ * @param {Log4js.Logger} logger log4js instance this appender is attached to\r
+ * @author Stephan Strittmatter\r
+ */\r
+Log4js.Appender = function () {\r
+       /**\r
+        * Reference to calling logger\r
+        * @type Log4js.Logger\r
+        * @private\r
+        */\r
+        this.logger = null;\r
+};\r
+\r
+Log4js.Appender.prototype = {\r
+       /** \r
+        * appends the given loggingEvent appender specific\r
+        * @param {Log4js.LoggingEvent} loggingEvent loggingEvent to append\r
+        */\r
+       doAppend: function(loggingEvent) {\r
+               return;\r
+       },\r
+       /** \r
+        * clears the Appender\r
+        */\r
+       doClear: function() {\r
+               return;\r
+       },\r
+       \r
+       /**\r
+        * Set the Layout for this appender.\r
+        * @param {Log4js.Layout} layout Layout for formatting loggingEvent\r
+        */\r
+       setLayout: function(layout){\r
+               this.layout = layout;\r
+       },\r
+       /**\r
+        * Set reference to the logger.\r
+        * @param {Log4js.Logger} the invoking logger\r
+        */\r
+       setLogger: function(logger){\r
+               // add listener to the logger methods\r
+               logger.onlog.addListener(Log4js.bind(this.doAppend, this));\r
+               logger.onclear.addListener(Log4js.bind(this.doClear, this));\r
+       \r
+               this.logger = logger;\r
+       }\r
+};\r
+\r
+/**\r
+ * Interface for Layouts.\r
+ * Use this Layout as "interface" for other Layouts. It is doing nothing.\r
+ *\r
+ * @constructor\r
+ * @author Stephan Strittmatter\r
+ */\r
+Log4js.Layout = function(){return;};\r
+Log4js.Layout.prototype = {\r
+       /** \r
+        * Implement this method to create your own layout format.\r
+        * @param {Log4js.LoggingEvent} loggingEvent loggingEvent to format\r
+        * @return formatted String\r
+        * @type String\r
+        */\r
+       format: function(loggingEvent) {\r
+               return "";\r
+       },\r
+       /** \r
+        * Returns the content type output by this layout. \r
+        * @return The base class returns "text/plain".\r
+        * @type String\r
+        */\r
+       getContentType: function() {\r
+               return "text/plain";\r
+       },\r
+       /** \r
+        * @return Returns the header for the layout format. The base class returns null.\r
+        * @type String\r
+        */\r
+       getHeader: function() {\r
+               return null;\r
+       },\r
+       /** \r
+        * @return Returns the footer for the layout format. The base class returns null.\r
+        * @type String\r
+        */\r
+       getFooter: function() {\r
+               return null;\r
+       },\r
+       \r
+       /**\r
+        * @return Separator between events\r
+        * @type String\r
+        */\r
+       getSeparator: function() {\r
+               return "";\r
+       }\r
+};\r
+\r
+/**\r
+ * Console Appender writes the logs to a console.  If "inline" is\r
+ * set to "false" the console launches in another window otherwise\r
+ * the window is inline on the page and toggled on and off with "Alt-D".\r
+ * Note: At FireFox &gb; 2.0 the keystroke is little different now: "SHIFT+ALT+D".\r
+ *\r
+ * @constructor\r
+ * @extends Log4js.Appender\r
+ * @param {boolean} isInline boolean value that indicates whether the console be placed inline, default is to launch in new window\r
+ *\r
+ * @author Corey Johnson - original console code in Lumberjack (http://gleepglop.com/javascripts/logger/)\r
+ * @author Seth Chisamore - adapted for use as a log4js appender\r
+ */\r
+Log4js.ConsoleAppender = function(isInline) {\r
+       \r
+       /**\r
+        * @type Log4js.Layout\r
+        * @private\r
+        */\r
+       this.layout = new Log4js.PatternLayout(Log4js.PatternLayout.TTCC_CONVERSION_PATTERN);\r
+       /**\r
+        * @type boolean\r
+        * @private\r
+        */\r
+       this.inline = isInline;\r
+\r
+       /**\r
+        * @type String\r
+        * @private\r
+        */\r
+       this.accesskey = "d";\r
+       \r
+       /**\r
+        * @private\r
+        */\r
+       this.tagPattern = null;\r
+       \r
+       this.commandHistory = [];\r
+       this.commandIndex = 0;\r
+       \r
+       /**\r
+        * true if popup is blocked.\r
+        */\r
+       this.popupBlocker = false;\r
+       \r
+       /**\r
+        * current output div-element.\r
+        */\r
+       this.outputElement = null;\r
+       \r
+       this.docReference = null;\r
+       this.winReference = null;               \r
+               \r
+       if(this.inline) {\r
+               Log4js.attachEvent(window, 'load', Log4js.bind(this.initialize, this));\r
+       }\r
+};\r
+\r
+Log4js.ConsoleAppender.prototype = Log4js.extend(new Log4js.Appender(), {  \r
+\r
+       /**\r
+        * Set the access key to show/hide the inline console (default &quote;d&quote;)\r
+        * @param key access key to show/hide the inline console\r
+        */     \r
+       setAccessKey : function(key) {\r
+               this.accesskey = key;\r
+       },\r
+       \r
+       /**\r
+        * @private\r
+        */\r
+       initialize : function() {\r
+               \r
+               if(!this.inline) {\r
+                       var doc = null; \r
+                       var win = null;\r
+                       window.top.consoleWindow = window.open("", this.logger.category, \r
+                               "left=0,top=0,width=700,height=700,scrollbars=no,status=no,resizable=yes;toolbar=no");\r
+                       window.top.consoleWindow.opener = self;\r
+                       win = window.top.consoleWindow;\r
+                                                               \r
+                       if (!win) { \r
+                               this.popupBlocker=true; \r
+                               alert("Popup window manager blocking the Log4js popup window to bedisplayed.\n\n" \r
+                                       + "Please disabled this to properly see logged events.");  \r
+                       } else {        \r
+\r
+                               doc = win.document;\r
+                               doc.open();\r
+                               doc.write("<!DOCTYPE html PUBLIC -//W3C//DTD XHTML 1.0 Transitional//EN ");\r
+                               doc.write("  http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd>\n\n");\r
+                               doc.write("<html><head><title>Log4js - " + this.logger.category + "</title>\n");\r
+                               doc.write("</head><body style=\"background-color:darkgray\"></body>\n");\r
+                               win.blur();\r
+                               win.focus();\r
+                       }\r
+                       \r
+                       this.docReference = doc;\r
+                       this.winReference = win;\r
+               } else {\r
+                       this.docReference = document;\r
+                       this.winReference = window;                     \r
+               }\r
+                               \r
+               this.outputCount = 0;\r
+               this.tagPattern = ".*";\r
+         \r
+               // I hate writing javascript in HTML... but what's a better alternative\r
+               this.logElement = this.docReference.createElement('div');\r
+               this.docReference.body.appendChild(this.logElement);\r
+               this.logElement.style.display = 'none';\r
+               \r
+               this.logElement.style.position = "absolute";\r
+               this.logElement.style.left = '0px';\r
+               this.logElement.style.width = '100%';\r
+       \r
+               this.logElement.style.textAlign = "left";\r
+               this.logElement.style.fontFamily = "lucida console";\r
+               this.logElement.style.fontSize = "100%";\r
+               this.logElement.style.backgroundColor = 'darkgray';      \r
+               this.logElement.style.opacity = 0.9;\r
+               this.logElement.style.zIndex = 2000; \r
+       \r
+               // Add toolbarElement\r
+               this.toolbarElement = this.docReference.createElement('div');\r
+               this.logElement.appendChild(this.toolbarElement);     \r
+               this.toolbarElement.style.padding = "0 0 0 2px";\r
+       \r
+               // Add buttons        \r
+               this.buttonsContainerElement = this.docReference.createElement('span');\r
+               this.toolbarElement.appendChild(this.buttonsContainerElement); \r
+       \r
+               if(this.inline) {\r
+                       var closeButton = this.docReference.createElement('button');\r
+                       closeButton.style.cssFloat = "right";\r
+                       closeButton.style.styleFloat = "right"; // IE dom bug...doesn't understand cssFloat\r
+                       closeButton.style.color = "black";\r
+                       closeButton.innerHTML = "close";\r
+                       closeButton.onclick = Log4js.bind(this.toggle, this);\r
+                       this.buttonsContainerElement.appendChild(closeButton);\r
+               }\r
+               \r
+               var clearButton = this.docReference.createElement('button');\r
+               clearButton.style.cssFloat = "right";\r
+               clearButton.style.styleFloat = "right"; // IE dom bug...doesn't understand cssFloat\r
+               clearButton.style.color = "black";\r
+               clearButton.innerHTML = "clear";\r
+               clearButton.onclick = Log4js.bind(this.logger.clear, this.logger);\r
+               this.buttonsContainerElement.appendChild(clearButton);\r
+       \r
+\r
+               //Add CategoryName and  Level Filter\r
+               this.tagFilterContainerElement = this.docReference.createElement('span');\r
+               this.toolbarElement.appendChild(this.tagFilterContainerElement);\r
+               this.tagFilterContainerElement.style.cssFloat = 'left';\r
+               \r
+               this.tagFilterContainerElement.appendChild(this.docReference.createTextNode("Log4js - " + this.logger.category));\r
+               this.tagFilterContainerElement.appendChild(this.docReference.createTextNode(" | Level Filter: "));\r
+               \r
+               this.tagFilterElement = this.docReference.createElement('input');\r
+               this.tagFilterContainerElement.appendChild(this.tagFilterElement);\r
+               this.tagFilterElement.style.width = '200px';                    \r
+               this.tagFilterElement.value = this.tagPattern;    \r
+               this.tagFilterElement.setAttribute('autocomplete', 'off'); // So Firefox doesn't flip out\r
+               \r
+               Log4js.attachEvent(this.tagFilterElement, 'keyup', Log4js.bind(this.updateTags, this));\r
+               Log4js.attachEvent(this.tagFilterElement, 'click', Log4js.bind( function() {this.tagFilterElement.select();}, this));\r
+               \r
+               // Add outputElement\r
+               this.outputElement = this.docReference.createElement('div');\r
+               this.logElement.appendChild(this.outputElement);  \r
+               this.outputElement.style.overflow = "auto";              \r
+               this.outputElement.style.clear = "both";\r
+               this.outputElement.style.height = (this.inline) ? ("200px"):("650px");\r
+               this.outputElement.style.width = "100%";\r
+               this.outputElement.style.backgroundColor = 'black'; \r
+                         \r
+               this.inputContainerElement = this.docReference.createElement('div');\r
+               this.inputContainerElement.style.width = "100%";\r
+               this.logElement.appendChild(this.inputContainerElement);      \r
+               \r
+               this.inputElement = this.docReference.createElement('input');\r
+               this.inputContainerElement.appendChild(this.inputElement);  \r
+               this.inputElement.style.width = '100%';\r
+               this.inputElement.style.borderWidth = '0px'; // Inputs with 100% width always seem to be too large (I HATE THEM) they only work if the border, margin and padding are 0\r
+               this.inputElement.style.margin = '0px';\r
+               this.inputElement.style.padding = '0px';\r
+               this.inputElement.value = 'Type command here'; \r
+               this.inputElement.setAttribute('autocomplete', 'off'); // So Firefox doesn't flip out\r
+       \r
+               Log4js.attachEvent(this.inputElement, 'keyup', Log4js.bind(this.handleInput, this));\r
+               Log4js.attachEvent(this.inputElement, 'click', Log4js.bind( function() {this.inputElement.select();}, this));\r
+               \r
+               if(this.inline){\r
+                       window.setInterval(Log4js.bind(this.repositionWindow, this), 500);\r
+                       this.repositionWindow();        \r
+                       // Allow acess key link          \r
+                       var accessElement = this.docReference.createElement('button');\r
+                       accessElement.style.position = "absolute";\r
+                       accessElement.style.top = "-100px";\r
+                       accessElement.accessKey = this.accesskey;\r
+                       accessElement.onclick = Log4js.bind(this.toggle, this);\r
+                       this.docReference.body.appendChild(accessElement);\r
+               } else {\r
+                       this.show();\r
+               }\r
+       },\r
+       /**\r
+        * shows/hide an element\r
+        * @private\r
+        * @return true if shown\r
+        */\r
+       toggle : function() {\r
+               if (this.logElement.style.display == 'none') {\r
+                       this.show();\r
+                       return true;\r
+               } else {\r
+                       this.hide();\r
+                       return false;\r
+               }\r
+       }, \r
+       /**\r
+        * @private\r
+        */\r
+       show : function() {\r
+               this.logElement.style.display = '';\r
+               this.outputElement.scrollTop = this.outputElement.scrollHeight; // Scroll to bottom when toggled\r
+               this.inputElement.select();\r
+       }, \r
+       /**\r
+        * @private\r
+        */     \r
+       hide : function() {\r
+               this.logElement.style.display = 'none';\r
+       },  \r
+       /**\r
+        * @private\r
+        * @param message\r
+        * @style\r
+        */     \r
+       output : function(message, style) {\r
+\r
+               // If we are at the bottom of the window, then keep scrolling with the output                   \r
+               var shouldScroll = (this.outputElement.scrollTop + (2 * this.outputElement.clientHeight)) >= this.outputElement.scrollHeight;\r
+               \r
+               this.outputCount++;\r
+               style = (style ? style += ';' : '');            \r
+               style += 'padding:1px;margin:0 0 5px 0';             \r
+                 \r
+               if (this.outputCount % 2 === 0) {\r
+                       style += ";background-color:#101010";\r
+               }\r
+               \r
+               message = message || "undefined";\r
+               message = message.toString();\r
+               \r
+               this.outputElement.innerHTML += "<pre style='" + style + "'>" + message + "</pre>";\r
+               \r
+               if (shouldScroll) {                             \r
+                       this.outputElement.scrollTop = this.outputElement.scrollHeight;\r
+               }\r
+       },\r
+       \r
+       /**\r
+        * @private\r
+        */\r
+       updateTags : function() {\r
+               \r
+               var pattern = this.tagFilterElement.value;\r
+       \r
+               if (this.tagPattern == pattern) {\r
+                       return;\r
+               }\r
+               \r
+               try {\r
+                       new RegExp(pattern);\r
+               } catch (e) {\r
+                       return;\r
+               }\r
+               \r
+               this.tagPattern = pattern;\r
+\r
+               this.outputElement.innerHTML = "";\r
+               \r
+               // Go through each log entry again\r
+               this.outputCount = 0;\r
+               for (var i = 0; i < this.logger.loggingEvents.length; i++) {\r
+                       this.doAppend(this.logger.loggingEvents[i]);\r
+               }  \r
+       },\r
+\r
+       /**\r
+        * @private\r
+        */     \r
+       repositionWindow : function() {\r
+               var offset = window.pageYOffset || this.docReference.documentElement.scrollTop || this.docReference.body.scrollTop;\r
+               var pageHeight = self.innerHeight || this.docReference.documentElement.clientHeight || this.docReference.body.clientHeight;\r
+               this.logElement.style.top = (offset + pageHeight - this.logElement.offsetHeight) + "px";\r
+       },\r
+\r
+       /**\r
+        * @param loggingEvent event to be logged\r
+        * @see Log4js.Appender#doAppend\r
+        */\r
+       doAppend : function(loggingEvent) {\r
+               \r
+               if(this.popupBlocker) {\r
+                       //popup blocked, we return in this case\r
+                       return;\r
+               }\r
+               \r
+               if ((!this.inline) && (!this.winReference || this.winReference.closed)) {\r
+                       this.initialize();\r
+               }\r
+               \r
+               if (this.tagPattern !== null && \r
+                       loggingEvent.level.toString().search(new RegExp(this.tagPattern, 'igm')) == -1) {\r
+                       return;\r
+               }\r
+               \r
+               var style = '';\r
+               \r
+               if (loggingEvent.level.toString().search(/ERROR/) != -1) { \r
+                       style += 'color:red';\r
+               } else if (loggingEvent.level.toString().search(/FATAL/) != -1) { \r
+                       style += 'color:red';\r
+               } else if (loggingEvent.level.toString().search(/WARN/) != -1) { \r
+                       style += 'color:orange';\r
+               } else if (loggingEvent.level.toString().search(/DEBUG/) != -1) {\r
+                       style += 'color:green';\r
+               } else if (loggingEvent.level.toString().search(/INFO/) != -1) {\r
+                       style += 'color:white';\r
+               } else {\r
+                       style += 'color:yellow';\r
+               }\r
+       \r
+               this.output(this.layout.format(loggingEvent), style);   \r
+       },\r
+\r
+       /**\r
+        * @see Log4js.Appender#doClear\r
+        */\r
+       doClear : function() {\r
+               this.outputElement.innerHTML = "";\r
+       },\r
+       /**\r
+        * @private\r
+        * @param e\r
+        */\r
+       handleInput : function(e) {\r
+               if (e.keyCode == 13 ) {      \r
+                       var command = this.inputElement.value;\r
+                       \r
+                       switch(command) {\r
+                               case "clear":\r
+                                       this.logger.clear();  \r
+                                       break;\r
+                                       \r
+                               default:        \r
+                                       var consoleOutput = "";\r
+                               \r
+                                       try {\r
+                                               consoleOutput = eval(this.inputElement.value);\r
+                                       } catch (e) {  \r
+                                               this.logger.error("Problem parsing input <" + command + ">" + e.message);\r
+                                               break;\r
+                                       }\r
+                                               \r
+                                       this.logger.trace(consoleOutput);\r
+                                       break;\r
+                       }        \r
+               \r
+                       if (this.inputElement.value !== "" && this.inputElement.value !== this.commandHistory[0]) {\r
+                               this.commandHistory.unshift(this.inputElement.value);\r
+                       }\r
+                 \r
+                       this.commandIndex = 0;\r
+                       this.inputElement.value = "";                                                     \r
+               } else if (e.keyCode == 38 && this.commandHistory.length > 0) {\r
+               this.inputElement.value = this.commandHistory[this.commandIndex];\r
+\r
+                       if (this.commandIndex < this.commandHistory.length - 1) {\r
+                       this.commandIndex += 1;\r
+               }\r
+       } else if (e.keyCode == 40 && this.commandHistory.length > 0) {\r
+               if (this.commandIndex > 0) {                                      \r
+                       this.commandIndex -= 1;\r
+               }                       \r
+\r
+                       this.inputElement.value = this.commandHistory[this.commandIndex];\r
+               } else {\r
+               this.commandIndex = 0;\r
+       }\r
+       },\r
+       \r
+       /** \r
+        * toString\r
+        */\r
+        toString: function() {\r
+               return "Log4js.ConsoleAppender[inline=" + this.inline + "]"; \r
+        }\r
+}); \r
+\r
+/**\r
+ * Metatag Appender writing the logs to meta tags\r
+ *\r
+ * @extends Log4js.Appender\r
+ * @constructor\r
+ * @param logger log4js instance this appender is attached to\r
+ * @author Stephan Strittmatter\r
+ */\r
+Log4js.MetatagAppender = function() {\r
+       this.currentLine = 0;\r
+};\r
+Log4js.MetatagAppender.prototype = Log4js.extend(new Log4js.Appender(), {  \r
+       /**\r
+        * @param loggingEvent event to be logged\r
+        * @see Log4js.Appender#doAppend\r
+        */\r
+       doAppend: function(loggingEvent) {\r
+               var now = new Date();\r
+               var lines = loggingEvent.message.split("\n");\r
+               var headTag = document.getElementsByTagName("head")[0];\r
+\r
+               for (var i = 1; i <= lines.length; i++) {\r
+                       var value = lines[i - 1];\r
+                       if (i == 1) {\r
+                               value = loggingEvent.level.toString() + ": " + value;\r
+                       } else {\r
+                               value = "> " + value;\r
+                       }\r
+\r
+                       var metaTag = document.createElement("meta");\r
+                       metaTag.setAttribute("name", "X-log4js:" + this.currentLine);\r
+                       metaTag.setAttribute("content", value);\r
+                       headTag.appendChild(metaTag);\r
+                       this.currentLine += 1;\r
+               }\r
+       },\r
+\r
+       /** \r
+        * toString\r
+        */\r
+        toString: function() {\r
+               return "Log4js.MetatagAppender"; \r
+        }\r
+});\r
+\r
+/**\r
+ * AJAX Appender sending {@link Log4js.LoggingEvent}s asynchron via \r
+ * <code>XMLHttpRequest</code> to server.<br />\r
+ * The {@link Log4js.LoggingEvent} is POSTed as response content and is \r
+ * formatted by the accociated layout. Default layout is {@link Log4js.XMLLayout}. \r
+ * The <code>threshold</code> defines when the logs \r
+ * should be send to the server. By default every event is sent on its\r
+ * own (threshold=1). If it is set to 10, then the events are send in groups of\r
+ * 10 events.\r
+ *\r
+ * @extends Log4js.Appender \r
+ * @constructor\r
+ * @param {Log4js.Logger} logger log4js instance this appender is attached to\r
+ * @param {String} loggingUrl url where appender will post log messages to\r
+ * @author Stephan Strittmatter\r
+ */\r
+Log4js.AjaxAppender = function(loggingUrl) {\r
+\r
+       /**\r
+        * is still esnding data to server\r
+        * @type boolean\r
+        * @private\r
+        */\r
+       this.isInProgress = false;\r
+       \r
+       /**\r
+        * @type String\r
+        * @private\r
+        */\r
+       this.loggingUrl = loggingUrl || "logging.log4js";\r
+       \r
+       /**\r
+        * @type Integer\r
+        * @private\r
+        */\r
+       this.threshold = 1;\r
+       \r
+       /**\r
+        * timeout when request is aborted.\r
+        * @private\r
+        */\r
+       this.timeout = 2000;\r
+       \r
+       /**\r
+        * List of LoggingEvents which should be send after threshold is reached.\r
+        * @type Map\r
+        * @private\r
+        */\r
+       this.loggingEventMap = new Log4js.FifoBuffer();\r
+\r
+       /**\r
+        * @type Log4js.Layout\r
+        * @private\r
+        */\r
+       this.layout = new Log4js.XMLLayout();\r
+       /**\r
+        * @type XMLHttpRequest\r
+        * @private\r
+        */     \r
+       this.httpRequest = null;\r
+};\r
+\r
+Log4js.AjaxAppender.prototype = Log4js.extend(new Log4js.Appender(), {  \r
+       /**\r
+        * sends the logs to the server\r
+        * @param loggingEvent event to be logged\r
+        * @see Log4js.Appender#doAppend\r
+        */\r
+       doAppend: function(loggingEvent) {\r
+               log4jsLogger.trace("> AjaxAppender.append");\r
+       \r
+               if (this.loggingEventMap.length() <= this.threshold || this.isInProgress === true) {\r
+                       this.loggingEventMap.push(loggingEvent);\r
+               }\r
+               \r
+               if(this.loggingEventMap.length() >= this.threshold && this.isInProgress === false) {\r
+                       //if threshold is reached send the events and reset current threshold\r
+                       this.send();\r
+               }\r
+               \r
+               log4jsLogger.trace("< AjaxAppender.append");\r
+       },\r
+       \r
+       /** @see Appender#doClear */\r
+       doClear: function() {\r
+               log4jsLogger.trace("> AjaxAppender.doClear" );\r
+               if(this.loggingEventMap.length() > 0) {\r
+                       this.send();\r
+               }\r
+               log4jsLogger.trace("< AjaxAppender.doClear" );\r
+       },\r
+       \r
+       /**\r
+        * Set the threshold when logs have to be send. Default threshold is 1.\r
+        * @praram {int} threshold new threshold\r
+        */\r
+       setThreshold: function(threshold) {\r
+               log4jsLogger.trace("> AjaxAppender.setThreshold: " + threshold );\r
+               this.threshold = threshold;\r
+               log4jsLogger.trace("< AjaxAppender.setThreshold" );\r
+       },\r
+       \r
+       /**\r
+        * Set the timeout in milli seconds until sending request is aborted.\r
+        * Default is 2000 ms.\r
+        * @param {int} milliseconds the new timeout\r
+        */\r
+       setTimeout: function(milliseconds) {\r
+               this.timeout = milliseconds;\r
+       },\r
+       \r
+       /**\r
+        * send the request.\r
+        */\r
+       send: function() {\r
+               if(this.loggingEventMap.length() >0) {\r
+                       \r
+                       log4jsLogger.trace("> AjaxAppender.send");\r
+                       \r
+                       \r
+                       this.isInProgress = true;\r
+                       var a = [];\r
+       \r
+                       for(var i = 0; i < this.loggingEventMap.length() && i < this.threshold; i++) {\r
+                               a.push(this.layout.format(this.loggingEventMap.pull()));\r
+                       } \r
+                                       \r
+                       var content = this.layout.getHeader();  \r
+                       content += a.join(this.layout.getSeparator());\r
+                       content += this.layout.getFooter();\r
+                       \r
+                       var appender = this;\r
+                       if(this.httpRequest === null){\r
+                               this.httpRequest = this.getXmlHttpRequest();\r
+                       }\r
+                       this.httpRequest.onreadystatechange = function() {\r
+                               appender.onReadyStateChanged.call(appender);\r
+                       };\r
+                       \r
+                       this.httpRequest.open("POST", this.loggingUrl, true);\r
+                       // set the request headers.\r
+                       //this.httpRequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");\r
+                       this.httpRequest.setRequestHeader("Content-type", this.layout.getContentType());\r
+                       //REFERER will be the top-level\r
+                       // URI which may differ from the location of the error if\r
+                       // it occurs in an included .js file\r
+                       this.httpRequest.setRequestHeader("REFERER", location.href);\r
+                       this.httpRequest.setRequestHeader("Content-length", content.length);\r
+                       this.httpRequest.setRequestHeader("Connection", "close");\r
+                       this.httpRequest.send( content );\r
+                       \r
+                       appender = this;\r
+                       \r
+                       try {\r
+                               window.setTimeout(function(){\r
+                                       log4jsLogger.trace("> AjaxAppender.timeout");\r
+                                       appender.httpRequest.onreadystatechange = function(){return;};\r
+                                       appender.httpRequest.abort();\r
+                                       //this.httpRequest = null;\r
+                                       appender.isInProgress = false;\r
+               \r
+                                       if(appender.loggingEventMap.length() > 0) {\r
+                                               appender.send();\r
+                                       }\r
+                                       log4jsLogger.trace("< AjaxAppender.timeout");\r
+                               }, this.timeout);\r
+                       } catch (e) {\r
+                               log4jsLogger.fatal(e);\r
+                       }\r
+                       log4jsLogger.trace("> AjaxAppender.send");\r
+               }\r
+       },\r
+       \r
+       /**\r
+        * @private\r
+        */\r
+       onReadyStateChanged: function() {\r
+               log4jsLogger.trace("> AjaxAppender.onReadyStateChanged");\r
+               var req = this.httpRequest;\r
+               if (this.httpRequest.readyState != 4) { \r
+                       log4jsLogger.trace("< AjaxAppender.onReadyStateChanged: readyState " + req.readyState + " != 4");\r
+                       return; \r
+               }\r
+               \r
+               var success = ((typeof req.status === "undefined") || req.status === 0 || (req.status >= 200 && req.status < 300));\r
+               \r
+               if (success) {\r
+                       log4jsLogger.trace("  AjaxAppender.onReadyStateChanged: success");\r
+\r
+                       //ready sending data\r
+                       this.isInProgress = false;\r
+\r
+               } else {\r
+                       var msg = "  AjaxAppender.onReadyStateChanged: XMLHttpRequest request to URL " + this.loggingUrl + " returned status code " + this.httpRequest.status;\r
+                       log4jsLogger.error(msg);\r
+               }\r
+               \r
+               log4jsLogger.trace("< AjaxAppender.onReadyStateChanged: readyState == 4");              \r
+       },\r
+       /**\r
+        * Get the XMLHttpRequest object independent of browser.\r
+        * @private\r
+        */\r
+       getXmlHttpRequest: function() {\r
+               log4jsLogger.trace("> AjaxAppender.getXmlHttpRequest");\r
+               \r
+               var httpRequest = false;\r
+\r
+               try {           \r
+                       if (window.XMLHttpRequest) { // Mozilla, Safari, IE7...\r
+                                       httpRequest = new XMLHttpRequest();\r
+                               if (httpRequest.overrideMimeType) {\r
+                                       httpRequest.overrideMimeType(this.layout.getContentType());\r
+                               }\r
+                       } else if (window.ActiveXObject) { // IE\r
+                               try {\r
+                                       httpRequest = new ActiveXObject("Msxml2.XMLHTTP");\r
+                               } catch (e) {\r
+                                       httpRequest = new ActiveXObject("Microsoft.XMLHTTP");\r
+                               }\r
+                       }\r
+               } catch (e) {\r
+                       httpRequest = false;\r
+               }\r
+               \r
+               if (!httpRequest) {\r
+                       log4jsLogger.fatal("Unfortunatelly your browser does not support AjaxAppender for log4js!");\r
+               }\r
+               \r
+               log4jsLogger.trace("< AjaxAppender.getXmlHttpRequest");\r
+               return httpRequest;\r
+       },\r
+       \r
+       /** \r
+        * toString\r
+        */\r
+        toString: function() {\r
+               return "Log4js.AjaxAppender[loggingUrl=" + this.loggingUrl + ", threshold=" + this.threshold + "]"; \r
+        }\r
+});\r
+\r
+/**\r
+ * File Appender writing the logs to a text file.\r
+ * PLEASE NOTE - Only works in IE and Mozilla \r
+ * use ActiveX to write file on IE\r
+ * use XPCom components  to write file on Mozilla\r
+ * \r
+ * @extends Log4js.Appender \r
+ * @constructor\r
+ * @param logger log4js instance this appender is attached to\r
+ * @param file file log messages will be written to\r
+ * @author Seth Chisamore\r
+ * @author Nicolas Justin njustin@idealx.com\r
+ * @author Gregory Kokanosky gkokanosky@idealx.com\r
+ */\r
+Log4js.FileAppender = function(file) {\r
+\r
+       this.layout = new Log4js.SimpleLayout();\r
+       this.isIE = 'undefined';\r
+       \r
+       this.file = file || "log4js.log";       \r
+       \r
+       try{\r
+               this.fso = new ActiveXObject("Scripting.FileSystemObject");\r
+               this.isIE = true;\r
+       } catch(e){\r
+               try {\r
+                       netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");\r
+                       this.fso =  Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);\r
+                       this.isIE = false; //mozilla & co\r
+               } catch (e) {\r
+                       log4jsLogger.error(e);\r
+               }\r
+       }\r
+};\r
+\r
+Log4js.FileAppender.prototype = Log4js.extend(new Log4js.Appender(), {  \r
+       /**\r
+        * @param loggingEvent event to be logged\r
+        * @see Log4js.Appender#doAppend\r
+        */\r
+       doAppend: function(loggingEvent) {\r
+               try {\r
+                       var fileHandle = null;\r
+                       \r
+                       if( this.isIE === 'undefined') {\r
+                               log4jsLogger.error("Unsupported ")\r
+                       }\r
+                       else if( this.isIE ){\r
+                               // try opening existing file, create if needed\r
+                               fileHandle = this.fso.OpenTextFile(this.file, 8, true);        \r
+                               // write out our data\r
+                               fileHandle.WriteLine(this.layout.format(loggingEvent));\r
+                               fileHandle.close();   \r
+                       } else {\r
+                               netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");\r
+                               this.fso.initWithPath(this.file);\r
+                       if(!this.fso.exists()) {\r
+                               //create file if needed\r
+                       this.fso.create(0x00, 0600);\r
+                       }\r
+                               \r
+                               fileHandle = Components.classes["@mozilla.org/network/file-output-stream;1"].createInstance(Components.interfaces.nsIFileOutputStream);\r
+                       fileHandle.init( this.fso, 0x04 | 0x08 | 0x10, 064, 0);\r
+                               var line = this.layout.format(loggingEvent);\r
+                       fileHandle.write(line, line.length); //write data\r
+                       fileHandle.close();\r
+                       }\r
+               } catch (e) {\r
+                       log4jsLogger.error(e);\r
+               }\r
+       },\r
+       /*\r
+        * @see Log4js.Appender#doClear\r
+        */\r
+       doClear: function() {\r
+               try {\r
+                       if( this.isIE ){\r
+                               var fileHandle = this.fso.GetFile(this.file);\r
+                               fileHandle.Delete();\r
+                       } else {\r
+                               netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");\r
+                               this.fso.initWithPath(this.file);\r
+                               if(this.fso.exists()) {\r
+                                       this.fso.remove(false);\r
+                               }\r
+                       }\r
+               } catch (e) {\r
+                       log4jsLogger.error(e);\r
+               }\r
+       },\r
+       \r
+       /** \r
+        * toString\r
+        */\r
+        toString: function() {\r
+               return "Log4js.FileAppender[file=" + this.file + "]"; \r
+        }\r
+});\r
+\r
+/**\r
+ * Windows Event Appender writes the logs to the Windows Event log.\r
+ * PLEASE NOTE - Only works in IE..uses ActiveX to write to Windows Event log\r
+ *\r
+ * @extends Log4js.Appender \r
+ * @constructor\r
+ * @param logger log4js instance this appender is attached to\r
+ * @author Seth Chisamore\r
+ */\r
+Log4js.WindowsEventAppender = function() {\r
+       \r
+       this.layout = new Log4js.SimpleLayout();\r
+       \r
+       try {\r
+               this.shell = new ActiveXObject("WScript.Shell");\r
+       } catch(e) {\r
+               log4jsLogger.error(e);\r
+       }\r
+};\r
+\r
+Log4js.WindowsEventAppender.prototype = Log4js.extend(new Log4js.Appender(), {  \r
+       /**\r
+        * @param loggingEvent event to be logged\r
+        * @see Log4js.Appender#doAppend\r
+        */\r
+       doAppend: function(loggingEvent) {\r
+               var winLevel = 4;\r
+               \r
+               // Map log level to windows event log level.\r
+               // Windows events: - SUCCESS: 0, ERROR: 1, WARNING: 2, INFORMATION: 4, AUDIT_SUCCESS: 8, AUDIT_FAILURE: 16\r
+               switch (loggingEvent.level) {   \r
+                       case Log4js.Level.FATAL:\r
+                               winLevel = 1;\r
+                               break;\r
+                       case Log4js.Level.ERROR:\r
+                               winLevel = 1;\r
+                               break;\r
+                       case Log4js.Level.WARN:\r
+                               winLevel = 2;\r
+                               break;\r
+                       default:\r
+                               winLevel = 4;\r
+                               break;\r
+               }\r
+               \r
+               try {\r
+                       this.shell.LogEvent(winLevel, this.level.format(loggingEvent));\r
+               } catch(e) {\r
+                       log4jsLogger.error(e);\r
+               }\r
+       },\r
+       \r
+       /** \r
+        * toString\r
+        */\r
+        toString: function() {\r
+               return "Log4js.WindowsEventAppender"; \r
+        } \r
+});\r
+\r
+/**\r
+ * JS Alert Appender writes the logs to the JavaScript alert dialog box\r
+ * @constructor\r
+ * @extends Log4js.Appender  \r
+ * @param logger log4js instance this appender is attached to\r
+ * @author S&eacute;bastien LECACHEUR\r
+ */\r
+Log4js.JSAlertAppender = function() {\r
+\r
+       this.layout = new Log4js.SimpleLayout();\r
+};\r
+\r
+Log4js.JSAlertAppender.prototype = Log4js.extend(new Log4js.Appender(), {  \r
+       /** \r
+        * @see Log4js.Appender#doAppend\r
+        */\r
+       doAppend: function(loggingEvent) {\r
+               alert(this.layout.getHeader() + this.layout.format(loggingEvent) + this.layout.getFooter());\r
+       },\r
+       \r
+       /** \r
+        * toString\r
+        */\r
+        toString: function() {\r
+               return "Log4js.JSAlertAppender"; \r
+        }      \r
+});\r
+\r
+/**\r
+ * Appender writes the logs to the JavaScript console of Mozilla browser\r
+ * More infos: http://kb.mozillazine.org/index.php?title=JavaScript_Console&redirect=no\r
+ * PLEASE NOTE - Only works in Mozilla browser\r
+ * @constructor\r
+ * @extends Log4js.Appender  \r
+ * @param logger log4js instance this appender is attached to\r
+ * @author Stephan Strittmatter\r
+ */\r
+Log4js.MozillaJSConsoleAppender = function() {\r
+       this.layout = new Log4js.SimpleLayout();\r
+       try {\r
+               netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");\r
+               this.jsConsole = Components.classes["@mozilla.org/consoleservice;1"].getService(Components.interfaces.nsIConsoleService);\r
+               this.scriptError = Components.classes["@mozilla.org/scripterror;1"].createInstance(Components.interfaces.nsIScriptError);\r
+       } catch (e) {\r
+               log4jsLogger.error(e);\r
+       }\r
+};\r
+\r
+Log4js.MozillaJSConsoleAppender.prototype = Log4js.extend(new Log4js.Appender(), {  \r
+       /** \r
+        * @see Log4js.Appender#doAppend\r
+        */\r
+       doAppend: function(loggingEvent) {\r
+               try {\r
+                       netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");\r
+                       this.scriptError.init(this.layout.format(loggingEvent), null, null, null, null, this.getFlag(loggingEvent), loggingEvent.categoryName);\r
+                       this.jsConsole.logMessage(this.scriptError);\r
+               } catch (e) {\r
+                       log4jsLogger.error(e);\r
+               }\r
+       },\r
+       \r
+       /** \r
+        * toString\r
+        */\r
+        toString: function() {\r
+               return "Log4js.MozillaJSConsoleAppender"; \r
+        },\r
+        \r
+       /**\r
+        * Map Log4js.Level to jsConsole Flags:\r
+        * <ul>\r
+        * <li>nsIScriptError.errorFlag (0) = Level.Error</li>\r
+        * <li>nsIScriptError.warningFlag (1)= Log4js.Level.WARN</li>\r
+        * <li>nsIScriptError.exceptionFlag (2) = Log4js.Level.FATAL</li>\r
+        * <li>nsIScriptError.strictFlag (4) = unused</li>\r
+        * </ul>\r
+        * @private\r
+        */     \r
+       getFlag: function(loggingEvent)\r
+       {\r
+               var retval;\r
+               switch (loggingEvent.level) {   \r
+                       case Log4js.Level.FATAL:\r
+                               retval = 2;//nsIScriptError.exceptionFlag = 2\r
+                               break;\r
+                       case Log4js.Level.ERROR:\r
+                               retval = 0;//nsIScriptError.errorFlag\r
+                               break;\r
+                       case Log4js.Level.WARN:\r
+                               retval = 1;//nsIScriptError.warningFlag = 1\r
+                               break;\r
+                       default:\r
+                               retval = 1;//nsIScriptError.warningFlag = 1\r
+                               break;\r
+               }\r
+               \r
+               return retval;          \r
+       }\r
+});\r
+\r
+/**\r
+ * Appender writes the logs to the JavaScript console of Opera browser\r
+ * PLEASE NOTE - Only works in Opera browser\r
+ * @constructor\r
+ * @extends Log4js.Appender  \r
+ * @param logger log4js instance this appender is attached to\r
+ * @author Stephan Strittmatter\r
+ */\r
+Log4js.OperaJSConsoleAppender = function() {\r
+       this.layout = new Log4js.SimpleLayout();\r
+};\r
+\r
+Log4js.OperaJSConsoleAppender.prototype = Log4js.extend(new Log4js.Appender(), {  \r
+       /** \r
+        * @see Log4js.Appender#doAppend\r
+        */\r
+       doAppend: function(loggingEvent) {\r
+               opera.postError(this.layout.format(loggingEvent));\r
+       },\r
+       \r
+       /** \r
+        * toString\r
+        */\r
+        toString: function() {\r
+               return "Log4js.OperaJSConsoleAppender"; \r
+        }\r
+});\r
+\r
+/**\r
+ * Appender writes the logs to the JavaScript console of Safari browser\r
+ * PLEASE NOTE - Only works in Safari browser\r
+ * @constructor\r
+ * @extends Log4js.Appender  \r
+ * @param logger log4js instance this appender is attached to\r
+ * @author Stephan Strittmatter\r
+ */\r
+Log4js.SafariJSConsoleAppender = function() {\r
+       this.layout = new Log4js.SimpleLayout();\r
+};\r
+\r
+Log4js.SafariJSConsoleAppender.prototype = Log4js.extend(new Log4js.Appender(), {  \r
+       /** \r
+        * @see Log4js.Appender#doAppend\r
+        */\r
+       doAppend: function(loggingEvent) {\r
+               window.console.log(this.layout.format(loggingEvent));\r
+       },\r
+       \r
+       /** \r
+        * toString\r
+        */\r
+        toString: function() {\r
+               return "Log4js.SafariJSConsoleAppender"; \r
+        }\r
+});\r
+\r
+/**\r
+ * JavaScript Console Appender which is browser independent.\r
+ * It checks internally for the current browser and adds delegate to\r
+ * specific JavaScript Console Appender of the browser.\r
+ * \r
+ * @author Stephan Strittmatter\r
+ * @since 1.0\r
+ */\r
+Log4js.BrowserConsoleAppender = function() {\r
+       /**\r
+        * Delegate for browser specific implementation\r
+        * @type Log4js.Appender\r
+        * @private\r
+        */\r
+       this.consoleDelegate = null;\r
+       \r
+       if (window.console) {\r
+               this.consoleDelegate = new Log4js.SafariJSConsoleAppender(); \r
+       }\r
+    else if (window.opera) {\r
+               this.consoleDelegate = new Log4js.OperaJSConsoleAppender(); \r
+       }\r
+       else if(netscape) {\r
+               this.consoleDelegate = new Log4js.MozJSConsoleAppender(); \r
+       }\r
+    else {\r
+       //@todo\r
+       log4jsLogger.error("Unsupported Browser");\r
+    }\r
+};\r
+\r
+Log4js.BrowserConsoleAppender.prototype = Log4js.extend(new Log4js.Appender(), {  \r
+       /** \r
+        * @see Log4js.Appender#doAppend\r
+        */\r
+       doAppend: function(loggingEvent) {\r
+               this.consoleDelegate.doAppend(loggingEvent);\r
+       },\r
+       /** \r
+        * @see Log4js.Appender#doClear\r
+        */\r
+       doClear: function() {\r
+               this.consoleDelegate.doClear();\r
+       },\r
+       /**\r
+        * @see Log4js.Appender#setLayout\r
+        */\r
+       setLayout: function(layout){\r
+               this.consoleDelegate.setLayout(layout);\r
+       },\r
+       \r
+       /** \r
+        * toString\r
+        */\r
+        toString: function() {\r
+               return "Log4js.BrowserConsoleAppender: " + this.consoleDelegate.toString(); \r
+        }\r
+});\r
+\r
+/**\r
+ * SimpleLayout consists of the level of the log statement, followed by " - " \r
+ * and then the log message itself. For example,\r
+ * <code>DEBUG - Hello world</code>\r
+ *\r
+ * @constructor\r
+ * @extends Log4js.Layout\r
+ * @extends Layout\r
+ * @author Stephan Strittmatter\r
+ */\r
+Log4js.SimpleLayout = function() {\r
+       this.LINE_SEP  = "\n";\r
+       this.LINE_SEP_LEN = 1;\r
+};\r
+\r
+Log4js.SimpleLayout.prototype = Log4js.extend(new Log4js.Layout(), {\r
+       /** \r
+        * Implement this method to create your own layout format.\r
+        * @param {Log4js.LoggingEvent} loggingEvent loggingEvent to format\r
+        * @return formatted String\r
+        * @type String\r
+        */\r
+       format: function(loggingEvent) {\r
+               return loggingEvent.level.toString() + " - " + loggingEvent.message + this.LINE_SEP;\r
+       },\r
+       /** \r
+        * Returns the content type output by this layout. \r
+        * @return The base class returns "text/plain".\r
+        * @type String\r
+        */\r
+       getContentType: function() {\r
+               return "text/plain";\r
+       },\r
+       /** \r
+        * @return Returns the header for the layout format. The base class returns null.\r
+        * @type String\r
+        */\r
+       getHeader: function() {\r
+               return "";\r
+       },\r
+       /** \r
+        * @return Returns the footer for the layout format. The base class returns null.\r
+        * @type String\r
+        */\r
+       getFooter: function() {\r
+               return "";\r
+       }\r
+});\r
+       \r
+/**\r
+ * BasicLayout is a simple layout for storing the loggs. The loggs are stored\r
+ * in following format:\r
+ * <pre>\r
+ * categoryName~startTime [logLevel] message\n\r
+ * </pre>\r
+ *\r
+ * @constructor\r
+ * @extends Log4js.Layout\r
+ * @author Stephan Strittmatter\r
+ */\r
+Log4js.BasicLayout = function() {\r
+       this.LINE_SEP  = "\n";\r
+};\r
+\r
+Log4js.BasicLayout.prototype = Log4js.extend(new Log4js.Layout(), {\r
+       /** \r
+        * Implement this method to create your own layout format.\r
+        * @param {Log4js.LoggingEvent} loggingEvent loggingEvent to format\r
+        * @return formatted String\r
+        * @type String\r
+        */\r
+       format: function(loggingEvent) {\r
+               return loggingEvent.categoryName + "~" + loggingEvent.startTime.toLocaleString() + " [" + loggingEvent.level.toString() + "] " + loggingEvent.message + this.LINE_SEP;\r
+       },\r
+       /** \r
+        * Returns the content type output by this layout. \r
+        * @return The base class returns "text/plain".\r
+        * @type String\r
+        */\r
+       getContentType: function() {\r
+               return "text/plain";\r
+       },\r
+       /** \r
+        * @return Returns the header for the layout format. The base class returns null.\r
+        * @type String\r
+        */\r
+       getHeader: function() {\r
+               return "";\r
+       },\r
+       /** \r
+        * @return Returns the footer for the layout format. The base class returns null.\r
+        * @type String\r
+        */\r
+       getFooter: function() {\r
+               return "";\r
+       }\r
+});\r
+\r
+/**\r
+ * HtmlLayout write the logs in Html format.\r
+ *\r
+ * @constructor\r
+ * @extends Log4js.Layout\r
+ * @author Stephan Strittmatter\r
+ */\r
+Log4js.HtmlLayout = function() {return;};\r
+\r
+Log4js.HtmlLayout.prototype = Log4js.extend(new Log4js.Layout(), {\r
+       /** \r
+        * Implement this method to create your own layout format.\r
+        * @param {Log4js.LoggingEvent} loggingEvent loggingEvent to format\r
+        * @return formatted String\r
+        * @type String\r
+        */\r
+       format: function(loggingEvent) {\r
+               return "<div style=\"" + this.getStyle(loggingEvent) + "\">" + loggingEvent.getFormattedTimestamp() + " - " + loggingEvent.level.toString() + " - " + loggingEvent.message + "</div>\n";\r
+       },\r
+       /** \r
+        * Returns the content type output by this layout. \r
+        * @return The base class returns "text/html".\r
+        * @type String\r
+        */\r
+       getContentType: function() {\r
+               return "text/html";\r
+       },\r
+       /** \r
+        * @return Returns the header for the layout format. The base class returns null.\r
+        * @type String\r
+        */\r
+       getHeader: function() {\r
+               return "<html><head><title>log4js</head><body>";\r
+       },\r
+       /** \r
+        * @return Returns the footer for the layout format. The base class returns null.\r
+        * @type String\r
+        */\r
+       getFooter: function() {\r
+               return "</body></html>";\r
+       },\r
+       \r
+       getStyle: function(loggingEvent)\r
+       {\r
+               var style;\r
+               if (loggingEvent.level.toString().search(/ERROR/) != -1) { \r
+                       style = 'color:red';\r
+               } else if (loggingEvent.level.toString().search(/FATAL/) != -1) { \r
+                       style = 'color:red';\r
+               } else if (loggingEvent.level.toString().search(/WARN/) != -1) { \r
+                       style = 'color:orange';\r
+               } else if (loggingEvent.level.toString().search(/DEBUG/) != -1) {\r
+                       style = 'color:green';\r
+               } else if (loggingEvent.level.toString().search(/INFO/) != -1) {\r
+                       style = 'color:white';\r
+               } else {\r
+                       style = 'color:yellow';\r
+               }       \r
+               return style;\r
+       }\r
+});\r
+\r
+/**\r
+ * XMLLayout write the logs in XML format.\r
+ * Layout is simmilar to log4j's XMLLayout:\r
+ * <pre>\r
+ * <log4js:event category="category" level="Level" client="Client" referer="ref" timestam="Date">\r
+ * <log4js:message>Logged message</log4js:message>\r
+ * </log4js:event>\r
+ * </pre>\r
+ * @constructor\r
+ * @extends Layout\r
+ * @author Stephan Strittmatter\r
+ */\r
+Log4js.XMLLayout = function(){return;};\r
+Log4js.XMLLayout.prototype = Log4js.extend(new Log4js.Layout(), {\r
+       /** \r
+        * Implement this method to create your own layout format.\r
+        * @param {Log4js.LoggingEvent} loggingEvent loggingEvent to format\r
+        * @return formatted String\r
+        * @type String\r
+        */\r
+       format: function(loggingEvent) {\r
+               var useragent = "unknown";\r
+               try {\r
+                       useragent = navigator.userAgent;\r
+               } catch(e){\r
+                       useragent = "unknown";\r
+               }\r
+               \r
+               var referer = "unknown";\r
+               try {\r
+                       referer = location.href;\r
+               } catch(e){\r
+                       referer = "unknown";\r
+               }\r
+                               \r
+               var content = "<log4js:event logger=\"";\r
+               content += loggingEvent.categoryName + "\" level=\"";\r
+               content += loggingEvent.level.toString() + "\" useragent=\"";\r
+               content += useragent + "\" referer=\"";\r
+               content += referer.replace(/&/g, "&amp;") + "\" timestamp=\"";\r
+               content += loggingEvent.getFormattedTimestamp() + "\">\n";\r
+               content += "\t<log4js:message><![CDATA[" + this.escapeCdata(loggingEvent.message) + "]]></log4js:message>\n";   \r
+               \r
+               if (loggingEvent.exception) {\r
+                       content += this.formatException(loggingEvent.exception) ;\r
+               }\r
+               content += "</log4js:event>\n";\r
+        \r
+      return content;\r
+       },\r
+       /** \r
+        * Returns the content type output by this layout. \r
+        * @return The base class returns "text/xml".\r
+        * @type String\r
+        */\r
+       getContentType: function() {\r
+               return "text/xml";\r
+       },\r
+       /** \r
+        * @return Returns the header for the layout format. The base class returns null.\r
+        * @type String\r
+        */\r
+       getHeader: function() {\r
+               return "<log4js:eventSet version=\"" + Log4js.version + \r
+                       "\" xmlns:log4js=\"http://log4js.berlios.de/2007/log4js/\">\n";\r
+       },\r
+       /** \r
+        * @return Returns the footer for the layout format. The base class returns null.\r
+        * @type String\r
+        */\r
+       getFooter: function() {\r
+               return "</log4js:eventSet>\n";\r
+       },\r
+       \r
+       getSeparator: function() {\r
+               return "\n";\r
+       },\r
+       \r
+       /**\r
+        * better readable formatted Exceptions.\r
+        * @param ex {Exception} the exception to be formatted.\r
+        * @return {String} the formatted String representation of the exception.\r
+        * @private\r
+        */\r
+       formatException: function(ex) {\r
+               if (ex) {\r
+                       var exStr = "\t<log4js:throwable>"; \r
+                       if (ex.message) {\r
+                               exStr +=  "\t\t<log4js:message><![CDATA[" + this.escapeCdata(ex.message) + "]]></log4js:message>\n";    \r
+                       } \r
+                       if (ex.description) {\r
+                               exStr +=  "\t\t<log4js:description><![CDATA[" + this.escapeCdata(ex.description) + "]]></log4js:description>\n";        \r
+                       }\r
+                       \r
+                       exStr +=  "\t\t<log4js:stacktrace>";\r
+                       exStr +=  "\t\t\t<log4js:location fileName=\""+ex.fileName+"\" lineNumber=\""+ex.lineNumber+"\" />";\r
+                       exStr +=  "\t\t</log4js:stacktrace>";\r
+                       exStr = "\t</log4js:throwable>";\r
+                       return exStr;\r
+               }\r
+               return null;\r
+       },\r
+       /**\r
+        * Escape Cdata messages\r
+        * @param str {String} message to escape\r
+        * @return {String} the escaped message\r
+        * @private\r
+        */\r
+       escapeCdata: function(str) {\r
+               return str.replace(/\]\]>/, "]]>]]&gt;<![CDATA[");\r
+       }\r
+});\r
+\r
+/**\r
+ * JSONLayout write the logs in JSON format.\r
+ * JSON library is required to use this Layout. See also {@link http://www.json.org}\r
+ * @constructor\r
+ * @extends Log4js.Layout\r
+ * @author Stephan Strittmatter\r
+ */\r
+Log4js.JSONLayout = function() {\r
+       this.df = new Log4js.DateFormatter();\r
+};\r
+Log4js.JSONLayout.prototype = Log4js.extend(new Log4js.Layout(), {\r
+       /** \r
+        * Implement this method to create your own layout format.\r
+        * @param {Log4js.LoggingEvent} loggingEvent loggingEvent to format\r
+        * @return formatted String\r
+        * @type String\r
+        */\r
+       format: function(loggingEvent) {\r
+               \r
+                               var useragent = "unknown";\r
+               try {\r
+                       useragent = navigator.userAgent;\r
+               } catch(e){\r
+                       useragent = "unknown";\r
+               }\r
+               \r
+               var referer = "unknown";\r
+               try {\r
+                       referer = location.href;\r
+               } catch(e){\r
+                       referer = "unknown";\r
+               }\r
+               \r
+               var jsonString = "{\n \"LoggingEvent\": {\n";\r
+               \r
+               jsonString += "\t\"logger\": \"" +  loggingEvent.categoryName + "\",\n";\r
+               jsonString += "\t\"level\": \"" +  loggingEvent.level.toString() + "\",\n";\r
+               jsonString += "\t\"message\": \"" +  loggingEvent.message + "\",\n"; \r
+               jsonString += "\t\"referer\": \"" + referer + "\",\n"; \r
+               jsonString += "\t\"useragent\": \"" + useragent + "\",\n"; \r
+               jsonString += "\t\"timestamp\": \"" +  this.df.formatDate(loggingEvent.startTime, "yyyy-MM-ddThh:mm:ssZ") + "\",\n";\r
+               jsonString += "\t\"exception\": \"" +  loggingEvent.exception + "\"\n"; \r
+               jsonString += "}}";      \r
+        \r
+        return jsonString;\r
+       },\r
+       /** \r
+        * Returns the content type output by this layout. \r
+        * @return The base class returns "text/xml".\r
+        * @type String\r
+        */\r
+       getContentType: function() {\r
+               return "text/json";\r
+       },\r
+       /** \r
+        * @return Returns the header for the layout format. The base class returns null.\r
+        * @type String\r
+        */\r
+       getHeader: function() {\r
+               return "{\"Log4js\": [\n";\r
+       },\r
+       /** \r
+        * @return Returns the footer for the layout format. The base class returns null.\r
+        * @type String\r
+        */\r
+       getFooter: function() {\r
+               return "\n]}";\r
+       },\r
+       \r
+       getSeparator: function() {\r
+               return ",\n";\r
+       }\r
+});\r
+\r
+/** \r
+ * PatternLayout \r
+ */\r
+Log4js.PatternLayout = function(pattern) {\r
+       if (pattern) {\r
+               this.pattern = pattern;\r
+       } else {\r
+               this.pattern = Log4js.PatternLayout.DEFAULT_CONVERSION_PATTERN;\r
+       }\r
+};\r
+\r
+Log4js.PatternLayout.TTCC_CONVERSION_PATTERN = "%r %p %c - %m%n";\r
+Log4js.PatternLayout.DEFAULT_CONVERSION_PATTERN = "%m%n";\r
+Log4js.PatternLayout.ISO8601_DATEFORMAT = "yyyy-MM-dd HH:mm:ss,SSS";\r
+Log4js.PatternLayout.DATETIME_DATEFORMAT = "dd MMM YYYY HH:mm:ss,SSS";\r
+Log4js.PatternLayout.ABSOLUTETIME_DATEFORMAT = "HH:mm:ss,SSS";\r
+\r
+Log4js.PatternLayout.prototype = Log4js.extend(new Log4js.Layout(), {\r
+       /** \r
+        * Returns the content type output by this layout. \r
+        * @return "text/plain".\r
+        * @type String\r
+        */\r
+       getContentType: function() {\r
+               return "text/plain";\r
+       },\r
+       /** \r
+        * @return Returns the header for the layout format.\r
+        * @type String\r
+        */\r
+       getHeader: function() {\r
+               return null;\r
+       },\r
+       /** \r
+        * @return Returns the footer for the layout format.\r
+        * @type String\r
+        */\r
+       getFooter: function() {\r
+               return null;\r
+       },\r
+       \r
+       format: function(loggingEvent) {\r
+               var regex = /%(-?[0-9]+)?(\.?[0-9]+)?([cdmnpr%])(\{([^\}]+)\})?|([^%]+)/;\r
+               var formattedString = "";\r
+               var result;\r
+               var searchString = this.pattern;\r
+\r
+               // Cannot use regex global flag since it doesn't work in IE5\r
+               while ((result = regex.exec(searchString))) {\r
+                       var matchedString = result[0];\r
+                       var padding = result[1];\r
+                       var truncation = result[2];\r
+                       var conversionCharacter = result[3];\r
+                       var specifier = result[5];\r
+                       var text = result[6];\r
+\r
+                       // Check if the pattern matched was just normal text\r
+                       if (text) {\r
+                               formattedString += "" + text;\r
+                       } else {\r
+                               // Create a raw replacement string based on the conversion\r
+                               // character and specifier\r
+                               var replacement = "";\r
+                               switch(conversionCharacter) {\r
+                                       case "c":\r
+                                               var loggerName = loggingEvent.categoryName;\r
+                                               if (specifier) {\r
+                                                       var precision = parseInt(specifier, 10);\r
+                                                       var loggerNameBits = loggingEvent.categoryName.split(".");\r
+                                                       if (precision >= loggerNameBits.length) {\r
+                                                               replacement = loggerName;\r
+                                                       } else {\r
+                                                               replacement = loggerNameBits.slice(loggerNameBits.length - precision).join(".");\r
+                                                       }\r
+                                               } else {\r
+                                                       replacement = loggerName;\r
+                                               }\r
+                                               break;\r
+                                       case "d":\r
+                                               var dateFormat = Log4js.PatternLayout.ISO8601_DATEFORMAT;\r
+                                               if (specifier) {\r
+                                                       dateFormat = specifier;\r
+                                                       // Pick up special cases\r
+                                                       if (dateFormat == "ISO8601") {\r
+                                                               dateFormat = Log4js.PatternLayout.ISO8601_DATEFORMAT;\r
+                                                       } else if (dateFormat == "ABSOLUTE") {\r
+                                                               dateFormat = Log4js.PatternLayout.ABSOLUTETIME_DATEFORMAT;\r
+                                                       } else if (dateFormat == "DATE") {\r
+                                                               dateFormat = Log4js.PatternLayout.DATETIME_DATEFORMAT;\r
+                                                       }\r
+                                               }\r
+                                               // Format the date\r
+                                               replacement = (new Log4js.SimpleDateFormat(dateFormat)).format(loggingEvent.startTime);\r
+                                               break;\r
+                                       case "m":\r
+                                               replacement = loggingEvent.message;\r
+                                               break;\r
+                                       case "n":\r
+                                               replacement = "\n";\r
+                                               break;\r
+                                       case "p":\r
+                                               replacement = loggingEvent.level.toString();\r
+                                               break;\r
+                                       case "r":\r
+                                               replacement = "" + loggingEvent.startTime.toLocaleTimeString(); //TODO: .getDifference(Log4js.applicationStartDate);\r
+                                               break;\r
+                                       case "%":\r
+                                               replacement = "%";\r
+                                               break;\r
+                                       default:\r
+                                               replacement = matchedString;\r
+                                               break;\r
+                               }\r
+                               // Format the replacement according to any padding or\r
+                               // truncation specified\r
+\r
+                               var len;\r
+\r
+                               // First, truncation\r
+                               if (truncation) {\r
+                                       len = parseInt(truncation.substr(1), 10);\r
+                                       replacement = replacement.substring(0, len);\r
+                               }\r
+                               // Next, padding\r
+                               if (padding) {\r
+                                       if (padding.charAt(0) == "-") {\r
+                                               len = parseInt(padding.substr(1), 10);\r
+                                               // Right pad with spaces\r
+                                               while (replacement.length < len) {\r
+                                                       replacement += " ";\r
+                                               }\r
+                                       } else {\r
+                                               len = parseInt(padding, 10);\r
+                                               // Left pad with spaces\r
+                                               while (replacement.length < len) {\r
+                                                       replacement = " " + replacement;\r
+                                               }\r
+                                       }\r
+                               }\r
+                               formattedString += replacement;\r
+                       }\r
+                       searchString = searchString.substr(result.index + result[0].length);\r
+               }\r
+               return formattedString;\r
+       }\r
+});\r
+\r
+/**\r
+ * @private\r
+ * @ignore\r
+ */\r
+if (!Array.prototype.push) {\r
+       /**\r
+        * Functions taken from Prototype library, didn't want to require for just few \r
+        * functions.\r
+        * More info at {@link http://\r
+        * prototype.conio.net/}\r
+        * @private\r
+        */\r
+       Array.prototype.push = function() {\r
+               var startLength = this.length;\r
+               for (var i = 0; i < arguments.length; i++) {\r
+                       this[startLength + i] = arguments[i];\r
+               }\r
+               return this.length;\r
+       };\r
+}\r
+\r
+/**\r
+ * FIFO buffer\r
+ * @private\r
+ */\r
+Log4js.FifoBuffer = function()\r
+{\r
+  this.array = new Array();\r
+};\r
+\r
+Log4js.FifoBuffer.prototype = {\r
+\r
+       /**\r
+        * @param {Object} obj any object added to buffer\r
+        */\r
+       push : function(obj) {\r
+        this.array[this.array.length] = obj;\r
+        return this.array.length;\r
+       },\r
+       \r
+       /**\r
+        * @return first putted in Object\r
+        */\r
+       pull : function() {\r
+               if (this.array.length > 0) {\r
+                       var firstItem = this.array[0];\r
+                       for (var i = 0; i < this.array.length - 1; i++) {\r
+                               this.array[i] = this.array[i + 1];\r
+                       }\r
+                       this.array.length = this.array.length - 1;\r
+                       return firstItem;\r
+               }\r
+               return null;\r
+       },\r
+       \r
+       length : function() {\r
+               return this.array.length;\r
+       }\r
+};\r
+\r
+\r
+\r
+/**\r
+ * Date Formatter\r
+ * addZero() and formatDate() are courtesy of Mike Golding:\r
+ * http://www.mikezilla.com/exp0015.html\r
+ * @private\r
+ */ \r
+Log4js.DateFormatter = function() {\r
+       return;\r
+};\r
+/**\r
+ * default format of date (ISO-8601)\r
+ * @static\r
+ * @final\r
+ */\r
+Log4js.DateFormatter.DEFAULT_DATE_FORMAT = "yyyy-MM-ddThh:mm:ssO";\r
+\r
+\r
+Log4js.DateFormatter.prototype = {\r
+       /**\r
+        * Formats the given date by the given pattern.<br />\r
+        * Following switches are supported:\r
+        * <ul>\r
+        * <li>yyyy: The year</li>\r
+        * <li>MM: the month</li>\r
+        * <li>dd: the day of month<li>\r
+        * <li>hh: the hour<li>\r
+        * <li>mm: minutes</li>\r
+        * <li>O: timezone offset</li>\r
+        * </ul>\r
+        * @param {Date} vDate the date to format\r
+        * @param {String} vFormat the format pattern\r
+        * @return {String} formatted date string\r
+        * @static\r
+        */\r
+       formatDate : function(vDate, vFormat) {\r
+         var vDay = this.addZero(vDate.getDate());\r
+         var vMonth = this.addZero(vDate.getMonth()+1);\r
+         var vYearLong = this.addZero(vDate.getFullYear());\r
+         var vYearShort = this.addZero(vDate.getFullYear().toString().substring(3,4));\r
+         var vYear = (vFormat.indexOf("yyyy")>-1?vYearLong:vYearShort);\r
+         var vHour  = this.addZero(vDate.getHours());\r
+         var vMinute = this.addZero(vDate.getMinutes());\r
+         var vSecond = this.addZero(vDate.getSeconds());\r
+         var vTimeZone = this.O(vDate);\r
+         var vDateString = vFormat.replace(/dd/g, vDay).replace(/MM/g, vMonth).replace(/y{1,4}/g, vYear);\r
+         vDateString = vDateString.replace(/hh/g, vHour).replace(/mm/g, vMinute).replace(/ss/g, vSecond);\r
+         vDateString = vDateString.replace(/O/g, vTimeZone);\r
+         return vDateString;\r
+       },\r
+               \r
+       /**\r
+        * @private\r
+        * @static\r
+        */\r
+       addZero : function(vNumber) {\r
+         return ((vNumber < 10) ? "0" : "") + vNumber;\r
+       },\r
+       \r
+       /**\r
+        * Formates the TimeOffest\r
+        * Thanks to http://www.svendtofte.com/code/date_format/\r
+        * @private\r
+        */\r
+       O : function (date) {\r
+               // Difference to Greenwich time (GMT) in hours\r
+               var os = Math.abs(date.getTimezoneOffset());\r
+               var h = String(Math.floor(os/60));\r
+               var m = String(os%60);\r
+               h.length == 1? h = "0"+h:1;\r
+               m.length == 1? m = "0"+m:1;\r
+               return date.getTimezoneOffset() < 0 ? "+"+h+m : "-"+h+m;\r
+       }\r
+};\r
+\r
+\r
+/**\r
+ * internal Logger to be used\r
+ * @private\r
+ */\r
+var log4jsLogger = Log4js.getLogger("Log4js");\r
+log4jsLogger.addAppender(new Log4js.ConsoleAppender());\r
+log4jsLogger.setLevel(Log4js.Level.ALL);
\ No newline at end of file
diff --git a/fluidbook/compile/_js/resources/Base.esapi.properties.js b/fluidbook/compile/_js/resources/Base.esapi.properties.js
new file mode 100644 (file)
index 0000000..3bbdd55
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * OWASP Enterprise Security API (ESAPI)
+ *
+ * This file is part of the Open Web Application Security Project (OWASP)
+ * Enterprise Security API (ESAPI) project. For details, please see
+ * <a href="http://www.owasp.org/index.php/ESAPI">http://www.owasp.org/index.php/ESAPI</a>.
+ *
+ * Copyright (c) 2008 - The OWASP Foundation
+ *
+ * The ESAPI is published by OWASP under the BSD license. You should read and accept the
+ * LICENSE before you use, modify, and/or redistribute this software.
+ */
+
+$namespace('Base.esapi.properties');
+
+Base.esapi.properties = {
+    application: {
+        // Change this value to reflect your application, or override it in an application scoped configuration.
+        Name: 'ESAPI4JS Base Application'
+    },
+
+    httputilities: {
+        cookies: {
+            ForceSecure: true
+        }
+    },
+
+    logging: {
+        Implementation: org.owasp.esapi.reference.logging.Log4JSLogFactory,
+        Level: org.owasp.esapi.Logger.ERROR,
+        // For a console that pops up in a seperate window
+        // Appenders: [ new ConsoleAppender(true) ],
+        // To log to a logging service on the server
+        // Appenders: [ new AjaxAppender( '/log/' ) ],
+        // Default to log nowhere
+        Appenders: [  ],
+        LogUrl: false,
+        LogApplicationName: false,
+        EncodingRequired: true
+    },
+
+    encoder: {
+        Implementation: org.owasp.esapi.reference.encoding.DefaultEncoder,
+        AllowMultipleEncoding: false
+    },
+
+    localization: {
+        StandardResourceBundle: ESAPI_Standard_en_US,
+        DefaultLocale: 'en-US'
+    },
+
+    validation: {
+        Implementation: org.owasp.esapi.reference.validation.DefaultValidator,
+        AccountName: '^[a-zA-Z0-9]{3,20}$',
+        SafeString: '[a-zA-Z0-9\\-_+]*',
+        Email: '^[A-Za-z0-9._%-]+@[A-Za-z0-9.-]+\\.[a-zA-Z]{2,4}$',
+        IPAddress: '^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$',
+        URL: '^(ht|f)tp(s?)\\:\\/\\/[0-9a-zA-Z]([-.\\w]*[0-9a-zA-Z])*(:(0-9)*)*(\\/?)([a-zA-Z0-9\\-\\.\\?\\,\\:\\\'\\/\\\\\\+=&amp;%\\$#_]*)?$',
+        CreditCard: '^(\\d{4}[- ]?){3}\\d{4}$',
+        SSN: '^(?!000)([0-6]\\d{2}|7([0-6]\\d|7[012]))([ -]?)(?!00)\\d\\d\\3(?!0000)\\d{4}$',
+        HttpScheme: '^(http|https)$',
+        HttpServerName: '^[a-zA-Z0-9_.\\-]*$',
+        HttpParameterName: '^[a-zA-Z0-9_]{1,32}$',
+        HttpParameterValue: '^[a-zA-Z0-9.\\-\\/+=_ ]*$',
+        HttpCookieName: '^[a-zA-Z0-9\\-_]{1,32}$',
+        HttpCookieValue: '^[a-zA-Z0-9\\-\\/+=_ ]*$'
+    }
+};
\ No newline at end of file
index 646b2292b29123e8391d0c54dc829322590c5b50..73bf4f973c3869bd415c2e4c742b9bc9755dbb44 100644 (file)
@@ -1 +1,854 @@
-/**\r * SWFAddress 2.4: Deep linking for Flash and Ajax <http://www.asual.com/swfaddress/>\r *\r * SWFAddress is (c) 2006-2009 Rostislav Hristov and contributors\r * This software is released under the MIT License <http://www.opensource.org/licenses/mit-license.php>\r *\r */\r\rif (typeof asual == "undefined") var asual = {};\rif (typeof asual.util == "undefined") asual.util = {};\r\rasual.util.Browser = new function() {\r \r    var _agent = navigator.userAgent.toLowerCase(),\r        _safari = /webkit/.test(_agent),\r        _opera = /opera/.test(_agent),\r        _msie = /msie/.test(_agent) && !/opera/.test(_agent),\r        _mozilla = /mozilla/.test(_agent) && !/(compatible|webkit)/.test(_agent),\r        _version = parseFloat(_msie ? _agent.substr(_agent.indexOf('msie') + 4) : \r            (_agent.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/) || [0,'0'])[1]);\r\r    this.toString = function() {\r        return '[class Browser]';\r    };\r\r    this.getVersion = function() {\r        return _version;\r    };\r\r    this.isMSIE = function() {\r        return _msie;\r    };\r\r    this.isSafari = function() {\r        return _safari;\r    };\r\r    this.isOpera = function() {\r        return _opera;\r    };\r\r    this.isMozilla = function() {\r        return _mozilla;\r    };\r};\r\rasual.util.Events = new function() {\r\r    var DOM_LOADED = 'DOMContentLoaded', \r        STOP = 'onstop',\r        _w = window,\r        _d = document,\r        _cache = [],\r        _util = asual.util,\r        _browser = _util.Browser,\r        _msie = _browser.isMSIE(),\r        _safari = _browser.isSafari();\r\r    this.toString = function() {\r        return '[class Events]';\r    };\r\r    this.addListener = function(obj, type, listener) {\r        _cache.push({o: obj, t: type, l: listener});\r        if (!(type == DOM_LOADED && (_msie || _safari))) {\r            if (obj.addEventListener)\r                obj.addEventListener(type, listener, false);\r            else if (obj.attachEvent)\r                obj.attachEvent('on' + type, listener);\r        }\r    };\r\r    this.removeListener = function(obj, type, listener) {\r        for (var i = 0, e; e = _cache[i]; i++) {\r            if (e.o == obj && e.t == type && e.l == listener) {\r                _cache.splice(i, 1);\r                break;\r            }\r        }\r        if (!(type == DOM_LOADED && (_msie || _safari))) {\r            if (obj.removeEventListener)\r                obj.removeEventListener(type, listener, false);\r            else if (obj.detachEvent)\r                obj.detachEvent('on' + type, listener);\r        }\r    };\r\r    var _unload = function() {\r        for (var i = 0, evt; evt = _cache[i]; i++) {\r            if (evt.t != DOM_LOADED)\r                _util.Events.removeListener(evt.o, evt.t, evt.l);\r        }\r    };\r\r    var _unloadFix = function() {\r        if (_d.readyState == 'interactive') {\r            function stop() {\r                _d.detachEvent(STOP, stop);\r                _unload();\r            };\r            _d.attachEvent(STOP, stop);\r            _w.setTimeout(function() {\r                _d.detachEvent(STOP, stop);\r            }, 0);\r        }\r    };\r\r    if (_msie || _safari) {\r        (function (){\r            try {\r                if ((_msie && _d.body) || !/loaded|complete/.test(_d.readyState))\r                    _d.documentElement.doScroll('left');\r            } catch(e) {\r                return setTimeout(arguments.callee, 0);\r            }\r            for (var i = 0, e; e = _cache[i]; i++)\r                if (e.t == DOM_LOADED) e.l.call(null);\r        })();\r    }\r\r    if (_msie)\r        _w.attachEvent('onbeforeunload', _unloadFix);\r\r    this.addListener(_w, 'unload', _unload);\r};\r\rasual.util.Functions = new function() {\r\r    this.toString = function() {\r        return '[class Functions]';\r    };\r\r    this.bind = function(method, object, param) {\r        for (var i = 2, p, arr = []; p = arguments[i]; i++)\r            arr.push(p);\r        return function() {\r            return method.apply(object, arr);\r        }\r    };\r};\r\rvar SWFAddressEvent = function(type) {\r\r    this.toString = function() {\r        return '[object SWFAddressEvent]';\r    };\r\r    this.type = type;\r\r    this.target = [SWFAddress][0];\r\r    this.value = SWFAddress.getValue();\r\r    this.path = SWFAddress.getPath();\r\r    this.pathNames = SWFAddress.getPathNames();\r\r    this.parameters = {};\r\r    var _parameterNames = SWFAddress.getParameterNames();\r    for (var i = 0, l = _parameterNames.length; i < l; i++)\r        this.parameters[_parameterNames[i]] = SWFAddress.getParameter(_parameterNames[i]);\r\r    this.parameterNames = _parameterNames;\r\r};\r\rSWFAddressEvent.INIT = 'init';\r\rSWFAddressEvent.CHANGE = 'change';\r\rSWFAddressEvent.INTERNAL_CHANGE = 'internalChange';\r\rSWFAddressEvent.EXTERNAL_CHANGE = 'externalChange';\r\rvar SWFAddress = new function() {\r\r    var _getHash = function() {\r        var index = _l.href.indexOf('#');\r        return index != -1 ? _ec(_dc(_l.href.substr(index + 1))) : '';\r    };\r\r    var _getWindow = function() {\r        return window;\r    };\r\r    var _strictCheck = function(value, force) {\r        if (_opts.strict)\r            value = force ? (value.substr(0, 1) != '/' ? '/' + value : value) : (value == '' ? '/' : value);\r        return value;\r    };\r\r    var _ieLocal = function(value, direction) {\r        return (_msie && _l.protocol == 'file:') ? \r            (direction ? _value.replace(/\?/, '%3F') : _value.replace(/%253F/, '?')) : value;\r    };\r\r    var _searchScript = function(el) {\r        if (el.childNodes) {\r            for (var i = 0, l = el.childNodes.length, s; i < l; i++) {\r                if (el.childNodes[i].src)\r                    _url = String(el.childNodes[i].src);\r                if (s = _searchScript(el.childNodes[i]))\r                    return s;\r            }\r        }\r    };\r\r    var _titleCheck = function() {\r        if (_d.title != _title && _d.title.indexOf('#') != -1)\r            _d.title = _title;\r    };\r\r    var _listen = function() {\r        if (!_silent) {\r            var hash = _getHash();\r            var diff = !(_value == hash);\r            if (_safari && _version < 523) {\r                if (_length != _h.length) {\r                    _length = _h.length;\r                    if (typeof _stack[_length - 1] != UNDEFINED)\r                        _value = _stack[_length - 1];\r                    _update.call(this, false);\r                }\r            } else if (_msie && diff) {\r                if (_version < 7)\r                    _l.reload();\r                else\r                    this.setValue(hash);\r            } else if (diff) {\r                _value = hash;\r                _update.call(this, false);\r            }\r            if (_msie)\r                _titleCheck.call(this);\r        }\r    };\r\r    var _bodyClick = function(e) {\r        if (_popup.length > 0) {\r            var popup = window.open(_popup[0], _popup[1], eval(_popup[2]));\r            if (typeof _popup[3] != UNDEFINED)\r                eval(_popup[3]);\r        }\r        _popup = [];\r    };\r\r    var _swfChange = function() {\r        for (var i = 0, id, obj, value = SWFAddress.getValue(), setter = 'setSWFAddressValue'; id = _ids[i]; i++) {\r            obj = document.getElementById(id);\r            if (obj) {\r                if (obj.parentNode && typeof obj.parentNode.so != UNDEFINED) {\r                    obj.parentNode.so.call(setter, value);\r                } else {\r                    if (!(obj && typeof obj[setter] != UNDEFINED)) {\r                        var objects = obj.getElementsByTagName('object');\r                        var embeds = obj.getElementsByTagName('embed');\r                        obj = ((objects[0] && typeof objects[0][setter] != UNDEFINED) ? \r                            objects[0] : ((embeds[0] && typeof embeds[0][setter] != UNDEFINED) ? \r                                embeds[0] : null));\r                    }\r                    if (obj)\r                        obj[setter](value);\r                } \r            } else if (obj = document[id]) {\r                if (typeof obj[setter] != UNDEFINED)\r                    obj[setter](value);\r            }\r        }\r    };\r\r    var _jsDispatch = function(type) {\r        this.dispatchEvent(new SWFAddressEvent(type));\r        type = type.substr(0, 1).toUpperCase() + type.substr(1);\r        if(typeof this['on' + type] == FUNCTION)\r            this['on' + type]();\r    };\r\r    var _jsInit = function() {\r        if (_util.Browser.isSafari())\r            _d.body.addEventListener('click', _bodyClick);\r        _jsDispatch.call(this, 'init');\r    };\r\r    var _jsChange = function() {\r        _swfChange();\r        _jsDispatch.call(this, 'change');\r    };\r\r    var _update = function(internal) {\r        _jsChange.call(this);\r        if (internal) {\r            _jsDispatch.call(this, 'internalChange');\r        } else {\r            _jsDispatch.call(this, 'externalChange');\r        }\r        _st(_functions.bind(_track, this), 10);\r    };\r\r    var _track = function() {\r        var value = (_l.pathname + (/\/$/.test(_l.pathname) ? '' : '/') + this.getValue()).replace(/\/\//, '/').replace(/^\/$/, '');\r        var fn = _t[_opts.tracker];\r        if (typeof fn == FUNCTION)\r            fn(value);\r        else if (typeof _t.pageTracker != UNDEFINED && typeof _t.pageTracker._trackPageview == FUNCTION)\r            _t.pageTracker._trackPageview(value);\r        else if (typeof _t.urchinTracker == FUNCTION) \r            _t.urchinTracker(value);\r    };\r\r    var _htmlWrite = function() {\r        var doc = _frame.contentWindow.document;\r        doc.open();\r        doc.write('<html><head><title>' + _d.title + '</title><script>var ' + ID + ' = "' + _getHash() + '";</script></head></html>');\r        doc.close();\r    };\r\r    var _htmlLoad = function() {\r        var win = _frame.contentWindow;\r        var src = win.location.href;\r        _value = (typeof win[ID] != UNDEFINED ? win[ID] : '');\r        if (_value != _getHash()) {\r            _update.call(SWFAddress, false);\r            _l.hash = _ieLocal(_value, TRUE);\r        }\r    };\r\r    var _load = function() {\r        if (!_loaded) {\r            _loaded = TRUE;\r            if (_msie && _version < 8) {\r                var frameset = _d.getElementsByTagName('frameset')[0];\r                _frame = _d.createElement((frameset ? '' : 'i') + 'frame');\r                if (frameset) {\r                    frameset.insertAdjacentElement('beforeEnd', _frame);\r                    frameset[frameset.cols ? 'cols' : 'rows'] += ',0';\r                    _frame.src = 'javascript:false';\r                    _frame.noResize = true;\r                    _frame.frameBorder = _frame.frameSpacing = 0;\r                } else {\r                    _frame.src = 'javascript:false';\r                    _frame.style.display = 'none';\r                    _d.body.insertAdjacentElement('afterBegin', _frame);\r                }\r                _st(function() {\r                    _events.addListener(_frame, 'load', _htmlLoad);            \r                    if (typeof _frame.contentWindow[ID] == UNDEFINED) \r                        _htmlWrite();\r                }, 50);\r            } else if (_safari) {\r                if (_version < 418) {\r                    _d.body.innerHTML += '<form id="' + ID + '" style="position:absolute;top:-9999px;" method="get"></form>';\r                    _form = _d.getElementById(ID);\r                }\r                if (typeof _l[ID] == UNDEFINED) _l[ID] = {};\r                if (typeof _l[ID][_l.pathname] != UNDEFINED) _stack = _l[ID][_l.pathname].split(',');\r            }\r\r            _st(_functions.bind(function() {\r                _jsInit.call(this);\r                _jsChange.call(this);\r                _track.call(this);\r            }, this), 1);\r\r            if (_msie && _version >= 8) {\r                _d.body.onhashchange = _functions.bind(_listen, this);\r                _si(_functions.bind(_titleCheck, this), 50);\r            } else {\r                _si(_functions.bind(_listen, this), 50);\r            }\r        }\r    };\r\r    var ID = 'swfaddress',\r        FUNCTION = 'function',\r        UNDEFINED = 'undefined',\r        TRUE = true,\r        FALSE = false,\r        _util = asual.util,\r        _browser = _util.Browser, \r        _events = _util.Events,\r        _functions = _util.Functions,\r        _version = _browser.getVersion(),\r        _msie = _browser.isMSIE(),\r        _mozilla = _browser.isMozilla(),\r        _opera = _browser.isOpera(),\r        _safari = _browser.isSafari(),\r        _supported = FALSE,\r        _t = _getWindow(),\r        _d = _t.document,\r        _h = _t.history, \r        _l = _t.location,\r        _si = setInterval,\r        _st = setTimeout, \r        _dc = decodeURI,\r        _ec = encodeURI,\r        _frame,\r        _form,\r        _url,\r        _title = _d.title, \r        _length = _h.length, \r        _silent = FALSE,\r        _loaded = FALSE,\r        _justset = TRUE,\r        _juststart = TRUE,\r        _ref = this,\r        _stack = [], \r        _ids = [],\r        _popup = [],\r        _listeners = {},\r        _value = _getHash(),\r        _opts = {history: TRUE, strict: TRUE};    \r\r    if (_msie && _d.documentMode && _d.documentMode != _version)\r        _version = _d.documentMode != 8 ? 7 : 8;\r\r    _supported = \r        (_mozilla && _version >= 1) || \r        (_msie && _version >= 6) ||\r        (_opera && _version >= 9.5) ||\r        (_safari && _version >= 312);\r\r    if (_supported) {\r\r        if (_opera) \r            history.navigationMode = 'compatible';\r\r        for (var i = 1; i < _length; i++)\r            _stack.push('');\r\r        _stack.push(_getHash());\r\r        if (_msie && _l.hash != _getHash())\r            _l.hash = '#' + _ieLocal(_getHash(), TRUE);\r\r        _searchScript(document);\r        var _qi = _url ? _url.indexOf('?') : -1;\r        if (_qi != -1) {\r            var param, params = _url.substr(_qi + 1).split('&');\r            for (var i = 0, p; p = params[i]; i++) {\r                param = p.split('=');\r                if (/^(history|strict)$/.test(param[0])) {\r                    _opts[param[0]] = (isNaN(param[1]) ? /^(true|yes)$/i.test(param[1]) : (parseInt(param[1]) != 0));\r                }\r                if (/^tracker$/.test(param[0]))\r                    _opts[param[0]] = param[1];\r            }\r        }\r\r        if (_msie)\r            _titleCheck.call(this);\r\r        if (window == _t)\r            _events.addListener(document, 'DOMContentLoaded', _functions.bind(_load, this));\r        _events.addListener(_t, 'load', _functions.bind(_load, this));\r\r    } else if ((!_supported && _l.href.indexOf('#') != -1) || \r        (_safari && _version < 418 && _l.href.indexOf('#') != -1 && _l.search != '')){\r        _d.open();\r        _d.write('<html><head><meta http-equiv="refresh" content="0;url=' + \r            _l.href.substr(0, _l.href.indexOf('#')) + '" /></head></html>');\r        _d.close();\r    } else {\r        _track();\r    }\r\r    this.toString = function() {\r        return '[class SWFAddress]';\r    };\r\r    this.back = function() {\r        _h.back();\r    };\r\r    this.forward = function() {\r        _h.forward();\r    };\r\r    this.up = function() {\r        var path = this.getPath();\r        this.setValue(path.substr(0, path.lastIndexOf('/', path.length - 2) + (path.substr(path.length - 1) == '/' ? 1 : 0)));\r    };\r\r    this.go = function(delta) {\r        _h.go(delta);\r    };\r\r    this.href = function(url, target) {\r        target = typeof target != UNDEFINED ? target : '_self';     \r        if (target == '_self')\r            self.location.href = url; \r        else if (target == '_top')\r            _l.href = url; \r        else if (target == '_blank')\r            window.open(url); \r        else\r            _t.frames[target].location.href = url; \r    };\r\r    this.popup = function(url, name, options, handler) {\r        try {\r            var popup = window.open(url, name, eval(options));\r            if (typeof handler != UNDEFINED)\r                eval(handler);\r        } catch (ex) {}\r        _popup = arguments;\r    };\r\r    this.getIds = function() {\r        return _ids;\r    };\r\r    this.getId = function(index) {\r        return _ids[0];\r    };\r\r    this.setId = function(id) {\r        _ids[0] = id;\r    };\r\r    this.addId = function(id) {\r        this.removeId(id);\r        _ids.push(id);\r    };\r\r    this.removeId = function(id) {\r        for (var i = 0; i < _ids.length; i++) {\r            if (id == _ids[i]) {\r                _ids.splice(i, 1);\r                break;\r            }\r        }\r    };\r\r    this.addEventListener = function(type, listener) {\r        if (typeof _listeners[type] == UNDEFINED)\r            _listeners[type] = [];\r        _listeners[type].push(listener);\r    };\r\r    this.removeEventListener = function(type, listener) {\r        if (typeof _listeners[type] != UNDEFINED) {\r            for (var i = 0, l; l = _listeners[type][i]; i++)\r                if (l == listener) break;\r            _listeners[type].splice(i, 1);\r        }\r    };\r\r    this.dispatchEvent = function(event) {\r        if (this.hasEventListener(event.type)) {\r            event.target = this;\r            for (var i = 0, l; l = _listeners[event.type][i]; i++)\r                l(event);\r            return TRUE;           \r        }\r        return FALSE;\r    };\r\r    this.hasEventListener = function(type) {\r        return (typeof _listeners[type] != UNDEFINED && _listeners[type].length > 0);\r    };\r\r    this.getBaseURL = function() {\r        var url = _l.href;\r        if (url.indexOf('#') != -1)\r            url = url.substr(0, url.indexOf('#'));\r        if (url.substr(url.length - 1) == '/')\r            url = url.substr(0, url.length - 1);\r        return url;\r    };\r\r    this.getStrict = function() {\r        return _opts.strict;\r    };\r\r    this.setStrict = function(strict) {\r        _opts.strict = strict;\r    };\r\r    this.getHistory = function() {\r        return _opts.history;\r    };\r\r    this.setHistory = function(history) {\r        _opts.history = history;\r    };\r\r    this.getTracker = function() {\r        return _opts.tracker;\r    };\r\r    this.setTracker = function(tracker) {\r        _opts.tracker = tracker;\r    };\r\r    this.getTitle = function() {\r        return _d.title;\r    };\r\r    this.setTitle = function(title) {\r        if (!_supported) return null;\r        if (typeof title == UNDEFINED) return;\r        if (title == 'null') title = '';\r        title = _dc(title);\r        _st(function() {\r            _title = _d.title = title;\r            if (_juststart && _frame && _frame.contentWindow && _frame.contentWindow.document) {\r                _frame.contentWindow.document.title = title;\r                _juststart = FALSE;\r            }\r            if (!_justset && _mozilla)\r                _l.replace(_l.href.indexOf('#') != -1 ? _l.href : _l.href + '#');\r            _justset = FALSE;\r        }, 10);\r    };\r\r    this.getStatus = function() {\r        return _t.status;\r    };\r\r    this.setStatus = function(status) {\r        if (!_supported) return null;\r        if (typeof status == UNDEFINED) return;\r        if (status == 'null') status = '';\r        status = _dc(status);\r        if (!_safari) {\r            status = _strictCheck((status != 'null') ? status : '', TRUE);\r            if (status == '/') status = '';\r            if (!(/http(s)?:\/\//.test(status))) {\r                var index = _l.href.indexOf('#');\r                status = (index == -1 ? _l.href : _l.href.substr(0, index)) + '#' + status;\r            }\r            _t.status = status;\r        }\r    };\r\r    this.resetStatus = function() {\r        _t.status = '';\r    };\r\r    this.getValue = function() {\r        if (!_supported) return null;\r        return _dc(_strictCheck(_ieLocal(_value, FALSE), FALSE));\r    };\r\r    this.setValue = function(value) {\r        if (!_supported) return null;\r        if (typeof value == UNDEFINED) return;\r        if (value == 'null') value = '';\r        value = _ec(_dc(_strictCheck(value, TRUE)));\r        if (value == '/') value = '';\r        if (_value == value) return;\r        _justset = TRUE;\r        _value = value;\r        _silent = TRUE;\r        _update.call(SWFAddress, true);\r        _stack[_h.length] = _value;\r        if (_safari) {\r            if (_opts.history) {\r                _l[ID][_l.pathname] = _stack.toString();\r                _length = _h.length + 1;\r                if (_version < 418) {\r                    if (_l.search == '') {\r                        _form.action = '#' + _value;\r                        _form.submit();\r                    }\r                } else if (_version < 523 || _value == '') {\r                    var evt = _d.createEvent('MouseEvents');\r                    evt.initEvent('click', TRUE, TRUE);\r                    var anchor = _d.createElement('a');\r                    anchor.href = '#' + _value;\r                    anchor.dispatchEvent(evt);                \r                } else {\r                    _l.hash = '#' + _value;\r                }\r            } else {\r                _l.replace('#' + _value);\r            }\r        } else if (_value != _getHash()) {\r            if (_opts.history)\r                _l.hash = '#' + _dc(_ieLocal(_value, TRUE));\r            else\r                _l.replace('#' + _dc(_value));\r        }\r        if ((_msie && _version < 8) && _opts.history) {\r            _st(_htmlWrite, 50);\r        }\r        if (_safari)\r            _st(function(){ _silent = FALSE; }, 1);\r        else\r            _silent = FALSE;\r    };\r\r    this.getPath = function() {\r        var value = this.getValue();\r        if (value.indexOf('?') != -1) {\r            return value.split('?')[0];\r        } else if (value.indexOf('#') != -1) {\r            return value.split('#')[0];\r        } else {\r            return value;   \r        }        \r    };\r\r    this.getPathNames = function() {\r        var path = this.getPath(), names = path.split('/');\r        if (path.substr(0, 1) == '/' || path.length == 0)\r            names.splice(0, 1);\r        if (path.substr(path.length - 1, 1) == '/')\r            names.splice(names.length - 1, 1);\r        return names;\r    };\r\r    this.getQueryString = function() {\r        var value = this.getValue(), index = value.indexOf('?');\r        if (index != -1 && index < value.length) \r            return value.substr(index + 1);\r    };\r\r    this.getParameter = function(param) {\r        var value = this.getValue();\r        var index = value.indexOf('?');\r        if (index != -1) {\r            value = value.substr(index + 1);\r            var p, params = value.split('&'), i = params.length, r = [];\r            while(i--) {\r                p = params[i].split('=');\r                if (p[0] == param)\r                    r.push(p[1]);\r            }\r            if (r.length != 0)\r                return r.length != 1 ? r : r[0];\r        }\r    };\r\r    this.getParameterNames = function() {\r        var value = this.getValue();\r        var index = value.indexOf('?');\r        var names = [];\r        if (index != -1) {\r            value = value.substr(index + 1);\r            if (value != '' && value.indexOf('=') != -1) {\r                var params = value.split('&'), i = 0;\r                while(i < params.length) {\r                    names.push(params[i].split('=')[0]);\r                    i++;\r                }\r            }\r        }\r        return names;\r    };\r\r    this.onInit = null;\r\r    this.onChange = null;\r\r    this.onInternalChange = null;\r\r    this.onExternalChange = null;\r\r    (function() {\r\r        var _args;\r\r        if (typeof FlashObject != UNDEFINED) SWFObject = FlashObject;\r        if (typeof SWFObject != UNDEFINED && SWFObject.prototype && SWFObject.prototype.write) {\r            var _s1 = SWFObject.prototype.write;\r            SWFObject.prototype.write = function() {\r                _args = arguments;\r                if (this.getAttribute('version').major < 8) {\r                    this.addVariable('$swfaddress', SWFAddress.getValue());\r                    ((typeof _args[0] == 'string') ? \r                        document.getElementById(_args[0]) : _args[0]).so = this;\r                }\r                var success;\r                if (success = _s1.apply(this, _args))\r                    _ref.addId(this.getAttribute('id'));\r                return success;\r            }\r        } \r\r        if (typeof swfobject != UNDEFINED) {\r            var _s2r = swfobject.registerObject;\r            swfobject.registerObject = function() {\r                _args = arguments;\r                _s2r.apply(this, _args);\r                _ref.addId(_args[0]);\r            }\r            var _s2c = swfobject.createSWF;\r            swfobject.createSWF = function() {\r                _args = arguments;\r                var swf = _s2c.apply(this, _args);\r                if (swf)\r                    _ref.addId(_args[0].id);\r                return swf;\r            }\r            var _s2e = swfobject.embedSWF;\r            swfobject.embedSWF = function() {\r                _args = arguments;\r                if (typeof _args[8] == UNDEFINED)\r                    _args[8] = {};\r                if (typeof _args[8].id == UNDEFINED)\r                    _args[8].id = _args[1];\r                _s2e.apply(this, _args);\r                _ref.addId(_args[8].id);\r            }\r        }\r\r        if (typeof UFO != UNDEFINED) {\r            var _u = UFO.create;\r            UFO.create = function() {\r                _args = arguments;\r                _u.apply(this, _args);\r                _ref.addId(_args[0].id);\r            }\r        }\r\r        if (typeof AC_FL_RunContent != UNDEFINED) {\r            var _a = AC_FL_RunContent;\r            AC_FL_RunContent = function() {\r                _args = arguments;        \r                _a.apply(this, _args);\r                for (var i = 0, l = _args.length; i < l; i++)\r                    if (_args[i]== 'id') _ref.addId(_args[i+1]);\r            }\r        }\r\r    })();\r};\r
\ No newline at end of file
+/**
+ * SWFAddress 2.4: Deep linking for Flash and Ajax <http://www.asual.com/swfaddress/>
+ *
+ * SWFAddress is (c) 2006-2009 Rostislav Hristov and contributors
+ * This software is released under the MIT License <http://www.opensource.org/licenses/mit-license.php>
+ *
+ */
+
+if (typeof asual == "undefined")
+       var asual = {};
+if (typeof asual.util == "undefined")
+       asual.util = {};
+
+asual.util.Browser = new function() {
+
+       var _agent = navigator.userAgent.toLowerCase(),
+                       _safari = /webkit/.test(_agent),
+                       _opera = /opera/.test(_agent),
+                       _msie = /msie/.test(_agent) && !/opera/.test(_agent),
+                       _mozilla = /mozilla/.test(_agent) && !/(compatible|webkit)/.test(_agent),
+                       _version = parseFloat(_msie ? _agent.substr(_agent.indexOf('msie') + 4) :
+                                       (_agent.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/) || [0, '0'])[1]);
+
+       this.toString = function() {
+               return '[class Browser]';
+       };
+
+       this.getVersion = function() {
+               return _version;
+       };
+
+       this.isMSIE = function() {
+               return _msie;
+       };
+
+       this.isSafari = function() {
+               return _safari;
+       };
+
+       this.isOpera = function() {
+               return _opera;
+       };
+
+       this.isMozilla = function() {
+               return _mozilla;
+       };
+};
+
+asual.util.Events = new function() {
+
+       var DOM_LOADED = 'DOMContentLoaded',
+                       STOP = 'onstop',
+                       _w = window,
+                       _d = document,
+                       _cache = [],
+                       _util = asual.util,
+                       _browser = _util.Browser,
+                       _msie = _browser.isMSIE(),
+                       _safari = _browser.isSafari();
+
+       this.toString = function() {
+               return '[class Events]';
+       };
+
+       this.addListener = function(obj, type, listener) {
+               _cache.push({o: obj, t: type, l: listener});
+               if (!(type == DOM_LOADED && (_msie || _safari))) {
+                       if (obj.addEventListener)
+                               obj.addEventListener(type, listener, false);
+                       else if (obj.attachEvent)
+                               obj.attachEvent('on' + type, listener);
+               }
+       };
+
+       this.removeListener = function(obj, type, listener) {
+               for (var i = 0, e; e = _cache[i]; i++) {
+                       if (e.o == obj && e.t == type && e.l == listener) {
+                               _cache.splice(i, 1);
+                               break;
+                       }
+               }
+               if (!(type == DOM_LOADED && (_msie || _safari))) {
+                       if (obj.removeEventListener)
+                               obj.removeEventListener(type, listener, false);
+                       else if (obj.detachEvent)
+                               obj.detachEvent('on' + type, listener);
+               }
+       };
+
+       var _unload = function() {
+               for (var i = 0, evt; evt = _cache[i]; i++) {
+                       if (evt.t != DOM_LOADED)
+                               _util.Events.removeListener(evt.o, evt.t, evt.l);
+               }
+       };
+
+       var _unloadFix = function() {
+               if (_d.readyState == 'interactive') {
+                       function stop() {
+                               _d.detachEvent(STOP, stop);
+                               _unload();
+                       }
+                       ;
+                       _d.attachEvent(STOP, stop);
+                       _w.setTimeout(function() {
+                               _d.detachEvent(STOP, stop);
+                       }, 0);
+               }
+       };
+
+       if (_msie || _safari) {
+               (function() {
+                       try {
+                               if ((_msie && _d.body) || !/loaded|complete/.test(_d.readyState))
+                                       _d.documentElement.doScroll('left');
+                       } catch (e) {
+                               return setTimeout(arguments.callee, 0);
+                       }
+                       for (var i = 0, e; e = _cache[i]; i++)
+                               if (e.t == DOM_LOADED)
+                                       e.l.call(null);
+               })();
+       }
+
+       if (_msie)
+               _w.attachEvent('onbeforeunload', _unloadFix);
+
+       this.addListener(_w, 'unload', _unload);
+};
+
+asual.util.Functions = new function() {
+
+       this.toString = function() {
+               return '[class Functions]';
+       };
+
+       this.bind = function(method, object, param) {
+               for (var i = 2, p, arr = []; p = arguments[i]; i++)
+                       arr.push(p);
+               return function() {
+                       return method.apply(object, arr);
+               }
+       };
+};
+
+var SWFAddressEvent = function(type) {
+
+       this.toString = function() {
+               return '[object SWFAddressEvent]';
+       };
+
+       this.type = type;
+
+       this.target = [SWFAddress][0];
+
+       this.value = SWFAddress.getValue();
+
+       this.path = SWFAddress.getPath();
+
+       this.pathNames = SWFAddress.getPathNames();
+
+       this.parameters = {};
+
+       var _parameterNames = SWFAddress.getParameterNames();
+       for (var i = 0, l = _parameterNames.length; i < l; i++)
+               this.parameters[_parameterNames[i]] = SWFAddress.getParameter(_parameterNames[i]);
+
+       this.parameterNames = _parameterNames;
+
+};
+
+SWFAddressEvent.INIT = 'init';
+
+SWFAddressEvent.CHANGE = 'change';
+
+SWFAddressEvent.INTERNAL_CHANGE = 'internalChange';
+
+SWFAddressEvent.EXTERNAL_CHANGE = 'externalChange';
+
+var SWFAddress = new function() {
+
+       var _getHash = function() {
+               var index = _l.href.indexOf('#');
+               return index != -1 ? _ec(_dc(_l.href.substr(index + 1))) : '';
+       };
+
+       var _getWindow = function() {
+               return window;
+       };
+
+       var _strictCheck = function(value, force) {
+               if (_opts.strict)
+                       value = force ? (value.substr(0, 1) != '/' ? '/' + value : value) : (value == '' ? '/' : value);
+               return value;
+       };
+
+       var _ieLocal = function(value, direction) {
+               return (_msie && _l.protocol == 'file:') ?
+                               (direction ? _value.replace(/\?/, '%3F') : _value.replace(/%253F/, '?')) : value;
+       };
+
+       var _searchScript = function(el) {
+               if (el.childNodes) {
+                       for (var i = 0, l = el.childNodes.length, s; i < l; i++) {
+                               if (el.childNodes[i].src)
+                                       _url = String(el.childNodes[i].src);
+                               if (s = _searchScript(el.childNodes[i]))
+                                       return s;
+                       }
+               }
+       };
+
+       var _titleCheck = function() {
+               if (_d.title != _title && _d.title.indexOf('#') != -1)
+                       _d.title = _title;
+       };
+
+       var _listen = function() {
+               if (!_silent) {
+                       var hash = _getHash();
+                       var diff = !(_value == hash);
+                       if (_safari && _version < 523) {
+                               if (_length != _h.length) {
+                                       _length = _h.length;
+                                       if (typeof _stack[_length - 1] != UNDEFINED)
+                                               _value = _stack[_length - 1];
+                                       _update.call(this, false);
+                               }
+                       } else if (_msie && diff) {
+                               if (_version < 7)
+                                       _l.reload();
+                               else
+                                       this.setValue(hash);
+                       } else if (diff) {
+                               _value = hash;
+                               _update.call(this, false);
+                       }
+                       if (_msie)
+                               _titleCheck.call(this);
+               }
+       };
+
+       var _bodyClick = function(e) {
+               if (_popup.length > 0) {
+                       var popup = window.open(_popup[0], _popup[1], eval(_popup[2]));
+                       if (typeof _popup[3] != UNDEFINED)
+                               eval(_popup[3]);
+               }
+               _popup = [];
+       };
+
+       var _swfChange = function() {
+               for (var i = 0, id, obj, value = SWFAddress.getValue(), setter = 'setSWFAddressValue'; id = _ids[i]; i++) {
+                       obj = document.getElementById(id);
+                       if (obj) {
+                               if (obj.parentNode && typeof obj.parentNode.so != UNDEFINED) {
+                                       obj.parentNode.so.call(setter, value);
+                               } else {
+                                       if (!(obj && typeof obj[setter] != UNDEFINED)) {
+                                               var objects = obj.getElementsByTagName('object');
+                                               var embeds = obj.getElementsByTagName('embed');
+                                               obj = ((objects[0] && typeof objects[0][setter] != UNDEFINED) ?
+                                                               objects[0] : ((embeds[0] && typeof embeds[0][setter] != UNDEFINED) ?
+                                                               embeds[0] : null));
+                                       }
+                                       if (obj)
+                                               obj[setter](value);
+                               }
+                       } else if (obj = document[id]) {
+                               if (typeof obj[setter] != UNDEFINED)
+                                       obj[setter](value);
+                       }
+               }
+       };
+
+       var _jsDispatch = function(type) {
+               this.dispatchEvent(new SWFAddressEvent(type));
+               type = type.substr(0, 1).toUpperCase() + type.substr(1);
+               if (typeof this['on' + type] == FUNCTION)
+                       this['on' + type]();
+       };
+
+       var _jsInit = function() {
+               if (_util.Browser.isSafari())
+                       _d.body.addEventListener('click', _bodyClick);
+               _jsDispatch.call(this, 'init');
+       };
+
+       var _jsChange = function() {
+               _swfChange();
+               _jsDispatch.call(this, 'change');
+       };
+
+       var _update = function(internal) {
+               _jsChange.call(this);
+               if (internal) {
+                       _jsDispatch.call(this, 'internalChange');
+               } else {
+                       _jsDispatch.call(this, 'externalChange');
+               }
+               _st(_functions.bind(_track, this), 10);
+       };
+
+       var _track = function() {
+               var value = (_l.pathname + (/\/$/.test(_l.pathname) ? '' : '/') + this.getValue()).replace(/\/\//, '/').replace(/^\/$/, '');
+               var fn = _t[_opts.tracker];
+               if (typeof fn == FUNCTION)
+                       fn(value);
+               else if (typeof _t.pageTracker != UNDEFINED && typeof _t.pageTracker._trackPageview == FUNCTION)
+                       _t.pageTracker._trackPageview(value);
+               else if (typeof _t.urchinTracker == FUNCTION)
+                       _t.urchinTracker(value);
+       };
+
+       var _htmlWrite = function() {
+               var doc = _frame.contentWindow.document;
+               doc.open();
+               doc.write('<html><head><title>' + _d.title + '</title><script>var ' + ID + ' = "' + _getHash() + '";</script></head></html>');
+               doc.close();
+       };
+
+       var _htmlLoad = function() {
+               var win = _frame.contentWindow;
+               var src = win.location.href;
+               _value = (typeof win[ID] != UNDEFINED ? win[ID] : '');
+               if (_value != _getHash()) {
+                       _update.call(SWFAddress, false);
+                       _l.hash = _ieLocal(_value, TRUE);
+               }
+       };
+
+       var _load = function() {
+               if (!_loaded) {
+                       _loaded = TRUE;
+                       if (_msie && _version < 8) {
+                               var frameset = _d.getElementsByTagName('frameset')[0];
+                               _frame = _d.createElement((frameset ? '' : 'i') + 'frame');
+                               if (frameset) {
+                                       frameset.insertAdjacentElement('beforeEnd', _frame);
+                                       frameset[frameset.cols ? 'cols' : 'rows'] += ',0';
+                                       _frame.src = 'javascript:false';
+                                       _frame.noResize = true;
+                                       _frame.frameBorder = _frame.frameSpacing = 0;
+                               } else {
+                                       _frame.src = 'javascript:false';
+                                       _frame.style.display = 'none';
+                                       _d.body.insertAdjacentElement('afterBegin', _frame);
+                               }
+                               _st(function() {
+                                       _events.addListener(_frame, 'load', _htmlLoad);
+                                       if (typeof _frame.contentWindow[ID] == UNDEFINED)
+                                               _htmlWrite();
+                               }, 50);
+                       } else if (_safari) {
+                               if (_version < 418) {
+                                       _d.body.innerHTML += '<form id="' + ID + '" style="position:absolute;top:-9999px;" method="get"></form>';
+                                       _form = _d.getElementById(ID);
+                               }
+                               if (typeof _l[ID] == UNDEFINED)
+                                       _l[ID] = {};
+                               if (typeof _l[ID][_l.pathname] != UNDEFINED)
+                                       _stack = _l[ID][_l.pathname].split(',');
+                       }
+
+                       _st(_functions.bind(function() {
+                               _jsInit.call(this);
+                               _jsChange.call(this);
+                               _track.call(this);
+                       }, this), 1);
+
+                       if (_msie && _version >= 8) {
+                               _d.body.onhashchange = _functions.bind(_listen, this);
+                               _si(_functions.bind(_titleCheck, this), 50);
+                       } else {
+                               _si(_functions.bind(_listen, this), 50);
+                       }
+               }
+       };
+
+       var ID = 'swfaddress',
+                       FUNCTION = 'function',
+                       UNDEFINED = 'undefined',
+                       TRUE = true,
+                       FALSE = false,
+                       _util = asual.util,
+                       _browser = _util.Browser,
+                       _events = _util.Events,
+                       _functions = _util.Functions,
+                       _version = _browser.getVersion(),
+                       _msie = _browser.isMSIE(),
+                       _mozilla = _browser.isMozilla(),
+                       _opera = _browser.isOpera(),
+                       _safari = _browser.isSafari(),
+                       _supported = FALSE,
+                       _t = _getWindow(),
+                       _d = _t.document,
+                       _h = _t.history,
+                       _l = _t.location,
+                       _si = setInterval,
+                       _st = setTimeout,
+                       _dc = decodeURI,
+                       _ec = encodeURI,
+                       _frame,
+                       _form,
+                       _url,
+                       _title = _d.title,
+                       _length = _h.length,
+                       _silent = FALSE,
+                       _loaded = FALSE,
+                       _justset = TRUE,
+                       _juststart = TRUE,
+                       _ref = this,
+                       _stack = [],
+                       _ids = [],
+                       _popup = [],
+                       _listeners = {},
+                       _value = _getHash(),
+                       _opts = {history: TRUE, strict: TRUE};
+
+       if (_msie && _d.documentMode && _d.documentMode != _version)
+               _version = _d.documentMode != 8 ? 7 : 8;
+
+       _supported =
+                       (_mozilla && _version >= 1) ||
+                       (_msie && _version >= 6) ||
+                       (_opera && _version >= 9.5) ||
+                       (_safari && _version >= 312);
+
+       if (_supported) {
+
+               if (_opera)
+                       history.navigationMode = 'compatible';
+
+               for (var i = 1; i < _length; i++)
+                       _stack.push('');
+
+               _stack.push(_getHash());
+
+               if (_msie && _l.hash != _getHash())
+                       _l.hash = '#' + _ieLocal(_getHash(), TRUE);
+
+               _searchScript(document);
+               var _qi = _url ? _url.indexOf('?') : -1;
+               if (_qi != -1) {
+                       var param, params = _url.substr(_qi + 1).split('&');
+                       for (var i = 0, p; p = params[i]; i++) {
+                               param = p.split('=');
+                               if (/^(history|strict)$/.test(param[0])) {
+                                       _opts[param[0]] = (isNaN(param[1]) ? /^(true|yes)$/i.test(param[1]) : (parseInt(param[1]) != 0));
+                               }
+                               if (/^tracker$/.test(param[0]))
+                                       _opts[param[0]] = param[1];
+                       }
+               }
+
+               if (_msie)
+                       _titleCheck.call(this);
+
+               if (window == _t)
+                       _events.addListener(document, 'DOMContentLoaded', _functions.bind(_load, this));
+               _events.addListener(_t, 'load', _functions.bind(_load, this));
+
+       } /*else if ((!_supported && _l.href.indexOf('#') != -1) ||
+        (_safari && _version < 418 && _l.href.indexOf('#') != -1 && _l.search != '')){
+        _d.open();
+        _d.write('<html><head><meta http-equiv="refresh" content="0;url=' +
+        _l.href.substr(0, _l.href.indexOf('#')) + '" /></head></html>');
+        _d.close();
+        } */ else {
+               _track();
+       }
+
+       this.toString = function() {
+               return '[class SWFAddress]';
+       };
+
+       this.back = function() {
+               _h.back();
+       };
+
+       this.forward = function() {
+               _h.forward();
+       };
+
+       this.up = function() {
+               var path = this.getPath();
+               this.setValue(path.substr(0, path.lastIndexOf('/', path.length - 2) + (path.substr(path.length - 1) == '/' ? 1 : 0)));
+       };
+
+       this.go = function(delta) {
+               _h.go(delta);
+       };
+
+       this.href = function(url, target) {
+               target = typeof target != UNDEFINED ? target : '_self';
+               if (target == '_self')
+                       self.location.href = url;
+               else if (target == '_top')
+                       _l.href = url;
+               else if (target == '_blank')
+                       window.open(url);
+               else
+                       _t.frames[target].location.href = url;
+       };
+
+       this.popup = function(url, name, options, handler) {
+               try {
+                       var popup = window.open(url, name, eval(options));
+                       if (typeof handler != UNDEFINED)
+                               eval(handler);
+               } catch (ex) {
+               }
+               _popup = arguments;
+       };
+
+       this.getIds = function() {
+               return _ids;
+       };
+
+       this.getId = function(index) {
+               return _ids[0];
+       };
+
+       this.setId = function(id) {
+               _ids[0] = id;
+       };
+
+       this.addId = function(id) {
+               this.removeId(id);
+               _ids.push(id);
+       };
+
+       this.removeId = function(id) {
+               for (var i = 0; i < _ids.length; i++) {
+                       if (id == _ids[i]) {
+                               _ids.splice(i, 1);
+                               break;
+                       }
+               }
+       };
+
+       this.addEventListener = function(type, listener) {
+               if (typeof _listeners[type] == UNDEFINED)
+                       _listeners[type] = [];
+               _listeners[type].push(listener);
+       };
+
+       this.removeEventListener = function(type, listener) {
+               if (typeof _listeners[type] != UNDEFINED) {
+                       for (var i = 0, l; l = _listeners[type][i]; i++)
+                               if (l == listener)
+                                       break;
+                       _listeners[type].splice(i, 1);
+               }
+       };
+
+       this.dispatchEvent = function(event) {
+               if (this.hasEventListener(event.type)) {
+                       event.target = this;
+                       for (var i = 0, l; l = _listeners[event.type][i]; i++)
+                               l(event);
+                       return TRUE;
+               }
+               return FALSE;
+       };
+
+       this.hasEventListener = function(type) {
+               return (typeof _listeners[type] != UNDEFINED && _listeners[type].length > 0);
+       };
+
+       this.getBaseURL = function() {
+               var url = _l.href;
+               if (url.indexOf('#') != -1)
+                       url = url.substr(0, url.indexOf('#'));
+               if (url.substr(url.length - 1) == '/')
+                       url = url.substr(0, url.length - 1);
+               return url;
+       };
+
+       this.getStrict = function() {
+               return _opts.strict;
+       };
+
+       this.setStrict = function(strict) {
+               _opts.strict = strict;
+       };
+
+       this.getHistory = function() {
+               return _opts.history;
+       };
+
+       this.setHistory = function(history) {
+               _opts.history = history;
+       };
+
+       this.getTracker = function() {
+               return _opts.tracker;
+       };
+
+       this.setTracker = function(tracker) {
+               _opts.tracker = tracker;
+       };
+
+       this.getTitle = function() {
+               return _d.title;
+       };
+
+       this.setTitle = function(title) {
+               if (!_supported)
+                       return null;
+               if (typeof title == UNDEFINED)
+                       return;
+               if (title == 'null')
+                       title = '';
+               title = _dc(title);
+               _st(function() {
+                       _title = _d.title = title;
+                       if (_juststart && _frame && _frame.contentWindow && _frame.contentWindow.document) {
+                               _frame.contentWindow.document.title = title;
+                               _juststart = FALSE;
+                       }
+                       if (!_justset && _mozilla)
+                               _l.replace(_l.href.indexOf('#') != -1 ? _l.href : _l.href + '#');
+                       _justset = FALSE;
+               }, 10);
+       };
+
+       this.getStatus = function() {
+               return _t.status;
+       };
+
+       this.setStatus = function(status) {
+               if (!_supported)
+                       return null;
+               if (typeof status == UNDEFINED)
+                       return;
+               if (status == 'null')
+                       status = '';
+               status = _dc(status);
+               if (!_safari) {
+                       status = _strictCheck((status != 'null') ? status : '', TRUE);
+                       if (status == '/')
+                               status = '';
+                       if (!(/http(s)?:\/\//.test(status))) {
+                               var index = _l.href.indexOf('#');
+                               status = (index == -1 ? _l.href : _l.href.substr(0, index)) + '#' + status;
+                       }
+                       _t.status = status;
+               }
+       };
+
+       this.resetStatus = function() {
+               _t.status = '';
+       };
+
+       this.getValue = function() {
+               if (!_supported)
+                       return null;
+               return _dc(_strictCheck(_ieLocal(_value, FALSE), FALSE));
+       };
+
+       this.setValue = function(value) {
+               if (!_supported)
+                       return null;
+               if (typeof value == UNDEFINED)
+                       return;
+               if (value == 'null')
+                       value = '';
+               value = _ec(_dc(_strictCheck(value, TRUE)));
+               if (value == '/')
+                       value = '';
+               if (_value == value)
+                       return;
+               _justset = TRUE;
+               _value = value;
+               _silent = TRUE;
+               _update.call(SWFAddress, true);
+               _stack[_h.length] = _value;
+               if (_safari) {
+                       if (_opts.history) {
+                               _l[ID][_l.pathname] = _stack.toString();
+                               _length = _h.length + 1;
+                               if (_version < 418) {
+                                       if (_l.search == '') {
+                                               _form.action = '#' + _value;
+                                               _form.submit();
+                                       }
+                               } else if (_version < 523 || _value == '') {
+                                       var evt = _d.createEvent('MouseEvents');
+                                       evt.initEvent('click', TRUE, TRUE);
+                                       var anchor = _d.createElement('a');
+                                       anchor.href = '#' + _value;
+                                       anchor.dispatchEvent(evt);
+                               } else {
+                                       _l.hash = '#' + _value;
+                               }
+                       } else {
+                               _l.replace('#' + _value);
+                       }
+               } else if (_value != _getHash()) {
+                       if (_opts.history)
+                               _l.hash = '#' + _dc(_ieLocal(_value, TRUE));
+                       else
+                               _l.replace('#' + _dc(_value));
+               }
+               if ((_msie && _version < 8) && _opts.history) {
+                       _st(_htmlWrite, 50);
+               }
+               if (_safari)
+                       _st(function() {
+                               _silent = FALSE;
+                       }, 1);
+               else
+                       _silent = FALSE;
+       };
+
+       this.getPath = function() {
+               var value = this.getValue();
+               if (value.indexOf('?') != -1) {
+                       return value.split('?')[0];
+               } else if (value.indexOf('#') != -1) {
+                       return value.split('#')[0];
+               } else {
+                       return value;
+               }
+       };
+
+       this.getPathNames = function() {
+               var path = this.getPath(), names = path.split('/');
+               if (path.substr(0, 1) == '/' || path.length == 0)
+                       names.splice(0, 1);
+               if (path.substr(path.length - 1, 1) == '/')
+                       names.splice(names.length - 1, 1);
+               return names;
+       };
+
+       this.getQueryString = function() {
+               var value = this.getValue(), index = value.indexOf('?');
+               if (index != -1 && index < value.length)
+                       return value.substr(index + 1);
+       };
+
+       this.getParameter = function(param) {
+               var value = this.getValue();
+               var index = value.indexOf('?');
+               if (index != -1) {
+                       value = value.substr(index + 1);
+                       var p, params = value.split('&'), i = params.length, r = [];
+                       while (i--) {
+                               p = params[i].split('=');
+                               if (p[0] == param)
+                                       r.push(p[1]);
+                       }
+                       if (r.length != 0)
+                               return r.length != 1 ? r : r[0];
+               }
+       };
+
+       this.getParameterNames = function() {
+               var value = this.getValue();
+               var index = value.indexOf('?');
+               var names = [];
+               if (index != -1) {
+                       value = value.substr(index + 1);
+                       if (value != '' && value.indexOf('=') != -1) {
+                               var params = value.split('&'), i = 0;
+                               while (i < params.length) {
+                                       names.push(params[i].split('=')[0]);
+                                       i++;
+                               }
+                       }
+               }
+               return names;
+       };
+
+       this.onInit = null;
+
+       this.onChange = null;
+
+       this.onInternalChange = null;
+
+       this.onExternalChange = null;
+
+       (function() {
+
+               var _args;
+
+               if (typeof FlashObject != UNDEFINED)
+                       SWFObject = FlashObject;
+               if (typeof SWFObject != UNDEFINED && SWFObject.prototype && SWFObject.prototype.write) {
+                       var _s1 = SWFObject.prototype.write;
+                       SWFObject.prototype.write = function() {
+                               _args = arguments;
+                               if (this.getAttribute('version').major < 8) {
+                                       this.addVariable('$swfaddress', SWFAddress.getValue());
+                                       ((typeof _args[0] == 'string') ?
+                                                       document.getElementById(_args[0]) : _args[0]).so = this;
+                               }
+                               var success;
+                               if (success = _s1.apply(this, _args))
+                                       _ref.addId(this.getAttribute('id'));
+                               return success;
+                       }
+               }
+
+               if (typeof swfobject != UNDEFINED) {
+                       var _s2r = swfobject.registerObject;
+                       swfobject.registerObject = function() {
+                               _args = arguments;
+                               _s2r.apply(this, _args);
+                               _ref.addId(_args[0]);
+                       }
+                       var _s2c = swfobject.createSWF;
+                       swfobject.createSWF = function() {
+                               _args = arguments;
+                               var swf = _s2c.apply(this, _args);
+                               if (swf)
+                                       _ref.addId(_args[0].id);
+                               return swf;
+                       }
+                       var _s2e = swfobject.embedSWF;
+                       swfobject.embedSWF = function() {
+                               _args = arguments;
+                               if (typeof _args[8] == UNDEFINED)
+                                       _args[8] = {};
+                               if (typeof _args[8].id == UNDEFINED)
+                                       _args[8].id = _args[1];
+                               _s2e.apply(this, _args);
+                               _ref.addId(_args[8].id);
+                       }
+               }
+
+               if (typeof UFO != UNDEFINED) {
+                       var _u = UFO.create;
+                       UFO.create = function() {
+                               _args = arguments;
+                               _u.apply(this, _args);
+                               _ref.addId(_args[0].id);
+                       }
+               }
+
+               if (typeof AC_FL_RunContent != UNDEFINED) {
+                       var _a = AC_FL_RunContent;
+                       AC_FL_RunContent = function() {
+                               _args = arguments;
+                               _a.apply(this, _args);
+                               for (var i = 0, l = _args.length; i < l; i++)
+                                       if (_args[i] == 'id')
+                                               _ref.addId(_args[i + 1]);
+                       }
+               }
+
+       })();
+};
index 98639fe8e0ea4594e4d48912491ca06130f9bc44..cbac22f025457f4ad759c9a5b8e89180f2b1f71c 100644 (file)
@@ -340,7 +340,7 @@ class wsPackagerHTML extends wsPackager {
        protected function mergeJavascript() {
                $dest = WS_COMPILE_ASSETS . '/fluidbook.js';
                $orig = WS_COMPILE_ASSETS . '/_js/';
-               $files = array('swfobject.js' => false, 'swfaddress.js' => true, 'fluidbook.js' => true);
+               $files = array('log4js.js' => false, 'esapi.js' => false, 'resources/i18n/ESAPI_Standard_en_US.properties.js' => false, 'resources/Base.esapi.properties.js' => false, 'swfobject.js' => false, 'swfaddress.js' => true, 'fluidbook.js' => true);
 
                $refresh = false;
                if (file_exists($dest)) {
index 3245a794b91c5197cbd0373c576cae008296eb65..238394a941e8f7a54b6c63e7f56d37d8dbeefb76 100644 (file)
-<?php\r
-\r
-class wsPackager {\r
-\r
-       protected $dir;\r
-       protected $vdir;\r
-       public $book;\r
-       protected $pages;\r
-       protected $theme;\r
-       protected $version;\r
-       protected $book_id;\r
-       protected $themeRoot;\r
-       protected $daoBook;\r
-       protected $zip;\r
-       protected $workingDir;\r
-       protected $whole = true;\r
-       public $cleanOnDestruct = true;\r
-\r
-       public static function package($book_id, $version, $zip = true) {\r
-               global $packager;\r
-\r
-               cubePHP::neverStop();\r
-               if ($version == 'html') {\r
-                       $packager = new wsPackagerHTML($book_id);\r
-               } elseif ($version == 'win-exe') {\r
-                       $packager = new wsPackagerWinEXE($book_id);\r
-               } elseif ($version == 'win-cd') {\r
-                       $packager = new wsPackagerWinCD($book_id);\r
-               } elseif ($version == 'win-ins') {\r
-                       $packager = new wsPackagerWinINST($book_id);\r
-               } elseif ($version == 'mac-exe') {\r
-                       $packager = new wsPackagerMacEXE($book_id);\r
-               } elseif ($version == 'v1') {\r
-                       $packager = new wsPackagerV1($book_id);\r
-               } else if ($version == 'phonegap') {\r
-                       $packager = new wsPackagerPhonegap($book_id);\r
-               }\r
-\r
-               return $packager->makePackage($zip);\r
-       }\r
-\r
-       public function __construct($book_id, $vdir = null, $whole = true) {\r
-               global $core;\r
-\r
-               $this->book_id = $book_id;\r
-\r
-               $this->vdir = $vdir;\r
-               $this->dir = ROOT . '/fluidbook/packager/' . $book_id . '/';\r
-               $this->whole = $whole;\r
-\r
-               if (!file_exists($this->dir)) {\r
-                       mkdir($this->dir, 0777, true);\r
-               }\r
-\r
-               $this->daoBook = new wsDAOBook($core->con);\r
-               $this->book = $this->daoBook->selectById($book_id);\r
-               $this->pages = $this->daoBook->getPagesOfBook($book_id, false);\r
-\r
-               $daoTheme = new wsDAOTheme($core->con);\r
-               $this->theme = $daoTheme->getThemeOfBook($book_id, true);\r
-               $this->themeRoot = WS_THEMES . '/' . $this->theme->theme_id . '/';\r
-\r
-               $this->workingDir = WS_BOOKS . '/working/' . $book_id . '/';\r
-\r
-               $this->compile();\r
-       }\r
-\r
-       protected function compile() {\r
-               $this->daoBook->compile($this->book_id, '2');\r
-       }\r
-\r
-       protected function preparePackage() {\r
-               $this->initTempDir();\r
-       }\r
-\r
-       public function makePackage($zip) {\r
-               $this->preparePackage();\r
-       }\r
-\r
-       protected function replaceContents($str, $toReplace) {\r
-               $res = $str;\r
-               foreach ($toReplace as $k => $v) {\r
-                       if (is_null($v)) {\r
-                               return;\r
-                       }\r
-                       $res = str_replace('$' . $k, $v, $res);\r
-               }\r
-               return $res;\r
-       }\r
-\r
-       protected function copyFluidbookFiles() {\r
-               // Copie du FB vers un répertoire temporaire\r
-               $cp = new cubeCommandLine('cp');\r
-               $cp->setArg('R');\r
-               $cp->setArg('p');\r
-               $cp->setArg(null, WS_BOOKS . '/final/' . $this->book->book_id . '/*');\r
-               $cp->setArg(null, $this->vdir);\r
-               $cp->execute();\r
-       }\r
-\r
-       protected function copyOtherFiles($files) {\r
-               foreach ($files as $source => $dest) {\r
-                       if (is_int($source)) {\r
-                               $source = $dest;\r
-                       }\r
-\r
-                       $s = WS_COMPILE_ASSETS . '/' . $source;\r
-                       if (is_file($s) && !file_exists($this->vdir . $dest)) {\r
-                               $this->copy($s, $this->vdir . $dest);\r
-                       } else if (is_dir($s)) {\r
-                               $cp = new cubeCommandLine('cp');\r
-                               $cp->setArg('R');\r
-                               $cp->setArg('p');\r
-                               $cp->setArg(null, $s);\r
-                               $cp->setArg(null, $this->vdir);\r
-                               $cp->execute();\r
-\r
-                               $mv = new cubeCommandLine('mv');\r
-                               $mv->setArg($this->vdir . '/' . $source);\r
-                               $mv->setArg($this->vdir . '/' . $dest);\r
-                               $mv->execute();\r
-                       }\r
-               }\r
-       }\r
-\r
-       protected function getBaseFile() {\r
-               return $this->version . '-' . date('Ymdhis', TIME) . '-' . cubeText::str2URL($this->book->parametres->title);\r
-       }\r
-\r
-       protected function getRelativeBase() {\r
-               return '/packager/download/' . $this->getBaseFile();\r
-       }\r
-\r
-       protected function getURLBase($ext = '') {\r
-               $res = '/fluidbook' . $this->getRelativeBase();\r
-               if ($ext != '') {\r
-                       $res .= '.' . $ext;\r
-               }\r
-               return $res;\r
-       }\r
-\r
-       protected function getPathBase($ext = '') {\r
-               $res = WS_FILES . $this->getRelativeBase();\r
-               if ($ext != '') {\r
-                       $res .= '.' . $ext;\r
-               }\r
-\r
-               return $res;\r
-       }\r
-\r
-       protected function zip($zipfile = null) {\r
-               if (!$this->whole) {\r
-                       return;\r
-               }\r
-               $url = $this->getURLBase('zip');\r
-               $final = $this->getPathBase('zip');\r
-               $rename = false;\r
-               if (is_null($zipfile)) {\r
-                       $zipfile = $final;\r
-               } else {\r
-                       $rename = true;\r
-               }\r
-\r
-               $zip = new cubeCommandLine('zip');\r
-               $zip->cd($this->vdir);\r
-               $zip->setArg(null, $zipfile);\r
-               $zip->setArg('0');\r
-               $zip->setArg('r');\r
-               $zip->setArg('u');\r
-               $zip->setArg(null, '.');\r
-               $zip->execute();\r
-\r
-               if (!file_exists(WS_FILES . '/packager/download')) {\r
-                       mkdir(WS_FILES . '/packager/download', 0777, true);\r
-               }\r
-\r
-               if ($rename) {\r
-                       rename($zipfile, $final);\r
-               }\r
-               return $url;\r
-       }\r
-\r
-       protected function initTempDir() {\r
-               if (is_null($this->vdir)) {\r
-                       $this->vdir = $this->dir . $this->version . '/';\r
-               }\r
-               $this->cleanVdir();\r
-               if (!file_exists($this->vdir . '/data')) {\r
-                       mkdir($this->vdir . '/data', 0777, true);\r
-               }\r
-       }\r
-\r
-       protected function cleanVdir() {\r
-               if (file_exists($this->vdir)) {\r
-                       return;\r
-                       // Suppression du répertoire si il existe\r
-                       $rm = new cubeCommandLine('rm');\r
-                       $rm->setArg('r');\r
-                       $rm->setArg('f');\r
-                       $rm->setArg(null, $this->vdir);\r
-                       $rm->execute();\r
-               }\r
-       }\r
-\r
-       protected function moveDatasSWF() {\r
-               if (file_exists($this->vdir . '/FluidbookDatas.swf')) {\r
-                       rename($this->vdir . '/FluidbookDatas.swf', $this->vdir . '/data/FluidbookDatas.swf');\r
-               }\r
-               if (file_exists($this->vdir . '/FluidbookDatasLight.swf')) {\r
-                       rename($this->vdir . '/FluidbookDatasLight.swf', $this->vdir . '/data/FluidbookDatasLight.swf');\r
-               }\r
-       }\r
-\r
-       protected function postPackage() {\r
-               \r
-       }\r
-\r
-       public function __destruct() {\r
-               if ($this->whole && $this->cleanOnDestruct) {\r
-                       $this->cleanVdir();\r
-               }\r
-       }\r
-\r
-       public function copy($source, $dest) {\r
-               if (!file_exists($source)) {\r
-                       return;\r
-               }\r
-               copy($source, $dest);\r
-               touch($dest, filemtime($source));\r
-       }\r
-\r
-}\r
-\r
+<?php
+
+class wsPackager {
+
+       protected $dir;
+       protected $vdir;
+       public $book;
+       protected $pages;
+       protected $theme;
+       protected $version;
+       protected $book_id;
+       protected $themeRoot;
+       protected $daoBook;
+       protected $zip;
+       protected $workingDir;
+       protected $whole = true;
+       public $cleanOnDestruct = true;
+
+       public static function package($book_id, $version, $zip = true) {
+               global $packager;
+
+               cubePHP::neverStop();
+               if ($version == 'html') {
+                       $packager = new wsPackagerHTML($book_id);
+               } elseif ($version == 'win-exe') {
+                       $packager = new wsPackagerWinEXE($book_id);
+               } elseif ($version == 'win-cd') {
+                       $packager = new wsPackagerWinCD($book_id);
+               } elseif ($version == 'win-ins') {
+                       $packager = new wsPackagerWinINST($book_id);
+               } elseif ($version == 'mac-exe') {
+                       $packager = new wsPackagerMacEXE($book_id);
+               } elseif ($version == 'v1') {
+                       $packager = new wsPackagerV1($book_id);
+               } else if ($version == 'phonegap') {
+                       $packager = new wsPackagerPhonegap($book_id);
+               }
+
+               return $packager->makePackage($zip);
+       }
+
+       public function __construct($book_id, $vdir = null, $whole = true) {
+               global $core;
+
+               $this->book_id = $book_id;
+
+               $this->vdir = $vdir;
+               $this->dir = ROOT . '/fluidbook/packager/' . $book_id . '/';
+               $this->whole = $whole;
+
+               if (!file_exists($this->dir)) {
+                       mkdir($this->dir, 0777, true);
+               }
+
+               $this->daoBook = new wsDAOBook($core->con);
+               $this->book = $this->daoBook->selectById($book_id);
+               $this->pages = $this->daoBook->getPagesOfBook($book_id, false);
+
+               $daoTheme = new wsDAOTheme($core->con);
+               $this->theme = $daoTheme->getThemeOfBook($book_id, true);
+               $this->themeRoot = WS_THEMES . '/' . $this->theme->theme_id . '/';
+
+               $this->workingDir = WS_BOOKS . '/working/' . $book_id . '/';
+
+               $this->compile();
+       }
+
+       protected function compile() {
+               $this->daoBook->compile($this->book_id, '2');
+       }
+
+       protected function preparePackage() {
+               $this->initTempDir();
+       }
+
+       public function makePackage($zip) {
+               $this->preparePackage();
+       }
+
+       protected function replaceContents($str, $toReplace) {
+               $res = $str;
+               foreach ($toReplace as $k => $v) {
+                       if (is_null($v)) {
+                               return;
+                       }
+                       $res = str_replace('$' . $k, $v, $res);
+               }
+               return $res;
+       }
+
+       protected function copyFluidbookFiles() {
+               // Copie du FB vers un répertoire temporaire
+               $cp = new cubeCommandLine('cp');
+               $cp->setArg('R');
+               $cp->setArg('p');
+               $cp->setArg(null, WS_BOOKS . '/final/' . $this->book->book_id . '/*');
+               $cp->setArg(null, $this->vdir);
+               $cp->execute();
+       }
+
+       protected function copyOtherFiles($files) {
+               foreach ($files as $source => $dest) {
+                       if (is_int($source)) {
+                               $source = $dest;
+                       }
+
+                       $s = WS_COMPILE_ASSETS . '/' . $source;
+                       if (is_file($s) && !file_exists($this->vdir . $dest)) {
+                               $this->copy($s, $this->vdir . $dest);
+                       } else if (is_dir($s)) {
+                               $cp = new cubeCommandLine('cp');
+                               $cp->setArg('R');
+                               $cp->setArg('p');
+                               $cp->setArg(null, $s);
+                               $cp->setArg(null, $this->vdir);
+                               $cp->execute();
+
+                               $mv = new cubeCommandLine('mv');
+                               $mv->setArg($this->vdir . '/' . $source);
+                               $mv->setArg($this->vdir . '/' . $dest);
+                               $mv->execute();
+                       }
+               }
+       }
+
+       protected function getBaseFile() {
+               return $this->version . '-' . date('Ymdhis', TIME) . '-' . cubeText::str2URL($this->book->parametres->title);
+       }
+
+       protected function getRelativeBase() {
+               return '/packager/download/' . $this->getBaseFile();
+       }
+
+       protected function getURLBase($ext = '') {
+               $res = '/fluidbook' . $this->getRelativeBase();
+               if ($ext != '') {
+                       $res .= '.' . $ext;
+               }
+               return $res;
+       }
+
+       protected function getPathBase($ext = '') {
+               $res = WS_FILES . $this->getRelativeBase();
+               if ($ext != '') {
+                       $res .= '.' . $ext;
+               }
+
+               return $res;
+       }
+
+       protected function zip($zipfile = null) {
+               if (!$this->whole) {
+                       return;
+               }
+               $url = $this->getURLBase('zip');
+               $final = $this->getPathBase('zip');
+               $rename = false;
+               if (is_null($zipfile)) {
+                       $zipfile = $final;
+               } else {
+                       $rename = true;
+               }
+
+               $zip = new cubeCommandLine('zip');
+               $zip->cd($this->vdir);
+               $zip->setArg(null, $zipfile);
+               $zip->setArg('0');
+               $zip->setArg('r');
+               $zip->setArg('u');
+               $zip->setArg(null, '.');
+               $zip->execute();
+
+               if (!file_exists(WS_FILES . '/packager/download')) {
+                       mkdir(WS_FILES . '/packager/download', 0777, true);
+               }
+
+               if ($rename) {
+                       rename($zipfile, $final);
+               }
+               return $url;
+       }
+
+       protected function initTempDir() {
+               if (is_null($this->vdir)) {
+                       $this->vdir = $this->dir . $this->version . '/';
+               }
+               $this->cleanVdir();
+               if (!file_exists($this->vdir . '/data')) {
+                       mkdir($this->vdir . '/data', 0777, true);
+               }
+       }
+
+       protected function cleanVdir() {
+               if (file_exists($this->vdir)) {
+
+                       // Suppression du répertoire si il existe
+                       $rm = new cubeCommandLine('rm');
+                       $rm->setArg('r');
+                       $rm->setArg('f');
+                       $rm->setArg(null, $this->vdir);
+                       $rm->execute();
+               }
+       }
+
+       protected function moveDatasSWF() {
+               if (file_exists($this->vdir . '/FluidbookDatas.swf')) {
+                       rename($this->vdir . '/FluidbookDatas.swf', $this->vdir . '/data/FluidbookDatas.swf');
+               }
+               if (file_exists($this->vdir . '/FluidbookDatasLight.swf')) {
+                       rename($this->vdir . '/FluidbookDatasLight.swf', $this->vdir . '/data/FluidbookDatasLight.swf');
+               }
+       }
+
+       protected function postPackage() {
+
+       }
+
+       public function __destruct() {
+               if ($this->whole && $this->cleanOnDestruct) {
+                       $this->cleanVdir();
+               }
+       }
+
+       public function copy($source, $dest) {
+               if (!file_exists($source)) {
+                       return;
+               }
+               copy($source, $dest);
+               touch($dest, filemtime($source));
+       }
+
+}
+
 ?>
\ No newline at end of file