function getHTTPObject()
{
    var httpRequest;

    if (window.XMLHttpRequest)
    {
        httpRequest = new XMLHttpRequest();
    }
    else if (window.ActiveXObject)
    {
        try
        {
            httpRequest = new ActiveXObject('Msxml2.XMLHTTP');
        }
        catch (e)
        {
            try
            {
                httpRequest = new ActiveXObject('Microsoft.XMLHTTP');
            }
            catch (e) {}
        }
    }

    return httpRequest;
}


function HTTPRequest(func, url, method, args, extra)
{
    var request;

    if (!(request = new getHTTPObject()))
    {
        alert('Could not create new HTTP object.');
        return;
    }

    if (!method)
    {
        method = 'GET';
    }

    method = method.toUpperCase();

    if ((method == 'GET') && args)
    {
        url += '?' + args;
    }

    if (func)
    {
        request.onreadystatechange = function()
        {
            if (request.readyState == 4)
            {
                func(request.responseText, extra);
            }
        }
    }

    try
    {
        request.open(method, url, true);
    }
    catch (e)
    {
        alert('Could not open HTTP ' + method + ' connection.\n' + e);
        return;
    }

    if ((method == 'POST') && args)
    {
        request.setRequestHeader('Content-type', 'application/x-www-form-urlencoded; charset=UTF-8');
        request.setRequestHeader('Content-length', args.length);
        request.setRequestHeader('Connection', 'close');
        request.send(args);
    }
    else
    {
        request.send(null);
    }
}


function parseResponse(response)
{
    var results = new Array();

    if (!response)
    {
        return results;
    }

    var idx = 0;
    var re = /^\d$/;

    while (response.substr(idx, 1).match(re))
    {
        idx++;
    }

    if (!idx)
    {
        results[0] = response;
        return results;
    }

    var len = Number(response.substr(0, idx));

    if (response.substr(idx, 1) != ':')
    {
        results[0] = response;
        return results;
    }

    response = response.substr(idx + 1);
    var data = response.substr(0, len);

    if (!data)
    {
        results[0] = response;
        return results;
    }

    results[0] = data;
    response = response.substr(len + 1);

    if (!response)
    {
        return results;
    }

    var tmp = parseResponse(response);

    if (!tmp || !tmp.length)
    {
        return results;
    }

    for (idx = 0; idx < tmp.length; idx++)
    {
        results[idx + 1] = tmp[idx];
    }

    return results;
}


function encodeUTF8(txt)
{
    if (!txt)
    {
        return '';
    }

    var utftext = '';

    for (var idx = 0; idx < txt.length; idx++)
    {
        var c = txt.charCodeAt(idx);

        if (c < 128)
        {
            utftext += String.fromCharCode(c);
        }
        else if((c > 127) && (c < 2048))
        {
            utftext += String.fromCharCode((c >> 6) | 192);
            utftext += String.fromCharCode((c & 63) | 128);
        }
        else
        {
            utftext += String.fromCharCode((c >> 12) | 224);
            utftext += String.fromCharCode(((c >> 6) & 63) | 128);
            utftext += String.fromCharCode((c & 63) | 128);
        }
    }

    return utftext;
}


function decodeUTF8(txt)
{
    var str = '';
    var idx = 0;
    var c = c1 = c2 = 0;

    while (idx < txt.length)
    {
        c = txt.charCodeAt(idx);

        if (c < 128)
        {
            str += String.fromCharCode(c);
            idx++;
        }
        else if ((c > 191) && (c < 224))
        {
            c2 = txt.charCodeAt(idx + 1);
            str += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
            idx += 2;
        }
        else
        {
            c2 = txt.charCodeAt(idx + 1);
            c3 = txt.charCodeAt(idx + 2);
            str += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
            idx += 3;
        }
    }

    return str;
}


function fixURIChars(txt)
{
    if (!txt)
    {
        return '';
    }

//    txt = txt.replace(/\$/g, '%24');
    txt = txt.replace(/%/g, '%25');
    txt = txt.replace(/&/g, '%26');
    txt = txt.replace(/\+/g, '%2B');
    txt = txt.replace(/,/g, '%2C');
    txt = txt.replace(/\//g, '%2F');
    txt = txt.replace(/:/g, '%3A');
    txt = txt.replace(/;/g, '%3B');
    txt = txt.replace(/</g, '%3C');
    txt = txt.replace(/=/g, '%3D');
    txt = txt.replace(/>/g, '%3E');
    txt = txt.replace(/\?/g, '%3F');
    txt = txt.replace(/@/g, '%40');
    return txt;
}


function addEvent(obj, type, fn)
{
    if (obj.addEventListener)
    {
        obj.addEventListener(type, fn, false);
        EventCache.add(obj, type, fn);
    }
    else if (obj.attachEvent)
    {
        obj['e' + type + fn] = fn;
        obj[type + fn] = function() { obj['e' + type + fn]( window.event ); }
        obj.attachEvent('on' + type, obj[type + fn]);
        EventCache.add(obj, type, fn);
    }
    else
    {
        obj['on' + type] = obj['e' + type + fn];
    }
}


var EventCache = function()
{
    var listEvents = [];

    return {
        listEvents : listEvents,

        add : function(node, sEventName, fHandler)
        {
            listEvents.push(arguments);
        },

        flush : function()
        {
            var i, item;

            for (i = listEvents.length - 1; i >= 0; i = i - 1)
            {
                item = listEvents[i];

                if (item[0].removeEventListener)
                {
                    item[0].removeEventListener(item[1], item[2], item[3]);
                };

                if (item[1].substring(0, 2) != 'on')
                {
                    item[1] = 'on' + item[1];
                };

                if (item[0].detachEvent)
                {
                    item[0].detachEvent(item[1], item[2]);
                };

                item[0][item[1]] = null;
            };
        }
    };
} ();


addEvent(window, 'unload', EventCache.flush);
