function sprintf ( ) {
    // Return a formatted string  
    // 
    // version: 909.322
    // discuss at: http://phpjs.org/functions/sprintf
    // +   original by: Ash Searle (http://hexmen.com/blog/)
    // + namespaced by: Michael White (http://getsprink.com)
    // +    tweaked by: Jack
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +      input by: Paulo Ricardo F. Santos
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +      input by: Brett Zamir (http://brett-zamir.me)
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // *     example 1: sprintf("%01.2f", 123.1);
    // *     returns 1: 123.10
    // *     example 2: sprintf("[%10s]", 'monkey');
    // *     returns 2: '[    monkey]'
    // *     example 3: sprintf("[%'#10s]", 'monkey');
    // *     returns 3: '[####monkey]'
    var regex = /%%|%(\d+\$)?([-+\'#0 ]*)(\*\d+\$|\*|\d+)?(\.(\*\d+\$|\*|\d+))?([scboxXuidfegEG])/g;
    var a = arguments, i = 0, format = a[i++];

    // pad()
    var pad = function (str, len, chr, leftJustify) {
        if (!chr) {chr = ' ';}
        var padding = (str.length >= len) ? '' : Array(1 + len - str.length >>> 0).join(chr);
        return leftJustify ? str + padding : padding + str;
    };

    // justify()
    var justify = function (value, prefix, leftJustify, minWidth, zeroPad, customPadChar) {
        var diff = minWidth - value.length;
        if (diff > 0) {
            if (leftJustify || !zeroPad) {
                value = pad(value, minWidth, customPadChar, leftJustify);
            } else {
                value = value.slice(0, prefix.length) + pad('', diff, '0', true) + value.slice(prefix.length);
            }
        }
        return value;
    };

    // formatBaseX()
    var formatBaseX = function (value, base, prefix, leftJustify, minWidth, precision, zeroPad) {
        // Note: casts negative numbers to positive ones
        var number = value >>> 0;
        prefix = prefix && number && {'2': '0b', '8': '0', '16': '0x'}[base] || '';
        value = prefix + pad(number.toString(base), precision || 0, '0', false);
        return justify(value, prefix, leftJustify, minWidth, zeroPad);
    };

    // formatString()
    var formatString = function (value, leftJustify, minWidth, precision, zeroPad, customPadChar) {
        if (precision != null) {
            value = value.slice(0, precision);
        }
        return justify(value, '', leftJustify, minWidth, zeroPad, customPadChar);
    };

    // doFormat()
    var doFormat = function (substring, valueIndex, flags, minWidth, _, precision, type) {
        var number;
        var prefix;
        var method;
        var textTransform;
        var value;

        if (substring == '%%') {return '%';}

        // parse flags
        var leftJustify = false, positivePrefix = '', zeroPad = false, prefixBaseX = false, customPadChar = ' ';
        var flagsl = flags.length;
        for (var j = 0; flags && j < flagsl; j++) {
            switch (flags.charAt(j)) {
                case ' ': positivePrefix = ' '; break;
                case '+': positivePrefix = '+'; break;
                case '-': leftJustify = true; break;
                case "'": customPadChar = flags.charAt(j+1); break;
                case '0': zeroPad = true; break;
                case '#': prefixBaseX = true; break;
            }
        }

        // parameters may be null, undefined, empty-string or real valued
        // we want to ignore null, undefined and empty-string values
        if (!minWidth) {
            minWidth = 0;
        } else if (minWidth == '*') {
            minWidth = +a[i++];
        } else if (minWidth.charAt(0) == '*') {
            minWidth = +a[minWidth.slice(1, -1)];
        } else {
            minWidth = +minWidth;
        }

        // Note: undocumented perl feature:
        if (minWidth < 0) {
            minWidth = -minWidth;
            leftJustify = true;
        }

        if (!isFinite(minWidth)) {
            throw new Error('sprintf: (minimum-)width must be finite');
        }

        if (!precision) {
            precision = 'fFeE'.indexOf(type) > -1 ? 6 : (type == 'd') ? 0 : undefined;
        } else if (precision == '*') {
            precision = +a[i++];
        } else if (precision.charAt(0) == '*') {
            precision = +a[precision.slice(1, -1)];
        } else {
            precision = +precision;
        }

        // grab value using valueIndex if required?
        value = valueIndex ? a[valueIndex.slice(0, -1)] : a[i++];

        switch (type) {
            case 's': return formatString(String(value), leftJustify, minWidth, precision, zeroPad, customPadChar);
            case 'c': return formatString(String.fromCharCode(+value), leftJustify, minWidth, precision, zeroPad);
            case 'b': return formatBaseX(value, 2, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
            case 'o': return formatBaseX(value, 8, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
            case 'x': return formatBaseX(value, 16, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
            case 'X': return formatBaseX(value, 16, prefixBaseX, leftJustify, minWidth, precision, zeroPad).toUpperCase();
            case 'u': return formatBaseX(value, 10, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
            case 'i':
            case 'd':
                number = parseInt(+value, 10);
                prefix = number < 0 ? '-' : positivePrefix;
                value = prefix + pad(String(Math.abs(number)), precision, '0', false);
                return justify(value, prefix, leftJustify, minWidth, zeroPad);
            case 'e':
            case 'E':
            case 'f':
            case 'F':
            case 'g':
            case 'G':
                number = +value;
                prefix = number < 0 ? '-' : positivePrefix;
                method = ['toExponential', 'toFixed', 'toPrecision']['efg'.indexOf(type.toLowerCase())];
                textTransform = ['toString', 'toUpperCase']['eEfFgG'.indexOf(type) % 2];
                value = prefix + Math.abs(number)[method](precision);
                return justify(value, prefix, leftJustify, minWidth, zeroPad)[textTransform]();
            default: return substring;
        }
    };

    return format.replace(regex, doFormat);
}

function floor (value) {
    // Returns the next lowest integer value from the number  
    // 
    // version: 909.322
    // discuss at: http://phpjs.org/functions/floor
    // +   original by: Onno Marsman
    // *     example 1: floor(8723321.4);
    // *     returns 1: 8723321
    
    return Math.floor(value);
}

function round (val, precision, mode) {
    // Returns the number rounded to specified precision  
    // 
    // version: 909.322
    // discuss at: http://phpjs.org/functions/round
    // +   original by: Philip Peterson
    // +    revised by: Onno Marsman
    // +      input by: Greenseed
    // +    revised by: T.Wild
    // %        note 1: Great work. Ideas for improvement:
    // %        note 1:  - code more compliant with developer guidelines
    // %        note 1:  - for implementing PHP constant arguments look at
    // %        note 1:  the pathinfo() function, it offers the greatest
    // %        note 1:  flexibility & compatibility possible
    // *     example 1: round(1241757, -3);
    // *     returns 1: 1242000
    // *     example 2: round(3.6);
    // *     returns 2: 4
    // *     example 3: round(2.835,2);
    // *     returns 3: 2.84
    /* Declare Variables
     * retVal  - temporay holder of the value to be returned
     * V       - String representation of val

     * integer - Integer portion of val
     * decimal - decimal portion of val
     * decp    - characterindex of . [decimal point] inV
     * negative- was val a negative value?
     *
     * _round_half_oe - Rounding function for ROUND_HALF_ODD and ROUND_HALF_EVEN

     * _round_half_ud - Rounding function for ROUND_HALF_UP and ROUND_HALF_DOWN
     * _round_half    - Primary function for round half rounding modes
     */
    var retVal=0,v='',integer='',decimal='',decp=0,negative=false;
    var _round_half_oe = function (dtR,dtLa,even){
        if (even === true) {
            if (dtLa == 50) {
                if ((dtR % 2) === 1) {
                    if (dtLa >= 5) {
                        dtR+=1;
                    } else {
                        dtR-=1;
                    }
                }
            }else if (dtLa >= 5) {
                dtR+=1;
            }
        }else{
            if (dtLa == 5) {
                if ((dtR % 2) === 0) {
                    if (dtLa >= 5) {
                        dtR+=1;
                    }else{
                        dtR-=1;
                    }
                }
            }else if (dtLa >= 5) {
                dtR+=1;
            }
        }

        return dtR;
    };
    var _round_half_ud = function (dtR,dtLa,up) {
        if (up === true) {
            if (dtLa>=5) {
                dtR+=1;
            }
        }else{
            if (dtLa>5) {
                dtR+=1;
            }
        }
        return dtR;
    };
    var _round_half = function (val,decplaces,mode){
    /*Declare variables
         *V       - string representation of Val
         *Vlen    - The length of V - used only when rounding intgerers

         *VlenDif - The difference between the lengths of the original V
         *          and the V after being truncated
         *decp    - character in index of . [decimal place] in V
         *integer - Integr protion of Val
         *decimal - Decimal portion of Val
         *DigitToRound - The digit to round

         *DigitToLookAt- The digit to comapre when rounding
         *
         *round - A function to do the rounding
         */
        var v = val.toString(),vlen=0,vlenDif=0;
        var decp = v.indexOf('.');

        var digitToRound = 0,digitToLookAt = 0;
        var integer='',decimal='';
        var round = null,bool=false;
        switch (mode) {
            case 'up':
                bool = true;
                // Fall-through
            case 'down':
                round = _round_half_ud;
                break;
            case 'even':
                bool = true;
            case 'odd':
                round = _round_half_oe;
                break;
        }
        if (decplaces < 0){ //Int round
            vlen=v.length;

            decplaces = vlen + decplaces;
            digitToLookAt = Number(v.charAt(decplaces));
            digitToRound  = Number(v.charAt(decplaces-1));
            digitToRound  = round(digitToRound,digitToLookAt,bool);
            v = v.slice(0,decplaces-1);
            vlenDif = vlen-v.length-1;

            if (digitToRound == 10){
                v = String(Number(v)+1)+"0";
            }else{
                v+=digitToRound;
            }

            v = Number(v)*(Math.pow(10,vlenDif));
        }else if (decplaces > 0){
            integer=v.slice(0,decp);
            decimal=v.slice(decp+1);
            digitToLookAt = Number(decimal.charAt(decplaces));

            digitToRound  = Number(decimal.charAt(decplaces-1));
            digitToRound  = round(digitToRound,digitToLookAt,bool);
            decimal=decimal.slice(0,decplaces-1);
            if (digitToRound==10){
                v=Number(integer+'.'+decimal)+(1*(Math.pow(10,(0-decimal.length))));
            }else{
                v=Number(integer+'.'+decimal+digitToRound);
            }
        }else{
            integer=v.slice(0,decp);
            decimal=v.slice(decp+1);
            digitToLookAt = Number(decimal.charAt(decplaces));

            digitToRound  = Number(integer.charAt(integer.length-1));
            digitToRound  = round(digitToRound,digitToLookAt,bool);
            decimal='0';
            integer = integer.slice(0,integer.length-1);
            if (digitToRound==10){
                v=Number(integer)+1;
            }else{
                v=Number(integer+digitToRound);
            }
        }
        return v;
    };


    //precision optional - defaults 0
    if (typeof precision == 'undefined') {
        precision = 0;
    }
    //mode optional - defaults round half up
    if (typeof mode == 'undefined') {
        mode = 'PHP_ROUND_HALF_UP';
    }

    if (val < 0){ //Remember if val is negative
        negative = true;
    }else{
        negative = false;
    }

    v = Math.abs(val).toString(); //Take a string representation of val
    decp = v.indexOf('.');        //And locate the decimal point
    if ((decp == -1) && (precision >=0)){
   /* If there is no deciaml point and the precision is greater than 0
         * there is no need to round, return val
         */
        return val;
    }else{
        if (decp == -1){
            //There are no decimals so intger=V and decimal=0
            integer = v;
            decimal = '0';
        }else{
            //Otherwise we have to split the decimals from the integer
            integer = v.slice(0,decp);
            if (precision >= 0){
                //If the precision is greater than 0 then split the decimals from the integer
                //We truncate the decimals to a number of places equal to the precision requested+1
                decimal = v.substr(decp+1,precision+1);
            }else{
                //If the precision is less than 0 ignore the decimals - set to 0
                decimal = '0';
            }
        }
        if ((precision > 0) && (precision >= decimal.length)){
            /*If the precision requested is more decimal places than already exist
            * there is no need to round - return val
            */
            return val;
        }else if ((precision < 0) && (Math.abs(precision) >= integer.length)){
           /*If the precison is less than 0, and is greater than than the
             *number of digits in integer, return 0 - mimics PHP
             */
            return 0;
        }
        val = Number(integer+'.'+decimal); // After sanitizing recreate val
    }

    //Call approriate function based on passed mode, fall through for integer constants
    switch (mode){
        case 0:
        case 'PHP_ROUND_HALF_UP':
            retVal = _round_half(val,precision,'up');
            break;
        case 1:
        case 'PHP_ROUND_HALF_DOWN':
            retVal = _round_half(val, precision,'down');
            break;
        case 2:
        case 'PHP_ROUND_HALF_EVEN':
            retVal = _round_half(val,precision,'even');
            break;
        case 3:
        case 'PHP_ROUND_HALF_ODD':
            retVal = _round_half(val,precision,'odd');
            break;
    }
    if (negative){
        return 0-retVal;
    }else{
        return retVal;
    }
}

function print_r (array, return_val) {
    // Prints out or returns information about the specified variable  
    // 
    // version: 909.322
    // discuss at: http://phpjs.org/functions/print_r
    // +   original by: Michael White (http://getsprink.com)
    // +   improved by: Ben Bryan
    // +      input by: Brett Zamir (http://brett-zamir.me)
    // +      improved by: Brett Zamir (http://brett-zamir.me)
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // -    depends on: echo
    // *     example 1: print_r(1, true);
    // *     returns 1: 1
    
    var output = "", pad_char = " ", pad_val = 4, d = this.window.document;
    var getFuncName = function (fn) {
        var name = (/\W*function\s+([\w\$]+)\s*\(/).exec(fn);
        if (!name) {
            return '(Anonymous)';
        }
        return name[1];
    };

    var repeat_char = function (len, pad_char) {
        var str = "";
        for (var i=0; i < len; i++) {
            str += pad_char;
        }
        return str;
    };

    var formatArray = function (obj, cur_depth, pad_val, pad_char) {
        if (cur_depth > 0) {
            cur_depth++;
        }

        var base_pad = repeat_char(pad_val*cur_depth, pad_char);
        var thick_pad = repeat_char(pad_val*(cur_depth+1), pad_char);
        var str = "";

        if (typeof obj === 'object' && obj !== null && obj.constructor && getFuncName(obj.constructor) !== 'PHPJS_Resource') {
            str += "Array\n" + base_pad + "(\n";
            for (var key in obj) {
                if (obj[key] instanceof Array) {
                    str += thick_pad + "["+key+"] => "+formatArray(obj[key], cur_depth+1, pad_val, pad_char);
                } else {
                    str += thick_pad + "["+key+"] => " + obj[key] + "\n";
                }
            }
            str += base_pad + ")\n";
        } else if (obj === null || obj === undefined) {
            str = '';
        } else { // for our "resource" class
            str = obj.toString();
        }

        return str;
    };

    output = formatArray(array, 0, pad_val, pad_char);

    if (return_val !== true) {
        if (d.body) {
            this.echo(output);
        }
        else {
            try {
                d = XULDocument; // We're in XUL, so appending as plain text won't work; trigger an error out of XUL
                this.echo('<pre xmlns="http://www.w3.org/1999/xhtml" style="white-space:pre;">'+output+'</pre>');
            }
            catch (e) {
                this.echo(output); // Outputting as plain text may work in some plain XML
            }
        }
        return true;
    } else {
        return output;
    }
}
function urlencode (str) {
    // URL-encodes string  
    // 
    // version: 910.813
    // discuss at: http://phpjs.org/functions/urlencode
    // +   original by: Philip Peterson
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +      input by: AJ
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: Brett Zamir (http://brett-zamir.me)
    // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +      input by: travc
    // +      input by: Brett Zamir (http://brett-zamir.me)
    // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: Lars Fischer
    // +      input by: Ratheous
    // +      reimplemented by: Brett Zamir (http://brett-zamir.me)
    // +   bugfixed by: Joris
    // %          note 1: This reflects PHP 5.3/6.0+ behavior
    // *     example 1: urlencode('Kevin van Zonneveld!');
    // *     returns 1: 'Kevin+van+Zonneveld%21'
    // *     example 2: urlencode('http://kevin.vanzonneveld.net/');
    // *     returns 2: 'http%3A%2F%2Fkevin.vanzonneveld.net%2F'
    // *     example 3: urlencode('http://www.google.nl/search?q=php.js&ie=utf-8&oe=utf-8&aq=t&rls=com.ubuntu:en-US:unofficial&client=firefox-a');
    // *     returns 3: 'http%3A%2F%2Fwww.google.nl%2Fsearch%3Fq%3Dphp.js%26ie%3Dutf-8%26oe%3Dutf-8%26aq%3Dt%26rls%3Dcom.ubuntu%3Aen-US%3Aunofficial%26client%3Dfirefox-a'
    var hexStr = function (dec) {
        return '%' + (dec < 16 ? '0' : '') + dec.toString(16).toUpperCase();
    };

    var ret = '',
            unreserved = /[\w.-]/; // A-Za-z0-9_.- // Tilde is not here for historical reasons; to preserve it, use rawurlencode instead
    str = (str+'').toString();

    for (var i = 0, dl = str.length; i < dl; i++) {
        var ch = str.charAt(i);
        if (unreserved.test(ch)) {
            ret += ch;
        }
        else {
            var code = str.charCodeAt(i);
            if (0xD800 <= code && code <= 0xDBFF) { // High surrogate (could change last hex to 0xDB7F to treat high private surrogates as single characters); https://developer.mozilla.org/index.php?title=en/Core_JavaScript_1.5_Reference/Global_Objects/String/charCodeAt
                ret += ((code - 0xD800) * 0x400) + (str.charCodeAt(i+1) - 0xDC00) + 0x10000;
                i++; // skip the next one as we just retrieved it as a low surrogate
            }
            // We never come across a low surrogate because we skip them, unless invalid
            // Reserved assumed to be in UTF-8, as in PHP
            else if (code === 32) {
                ret += '+'; // %20 in rawurlencode
            }
            else if (code < 128) { // 1 byte
                ret += hexStr(code);
            }
            else if (code >= 128 && code < 2048) { // 2 bytes
                ret += hexStr((code >> 6) | 0xC0);
                ret += hexStr((code & 0x3F) | 0x80);
            }
            else if (code >= 2048) { // 3 bytes (code < 65536)
                ret += hexStr((code >> 12) | 0xE0);
                ret += hexStr(((code >> 6) & 0x3F) | 0x80);
                ret += hexStr((code & 0x3F) | 0x80);
            }
        }
    }
    return ret;
}
function file_get_contents(url, flags, context, offset, maxLen){

	// Read the entire file into a string
	//
	// version: 906.111
	// discuss at: http://phpjs.org/functions/file_get_contents
	// +   original by: Legaev Andrey
	// +      input by: Jani Hartikainen
	// +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
	// +   improved by: Brett Zamir (http://brett-zamir.me)
	// +   input by: Raphael (Ao) RUDLER
	// +   bugfixed by: Brett Zamir (http://brett-zamir.me)
	// %        note 1: This function uses XmlHttpRequest and cannot retrieve resource from different domain without modifications.
	// %        note 2: Synchronous by default (as in PHP) so may lock up browser. Can
	// %        note 2: get async by setting a custom "phpjs.async" property to true and "notification" for an
	// %        note 2: optional callback (both as context params, with responseText, and other JS-specific
	// %        note 2: request properties available via 'this'). Note that file_get_contents() will not return the text
	// %        note 2: in such a case (use this.responseText within the callback). Or, consider using
	// %        note 2: jQuery's: $('#divId').load('http://url') instead.
	// %        note 3: The context argument is only implemented for http, and only partially (see below for
	// %        note 3: "Presently unimplemented HTTP context options"); also the arguments passed to
	// %        note 3: notification are incomplete
	// *     example 1: file_get_contents('http://kevin.vanzonneveld.net/pj_test_supportfile_1.htm');
	// *     returns 1: '123'
	// Note: could also be made to optionally add to global $http_response_header as per http://php.net/manual/en/reserved.variables.httpresponseheader.php
	var tmp, headers = [], newTmp = [], k = 0, i = 0, href = '', pathPos = -1, flagNames = 0, content = null, http_stream = false;
	var func = function(value){
		return value.substring(1) !== '';
	};
	
	// BEGIN REDUNDANT
	this.php_js = this.php_js ||
	{};
	this.php_js.ini = this.php_js.ini ||
	{};
	// END REDUNDANT
	
	var ini = this.php_js.ini;
	context = context || this.php_js.default_streams_context || null;
	
	if (!flags) {
		flags = 0;
	}
	var OPTS = {
		FILE_USE_INCLUDE_PATH: 1,
		FILE_TEXT: 32,
		FILE_BINARY: 64
	};
	if (typeof flags === 'number') { // Allow for a single string or an array of string flags
		flagNames = flags;
	}
	else {
		flags = [].concat(flags);
		for (i = 0; i < flags.length; i++) {
			if (OPTS[flags[i]]) {
				flagNames = flagNames | OPTS[flags[i]];
			}
		}
	}
	
	if (flagNames & OPTS.FILE_BINARY && (flagNames & OPTS.FILE_TEXT)) { // These flags shouldn't be together
		throw 'You cannot pass both FILE_BINARY and FILE_TEXT to file_get_contents()';
	}
	
	if ((flagNames & OPTS.FILE_USE_INCLUDE_PATH) && ini.include_path &&
	ini.include_path.local_value) {
		var slash = ini.include_path.local_value.indexOf('/') !== -1 ? '/' : '\\';
		url = ini.include_path.local_value + slash + url;
	}
	else 
		if (!/^(https?|file):/.test(url)) { // Allow references within or below the same directory (should fix to allow other relative references or root reference; could make dependent on parse_url())
			href = this.window.location.href;
			pathPos = url.indexOf('/') === 0 ? href.indexOf('/', 8) - 1 : href.lastIndexOf('/');
			url = href.slice(0, pathPos + 1) + url;
		}
	
	if (context) {
		var http_options = context.stream_options && context.stream_options.http;
		http_stream = !!http_options;
	}
	
	if (!context || http_stream) {
		var req = this.window.ActiveXObject ? new ActiveXObject('Microsoft.XMLHTTP') : new XMLHttpRequest();
		if (!req) {
			throw new Error('XMLHttpRequest not supported');
		}
		
		var method = http_stream ? http_options.method : 'GET';
		var async = !!(context && context.stream_params && context.stream_params['phpjs.async']);
		
		if (ini['phpjs.ajaxBypassCache'] && ini['phpjs.ajaxBypassCache'].local_value) {
			url += (url.match(/\?/) == null ? "?" : "&") + (new Date()).getTime(); // Give optional means of forcing bypass of cache
		}
		
		req.open(method, url, async);
		if (async) {
			var notification = context.stream_params.notification;
			if (typeof notification === 'function') {
				// Fix: make work with req.addEventListener if available: https://developer.mozilla.org/En/Using_XMLHttpRequest
				if (0 && req.addEventListener) { // Unimplemented so don't allow to get here
					/*
					 req.addEventListener('progress', updateProgress, false);
					 req.addEventListener('load', transferComplete, false);
					 req.addEventListener('error', transferFailed, false);
					 req.addEventListener('abort', transferCanceled, false);
					 */
				}
				else {
					req.onreadystatechange = function(aEvt){ // aEvt has stopPropagation(), preventDefault(); see https://developer.mozilla.org/en/NsIDOMEvent
						// Other XMLHttpRequest properties: multipart, responseXML, status, statusText, upload, withCredentials
						/*
						 PHP Constants:
						 STREAM_NOTIFY_RESOLVE   1       A remote address required for this stream has been resolved, or the resolution failed. See severity  for an indication of which happened.
						 STREAM_NOTIFY_CONNECT   2     A connection with an external resource has been established.
						 STREAM_NOTIFY_AUTH_REQUIRED 3     Additional authorization is required to access the specified resource. Typical issued with severity level of STREAM_NOTIFY_SEVERITY_ERR.
						 STREAM_NOTIFY_MIME_TYPE_IS  4     The mime-type of resource has been identified, refer to message for a description of the discovered type.
						 STREAM_NOTIFY_FILE_SIZE_IS  5     The size of the resource has been discovered.
						 STREAM_NOTIFY_REDIRECTED    6     The external resource has redirected the stream to an alternate location. Refer to message .
						 STREAM_NOTIFY_PROGRESS  7     Indicates current progress of the stream transfer in bytes_transferred and possibly bytes_max as well.
						 STREAM_NOTIFY_COMPLETED 8     There is no more data available on the stream.
						 STREAM_NOTIFY_FAILURE   9     A generic error occurred on the stream, consult message and message_code for details.
						 STREAM_NOTIFY_AUTH_RESULT   10     Authorization has been completed (with or without success).
						 
						 STREAM_NOTIFY_SEVERITY_INFO 0     Normal, non-error related, notification.
						 STREAM_NOTIFY_SEVERITY_WARN 1     Non critical error condition. Processing may continue.
						 STREAM_NOTIFY_SEVERITY_ERR  2     A critical error occurred. Processing cannot continue.
						 */
						var objContext = {
							responseText: req.responseText,
							responseXML: req.responseXML,
							status: req.status,
							statusText: req.statusText,
							readyState: req.readyState,
							evt: aEvt
						}; // properties are not available in PHP, but offered on notification via 'this' for convenience
						// notification args: notification_code, severity, message, message_code, bytes_transferred, bytes_max (all int's except string 'message')
						// Need to add message, etc.
						var bytes_transferred;
						switch (req.readyState) {
							case 0: //     UNINITIALIZED     open() has not been called yet.
								notification.call(objContext, 0, 0, '', 0, 0, 0);
								break;
							case 1: //     LOADING     send() has not been called yet.
								notification.call(objContext, 0, 0, '', 0, 0, 0);
								break;
							case 2: //     LOADED     send() has been called, and headers and status are available.
								notification.call(objContext, 0, 0, '', 0, 0, 0);
								break;
							case 3: //     INTERACTIVE     Downloading; responseText holds partial data.
								bytes_transferred = req.responseText.length * 2; // One character is two bytes
								notification.call(objContext, 7, 0, '', 0, bytes_transferred, 0);
								break;
							case 4: //     COMPLETED     The operation is complete.
								if (req.status >= 200 && req.status < 400) {
									bytes_transferred = req.responseText.length * 2; // One character is two bytes
									notification.call(objContext, 8, 0, '', req.status, bytes_transferred, 0);
								}
								else 
									if (req.status === 403) { // Fix: These two are finished except for message
										notification.call(objContext, 10, 2, '', req.status, 0, 0);
									}
									else { // Errors
										notification.call(objContext, 9, 2, '', req.status, 0, 0);
									}
								break;
							default:
								throw 'Unrecognized ready state for file_get_contents()';
						}
					}
				}
			}
		}
		
		if (http_stream) {
			var sendHeaders = http_options.header && http_options.header.split(/\r?\n/);
			var userAgentSent = false;
			for (i = 0; i < sendHeaders.length; i++) {
				var sendHeader = sendHeaders[i];
				var breakPos = sendHeader.search(/:\s*/);
				var sendHeaderName = sendHeader.substring(0, breakPos);
				req.setRequestHeader(sendHeaderName, sendHeader.substring(breakPos + 1));
				if (sendHeaderName === 'User-Agent') {
					userAgentSent = true;
				}
			}
			if (!userAgentSent) {
				var user_agent = http_options.user_agent ||
				(ini.user_agent && ini.user_agent.local_value);
				if (user_agent) {
					req.setRequestHeader('User-Agent', user_agent);
				}
			}
			content = http_options.content || null;
			/*
			
			 // Presently unimplemented HTTP context options
			
			 var request_fulluri = http_options.request_fulluri || false; // When set to TRUE, the entire URI will be used when constructing the request. (i.e. GET http://www.example.com/path/to/file.html HTTP/1.0). While this is a non-standard request format, some proxy servers require it.
			
			 var max_redirects = http_options.max_redirects || 20; // The max number of redirects to follow. Value 1 or less means that no redirects are followed.
			
			 var protocol_version = http_options.protocol_version || 1.0; // HTTP protocol version
			
			 var timeout = http_options.timeout || (ini.default_socket_timeout && ini.default_socket_timeout.local_value); // Read timeout in seconds, specified by a float
			
			 var ignore_errors = http_options.ignore_errors || false; // Fetch the content even on failure status codes.
			
			 */
			
		}
		
		if (flagNames & OPTS.FILE_TEXT) { // Overrides how encoding is treated (regardless of what is returned from the server)
			var content_type = 'text/html';
			if (http_options && http_options['phpjs.override']) { // Fix: Could allow for non-HTTP as well
				content_type = http_options['phpjs.override']; // We use this, e.g., in gettext-related functions if character set
				//   overridden earlier by bind_textdomain_codeset()
			}
			else {
				var encoding = (ini['unicode.stream_encoding'] && ini['unicode.stream_encoding'].local_value) || 'UTF-8';
				if (http_options && http_options.header && (/^content-type:/im).test(http_options.header)) { // We'll assume a content-type expects its own specified encoding if present
					content_type = http_options.header.match(/^content-type:\s*(.*)$/im)[1]; // We let any header encoding stand
				}
				if (!(/;\s*charset=/).test(content_type)) { // If no encoding
					content_type += '; charset=' + encoding;
				}
			}
			req.overrideMimeType(content_type);
		}
		// Default is FILE_BINARY, but for binary, we apparently deviate from PHP in requiring the flag, since many if not
		//     most people will also want a way to have it be auto-converted into native JavaScript text instead
		else 
			if (flagNames & OPTS.FILE_BINARY) { // Trick at https://developer.mozilla.org/En/Using_XMLHttpRequest to get binary
				req.overrideMimeType('text/plain; charset=x-user-defined');
			// Getting an individual byte then requires:
			// responseText.charCodeAt(x) & 0xFF; // throw away high-order byte (f7) where x is 0 to responseText.length-1 (see notes in our substr())
			}
		
		if (http_options && http_options['phpjs.sendAsBinary']) { // For content sent in a POST or PUT request (use with file_put_contents()?)
			req.sendAsBinary(content); // In Firefox, only available FF3+
		}
		else {
			req.send(content);
		}
		
		tmp = req.getAllResponseHeaders();
		if (tmp) {
			tmp = tmp.split('\n');
			for (k = 0; k < tmp.length; k++) {
				if (func(tmp[k])) {
					newTmp.push(tmp[k]);
				}
			}
			tmp = newTmp;
			for (i = 0; i < tmp.length; i++) {
				headers[i] = tmp[i];
			}
			this.$http_response_header = headers; // see http://php.net/manual/en/reserved.variables.httpresponseheader.php
		}
		
		if (offset || maxLen) {
			if (maxLen) {
				return req.responseText.substr(offset || 0, maxLen);
			}
			return req.responseText.substr(offset);
		}
		return req.responseText;
	}
	return false;
}











function date ( format, timestamp ) {
    // Format a local date/time  
    // 
    // version: 911.2217
    // discuss at: http://phpjs.org/functions/date
    // +   original by: Carlos R. L. Rodrigues (http://www.jsfromhell.com)
    // +      parts by: Peter-Paul Koch (http://www.quirksmode.org/js/beat.html)
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: MeEtc (http://yass.meetcweb.com)
    // +   improved by: Brad Touesnard
    // +   improved by: Tim Wiel
    // +   improved by: Bryan Elliott
    // +   improved by: Brett Zamir (http://brett-zamir.me)
    // +   improved by: David Randall
    // +      input by: Brett Zamir (http://brett-zamir.me)
    // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: Brett Zamir (http://brett-zamir.me)
    // +   improved by: Brett Zamir (http://brett-zamir.me)
    // +   improved by: Theriault
    // +  derived from: gettimeofday
    // +      input by: majak
    // +   bugfixed by: majak
    // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +      input by: Alex
    // +   bugfixed by: Brett Zamir (http://brett-zamir.me)
    // +   improved by: Theriault
    // +   improved by: Brett Zamir (http://brett-zamir.me)
    // +   improved by: Theriault
    // %        note 1: Uses global: php_js to store the default timezone
    // *     example 1: date('H:m:s \\m \\i\\s \\m\\o\\n\\t\\h', 1062402400);
    // *     returns 1: '09:09:40 m is month'
    // *     example 2: date('F j, Y, g:i a', 1062462400);
    // *     returns 2: 'September 2, 2003, 2:26 am'
    // *     example 3: date('Y W o', 1062462400);
    // *     returns 3: '2003 36 2003'
    // *     example 4: x = date('Y m d', (new Date()).getTime()/1000); // 2009 01 09
    // *     example 4: (x+'').length == 10
    // *     returns 4: true
    // *     example 5: date('W', 1104534000);
    // *     returns 5: '53'
    // *     example 6: date('B t', 1104534000);
    // *     returns 6: '999 31'
    // *     example 7: date('W', 1293750000); // 2010-12-31
    // *     returns 7: '52'
    // *     example 8: date('W', 1293836400); // 2011-01-01
    // *     returns 8: '52'
    // *     example 9: date('W Y-m-d', 1293974054); // 2011-01-02
    // *     returns 9: '52 2011-01-02'
    var that = this,
        jsdate = (
        (typeof timestamp === 'undefined') ? new Date() : // Not provided
        (timestamp instanceof Date) ? new Date(timestamp) : // Javascript Date()
        new Date(timestamp * 1000) // UNIX timestamp (auto-convert to int)
    ), //, tal= [], // Keep this here (works, but for code commented-out below for file size reasons)
        formatChr = /\\?([a-z])/gi,
        formatChrCb = function (t, s) {
            return f[t] ? f[t]() : s;
        },
        _pad = function (n, c) {
            if ((n = n + "").length < c) {
                return new Array((++c) - n.length).join("0") + n;
            } else {
                return n;
            }
        },
        txt_words = ["Sun", "Mon", "Tues", "Wednes", "Thurs", "Fri", "Satur",
        "January", "February", "March", "April", "May", "June", "July",
        "August", "September", "October", "November", "December"],
        txt_ordin = {1: "st", 2: "nd", 3: "rd", 21: "st", 22: "nd", 23: "rd", 31: "st"},
        f = {
        // Day
            d: function () {
                return _pad(f.j(), 2);
            },
            D: function () {
                return f.l().slice(0, 3);
            },
            j: function () {
                return jsdate.getDate();
            },
            l: function () {
                return txt_words[f.w()] + 'day';
            },
            N: function () {
                return f.w() || 7;
            },
            S: function () {
                return txt_ordin[f.j()] || 'th';
            },
            w: function () {
                return jsdate.getDay();
            },
            z: function () {
                return (jsdate - new Date(f.Y(), 0, 1)) / 864e5 >> 0;
            },
 
        // Week
            W: function () {
                var c = new Date(f.Y(), f.n() - 1, f.j() - f.N() + 3);
                return 1 + Math.round((c - (new Date(c.getFullYear(), 0, 4))) / 864e5 / 7);
            },
 
        // Month
            F: function () {
                return txt_words[6 + f.n()];
            },
            m: function () {
                return _pad(f.n(), 2);
            },
            M: function () {
                return f.F().slice(0, 3);
            },
            n: function () {
                return jsdate.getMonth() + 1;
            },
            t: function () {
                return (new Date(f.Y(), f.n() + 1, 0)).getDate();
            },
 
        // Year
            L: function () {
                var y = f.Y();
                return (!(y & 3) && (y % 1e2 || !(y % 4e2))) ? 1 : 0;
            },
            o: function () {
                return f.Y() + (f.n() === 12 && f.W() < 9 ? -1 : (f.n() === 1 && f.W() > 9 ? 1 : 0));
            },
            Y: function () {
                return jsdate.getFullYear();
            },
            y: function () {
                return (jsdate.getFullYear() + "").slice(2);
            },
 
        // Time
            a: function () {
                return jsdate.getHours() > 11 ? "pm" : "am";
            },
            A: function () {
                return f.a().toUpperCase();
            },
            B: function () {
                return _pad(Math.floor(((jsdate.getUTCHours() * 36e2) + (jsdate.getUTCMinutes() * 60) +
                                        jsdate.getUTCSeconds() + 36e2) / 86.4) % 1e3, 3);
            },
            g: function () {
                return jsdate.getHours() % 12 || 12;
            },
            G: function () {
                return jsdate.getHours();
            },
            h: function () {
                return _pad(f.g(), 2);
            },
            H: function () {
                return _pad(f.G(), 2);
            },
            i: function () {
                return _pad(jsdate.getMinutes(), 2);
            },
            s: function () {
                return _pad(jsdate.getSeconds(), 2);
            },
            u: function () {
                return _pad(jsdate.getMilliseconds() * 1000, 6);
            },
 
        // Timezone
            e: function () {
// The following works, but requires inclusion of the very large timezone_abbreviations_list() function
/*                var abbr='', i=0;
                if (that.php_js && that.php_js.default_timezone) {
                    return that.php_js.default_timezone;
                }
                if (!tal.length) {
                    tal = that.timezone_abbreviations_list();
                }
                for (abbr in tal) {
                    for (i=0; i < tal[abbr].length; i++) {
                        if (tal[abbr][i].offset === -jsdate.getTimezoneOffset()*60) {
                            return tal[abbr][i].timezone_id;
                        }
                    }
                }
*/
                return 'UTC';
            },
            I: function () {
                // Compares Jan 1 minus Jan 1 UTC to Jul 1 minus Jul 1 UTC.
                // If they are not equal, then DST is observed.
                return 0 + (((new Date(f.Y(), 0)) - Date.UTC(f.Y(), 0)) !== ((new Date(f.Y(), 6)) - Date.UTC(f.Y(), 6)));
            },
            O: function () {
                var a = jsdate.getTimezoneOffset();
                return (a > 0 ? "-" : "+") + _pad(Math.abs(a / 60 * 100), 4);
            },
            P: function () {
                var O = f.O();
                return (O.substr(0, 3) + ":" + O.substr(3, 2));
            },
            T: function () {
 
// The following works, but requires inclusion of the very large timezone_abbreviations_list() function
/*                var abbr='', i=0;
                if (!tal.length) {
                    tal = that.timezone_abbreviations_list();
                }
                if (that.php_js && that.php_js.default_timezone) {
                    for (abbr in tal) {
                        for (i=0; i < tal[abbr].length; i++) {
                            if (tal[abbr][i].timezone_id === that.php_js.default_timezone) {
                                return abbr.toUpperCase();
                            }
                        }
                    }
                }
                for (abbr in tal) {
                    for (i=0; i < tal[abbr].length; i++) {
                        if (tal[abbr][i].offset === -jsdate.getTimezoneOffset()*60) {
                            return abbr.toUpperCase();
                        }
                    }
                }
*/
                return 'UTC';
            },
            Z: function () {
                return -jsdate.getTimezoneOffset() * 60;
            },
 
        // Full Date/Time
            c: function () {
                return 'Y-m-d\\Th:i:sP'.replace(formatChr, formatChrCb);
            },
            r: function () {
                return 'D, d M Y H:i:s O'.replace(formatChr, formatChrCb);
            },
            U: function () {
                return Math.round(jsdate.getTime() / 1000);
            }
        };
    return format.replace(formatChr, formatChrCb);
}


function explode (delimiter, string, limit) {
    // Splits a string on string separator and return array of components. If limit is positive only limit number of components is returned. If limit is negative all components except the last abs(limit) are returned.  
    // 
    // version: 909.322
    // discuss at: http://phpjs.org/functions/explode
    // +     original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +     improved by: kenneth
    // +     improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +     improved by: d3x
    // +     bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // *     example 1: explode(' ', 'Kevin van Zonneveld');
    // *     returns 1: {0: 'Kevin', 1: 'van', 2: 'Zonneveld'}
    // *     example 2: explode('=', 'a=bc=d', 2);
    // *     returns 2: ['a', 'bc=d']
 
    var emptyArray = { 0: '' };
    
    // third argument is not required
    if ( arguments.length < 2 ||
        typeof arguments[0] == 'undefined' ||
        typeof arguments[1] == 'undefined' )
    {
        return null;
    }
 
    if ( delimiter === '' ||
        delimiter === false ||
        delimiter === null )
    {
        return false;
    }
 
    if ( typeof delimiter == 'function' ||
        typeof delimiter == 'object' ||
        typeof string == 'function' ||
        typeof string == 'object' )
    {
        return emptyArray;
    }
 
    if ( delimiter === true ) {
        delimiter = '1';
    }
    
    if (!limit) {
        return string.toString().split(delimiter.toString());
    } else {
        // support for limit argument
        var splitted = string.toString().split(delimiter.toString());
        var partA = splitted.splice(0, limit - 1);
        var partB = splitted.join(delimiter.toString());
        partA.push(partB);
        return partA;
    }
}


function strtotime (str, now) {
    // Convert string representation of date and time to a timestamp  
    // 
    // version: 911.1619
    // discuss at: http://phpjs.org/functions/strtotime
    // +   original by: Caio Ariede (http://caioariede.com)
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +      input by: David
    // +   improved by: Caio Ariede (http://caioariede.com)
    // +   improved by: Brett Zamir (http://brett-zamir.me)
    // +   bugfixed by: Wagner B. Soares
    // +   bugfixed by: Artur Tchernychev
    // %        note 1: Examples all have a fixed timestamp to prevent tests to fail because of variable time(zones)
    // *     example 1: strtotime('+1 day', 1129633200);
    // *     returns 1: 1129719600
    // *     example 2: strtotime('+1 week 2 days 4 hours 2 seconds', 1129633200);
    // *     returns 2: 1130425202
    // *     example 3: strtotime('last month', 1129633200);
    // *     returns 3: 1127041200
    // *     example 4: strtotime('2009-05-04 08:30:00');
    // *     returns 4: 1241418600
 
    var i, match, s, strTmp = '', parse = '';
 
    strTmp = str;
    strTmp = strTmp.replace(/\s{2,}|^\s|\s$/g, ' '); // unecessary spaces
    strTmp = strTmp.replace(/[\t\r\n]/g, ''); // unecessary chars
 
    if (strTmp == 'now') {
        return (new Date()).getTime()/1000; // Return seconds, not milli-seconds
    } else if (!isNaN(parse = Date.parse(strTmp))) {
        return (parse/1000);
    } else if (now) {
        now = new Date(now*1000); // Accept PHP-style seconds
    } else {
        now = new Date();
    }
 
    strTmp = strTmp.toLowerCase();
 
    var __is =
    {
        day:
        {
            'sun': 0,
            'mon': 1,
            'tue': 2,
            'wed': 3,
            'thu': 4,
            'fri': 5,
            'sat': 6
        },
        mon:
        {
            'jan': 0,
            'feb': 1,
            'mar': 2,
            'apr': 3,
            'may': 4,
            'jun': 5,
            'jul': 6,
            'aug': 7,
            'sep': 8,
            'oct': 9,
            'nov': 10,
            'dec': 11
        }
    };
 
    var process = function (m) {
        var ago = (m[2] && m[2] == 'ago');
        var num = (num = m[0] == 'last' ? -1 : 1) * (ago ? -1 : 1);
 
        switch (m[0]) {
            case 'last':
            case 'next':
                switch (m[1].substring(0, 3)) {
                    case 'yea':
                        now.setFullYear(now.getFullYear() + num);
                        break;
                    case 'mon':
                        now.setMonth(now.getMonth() + num);
                        break;
                    case 'wee':
                        now.setDate(now.getDate() + (num * 7));
                        break;
                    case 'day':
                        now.setDate(now.getDate() + num);
                        break;
                    case 'hou':
                        now.setHours(now.getHours() + num);
                        break;
                    case 'min':
                        now.setMinutes(now.getMinutes() + num);
                        break;
                    case 'sec':
                        now.setSeconds(now.getSeconds() + num);
                        break;
                    default:
                        var day;
                        if (typeof (day = __is.day[m[1].substring(0, 3)]) != 'undefined') {
                            var diff = day - now.getDay();
                            if (diff == 0) {
                                diff = 7 * num;
                            } else if (diff > 0) {
                                if (m[0] == 'last') {diff -= 7;}
                            } else {
                                if (m[0] == 'next') {diff += 7;}
                            }
                            now.setDate(now.getDate() + diff);
                        }
                }
                break;
 
            default:
                if (/\d+/.test(m[0])) {
                    num *= parseInt(m[0], 10);
 
                    switch (m[1].substring(0, 3)) {
                        case 'yea':
                            now.setFullYear(now.getFullYear() + num);
                            break;
                        case 'mon':
                            now.setMonth(now.getMonth() + num);
                            break;
                        case 'wee':
                            now.setDate(now.getDate() + (num * 7));
                            break;
                        case 'day':
                            now.setDate(now.getDate() + num);
                            break;
                        case 'hou':
                            now.setHours(now.getHours() + num);
                            break;
                        case 'min':
                            now.setMinutes(now.getMinutes() + num);
                            break;
                        case 'sec':
                            now.setSeconds(now.getSeconds() + num);
                            break;
                    }
                } else {
                    return false;
                }
                break;
        }
        return true;
    };
 
    match = strTmp.match(/^(\d{2,4}-\d{2}-\d{2})(?:\s(\d{1,2}:\d{2}(:\d{2})?)?(?:\.(\d+))?)?$/);
    if (match != null) {
        if (!match[2]) {
            match[2] = '00:00:00';
        } else if (!match[3]) {
            match[2] += ':00';
        }
 
        s = match[1].split(/-/g);
 
        for (i in __is.mon) {
            if (__is.mon[i] == s[1] - 1) {
                s[1] = i;
            }
        }
        s[0] = parseInt(s[0], 10);
 
        s[0] = (s[0] >= 0 && s[0] <= 69) ? '20'+(s[0] < 10 ? '0'+s[0] : s[0]+'') : (s[0] >= 70 && s[0] <= 99) ? '19'+s[0] : s[0]+'';
        return parseInt(this.strtotime(s[2] + ' ' + s[1] + ' ' + s[0] + ' ' + match[2])+(match[4] ? match[4]/1000 : ''), 10);
    }
 
    var regex = '([+-]?\\d+\\s'+
        '(years?|months?|weeks?|days?|hours?|min|minutes?|sec|seconds?'+
        '|sun\\.?|sunday|mon\\.?|monday|tue\\.?|tuesday|wed\\.?|wednesday'+
        '|thu\\.?|thursday|fri\\.?|friday|sat\\.?|saturday)'+
        '|(last|next)\\s'+
        '(years?|months?|weeks?|days?|hours?|min|minutes?|sec|seconds?'+
        '|sun\\.?|sunday|mon\\.?|monday|tue\\.?|tuesday|wed\\.?|wednesday'+
        '|thu\\.?|thursday|fri\\.?|friday|sat\\.?|saturday))'+
        '(\\sago)?';
 
    match = strTmp.match(new RegExp(regex, 'gi')); // Brett: seems should be case insensitive per docs, so added 'i'
    if (match == null) {
        return false;
    }
 
    for (i = 0; i < match.length; i++) {
        if (!process(match[i].split(' '))) {
            return false;
        }
    }
 
    return (now.getTime()/1000);
}

function serialize (mixed_value) {
    // Returns a string representation of variable (which can later be unserialized)  
    // 
    // version: 910.813
    // discuss at: http://phpjs.org/functions/serialize
    // +   original by: Arpad Ray (mailto:arpad@php.net)
    // +   improved by: Dino
    // +   bugfixed by: Andrej Pavlovic
    // +   bugfixed by: Garagoth
    // +      input by: DtTvB (http://dt.in.th/2008-09-16.string-length-in-bytes.html)
    // +   bugfixed by: Russell Walker (http://www.nbill.co.uk/)
    // +   bugfixed by: Jamie Beck (http://www.terabit.ca/)
    // +      input by: Martin (http://www.erlenwiese.de/)
    // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // -    depends on: utf8_encode
    // %          note: We feel the main purpose of this function should be to ease the transport of data between php & js
    // %          note: Aiming for PHP-compatibility, we have to translate objects to arrays
    // *     example 1: serialize(['Kevin', 'van', 'Zonneveld']);
    // *     returns 1: 'a:3:{i:0;s:5:"Kevin";i:1;s:3:"van";i:2;s:9:"Zonneveld";}'
    // *     example 2: serialize({firstName: 'Kevin', midName: 'van', surName: 'Zonneveld'});
    // *     returns 2: 'a:3:{s:9:"firstName";s:5:"Kevin";s:7:"midName";s:3:"van";s:7:"surName";s:9:"Zonneveld";}'
    var _getType = function (inp) {
        var type = typeof inp, match;
        var key;
        if (type == 'object' && !inp) {
            return 'null';
        }
        if (type == "object") {
            if (!inp.constructor) {
                return 'object';
            }
            var cons = inp.constructor.toString();
            match = cons.match(/(\w+)\(/);
            if (match) {
                cons = match[1].toLowerCase();
            }
            var types = ["boolean", "number", "string", "array"];
            for (key in types) {
                if (cons == types[key]) {
                    type = types[key];
                    break;
                }
            }
        }
        return type;
    };
    var type = _getType(mixed_value);
    var val, ktype = '';
    
    switch (type) {
        case "function": 
            val = ""; 
            break;
        case "boolean":
            val = "b:" + (mixed_value ? "1" : "0");
            break;
        case "number":
            val = (Math.round(mixed_value) == mixed_value ? "i" : "d") + ":" + mixed_value;
            break;
        case "string":
            mixed_value = this.utf8_encode(mixed_value);
            val = "s:" + encodeURIComponent(mixed_value).replace(/%../g, 'x').length + ":\"" + mixed_value + "\"";
            break;
        case "array":
        case "object":
            val = "a";
            /*
            if (type == "object") {
                var objname = mixed_value.constructor.toString().match(/(\w+)\(\)/);
                if (objname == undefined) {
                    return;
                }
                objname[1] = this.serialize(objname[1]);
                val = "O" + objname[1].substring(1, objname[1].length - 1);
            }
            */
            var count = 0;
            var vals = "";
            var okey;
            var key;
            for (key in mixed_value) {
                ktype = _getType(mixed_value[key]);
                if (ktype == "function") { 
                    continue; 
                }
                
                okey = (key.match(/^[0-9]+$/) ? parseInt(key, 10) : key);
                vals += this.serialize(okey) +
                        this.serialize(mixed_value[key]);
                count++;
            }
            val += ":" + count + ":{" + vals + "}";
            break;
        case "undefined": // Fall-through
        default: // if the JS object has a property which contains a null value, the string cannot be unserialized by PHP
            val = "N";
            break;
    }
    if (type != "object" && type != "array") {
        val += ";";
    }
    return val;
}
function utf8_encode ( argString ) {
    // Encodes an ISO-8859-1 string to UTF-8  
    // 
    // version: 909.322
    // discuss at: http://phpjs.org/functions/utf8_encode
    // +   original by: Webtoolkit.info (http://www.webtoolkit.info/)
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: sowberry
    // +    tweaked by: Jack
    // +   bugfixed by: Onno Marsman
    // +   improved by: Yves Sucaet
    // +   bugfixed by: Onno Marsman
    // +   bugfixed by: Ulrich
    // *     example 1: utf8_encode('Kevin van Zonneveld');
    // *     returns 1: 'Kevin van Zonneveld'
    var string = (argString+''); // .replace(/\r\n/g, "\n").replace(/\r/g, "\n");
 
    var utftext = "";
    var start, end;
    var stringl = 0;
 
    start = end = 0;
    stringl = string.length;
    for (var n = 0; n < stringl; n++) {
        var c1 = string.charCodeAt(n);
        var enc = null;
 
        if (c1 < 128) {
            end++;
        } else if (c1 > 127 && c1 < 2048) {
            enc = String.fromCharCode((c1 >> 6) | 192) + String.fromCharCode((c1 & 63) | 128);
        } else {
            enc = String.fromCharCode((c1 >> 12) | 224) + String.fromCharCode(((c1 >> 6) & 63) | 128) + String.fromCharCode((c1 & 63) | 128);
        }
        if (enc !== null) {
            if (end > start) {
                utftext += string.substring(start, end);
            }
            utftext += enc;
            start = end = n+1;
        }
    }
 
    if (end > start) {
        utftext += string.substring(start, string.length);
    }
 
    return utftext;
}


function urldecode (str) {
    // Decodes URL-encoded string  
    // 
    // version: 911.718
    // discuss at: http://phpjs.org/functions/urldecode
    // +   original by: Philip Peterson
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +      input by: AJ
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: Brett Zamir (http://brett-zamir.me)
    // +      input by: travc
    // +      input by: Brett Zamir (http://brett-zamir.me)
    // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: Lars Fischer
    // +      input by: Ratheous
    // +   improved by: Orlando
    // +      reimplemented by: Brett Zamir (http://brett-zamir.me)
    // %        note 1: info on what encoding functions to use from: http://xkr.us/articles/javascript/encode-compare/
    // %        note 2: Please be aware that this function expects to decode from UTF-8 encoded strings, as found on
    // %        note 2: pages served as UTF-8
    // *     example 1: urldecode('Kevin+van+Zonneveld%21');
    // *     returns 1: 'Kevin van Zonneveld!'
    // *     example 2: urldecode('http%3A%2F%2Fkevin.vanzonneveld.net%2F');
    // *     returns 2: 'http://kevin.vanzonneveld.net/'
    // *     example 3: urldecode('http%3A%2F%2Fwww.google.nl%2Fsearch%3Fq%3Dphp.js%26ie%3Dutf-8%26oe%3Dutf-8%26aq%3Dt%26rls%3Dcom.ubuntu%3Aen-US%3Aunofficial%26client%3Dfirefox-a');
    // *     returns 3: 'http://www.google.nl/search?q=php.js&ie=utf-8&oe=utf-8&aq=t&rls=com.ubuntu:en-US:unofficial&client=firefox-a'
    
    return decodeURIComponent(str).replace(/\+/g, '%20');
}


function unserialize (data) {
    // Takes a string representation of variable and recreates it  
    // 
    // version: 911.815
    // discuss at: http://phpjs.org/functions/unserialize
    // +     original by: Arpad Ray (mailto:arpad@php.net)
    // +     improved by: Pedro Tainha (http://www.pedrotainha.com)
    // +     bugfixed by: dptr1988
    // +      revised by: d3x
    // +     improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +        input by: Brett Zamir (http://brett-zamir.me)
    // +     improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +     improved by: Chris
    // +     improved by: James
    // +        input by: Martin (http://www.erlenwiese.de/)
    // +     bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +     improved by: Le Torbi
    // +     input by: kilops
    // +     bugfixed by: Brett Zamir (http://brett-zamir.me)
    // -      depends on: utf8_decode
    // %            note: We feel the main purpose of this function should be to ease the transport of data between php & js
    // %            note: Aiming for PHP-compatibility, we have to translate objects to arrays
    // *       example 1: unserialize('a:3:{i:0;s:5:"Kevin";i:1;s:3:"van";i:2;s:9:"Zonneveld";}');
    // *       returns 1: ['Kevin', 'van', 'Zonneveld']
    // *       example 2: unserialize('a:3:{s:9:"firstName";s:5:"Kevin";s:7:"midName";s:3:"van";s:7:"surName";s:9:"Zonneveld";}');
    // *       returns 2: {firstName: 'Kevin', midName: 'van', surName: 'Zonneveld'}
    var that = this;
    var utf8Overhead = function(chr) {
        // http://phpjs.org/functions/unserialize:571#comment_95906
        var code = chr.charCodeAt(0);
        if (code < 0x0080) {
            return 0;
        }
        if (code < 0x0800) {
             return 1;
        }
        return 2;
    };
 
 
    var error = function (type, msg, filename, line){throw new that.window[type](msg, filename, line);};
    var read_until = function (data, offset, stopchr){
        var buf = [];
        var chr = data.slice(offset, offset + 1);
        var i = 2;
        while (chr != stopchr) {
            if ((i+offset) > data.length) {
                error('Error', 'Invalid');
            }
            buf.push(chr);
            chr = data.slice(offset + (i - 1),offset + i);
            i += 1;
        }
        return [buf.length, buf.join('')];
    };
    var read_chrs = function (data, offset, length){
        var buf;
 
        buf = [];
        for (var i = 0;i < length;i++){
            var chr = data.slice(offset + (i - 1),offset + i);
            buf.push(chr);
            length -= utf8Overhead(chr); 
        }
        return [buf.length, buf.join('')];
    };
    var _unserialize = function (data, offset){
        var readdata;
        var readData;
        var chrs = 0;
        var ccount;
        var stringlength;
        var keyandchrs;
        var keys;
 
        if (!offset) {offset = 0;}
        var dtype = (data.slice(offset, offset + 1)).toLowerCase();
 
        var dataoffset = offset + 2;
        var typeconvert = function(x) {return x;};
 
        switch (dtype){
            case 'i':
                typeconvert = function (x) {return parseInt(x, 10);};
                readData = read_until(data, dataoffset, ';');
                chrs = readData[0];
                readdata = readData[1];
                dataoffset += chrs + 1;
            break;
            case 'b':
                typeconvert = function (x) {return parseInt(x, 10) !== 0;};
                readData = read_until(data, dataoffset, ';');
                chrs = readData[0];
                readdata = readData[1];
                dataoffset += chrs + 1;
            break;
            case 'd':
                typeconvert = function (x) {return parseFloat(x);};
                readData = read_until(data, dataoffset, ';');
                chrs = readData[0];
                readdata = readData[1];
                dataoffset += chrs + 1;
            break;
            case 'n':
                readdata = null;
            break;
            case 's':
                ccount = read_until(data, dataoffset, ':');
                chrs = ccount[0];
                stringlength = ccount[1];
                dataoffset += chrs + 2;
 
                readData = read_chrs(data, dataoffset+1, parseInt(stringlength, 10));
                chrs = readData[0];
                readdata = readData[1];
                dataoffset += chrs + 2;
                if (chrs != parseInt(stringlength, 10) && chrs != readdata.length){
                    error('SyntaxError', 'String length mismatch');
                }
 
                // Length was calculated on an utf-8 encoded string
                // so wait with decoding
                readdata = that.utf8_decode(readdata);
            break;
            case 'a':
                readdata = {};
 
                keyandchrs = read_until(data, dataoffset, ':');
                chrs = keyandchrs[0];
                keys = keyandchrs[1];
                dataoffset += chrs + 2;
 
                for (var i = 0; i < parseInt(keys, 10); i++){
                    var kprops = _unserialize(data, dataoffset);
                    var kchrs = kprops[1];
                    var key = kprops[2];
                    dataoffset += kchrs;
 
                    var vprops = _unserialize(data, dataoffset);
                    var vchrs = vprops[1];
                    var value = vprops[2];
                    dataoffset += vchrs;
 
                    readdata[key] = value;
                }
 
                dataoffset += 1;
            break;
            default:
                error('SyntaxError', 'Unknown / Unhandled data type(s): ' + dtype);
            break;
        }
        return [dtype, dataoffset - offset, typeconvert(readdata)];
    };
    
    return _unserialize((data+''), 0)[2];
}
function str_replace (search, replace, subject, count) {
    // Replaces all occurrences of search in haystack with replace  
    // 
    // version: 909.322
    // discuss at: http://phpjs.org/functions/str_replace
    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: Gabriel Paderni
    // +   improved by: Philip Peterson
    // +   improved by: Simon Willison (http://simonwillison.net)
    // +    revised by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
    // +   bugfixed by: Anton Ongson
    // +      input by: Onno Marsman
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +    tweaked by: Onno Marsman
    // +      input by: Brett Zamir (http://brett-zamir.me)
    // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   input by: Oleg Eremeev
    // +   improved by: Brett Zamir (http://brett-zamir.me)
    // +   bugfixed by: Oleg Eremeev
    // %          note 1: The count parameter must be passed as a string in order
    // %          note 1:  to find a global variable in which the result will be given
    // *     example 1: str_replace(' ', '.', 'Kevin van Zonneveld');
    // *     returns 1: 'Kevin.van.Zonneveld'
    // *     example 2: str_replace(['{name}', 'l'], ['hello', 'm'], '{name}, lars');
    // *     returns 2: 'hemmo, mars'
    var i = 0, j = 0, temp = '', repl = '', sl = 0, fl = 0,
            f = [].concat(search),
            r = [].concat(replace),
            s = subject,
            ra = r instanceof Array, sa = s instanceof Array;
    s = [].concat(s);
    if (count) {
        this.window[count] = 0;
    }
 
    for (i=0, sl=s.length; i < sl; i++) {
        if (s[i] === '') {
            continue;
        }
        for (j=0, fl=f.length; j < fl; j++) {
            temp = s[i]+'';
            repl = ra ? (r[j] !== undefined ? r[j] : '') : r[0];
            s[i] = (temp).split(f[j]).join(repl);
            if (count && s[i] !== temp) {
                this.window[count] += (temp.length-s[i].length)/f[j].length;}
        }
    }
    return sa ? s : s[0];
}


function checkdateformat(userinput){
var dateformat = /^\d{1,2}(\-|\/|\.)\d{1,2}\1\d{4}$/
return dateformat.test(userinput) //returns true or false depending on userinput
}
