function XHR(url){
    this.url = url;
}

XHR.prototype = {

    init: function(){
        if (this.request != null)
            throw "ERRBUSY";


        try {
            this.request = new XMLHttpRequest();
        }
        catch (e) {
            var XMLHTTP_IDS = new Array('MSXML2.XMLHTTP.5.0', 'MSXML2.XMLHTTP.4.0', 'MSXML2.XMLHTTP.3.0', 'MSXML2.XMLHTTP', 'Microsoft.XMLHTTP');

            var success = false;
            for (var i = 0; i < XMLHTTP_IDS.length && !success; i++) {
                try {
                    this.request = new ActiveXObject(XMLHTTP_IDS[i]);
                    success = true;
                }
                catch (e) {
                }
            }

            if (!success) {
                throw "ERRNOXHR";
            }
        }
    },

    asyncGet: function(){
        var me = this;

        this.data = null;
        try {
            this.init();
            try {
                this.request.onreadystatechange = function(){
                    me.response();
                };
                this.request.open('GET', this.url, true);
                this.request.send(null);
            }
            catch (e) {
                throw "ERRASYNCGET";
            }
        }
        catch (e) {
        	//alert(e);
            this.request = null;
            this.error(e);
//            throw e;
        }
    },

    syncGet: function(){

        this.data = null;
        try {
            this.init();
            try {
                this.request.open('GET', this.url, false);
                this.request.send(null);
                this.response();
            }
            catch (e) {
                throw "ERRSYNCGET";
            }
        }
        catch (e) {
            this.request = null;
            this.error(e);
        }
    },

    asyncPost: function(data){

        this.data = data;
        try {
            this.init();
            try {
                var me = this;
                this.request.onreadystatechange = function(){
                    me.response();
                };
                this.request.open('POST', this.url, true);
                this.request.send(data);
            }
            catch (e) {
                throw "ERRASYNCPOST";
            }
        }
        catch (e) {
            this.request = null;
            this.error(e, data);
        }
    },

    syncPost: function(data){

        this.data = data;
        try {
            this.init();
            try {
                this.request.open('POST', this.url, false);
                this.request.send(data);
                this.response();
            }
            catch (e) {
                throw "ERRSYNCPOST";
            }
        }
        catch (e) {
            this.request = null;
            this.error(e, data);
        }
    },

    response: function(){

        if (this.request.readyState == 4) {
            try {
                var status = this.request.status;

                if (status == undefined || status < 200 || status >= 300) {
                    this.error("ERRFAIL");
                }
                else {
                    this.handler(this.request);
                }
            }
            catch (e) {
            	//alert(e);
                this.error("ERRFAIL");
            }
            finally {
                this.request = null;
            }
        }
    },

    handler: function(){

    },

    isBusy: function(){
        return this.request != null;
    },

    error: function(msg){
        throw msg;
    }
};

if (!Object.prototype.toJSONString) {
    Array.prototype.toJSONString = function(){
        var a = ['['], b, i, l = this.length, v;

        function p(s){
            if (b) {
                a.push(',');
            }
            a.push(s);
            b = true;
        }

        for (i = 0; i < l; i += 1) {
            v = this[i];
            switch (typeof v) {
                case 'undefined':
                case 'function':
                case 'unknown':
                    break;
                case 'object':
                    if (v) {
                        if (typeof v.toJSONString === 'function') {
                            p(v.toJSONString());
                        }
                    }
                    else {
                        p("null");
                    }
                    break;
                default:
                    p(v.toJSONString());
            }
        }
        a.push(']');
        return a.join('');
    };

    Boolean.prototype.toJSONString = function(){
        return String(this);
    };

    Date.prototype.toJSONString = function(){

        function f(n){
            return n < 10 ? '0' + n : n;
        }

        return '"' + this.getFullYear() + '-' +
        f(this.getMonth() + 1) +
        '-' +
        f(this.getDate()) +
        'T' +
        f(this.getHours()) +
        ':' +
        f(this.getMinutes()) +
        ':' +
        f(this.getSeconds()) +
        '"';
    };

    Number.prototype.toJSONString = function(){
        return isFinite(this) ? String(this) : "null";
    };

    Object.prototype.toJSONString = function(){
        var a = ['{'], b, i, v;

        function p(s){
            if (b) {
                a.push(',');
            }
            a.push(i.toJSONString(), ':', s);
            b = true;
        }

        for (i in this) {
            if (this.hasOwnProperty(i)) {
                v = this[i];
                switch (typeof v) {
                    case 'undefined':
                    case 'function':
                    case 'unknown':
                        break;
                    case 'object':
                        if (v) {
                            if (typeof v.toJSONString === 'function') {
                                p(v.toJSONString());
                            }
                        }
                        else {
                            p("null");
                        }
                        break;
                    default:
                        p(v.toJSONString());
                }
            }
        }
        a.push('}');
        return a.join('');
    };


    (function(s){
        var m = {
            '\b': '\\b',
            '\t': '\\t',
            '\n': '\\n',
            '\f': '\\f',
            '\r': '\\r',
            '"': '\\"',
            '\\': '\\\\'
        };

        s.parseJSON = function(filter){
            try {
                if (/^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/.test(this)) {
                    var j = eval('(' + this + ')');
                    if (typeof filter === 'function') {
                        function walk(k, v){
                            if (v && typeof v === 'object') {
                                for (var i in v) {
                                    if (v.hasOwnProperty(i)) {
                                        v[i] = walk(i, v[i]);
                                    }
                                }
                            }
                            return filter(k, v);
                        }
                        return walk('', j);
                    }
                    return j;
                }
            }
            catch (e) {
            }
            throw new SyntaxError("parseJSON");
        };

        s.toJSONString = function(){
            if (/["\\\x00-\x1f]/.test(this)) {
                return '"' +
                this.replace(/([\x00-\x1f\\"])/g, function(a, b){
                    var c = m[b];
                    if (c) {
                        return c;
                    }
                    c = b.charCodeAt();
                    return '\\u00' +
                    Math.floor(c / 16).toString(16) +
                    (c % 16).toString(16);
                }) +
                '"';
            }
            return '"' + this + '"';
        };
    })(String.prototype);
}