function printrows()
{
    var msg1 = document.getElementById('v_tisk');

    if (msg1.href.test('.*/print$') == true)
    {
        alert('Pro vypsání záznamu pro tisk, je potřeba je neprve vybrat. \n Pro vybrání firmy zaškrtněte políčko vpravo od názvu firmy.');
    }
}
function sendmesage()
{
    var msg1 = document.getElementById('msg_a');

    if (msg1.href.test('#$') == true)
    {
        alert('Pro odeslíní dotazu, nejprve zvolte firmy, kterým chtcete dotaz zaslat. \n Pro vybrání firmy zaškrtněte políčko vpravo od názvu firmy.');
    }
}

function childProtect()
{
    var ansv = confirm('Snažíte se vstoupit na stánku určenou pouze pro dospělé.\n\
             Opravdu si přejete vstoupit?\n\
');
    if (ansv === true)
    {
        return true;
    }
    else
    {
        return false;
    }
}

var katnum = 1;

function addKat()
{
    if (katnum < 10)
    {


        var table = document.getElementById('kategorieTable');
        var rub = document.getElementById('rub_tr');
        var value = 0;


        if (katnum  == 0)
        {
            var text = rub.innerHTML.replace(/.+rub([0-9]).+/,'$1');
            var num = text.replace('([0-9]{1}).*', '$1');
            value =  parseInt(num.charAt(1).valueOf(), 10)+1;
        }
        else
        {
            value = katnum+1;
        }

        ins = rub.innerHTML.replace(/prvek\=rub([0-9])/,'prvek=rub' + value);
        ins = ins.replace(/\=\"rub([0-9])/,'="rub' + value);
        ins = ins.replace(/selected=\"selected\"/,'');
        //ins = ins.substr(0, ins.length-27);


        ntd1 = document.createElement("td");
        ntd1.innerHTML = ins;

        ntd2 = document.createElement("td");
        //ntd2.innerHTML = '<a onclick="addKat()">[+]</a>';

        ntr = document.createElement("tr");
        ntr.appendChild(ntd1);
        ntr.appendChild(ntd2);

        table.appendChild(ntr);
        katnum++;
    }
    if (katnum >= 10)
    {
        document.getElementById('addkat').className = 'hidden';
    }
//alert (katnum);
}

function replace()
{
    var nahore = document.getElementById('nahore');
    var dole = document.getElementById('dole');

//nahore.innerHTML = "HEMELE";
//setTimeout(function() {nahore.innerHTML = dole.innerHTML; dole.innerHTML = "";}, 2000);

}

function formKontrola() {
    var kontrola = true;
    var out = '';

    if (prijmenceKontrola() == false)
    {
        kontrola = false;
        out += "Pozor! Musíte zvolit příjemce.\n";
    }
    if (mailKontrola() == false)
    {
        kontrola = false;
        out += "Pozor! Váš email nebyl zadán v platném formátu.\n";
    }
    if (textKontrola() == false)
    {
        kontrola = false;
        out += "Pozor! Pole dotaz musí být vyplněno.\n";
    }
    if (captchaKontrola() == false)
    {
        kontrola = false;
        out += "Pozor! Musíte správně opsat kód z obrázku.\n";
    }

    if (kontrola == false)
    {
        alert(out);
        return false;
    }
    else
    {
        return true;
    }

}

function formKontrola3() {
    var kontrola = true;
    var out = '';

    if (prijmenceKontrola3() == false)
    {
        kontrola = false;
        out += "Pozor! Musíte zvolit příjemce.\n";
    }

    if (kontrola == false)
    {
        alert(out);
        return false;
    }
    else
    {
        return true;
    }

}

function enlarge()
{
    var area = document.getElementById('dotaz_area');
    area.style.height = "200px";
}

function reduce()
{
    var area = document.getElementById('dotaz_area');
    area.style.height = "";
}

function vysledek()
{

    if (xmlHttp.readyState == 4) {
        if (xmlHttp.status == 200) {

    }
    }
}

function naka(adresar)
{
    var xmlHttp;
    try {
        xmlHttp = new XMLHttpRequest();
    }
    catch(e) {
        var XmlHttpVersions = new Array('MSXML2.XMLHTTP.6.0', 'MSXML2.XMLHTTP.5.0', 'MSXML2.XMLHTTP.4.0', 'MSXML2.XMLHTTP.3.0', 'MSXML2.XMLHTTP', 'Microsoft.XMLHTTP');
        for (var i =0; i<XmlHttpVersions.length && !xmlHttp; i++) {
            try {
                xmlHttp = new ActiveXObject(XmlHttpVersions[i]);
            }
            catch(e) {

            }
        }
    }

    if (xmlHttp.readyState == 4 || xmlHttp.readyState == 0) {
        if (xmlHttp) {
            try {

                xmlHttp.open('GET', 'addPoint.php?adresar='+ adresar, true);
                xmlHttp.onreadystatechange = vysledek;
                xmlHttp.send(null);
            }
            catch (e) {}
        }
    }
}

function ext_odkaz()
{
    var as = document.getElementsByTagName('a');

    for (i = 0; i < as.length; i++)
    {
        if (as[i].id == 'ext_odkaz')
        {
            as[i].style.display = 'block';
        }
    }

//var ad = document.getElementById('ext_odkaz');
//ad.style.display = 'block';
}


function kliknuti(adresar,region,url)
{
    var xmlHttp;
    try {
        xmlHttp = new XMLHttpRequest();
    }
    catch(e) {
        var XmlHttpVersions = new Array('MSXML2.XMLHTTP.6.0', 'MSXML2.XMLHTTP.5.0', 'MSXML2.XMLHTTP.4.0', 'MSXML2.XMLHTTP.3.0', 'MSXML2.XMLHTTP', 'Microsoft.XMLHTTP');
        for (var i =0; i<XmlHttpVersions.length && !xmlHttp; i++) {
            try {
                xmlHttp = new ActiveXObject(XmlHttpVersions[i]);
            }
            catch(e) {

            }
        }
    }

    if (xmlHttp.readyState == 4 || xmlHttp.readyState == 0) {
        if (xmlHttp) {
            try {

                xmlHttp.open('GET', 'addPoint.php?adresar='+ adresar +'&region='+ region, true);

                xmlHttp.onreadystatechange = function()
                {
                    if (xmlHttp.readyState == 4) {
                        if (xmlHttp.status == 200) {
                            window.location = url;
                        }
                    }
                }
                xmlHttp.send(null);
            }
            catch (e) {}
        }
    }
}


function addPoint(adresar)
{
    if (window.XMLHttpRequest)
    {
        req = new XMLHttpRequest();
    }
    else if (window.ActiveXObject)
    {
        try
        {
            req = new ActiveXObject("Msxml2.XMLHTTP");
        } catch (eror)
{
            req = new ActiveXObject("Microsoft.XMLHTTP");
        }
    }
    if (req)
    {
        req.onreadystatechange = function()
        {
            if (req.readyState == 4)
            { //data is retrieved from server
                if (req.status == 200)
                { // which reprents ok status

                }
                else
                {
                    alert("There was a problem while using XMLHTTP:\n" + req.status);
                }
            }
        }
        req.open("GET", 'addPoint.php?adresar='+ adresar , true); // open url using get method
        req.send(null);
    }
}

function formKontrola2()
{
    var kontrola = true;
    var out = '';

    if (prijmenceKontrola2() == false)
    {
        kontrola = false;
        out += "Pozor! Musíte zvolit příjemce.\n";
    }
    if (mailKontrola() == false)
    {
        kontrola = false;
        out += "Pozor! Váš email nebyl zadán v platném formátu.\n";
    }
    if (textKontrola() == false)
    {
        kontrola = false;
        out += "Pozor! Pole dotaz musí být vyplněno.\n";
    }
    if (captchaKontrola() == false)
    {
        kontrola = false;
        out += "Pozor! Musíte správně opsat kód z obrázku.\n";
    }

    if (kontrola == false)
    {
        alert(out);
        return false;
    }
    else
    {
        return true;
    }

}

function formKontrola2()
{
    var kontrola = true;
    var out = '';

    if (textKontrola2() == false)
    {
        kontrola = false;
        out += "Pozor! Pole Popis chyby musí být vyplněno.\n";
    }
    if (captchaKontrola2() == false)
    {
        kontrola = false;
        out += "Pozor! Musíte správně opsat kód z obrázku.\n";
    }

    if (kontrola == false)
    {
        alert(out);
        return false;
    }
    else
    {
        return true;
    }

}

function captchaKontrola()
{
    var text1 = document.dotaz_formular.captcha_code.value;
    var text2 = document.dotaz_formular.captcha_input.value;

    if (text1 != hex_md5(text2))
    {
        return false;
    }
    else
    {
        return true;
    }

}

function captchaKontrola2()
{
    var text1 = document.err_formular.captcha_code.value;
    var text2 = document.err_formular.captcha_input.value;

    if (text1 != hex_md5(text2))
    {
        return false;
    }
    else
    {
        return true;
    }

}

function prijmenceKontrola()
{
    var text = document.dotaz_formular.adres_emaily;
    var tes = /^.+$/;
    if (tes.test(text.value) == false)
    {
        return false;
    }
    else
    {
        return true;
    }
}

function prijmenceKontrola3()
{
    var pole = document.getElementsByTagName("input");
    for (var i=0; i <= (pole.length-1); i++)
    {
        if (pole[i].type == 'checkbox' && pole[i].checked == true)
        {
            return true
        }
    }
    return false;
}


function prijmenceKontrola2()
{
    var text = document.dotaz_formular.adres_email;
    var tes = /^.+$/;
    if (tes.test(text.value) == false)
    {
        return false;
    }
    else
    {
        return true;
    }
}

function textKontrola()
{
    var text = document.dotaz_formular.dotaz;
    var tes = /^.+$/;
    if (tes.test(text.value) == false)
    {
        return false;
    }
    else
    {
        return true;
    }
}

function textKontrola2()
{
    var text = document.err_formular.dotaz;
    var tes = /^.+$/;
    if (tes.test(text.value) == false)
    {
        return false;
    }
    else
    {
        return true;
    }
}

function mailKontrola()
{
    var sender = document.dotaz_formular.sender_email;
    var mail = /^.+@.+\..{2,4}$/;
    if (mail.test(sender.value) == true)
    {
        return true;
    }
    else
    {
        return false;
    }
}

function multiMatilSelector()
{
    var adresy = document.dotaz_formular.adres_emaily;
    var pole = document.getElementsByTagName("input");
    var adres = document.getElementById('prijemci');
    var print = document.getElementById('v_tisk');
    var dotaz = document.getElementById('v_dotaz');
    /*var msg = document.getElementById('msg_a');*/
    var re1="w+";

    /*msg.href = '#';*/
    adresy.value = '';

    //adres.innerHTML = '';
    if (print)
    {
        print.href = 'print';
    }
    if (dotaz)
    {
        dotaz.href = 'zaslat_dotaz';
    }
    for (var i=0; i <= (pole.length-1); i++)
    {
        if (pole[i].type == 'checkbox' && pole[i].checked == true)
        {
            pole[i].parentNode.parentNode.parentNode.parentNode.className = 'k_v_firmazaznam1 aktivni';
            //adresy.value = adresy.value + pole[i].value + '~';
            adr=pole[i].value.match("__.+");
            result1=pole[i].value.match("[^{]+");

            if (print && adr != null)
            {
                print.href += adr;
            }

            if (dotaz && adr != null)
            {
                dotaz.href += adr;
            }
        //adres.innerHTML = adres.innerHTML + result1;
        //adres.innerHTML = adres.innerHTML + ';<br/>';
        }
        else
        {
            pole[i].parentNode.parentNode.parentNode.parentNode.className = 'k_v_firmazaznam1';
        }
    }

}

function Nechci()
{
    if (document.getElementById('nechcicheckbox').checked == true)
    {
        document.getElementById('nechci').style.display = 'none';
    }
    if (document.getElementById('nechcicheckbox').checked == false)
    {
        document.getElementById('nechci').style.display = 'block';
    }
}

function IcoDoLoginu()
{
    if (document.getElementById('login').value == "")
    {
        document.getElementById('login').value  = document.getElementById('ico').value;
    }
}

function getCity(strURL)
{
    var ph = document.getElementById('okres');
    //var sop = document.getElementById('sopdiv');

    if (ph.value != 76)
    {
    //sop.className="hidden";
    //obeccastdiv.className = "hidden";
    }

    if (window.XMLHttpRequest)
    {
        req = new XMLHttpRequest();
    }
    else if (window.ActiveXObject)
    {
        try
        {
            req = new ActiveXObject("Msxml2.XMLHTTP");
        } catch (eror)
{
            req = new ActiveXObject("Microsoft.XMLHTTP");
        }
    }
    if (req)
    {
        req.onreadystatechange = function()
        {
            if (req.readyState == 4)
            { //data is retrieved from server
                if (req.status == 200)
                { // which reprents ok status

                    document.getElementById('obecdiv').innerHTML=req.responseText;

                }
                else
                {
                    alert("There was a problem while using XMLHTTP:\n");
                }
            }
        }
        req.open("GET", strURL, true); // open url using get method
        req.send(null);
    }
}

function getCasti(strURL)
{
    if (window.XMLHttpRequest)
    {
        req = new XMLHttpRequest();
    }
    else if (window.ActiveXObject)
    {
        try
        {
            req = new ActiveXObject("Msxml2.XMLHTTP");
        } catch (eror)
{
            req = new ActiveXObject("Microsoft.XMLHTTP");
        }
    }
    if (req)
    {
        req.onreadystatechange = function()
        {
            if (req.readyState == 4)
            { //data is retrieved from server
                if (req.status == 200)
                { // which reprents ok status

                    document.getElementById('obeccastdiv').innerHTML=req.responseText;
                }
                else
                {
                    alert("There was a problem while using XMLHTTP:\n");
                }
            }
        }
        req.open("GET", strURL, true); // open url using get method
        req.send(null);
    }
}

function getCityGPS(strURL)
{
    if (window.XMLHttpRequest)
    {
        req = new XMLHttpRequest();
    }
    else if (window.ActiveXObject)
    {
        try
        {
            req = new ActiveXObject("Msxml2.XMLHTTP");
        } catch (eror)
{
            req = new ActiveXObject("Microsoft.XMLHTTP");
        }
    }
    if (req)
    {
        req.onreadystatechange = function()
        {
            if (req.readyState == 4)
            { //data is retrieved from server
                if (req.status == 200)
                { // which reprents ok status
                    var lat = req.responseXML.getElementsByTagName('lat')[0].firstChild.nodeValue;
                    var lon = req.responseXML.getElementsByTagName('lon')[0].firstChild.nodeValue;
                    map.setCenter(new GLatLng(lat,lon), 10);
                }
                else
                {
                    alert("There was a problem while using XMLHTTP:\n");
                }
            }
        }
        req.open("GET", strURL, true); // open url using get method
        req.send(null);
    }
}

function getCityGPS2(strURL)
{

    }

    function NechciZadatMapu()
    {
        if (document.getElementById('mapa_nechci_zadat').checked == true)
        {
            document.getElementById('div_mapa').style.display = 'none';
        }
        if (document.getElementById('mapa_nechci_zadat').checked == false)
        {
            document.getElementById('div_mapa').style.display = 'block';
        }
    }

    function NechciZadatOD()
    {
        if (document.getElementById('otd_nechci_zadat').checked == true)
        {
            document.getElementById('div_oteviraci_doba').style.display = 'none';
        }
        if (document.getElementById('otd_nechci_zadat').checked == false)
        {
            document.getElementById('div_oteviraci_doba').style.display = 'block';
        }
    }

    function pridatKontakt()
    {
        var num = 1;
        if (document.getElementById('kr_1').className == 'visible')
        {
            num++;
        }
        if (document.getElementById('kr_2').className == 'visible')
        {
            num++;
        }
        if (document.getElementById('kr_3').className == 'visible')
        {
            num++;
        }
        if (document.getElementById('kr_4').className == 'visible')
        {
            num++;
        }

        if (num <= 4)
        {
            var next = document.getElementById('kr_'+num);
            next.className = 'visible';
        }

        if (num >= 4)
        {
            var pridat = document.getElementById('pridatkontakt');
            pridat.className = "hidden";
        }
    }

    function ukazMapu()
    {
        if (document.getElementById('mapa').checked == true)
        {
            document.getElementById('mapad').className= 'visible';
        }
        if (document.getElementById('mapa').checked == false)
        {
            document.getElementById('mapad').className = 'hidden';
        }
    }

    function ukazOteviracku()
    {
        if (document.getElementById('oteviraci_doba').checked == true)
        {
            document.getElementById('oteviracka').className= 'visible';
        }
        if (document.getElementById('oteviraci_doba').checked == false)
        {
            document.getElementById('oteviracka').className = 'hidden';
        }
    }

    function formCheck()
    {
        var stat = true;
        var err = '\n(';
        if (document.getElementById('login').value == '')
        {
            stat = false;
            err = err + 'uživatelské jméno, ';
        }
        if (document.getElementById('nazev').value == '')
        {
            stat = false;
            err = err + 'název firmy, ';
        }
        if (document.getElementById('ulice').value == '')
        {
            stat = false;
            err = err + 'ulici, ';
        }
        if (document.getElementById('psc').value == '')
        {
            stat = false;
            err = err + 'psč, ';
        }
        if (document.getElementById('okres').value == '')
        {
            stat = false;
            err = err + 'okres, ';
        }
        else
        {
            if (document.getElementById('kod_obce').value == '')
            {
                stat = false;
                err = err + 'obec, ';
            }
            else
            {
                if ((document.getElementById('okres').value != '76') && (document.getElementById('kod_casti_obce').value == ''))
                {
                    stat = false;
                    err = err + 'část města, ';
                }
                if ((document.getElementById('okres').value == '76') && (document.getElementById('kod_sop').value == ''))
                {
                    stat = false;
                    err = err + 'správní oblast, ';
                }
                else
                {
                    if ((document.getElementById('okres').value == '76') && (document.getElementById('kod_casti_obce').value == ''))
                    {
                        stat = false;
                        err = err + 'část obce, ';
                    }
                }
            }
        }

        if (document.getElementById('popis_cinnosti').value == '')
        {
            stat = false;
            err = err + 'popis činnosti, ';
        }
        if (document.getElementById('ico').value == '')
        {
            stat = false;
            err = err + 'ičo, ';
        }
        if (document.getElementById('tel1').value == '')
        {
            stat = false;
            err = err + 'telefon, ';
        }
        if (document.getElementById('vyplnil_jmeno').value == '')
        {
            stat = false;
            err = err + 'jméno, ';
        }
        if (document.getElementById('vyplnil_mail').value == '')
        {
            stat = false;
        }
        if (stat == false)
        {
            alert('Je nuné vyplnit všechna pole označená červenou barvou.' + err + ')');
            return false;
        }
        return true;
    }

    function infoMSG()
    {
        alert("Na váš email byl odeslán email obsahující přístup na editační formulář.");
    }

    /*
 * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
 * Digest Algorithm, as defined in RFC 1321.
 * Version 2.2-beta Copyright (C) Paul Johnston 1999 - 2009
 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
 * Distributed under the BSD License
 * See http://pajhome.org.uk/crypt/md5 for more info.
 */

    /*
 * Configurable variables. You may need to tweak these to be compatible with
 * the server-side, but the defaults work in most cases.
 */
    var hexcase = 0;   /* hex output format. 0 - lowercase; 1 - uppercase        */
    var b64pad  = "";  /* base-64 pad character. "=" for strict RFC compliance   */

    /*
 * These are the functions you'll usually want to call
 * They take string arguments and return either hex or base-64 encoded strings
 */
    function hex_md5(s)    {
        return rstr2hex(rstr_md5(str2rstr_utf8(s)));
    }
    function b64_md5(s)    {
        return rstr2b64(rstr_md5(str2rstr_utf8(s)));
    }
    function any_md5(s, e) {
        return rstr2any(rstr_md5(str2rstr_utf8(s)), e);
    }
    function hex_hmac_md5(k, d)
    {
        return rstr2hex(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d)));
    }
    function b64_hmac_md5(k, d)
    {
        return rstr2b64(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d)));
    }
    function any_hmac_md5(k, d, e)
    {
        return rstr2any(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d)), e);
    }

    /*
 * Perform a simple self-test to see if the VM is working
 */
    function md5_vm_test()
    {
        return hex_md5("abc").toLowerCase() == "900150983cd24fb0d6963f7d28e17f72";
    }

    /*
 * Calculate the MD5 of a raw string
 */
    function rstr_md5(s)
    {
        return binl2rstr(binl_md5(rstr2binl(s), s.length * 8));
    }

    /*
 * Calculate the HMAC-MD5, of a key and some data (raw strings)
 */
    function rstr_hmac_md5(key, data)
    {
        var bkey = rstr2binl(key);
        if(bkey.length > 16) bkey = binl_md5(bkey, key.length * 8);

        var ipad = Array(16), opad = Array(16);
        for(var i = 0; i < 16; i++)
        {
            ipad[i] = bkey[i] ^ 0x36363636;
            opad[i] = bkey[i] ^ 0x5C5C5C5C;
        }

        var hash = binl_md5(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
        return binl2rstr(binl_md5(opad.concat(hash), 512 + 128));
    }

    /*
 * Convert a raw string to a hex string
 */
    function rstr2hex(input)
    {
        try {
            hexcase
        } catch(e) {
            hexcase=0;
        }
        var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
        var output = "";
        var x;
        for(var i = 0; i < input.length; i++)
        {
            x = input.charCodeAt(i);
            output += hex_tab.charAt((x >>> 4) & 0x0F)
            +  hex_tab.charAt( x        & 0x0F);
        }
        return output;
    }

    /*
 * Convert a raw string to a base-64 string
 */
    function rstr2b64(input)
    {
        try {
            b64pad
        } catch(e) {
            b64pad='';
        }
        var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
        var output = "";
        var len = input.length;
        for(var i = 0; i < len; i += 3)
        {
            var triplet = (input.charCodeAt(i) << 16)
            | (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0)
            | (i + 2 < len ? input.charCodeAt(i+2)      : 0);
            for(var j = 0; j < 4; j++)
            {
                if(i * 8 + j * 6 > input.length * 8) output += b64pad;
                else output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F);
            }
        }
        return output;
    }

    /*
 * Convert a raw string to an arbitrary string encoding
 */
    function rstr2any(input, encoding)
    {
        var divisor = encoding.length;
        var i, j, q, x, quotient;

        /* Convert to an array of 16-bit big-endian values, forming the dividend */
        var dividend = Array(Math.ceil(input.length / 2));
        for(i = 0; i < dividend.length; i++)
        {
            dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1);
        }

        /*
   * Repeatedly perform a long division. The binary array forms the dividend,
   * the length of the encoding is the divisor. Once computed, the quotient
   * forms the dividend for the next step. All remainders are stored for later
   * use.
   */
        var full_length = Math.ceil(input.length * 8 /
            (Math.log(encoding.length) / Math.log(2)));
        var remainders = Array(full_length);
        for(j = 0; j < full_length; j++)
        {
            quotient = Array();
            x = 0;
            for(i = 0; i < dividend.length; i++)
            {
                x = (x << 16) + dividend[i];
                q = Math.floor(x / divisor);
                x -= q * divisor;
                if(quotient.length > 0 || q > 0)
                    quotient[quotient.length] = q;
            }
            remainders[j] = x;
            dividend = quotient;
        }

        /* Convert the remainders to the output string */
        var output = "";
        for(i = remainders.length - 1; i >= 0; i--)
            output += encoding.charAt(remainders[i]);

        return output;
    }

    /*
 * Encode a string as utf-8.
 * For efficiency, this assumes the input is valid utf-16.
 */
    function str2rstr_utf8(input)
    {
        var output = "";
        var i = -1;
        var x, y;

        while(++i < input.length)
        {
            /* Decode utf-16 surrogate pairs */
            x = input.charCodeAt(i);
            y = i + 1 < input.length ? input.charCodeAt(i + 1) : 0;
            if(0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF)
            {
                x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF);
                i++;
            }

            /* Encode output as utf-8 */
            if(x <= 0x7F)
                output += String.fromCharCode(x);
            else if(x <= 0x7FF)
                output += String.fromCharCode(0xC0 | ((x >>> 6 ) & 0x1F),
                    0x80 | ( x         & 0x3F));
            else if(x <= 0xFFFF)
                output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F),
                    0x80 | ((x >>> 6 ) & 0x3F),
                    0x80 | ( x         & 0x3F));
            else if(x <= 0x1FFFFF)
                output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07),
                    0x80 | ((x >>> 12) & 0x3F),
                    0x80 | ((x >>> 6 ) & 0x3F),
                    0x80 | ( x         & 0x3F));
        }
        return output;
    }

    /*
 * Encode a string as utf-16
 */
    function str2rstr_utf16le(input)
    {
        var output = "";
        for(var i = 0; i < input.length; i++)
            output += String.fromCharCode( input.charCodeAt(i)        & 0xFF,
                (input.charCodeAt(i) >>> 8) & 0xFF);
        return output;
    }

    function str2rstr_utf16be(input)
    {
        var output = "";
        for(var i = 0; i < input.length; i++)
            output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF,
                input.charCodeAt(i)        & 0xFF);
        return output;
    }

    /*
 * Convert a raw string to an array of little-endian words
 * Characters >255 have their high-byte silently ignored.
 */
    function rstr2binl(input)
    {
        var output = Array(input.length >> 2);
        for(var i = 0; i < output.length; i++)
            output[i] = 0;
        for(var i = 0; i < input.length * 8; i += 8)
            output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (i%32);
        return output;
    }

    /*
 * Convert an array of little-endian words to a string
 */
    function binl2rstr(input)
    {
        var output = "";
        for(var i = 0; i < input.length * 32; i += 8)
            output += String.fromCharCode((input[i>>5] >>> (i % 32)) & 0xFF);
        return output;
    }

    /*
 * Calculate the MD5 of an array of little-endian words, and a bit length.
 */
    function binl_md5(x, len)
    {
        /* append padding */
        x[len >> 5] |= 0x80 << ((len) % 32);
        x[(((len + 64) >>> 9) << 4) + 14] = len;

        var a =  1732584193;
        var b = -271733879;
        var c = -1732584194;
        var d =  271733878;

        for(var i = 0; i < x.length; i += 16)
        {
            var olda = a;
            var oldb = b;
            var oldc = c;
            var oldd = d;

            a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
            d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
            c = md5_ff(c, d, a, b, x[i+ 2], 17,  606105819);
            b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
            a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
            d = md5_ff(d, a, b, c, x[i+ 5], 12,  1200080426);
            c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
            b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
            a = md5_ff(a, b, c, d, x[i+ 8], 7 ,  1770035416);
            d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
            c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
            b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
            a = md5_ff(a, b, c, d, x[i+12], 7 ,  1804603682);
            d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
            c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
            b = md5_ff(b, c, d, a, x[i+15], 22,  1236535329);

            a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
            d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
            c = md5_gg(c, d, a, b, x[i+11], 14,  643717713);
            b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
            a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
            d = md5_gg(d, a, b, c, x[i+10], 9 ,  38016083);
            c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
            b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
            a = md5_gg(a, b, c, d, x[i+ 9], 5 ,  568446438);
            d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
            c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
            b = md5_gg(b, c, d, a, x[i+ 8], 20,  1163531501);
            a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
            d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
            c = md5_gg(c, d, a, b, x[i+ 7], 14,  1735328473);
            b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);

            a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
            d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
            c = md5_hh(c, d, a, b, x[i+11], 16,  1839030562);
            b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
            a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
            d = md5_hh(d, a, b, c, x[i+ 4], 11,  1272893353);
            c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
            b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
            a = md5_hh(a, b, c, d, x[i+13], 4 ,  681279174);
            d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
            c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
            b = md5_hh(b, c, d, a, x[i+ 6], 23,  76029189);
            a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
            d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
            c = md5_hh(c, d, a, b, x[i+15], 16,  530742520);
            b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);

            a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
            d = md5_ii(d, a, b, c, x[i+ 7], 10,  1126891415);
            c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
            b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
            a = md5_ii(a, b, c, d, x[i+12], 6 ,  1700485571);
            d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
            c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
            b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
            a = md5_ii(a, b, c, d, x[i+ 8], 6 ,  1873313359);
            d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
            c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
            b = md5_ii(b, c, d, a, x[i+13], 21,  1309151649);
            a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
            d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
            c = md5_ii(c, d, a, b, x[i+ 2], 15,  718787259);
            b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);

            a = safe_add(a, olda);
            b = safe_add(b, oldb);
            c = safe_add(c, oldc);
            d = safe_add(d, oldd);
        }
        return Array(a, b, c, d);
    }

    /*
 * These functions implement the four basic operations the algorithm uses.
 */
    function md5_cmn(q, a, b, x, s, t)
    {
        return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
    }
    function md5_ff(a, b, c, d, x, s, t)
    {
        return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
    }
    function md5_gg(a, b, c, d, x, s, t)
    {
        return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
    }
    function md5_hh(a, b, c, d, x, s, t)
    {
        return md5_cmn(b ^ c ^ d, a, b, x, s, t);
    }
    function md5_ii(a, b, c, d, x, s, t)
    {
        return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
    }

    /*
 * Add integers, wrapping at 2^32. This uses 16-bit operations internally
 * to work around bugs in some JS interpreters.
 */
    function safe_add(x, y)
    {
        var lsw = (x & 0xFFFF) + (y & 0xFFFF);
        var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
        return (msw << 16) | (lsw & 0xFFFF);
    }

    /*
 * Bitwise rotate a 32-bit number to the left.
 */
    function bit_rol(num, cnt)
    {
        return (num << cnt) | (num >>> (32 - cnt));
    }