<commit_before>/*!
 * node.io
 * Copyright(c) 2010 Chris O'Hara <cohara87@gmail.com>
 * MIT Licensed
 */

var http = require('http'),
    urlparse = require('url').parse,
    query = require('querystring'),
    Job = require('./job').JobProto,
    utils = require('./utils');

/**
 * The default headers to send when using createClient()
 */
var default_headers = {
    accept: '*/*',
    'accept-charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.3',
    'user-agent': 'node.io'
};

/**
 * Makes a GET request to the specified resource. See doRequest().
 *
 * @param {String} resource
 * @param {Object} headers (optional)
 * @param {Function} callback
 * @param {Function} parse (optional)
 * @api public
 */
Job.prototype.get = function (resource, headers, callback, parse) {
    this.doRequest('GET', resource, null, headers, callback, parse);
};

/**
 * Makes a POST request to the specified resource. See doRequest().
 *
 * @param {String} resource
 * @param {Object} body (optional)
 * @param {Object} headers (optional)
 * @param {Function} callback
 * @param {Function} parse (optional)
 * @api public
 */
Job.prototype.post = function (resource, body, headers, callback, parse) {
    this.doRequest('POST', resource, body, headers, callback, parse);
};

/**
 * Makes a HEAD request to the specified resource. See doRequest().
 *
 * @param {String} resource
 * @param {Object} headers (optional)
 * @param {Function} callback
 * @api public
 */
Job.prototype.head = function (resource, headers, callback) {
    this.doRequest('HEAD', resource, null, headers, callback, null);
};

/**
 * Makes a GET request to the specified resource and returns a selector object.
 * See parseHtml() in ./dom.js
 *
 * @param {String} resource
 * @param {Object} headers (optional)
 * @param {Function} callback
 * @param {Function} parse (optional)
 * @api public
 */
Job.prototype.getHtml = function (resource, headers, callback, parse) {
    var self = this;

    //`headers` is optional
    if (typeof headers === 'function') {
        callback = headers;
        headers = default_headers;
    }

    this.get(resource, headers, function (err, data, headers, response) {
        if (err) {
            callback(err);
        } else {
            self.parseHtml(data, callback, response);
        }
    }, parse);
};

/**
 * Makes a POST request to the specified resource and returns a selector object.
 * See parseHtml() in ./dom.js
 *
 * @param {String} resource
 * @param {Object} body (optional)
 * @param {Object} headers (optional)
 * @param {Function} callback
 * @param {Function} parse (optional)
 * @api public
 */
Job.prototype.postHtml = function (resource, body, headers, callback, parse) {
    var self = this;

    //`body` and `headers` are optional
    if (typeof body === 'function') {
        callback = body;
        preparse = headers;
        headers = default_headers;
    } else if (typeof headers === 'function') {
        parse = callback;
        callback = headers;
        headers = default_headers;
    }

    this.post(resource, body, headers, function (err, data, headers, response) {
        if (err) {
            callback(err);
        } else {
            self.parseHtml(data, callback, response);
        }
    }, parse);
};

/**
 * Encodes the body of a request.
 *
 * @param {Object} body
 * @param {Boolean} use_json (optional)
 * @api public
 */
Job.prototype.encodeBody = function (body, use_json) {
    if (use_json) {
        JSON.stringify(body);
    } else {
        query.stringify(body);
    }
};

/**
 * Makes a request to the specified resource and returns the response body
 * response headers. `callback` takes (err, data, headers).
 *
 * `parse` is an optional callback which can be used to filter or decode the body
 * before `callback` is called.
 *
 * @param {String} method
 * @param {String} resource
 * @param {Object} body (optional)
 * @param {Object} headers (optional)
 * @param {Function} callback
 * @param {Function} parse (optional)
 * @api public
 */
Job.prototype.doRequest = function (method, resource, body, headers, callback, parse, redirects) {
    var self = this;

    //Internally keep track of the # of redirects
    redirects = redirects || 0;
    if (redirects > this.options.redirects) {
        callback('redirects');
        //self.fail_with('redirects');
        return;
    }

    //`body` and `headers` are optional
    if (typeof body === 'function') {
        parse = headers;
        callback = body;
        headers = default_headers;
        body = null;
    } else if (typeof headers === 'function') {
        parse = callback;
        callback = headers;
        headers = default_headers;
    } else {
        //Add default headers
        utils.put_default(headers, default_headers);
    }

    if (!resource.match(/https?:\/\//)) {
        resource = 'http://' + resource;
    }

    var url = urlparse(resource, false), port = url.port;

    if (!port) {
        port = (url.protocol === 'http:') ? 80 : 443;
    }

    var host = http.createClient(port, url.hostname),
        req_url = url.pathname;

    //Copy `headers` before modifying it
    headers = utils.put({}, headers);

    if (typeof headers.host === 'undefined') {
        headers.host = url.hostname;
    }

    //Add headers set before the doRequest call if from the same host (e.g. cookie, user-agent, referer, etc.)
    if (typeof this.last.headers === 'object' && this.last.host === url.hostname) {
        utils.put(headers, this.last.headers);
        this.last = {};
    }

    //Add headers added by setHeader, setCookie, etc.
    utils.put(headers, this.next);
    this.next = {};

    if (url.search) {
        req_url += url.search;
    }

    if (typeof body === 'object') {
        body = query.stringify(body);
    }

    if (body) {
        headers['Content-Length'] = body.length;
    }

    method = method.toUpperCase();

    var request = host.request(method, req_url, headers);

    this.debug('\033[7m'+method+'\033[0m '+resource);

    if (body) {
        request.write(body);
    }

    //This method is called on each event if the instance is already complete (i.e. timed out)
    var cleanup = function () {

        //I'll clean up this mess once I figure out which destroy() to call (API is unclear with 0.2.4 => 0.3.1)
        if (request) {
            if (request.socket && request.socket.destroy) {
                request.socket.destroy();
            }
            /* In node >=0.3.6 typeof request.destroy === 'function'
             * yet calling it fails..
            if (request.destroy) {
                request.destroy();
            }
            */
        }
        if (host.destroy) {
            host.destroy();
        }

    };

    //Watch for errors
    host.addListener('error', function (connectionException) {
        if (self.is_complete) return;
        self.debug('Request failed with: ('+connectionException.errno+') ' + connectionException + ' ('+resource+')');
        callback(connectionException);
        cleanup();
    });

    //Set a special timeout if the `timeout` option is set. Redirects do not reset the timeout
    if (this.options.timeout && redirects === 0) {
        self.cancel_timeout();
        self.timeout = setTimeout(function() {
            if (self.is_complete) return;
            self.debug('Request timed out ('+resource+')');
            //self.fail_with('timeout');
            callback('timeout');
            cleanup();
        }, this.options.timeout * 1000);
    }

    request.on('response', function (response) {
        if (self.is_complete) {
            return cleanup();
        }

        response.setEncoding('utf8');

        var code = response.statusCode || 200;

        self.debug('\033[7m'+code+'\033[0m '+resource);

        //Save the response headers for the next request (if to the same host)
        var cookies = response.headers['set-cookie'];
        self.last = {
            host: url.hostname,
            headers: {
                referer: resource,
                cookie: cookies instanceof Array ? cookies.join('; ') : cookies
            }
        };

        switch (Math.floor(code/100)) {
            case 4:
            case 5:
                callback(code);
                return;

            case 3:
                if (typeof response.headers.location === 'undefined') {
                    callback(code);
                } else {
                    self.debug('  \033[7m>\033[0m ' + response.headers.location);
                    self.doRequest(method, response.headers.location, body, headers, callback, parse, ++redirects);
                }
                return;
        }

        var body = '';
        response.on('data', function (chunk) {
            self.bytes_received += chunk.length;

            if (self.is_complete) {
                return cleanup();
            }

            body = body + chunk;
        });

        response.on('end', function () {
            if (self.is_complete) {
                return cleanup();
            }

            var parse_callback = function (err, data) {
                callback(null, data, response.headers, response);
            };

            if (!parse) {
                //If no parse function was specified, just return the body
                parse_callback(null, body);
            } else {
                //Call the parse function on the response body - handle async and sync cases
                var ret = parse(body, parse_callback);
                if (typeof ret !== 'undefined') {
                    parse_callback(null, ret);
                }
            }

            cleanup();
        });
    });

    if (request.end) {
        request.end();
    } else {
        request.close();
    }
};

/**
 * Sets a header on the next request.
 *
 * @param {Object|String} key
 * @param {String} value
 * @api public
 */
Job.prototype.setHeader = function (key, value) {
    if (typeof key === 'object') {
        utils.put(this.next, key);
    } else {
        this.next[key.toLowerCase()] = value;
    }
};

/**
 * Sets the Cookie for the next request.
 *
 * @param {String} cookie
 * @api public
 */
Job.prototype.setCookie = function (key, value) {
    if (value) {
        key = encodeURIComponent(key) + '=' + encodeURIComponent(value);
    }
    this.setHeader('cookie', key);
};

/**
 * Sets the User-Agent for the next request.
 *
 * @param {String} agent
 * @api public
 */
Job.prototype.setUserAgent = function (agent) {
    this.setHeader('user-agent', agent);
};

/**
 * Adds a cookie to the next request.
 *
 * @param {String} key
 * @param {String} value
 * @api public
 */
Job.prototype.addCookie = function (key, value) {
    key = encodeURIComponent(key);
    value = encodeURIComponent(value);
    if (typeof this.next.cookie !== 'undefined' && this.next.cookie.length) {
        this.next.cookie += '; ' + key + '=' + value;
    } else {
        this.next.cookie = key + '=' + value;
    }
};

/**
 * Returns the total bytes received by any doRequest() calls.
 *
 * @return {Number} bytes_received
 * @api public
 */
Job.prototype.getBytesReceived = function () {
    return this.bytes_received;
};

/**
 * Creates a new proxy with the specified (optional) callbacks. The callbacks
 * are used to synchronously modify the url, request headers, parse callback,
 * and response headers surrounding a doRequest().
 *
 * @param {Function} url_callback
 * @param {Function} req_header_callback
 * @param {Function} parse_callback
 * @param {Function} res_header_callback
 * @api public
 */
var Proxy = function (url_callback, req_header_callback, parse_callback, res_header_callback) {
    this.url_callback = url_callback;
    this.req_header_callback = req_header_callback;
    this.res_header_callback = res_header_callback;
    this.parse_callback = parse_callback;
};

/**
 * Proxifies the doRequest() method in the specified job instance.
 *
 * @param {Object} job
 * @return {Object} job
 * @api public
 */
Proxy.prototype.proxify = function (job) {
    var self = this, doRequest = job.doRequest;

    job.doRequest = function (method, resource, body, headers, callback, parse, redirects) {

        if (typeof headers === 'function') {
            parse = callback;
            callback = headers;
            headers = default_headers;
        }

        //Modify the request url
        if (self.url_callback) {
            resource = self.url_callback(resource);
        }

        //Modify request headers
        if (self.req_header_callback) {
            headers = self.req_header_callback(headers);
        }

        //Modify the response body
        if (self.parse_callback) {
            if (!parse) {
                parse = self.parse_callback;
            } else {
                //If a parse function is passed to fetch, chain it together with the proxy parse_callback
                var old_parse = parse;
                parse = function (err, data) {
                    var ret = self.parse_callback(data, old_parse);
                    if (typeof ret !== 'undefined') {
                        old_parse(null, ret);
                    }
                };
            }
        }

        //Modify response headers
        if (self.res_header_callback) {
            var old_callback = callback;
            callback = function (err, data, headers) {
                headers = self.res_header_callback(headers);
                return old_callback(err, data, headers);
            };
        }

        doRequest.apply(job, [method, resource, body, headers, callback, parse, redirects]);
    };

    return job;
};

/**
 * Creates a new proxy that routes requests through the specified host.
 *
 * Note: 100% UNTESTED - use at your own peril.
 *
 * @param {Function} host
 * @api public
 */
var HttpProxy = function (host) {
    var url_callback = function (url) {
        var u = urlparse(url);
        this.url_host = u.host;
        url = u.protocol + '//' + u.host + '/' + u.pathname;
        if (u.search) {
            url += u.search;
        }
        return u;
    };
    var header_callback = function (headers) {
        headers = headers || {};
        headers.host = this.url_host;
        return headers;
    };
    return new Proxy(url_callback, header_callback);
};

/**
 * Export proxies
 */
exports.HttpProxy = HttpProxy;
exports.Proxy = Proxy;
<commit_msg>Fixed a major request bug and added some more debug info<commit_after>/*!
 * node.io
 * Copyright(c) 2010 Chris O'Hara <cohara87@gmail.com>
 * MIT Licensed
 */

var http = require('http'),
    urlparse = require('url').parse,
    query = require('querystring'),
    Job = require('./job').JobProto,
    utils = require('./utils');

/**
 * The default headers to send when using createClient()
 */
var default_headers = {
    accept: '*/*',
    'accept-charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.3',
    'user-agent': 'node.io'
};

/**
 * Makes a GET request to the specified resource. See doRequest().
 *
 * @param {String} resource
 * @param {Object} headers (optional)
 * @param {Function} callback
 * @param {Function} parse (optional)
 * @api public
 */
Job.prototype.get = function (resource, headers, callback, parse) {
    this.doRequest('GET', resource, null, headers, callback, parse);
};

/**
 * Makes a POST request to the specified resource. See doRequest().
 *
 * @param {String} resource
 * @param {Object} body (optional)
 * @param {Object} headers (optional)
 * @param {Function} callback
 * @param {Function} parse (optional)
 * @api public
 */
Job.prototype.post = function (resource, body, headers, callback, parse) {
    this.doRequest('POST', resource, body, headers, callback, parse);
};

/**
 * Makes a HEAD request to the specified resource. See doRequest().
 *
 * @param {String} resource
 * @param {Object} headers (optional)
 * @param {Function} callback
 * @api public
 */
Job.prototype.head = function (resource, headers, callback) {
    this.doRequest('HEAD', resource, null, headers, callback, null);
};

/**
 * Makes a GET request to the specified resource and returns a selector object.
 * See parseHtml() in ./dom.js
 *
 * @param {String} resource
 * @param {Object} headers (optional)
 * @param {Function} callback
 * @param {Function} parse (optional)
 * @api public
 */
Job.prototype.getHtml = function (resource, headers, callback, parse) {
    var self = this;

    //`headers` is optional
    if (typeof headers === 'function') {
        callback = headers;
        headers = default_headers;
    }

    this.get(resource, headers, function (err, data, headers, response) {
        if (err) {
            callback(err);
        } else {
            self.parseHtml(data, callback, response);
        }
    }, parse);
};

/**
 * Makes a POST request to the specified resource and returns a selector object.
 * See parseHtml() in ./dom.js
 *
 * @param {String} resource
 * @param {Object} body (optional)
 * @param {Object} headers (optional)
 * @param {Function} callback
 * @param {Function} parse (optional)
 * @api public
 */
Job.prototype.postHtml = function (resource, body, headers, callback, parse) {
    var self = this;

    //`body` and `headers` are optional
    if (typeof body === 'function') {
        callback = body;
        preparse = headers;
        headers = default_headers;
    } else if (typeof headers === 'function') {
        parse = callback;
        callback = headers;
        headers = default_headers;
    }

    this.post(resource, body, headers, function (err, data, headers, response) {
        if (err) {
            callback(err);
        } else {
            self.parseHtml(data, callback, response);
        }
    }, parse);
};

/**
 * Encodes the body of a request.
 *
 * @param {Object} body
 * @param {Boolean} use_json (optional)
 * @api public
 */
Job.prototype.encodeBody = function (body, use_json) {
    if (use_json) {
        JSON.stringify(body);
    } else {
        query.stringify(body);
    }
};

/**
 * Makes a request to the specified resource and returns the response body
 * response headers. `callback` takes (err, data, headers).
 *
 * `parse` is an optional callback which can be used to filter or decode the body
 * before `callback` is called.
 *
 * @param {String} method
 * @param {String} resource
 * @param {Object} body (optional)
 * @param {Object} headers (optional)
 * @param {Function} callback
 * @param {Function} parse (optional)
 * @api public
 */
Job.prototype.doRequest = function (method, resource, body, headers, callback, parse, redirects) {
    var self = this, rid = Math.floor(Math.random() * 100000);

    //Internally keep track of the # of redirects
    redirects = redirects || 0;
    if (redirects > this.options.redirects) {
        callback('redirects');
        //self.fail_with('redirects');
        return;
    }

    //`body` and `headers` are optional
    if (typeof body === 'function') {
        parse = headers;
        callback = body;
        headers = default_headers;
        body = null;
    } else if (typeof headers === 'function') {
        parse = callback;
        callback = headers;
        headers = default_headers;
    } else {
        //Add default headers
        utils.put_default(headers, default_headers);
    }

    if (!resource.match(/https?:\/\//)) {
        resource = 'http://' + resource;
    }

    var url = urlparse(resource, false), port = url.port;

    if (!port) {
        port = (url.protocol === 'http:') ? 80 : 443;
    }

    var host = http.createClient(port, url.hostname),
        req_url = url.pathname || '/';

    //Copy `headers` before modifying it
    headers = utils.put({}, headers);

    if (typeof headers.host === 'undefined') {
        headers.host = url.hostname;
    }

    //Add headers set before the doRequest call if from the same host (e.g. cookie, user-agent, referer, etc.)
    if (typeof this.last.headers === 'object' && this.last.host === url.hostname) {
        utils.put(headers, this.last.headers);
        this.last = {};
    }

    //Add headers added by setHeader, setCookie, etc.
    utils.put(headers, this.next);
    this.next = {};

    if (url.search) {
        req_url += url.search;
    }

    if (typeof body === 'object') {
        body = query.stringify(body);
    }

    if (body) {
        headers['Content-Length'] = body.length;
    }

    method = method.toUpperCase();

    var request = host.request(method, req_url, headers);

    this.debug('\033[7m'+method+'\033[0m '+resource + ' (request ' + rid + ')');

    this.debug('  | ' + method + ' ' + req_url + ' HTTP/1.1');
    for (var h in headers) {
        this.debug('  | ' + h[0].toUpperCase() + h.substr(1) + ': ' + headers[h]);
    }

    if (body) {
        request.write(body);
    }

    //This method is called on each event if the instance is already complete (i.e. timed out)
    var cleanup = function () {

        //I'll clean up this mess once I figure out which destroy() to call (API is unclear with 0.2.4 => 0.3.1)
        if (request) {
            if (request.socket && request.socket.destroy) {
                request.socket.destroy();
            }
            /* In node >=0.3.6 typeof request.destroy === 'function'
             * yet calling it fails..
            if (request.destroy) {
                request.destroy();
            }
            */
        }
        if (host.destroy) {
            host.destroy();
        }

    };

    //Watch for errors
    host.addListener('error', function (connectionException) {
        if (self.is_complete) return;
        self.debug('Request failed with: ('+connectionException.errno+') ' + connectionException + ' ('+resource+')');
        callback(connectionException);
        cleanup();
    });

    //Set a special timeout if the `timeout` option is set. Redirects do not reset the timeout
    if (this.options.timeout && redirects === 0) {
        self.cancel_timeout();
        self.timeout = setTimeout(function() {
            if (self.is_complete) return;
            self.debug('Request timed out ('+resource+')');
            //self.fail_with('timeout');
            callback('timeout');
            cleanup();
        }, this.options.timeout * 1000);
    }

    request.on('response', function (response) {
        if (self.is_complete) {
            return cleanup();
        }

        response.setEncoding('utf8');

        var code = response.statusCode || 200;

        self.debug('\033[7m'+code+'\033[0m '+resource + ' (response ' + rid + ')');

        for (h in response.headers) {
            self.debug('  | ' + h[0].toUpperCase() + h.substr(1) + ': ' + response.headers[h]);
        }

        //Save the response headers for the next request (if to the same host)
        var cookies = response.headers['set-cookie'];
        self.last = {
            host: url.hostname,
            headers: {
                referer: resource,
                cookie: cookies instanceof Array ? cookies.join('; ') : cookies
            }
        };

        switch (Math.floor(code/100)) {
            case 4:
            case 5:
                callback(code);
                return;

            case 3:
                if (typeof response.headers.location === 'undefined') {
                    callback(code);
                } else {
                    self.debug('  \033[7m>\033[0m ' + response.headers.location);
                    self.doRequest(method, response.headers.location, body, headers, callback, parse, ++redirects);
                }
                return;
        }

        var body = '';
        response.on('data', function (chunk) {
            self.bytes_received += chunk.length;

            if (self.is_complete) {
                return cleanup();
            }

            body = body + chunk;
        });

        response.on('end', function () {
            if (self.is_complete) {
                return cleanup();
            }

            var parse_callback = function (err, data) {
                callback(null, data, response.headers, response);
            };

            if (!parse) {
                //If no parse function was specified, just return the body
                parse_callback(null, body);
            } else {
                //Call the parse function on the response body - handle async and sync cases
                var ret = parse(body, parse_callback);
                if (typeof ret !== 'undefined') {
                    parse_callback(null, ret);
                }
            }

            cleanup();
        });
    });

    if (request.end) {
        request.end();
    } else {
        request.close();
    }
};

/**
 * Sets a header on the next request.
 *
 * @param {Object|String} key
 * @param {String} value
 * @api public
 */
Job.prototype.setHeader = function (key, value) {
    if (typeof key === 'object') {
        utils.put(this.next, key);
    } else {
        this.next[key.toLowerCase()] = value;
    }
};

/**
 * Sets the Cookie for the next request.
 *
 * @param {String} cookie
 * @api public
 */
Job.prototype.setCookie = function (key, value) {
    if (value) {
        key = encodeURIComponent(key) + '=' + encodeURIComponent(value);
    }
    this.setHeader('cookie', key);
};

/**
 * Sets the User-Agent for the next request.
 *
 * @param {String} agent
 * @api public
 */
Job.prototype.setUserAgent = function (agent) {
    this.setHeader('user-agent', agent);
};

/**
 * Adds a cookie to the next request.
 *
 * @param {String} key
 * @param {String} value
 * @api public
 */
Job.prototype.addCookie = function (key, value) {
    key = encodeURIComponent(key);
    value = encodeURIComponent(value);
    if (typeof this.next.cookie !== 'undefined' && this.next.cookie.length) {
        this.next.cookie += '; ' + key + '=' + value;
    } else {
        this.next.cookie = key + '=' + value;
    }
};

/**
 * Returns the total bytes received by any doRequest() calls.
 *
 * @return {Number} bytes_received
 * @api public
 */
Job.prototype.getBytesReceived = function () {
    return this.bytes_received;
};

/**
 * Creates a new proxy with the specified (optional) callbacks. The callbacks
 * are used to synchronously modify the url, request headers, parse callback,
 * and response headers surrounding a doRequest().
 *
 * @param {Function} url_callback
 * @param {Function} req_header_callback
 * @param {Function} parse_callback
 * @param {Function} res_header_callback
 * @api public
 */
var Proxy = function (url_callback, req_header_callback, parse_callback, res_header_callback) {
    this.url_callback = url_callback;
    this.req_header_callback = req_header_callback;
    this.res_header_callback = res_header_callback;
    this.parse_callback = parse_callback;
};

/**
 * Proxifies the doRequest() method in the specified job instance.
 *
 * @param {Object} job
 * @return {Object} job
 * @api public
 */
Proxy.prototype.proxify = function (job) {
    var self = this, doRequest = job.doRequest;

    job.doRequest = function (method, resource, body, headers, callback, parse, redirects) {

        if (typeof headers === 'function') {
            parse = callback;
            callback = headers;
            headers = default_headers;
        }

        //Modify the request url
        if (self.url_callback) {
            resource = self.url_callback(resource);
        }

        //Modify request headers
        if (self.req_header_callback) {
            headers = self.req_header_callback(headers);
        }

        //Modify the response body
        if (self.parse_callback) {
            if (!parse) {
                parse = self.parse_callback;
            } else {
                //If a parse function is passed to fetch, chain it together with the proxy parse_callback
                var old_parse = parse;
                parse = function (err, data) {
                    var ret = self.parse_callback(data, old_parse);
                    if (typeof ret !== 'undefined') {
                        old_parse(null, ret);
                    }
                };
            }
        }

        //Modify response headers
        if (self.res_header_callback) {
            var old_callback = callback;
            callback = function (err, data, headers) {
                headers = self.res_header_callback(headers);
                return old_callback(err, data, headers);
            };
        }

        doRequest.apply(job, [method, resource, body, headers, callback, parse, redirects]);
    };

    return job;
};

/**
 * Creates a new proxy that routes requests through the specified host.
 *
 * Note: 100% UNTESTED - use at your own peril.
 *
 * @param {Function} host
 * @api public
 */
var HttpProxy = function (host) {
    var url_callback = function (url) {
        var u = urlparse(url);
        this.url_host = u.host;
        url = u.protocol + '//' + u.host + '/' + u.pathname;
        if (u.search) {
            url += u.search;
        }
        return u;
    };
    var header_callback = function (headers) {
        headers = headers || {};
        headers.host = this.url_host;
        return headers;
    };
    return new Proxy(url_callback, header_callback);
};

/**
 * Export proxies
 */
exports.HttpProxy = HttpProxy;
exports.Proxy = Proxy;
<|endoftext|>


<commit_before>var CursorType   = require('../constants/cursor');
var CommandCodes = require('../constants/commands');
var Types        = require('../constants/types');
var Packet       = require('../packets/packet');

function Execute(id, parameters)
{
  this.id = id;
  this.parameters = parameters;
}

Execute.prototype.toPacket = function()
{

  // TODO: don't try to calculate packet length in advance, allocate some big buffer in advance (header + 256 bytes?)
  // and copy + reallocate if not enough

  var i;
  // 0 + 4 - length, seqId
  // 4 + 1 - COM_EXECUTE
  // 5 + 4 - stmtId
  // 9 + 1 - flags
  // 10 + 4 - iteration-count (always 1)
  var length = 14;
  if (this.parameters && this.parameters.length > 0)
  {
    length += Math.floor((this.parameters.length + 7) / 8);
    length += 1; // new-params-bound-flag
    length += 2*this.parameters.length;  // type byte for each parameter if new-params-bound-flag is set
    for (i=0; i < this.parameters.length; i++)
    {
      if (this.parameters[i] !== null) {
        if (toString.call(this.parameters[i]) == '[object Date]') {
          var d = this.parameters[i];
          // TODO: move to asMysqlDateTime()
          this.parameters[i] = [d.getFullYear(), d.getMonth() + 1, d.getDate()].join('-') +
            ' ' + [d.getHours(), d.getMinutes(), d.getSeconds()].join(':');
        }
        if (Buffer.isBuffer(this.parameters[i])) {
          length += Packet.lengthCodedNumberLength(this.parameters[i].length);
          length += this.parameters[i].length;
        }
        else {
          var str = this.parameters[i].toString();
          var byteLen = Buffer.byteLength(str, 'utf8');
          length += Packet.lengthCodedNumberLength(byteLen);
          length += byteLen;
        }
      }
    }
  }

  var buffer = new Buffer(length);
  var packet = new Packet(0, buffer);
  packet.offset = 4;
  packet.writeInt8(CommandCodes.STMT_EXECUTE);
  packet.writeInt32(this.id);
  packet.writeInt8(CursorType.NO_CURSOR);  // flags
  packet.writeInt32(1); // iteration-count, always 1
  if (this.parameters && this.parameters.length > 0) {

    var bitmap = 0;
    var bitValue = 1;
    for (i=0; i < this.parameters.length; i++)
    {
      if (this.parameters[i] === null)
        bitmap += bitValue;
      bitValue *= 2;
      if (bitValue == 256) {
        packet.writeInt8(bitmap);
        bitmap = 0;
        bitValue = 1;
      }
    }
    if (bitValue != 1)
      packet.writeInt8(bitmap);

    // TODO: explain meaning of the flag
    // afaik, if set n*2 bytes with type of parameter are sent before parameters
    // if not, previous execution types are used (TODO prooflink)
    packet.writeInt8(1); // new-params-bound-flag

    // TODO: don't typecast always to sting, use parameters type
    for (i=0; i < this.parameters.length; i++)
    {
      if (this.parameters[i] !== null)
        packet.writeInt16(Types.VAR_STRING);
      else
        packet.writeInt16(Types.NULL);
    }
    for (i=0; i < this.parameters.length; i++)
    {
      if (this.parameters[i] !== null)
        if (Buffer.isBuffer(this.parameters[i]))
          packet.writeLengthCodedBuffer(this.parameters[i]);
        else
          packet.writeLengthCodedString(this.parameters[i].toString());
    }
  }
  return packet;
};

module.exports = Execute;
<commit_msg>Solve incompatibility with autoload<commit_after>var CursorType   = require('../constants/cursor');
var CommandCodes = require('../constants/commands');
var Types        = require('../constants/types');
var Packet       = require('../packets/packet');

function Execute(id, parameters)
{
  this.id = id;
  this.parameters = parameters;
}

Execute.prototype.toPacket = function()
{

  // TODO: don't try to calculate packet length in advance, allocate some big buffer in advance (header + 256 bytes?)
  // and copy + reallocate if not enough

  var i;
  // 0 + 4 - length, seqId
  // 4 + 1 - COM_EXECUTE
  // 5 + 4 - stmtId
  // 9 + 1 - flags
  // 10 + 4 - iteration-count (always 1)
  var length = 14;
  if (this.parameters && this.parameters.length > 0)
  {
    length += Math.floor((this.parameters.length + 7) / 8);
    length += 1; // new-params-bound-flag
    length += 2*this.parameters.length;  // type byte for each parameter if new-params-bound-flag is set
    for (i=0; i < this.parameters.length; i++)
    {
      if (this.parameters[i] !== null) {
        if (Object.prototype.toString.call(this.parameters[i]) == '[object Date]') {
          var d = this.parameters[i];
          // TODO: move to asMysqlDateTime()
          this.parameters[i] = [d.getFullYear(), d.getMonth() + 1, d.getDate()].join('-') +
            ' ' + [d.getHours(), d.getMinutes(), d.getSeconds()].join(':');
        }
        if (Buffer.isBuffer(this.parameters[i])) {
          length += Packet.lengthCodedNumberLength(this.parameters[i].length);
          length += this.parameters[i].length;
        }
        else {
          var str = this.parameters[i].toString();
          var byteLen = Buffer.byteLength(str, 'utf8');
          length += Packet.lengthCodedNumberLength(byteLen);
          length += byteLen;
        }
      }
    }
  }

  var buffer = new Buffer(length);
  var packet = new Packet(0, buffer);
  packet.offset = 4;
  packet.writeInt8(CommandCodes.STMT_EXECUTE);
  packet.writeInt32(this.id);
  packet.writeInt8(CursorType.NO_CURSOR);  // flags
  packet.writeInt32(1); // iteration-count, always 1
  if (this.parameters && this.parameters.length > 0) {

    var bitmap = 0;
    var bitValue = 1;
    for (i=0; i < this.parameters.length; i++)
    {
      if (this.parameters[i] === null)
        bitmap += bitValue;
      bitValue *= 2;
      if (bitValue == 256) {
        packet.writeInt8(bitmap);
        bitmap = 0;
        bitValue = 1;
      }
    }
    if (bitValue != 1)
      packet.writeInt8(bitmap);

    // TODO: explain meaning of the flag
    // afaik, if set n*2 bytes with type of parameter are sent before parameters
    // if not, previous execution types are used (TODO prooflink)
    packet.writeInt8(1); // new-params-bound-flag

    // TODO: don't typecast always to sting, use parameters type
    for (i=0; i < this.parameters.length; i++)
    {
      if (this.parameters[i] !== null)
        packet.writeInt16(Types.VAR_STRING);
      else
        packet.writeInt16(Types.NULL);
    }
    for (i=0; i < this.parameters.length; i++)
    {
      if (this.parameters[i] !== null)
        if (Buffer.isBuffer(this.parameters[i]))
          packet.writeLengthCodedBuffer(this.parameters[i]);
        else
          packet.writeLengthCodedString(this.parameters[i].toString());
    }
  }
  return packet;
};

module.exports = Execute;
<|endoftext|>


<commit_before>'use babel';
import YSPServer from './server/ysp_debug_server';
import YSPToolBar from './toolbar/ysp_toolbar';
import YSPMacSimulator from './mac_simulator';
import YSPSettingView from './toolbar/view/ysp_setting_view';
import ProjectConfig from './../project-config';

export default class Product {

    toolbar: null;
    simulator_tool: null;
    ysp_server: null;

    constructor(serializedState) {
        productSelf = this;

        //server 初始化&启动
        ysp_server = new YSPServer();
        ysp_server.run(function(port) {
            toolbar.setProjectInfo(require('./common').getLocalIp(), port);
        });
        ysp_server.setStatuBeat(function(stau, msg, clientarr) {
            toolbar.setShining(stau, msg, clientarr);
        });
        window.ysp_socket_server = ysp_server.getSocketServer();
        window.ysp_server = ysp_server;

        //模拟器 初始化
        simulator_tool = new YSPMacSimulator();
        simulator_tool.iPhoneSimulators((arr1, arr2) => {});

        //工具栏 初始化
        toolbar = new YSPToolBar();
        toolbar.show();
        toolbar.setCallback(function(action, data) {
            switch (action) {
                case "run":
                    handleRun(data);
                    break;
                case "setting":
                    new YSPSettingView().show();
                    break;
                default:

            }
        });
    }

    toggle() {
        toolbar.show();
    }

    run() {
        handleRun('iOS');
    }

    saveFile() {
        var b = ProjectConfig.quickDebug();
        if (b == true) {
            buildIOS(function() {
                window.ysp_socket_server.sendReload2Device("iOS");
            });
        }
    }

    stop() {
        // handleRun(true);
    }

    static staticBuild(callback) {
        buildIOS(callback);
    }
}

var runProgress = 0.99;
function funProgress() {
        runProgress = runProgress * 0.99;
        require('./common').emitter().emit('ysp_toolbar_setProgress', true, 'running', 1.0-runProgress);
}

function doProgress(success) {
    if (!success) {
        if (window.product_timer == null) {
            window.product_timer = window.setInterval(funProgress, 100);
        }
        require('./common').emitter().emit('ysp_toolbar_setProgress', true, 'running', 0);
    } else {
        require('./common').emitter().emit('ysp_toolbar_setProgress', true, 'running', 1);
        if (window.product_timer != null) {
            window.clearInterval(window.product_timer);
            window.product_timer = null;
        }
        require('./common').emitter().emit('ysp_toolbar_setProgress', false, 'running', 0);
    }
}

function handleRun(platform) {
    simulator_tool.stopIosApp();

    // if run Android
    if (ProjectConfig.isRunAndroid()) {
      console.log('android build start');
      doProgress(false);
      buildAndroid(function(err) {
          if (err == null) {
              console.log('android build success');
              window.ysp_socket_server.sendReload2Device("Android");
          } else {
              console.log('android build fail' + err);
          }
          doProgress(true);
      });
    }
    // if run iOS
    if (ProjectConfig.isRuniOS()) {
       require('./common').emitter().emit('ysp_toolbar_setProgress', true, 'running', 1);
      console.log('ios build start');
      buildIOS(function() {
         console.log('ios build success');
          window.ysp_socket_server.sendReload2Phone();
          simulator_tool.runIOS();
          require('./common').emitter().emit('ysp_toolbar_setProgress', false, 'running', 0);
      });
    }
}

function buildIOS(callback) {
    var path = require('path');
    var inputPath = path.normalize(require('./common').rootPath() + '/ios');
    var outputPath = path.normalize(require('./common').rootPath() + '/build/cache/ios');
    var zipInputPath = path.normalize(require('./common').rootPath() + '/build/cache');
    var zipOutputPath = path.normalize(require('./common').rootPath() + '/build/output/ios');
    try {
        require('ysp_ios_build').buildWithAtom(inputPath, outputPath);
        require('./common.js').createiOSZip(zipInputPath, zipOutputPath, function(zipPath) {
            callback();
        });
    } catch (e) {
        alert('buildIOS fail，info：' + e);
    } finally {}
}

function buildAndroid(callback) {
    try {
        require('./build/android_build').buildWithAtom(function() {
            callback();
        });
    } catch (e) {
        alert('buildAndroid fail，info：' + e);
    } finally {}
}
<commit_msg>进度条重置<commit_after>'use babel';
import YSPServer from './server/ysp_debug_server';
import YSPToolBar from './toolbar/ysp_toolbar';
import YSPMacSimulator from './mac_simulator';
import YSPSettingView from './toolbar/view/ysp_setting_view';
import ProjectConfig from './../project-config';

export default class Product {

    toolbar: null;
    simulator_tool: null;
    ysp_server: null;

    constructor(serializedState) {
        productSelf = this;

        //server 初始化&启动
        ysp_server = new YSPServer();
        ysp_server.run(function(port) {
            toolbar.setProjectInfo(require('./common').getLocalIp(), port);
        });
        ysp_server.setStatuBeat(function(stau, msg, clientarr) {
            toolbar.setShining(stau, msg, clientarr);
        });
        window.ysp_socket_server = ysp_server.getSocketServer();
        window.ysp_server = ysp_server;

        //模拟器 初始化
        simulator_tool = new YSPMacSimulator();
        simulator_tool.iPhoneSimulators((arr1, arr2) => {});

        //工具栏 初始化
        toolbar = new YSPToolBar();
        toolbar.show();
        toolbar.setCallback(function(action, data) {
            switch (action) {
                case "run":
                    handleRun(data);
                    break;
                case "setting":
                    new YSPSettingView().show();
                    break;
                default:

            }
        });
    }

    toggle() {
        toolbar.show();
    }

    run() {
        handleRun('iOS');
    }

    saveFile() {
        var b = ProjectConfig.quickDebug();
        if (b == true) {
            buildIOS(function() {
                window.ysp_socket_server.sendReload2Device("iOS");
            });
        }
    }

    stop() {
        // handleRun(true);
    }

    static staticBuild(callback) {
        buildIOS(callback);
    }
}

var runProgress = 0.99;
function funProgress() {
        runProgress = runProgress * 0.99;
        require('./common').emitter().emit('ysp_toolbar_setProgress', true, 'running', 1.0-runProgress);
}

function doProgress(success) {
    runProgress = 0.99;
    if (!success) {
        if (window.product_timer == null) {
            window.product_timer = window.setInterval(funProgress, 100);
        }
        require('./common').emitter().emit('ysp_toolbar_setProgress', true, 'running', 0);
    } else {
        require('./common').emitter().emit('ysp_toolbar_setProgress', true, 'running', 1);
        if (window.product_timer != null) {
            window.clearInterval(window.product_timer);
            window.product_timer = null;
        }
        require('./common').emitter().emit('ysp_toolbar_setProgress', false, 'running', 0);
    }
}

function handleRun(platform) {
    simulator_tool.stopIosApp();

    // if run Android
    if (ProjectConfig.isRunAndroid()) {
      console.log('android build start');
      doProgress(false);
      buildAndroid(function(err) {
          if (err == null) {
              console.log('android build success');
              window.ysp_socket_server.sendReload2Device("Android");
          } else {
              console.log('android build fail' + err);
          }
          doProgress(true);
      });
    }
    // if run iOS
    if (ProjectConfig.isRuniOS()) {
       require('./common').emitter().emit('ysp_toolbar_setProgress', true, 'running', 1);
      console.log('ios build start');
      buildIOS(function() {
         console.log('ios build success');
          window.ysp_socket_server.sendReload2Phone();
          simulator_tool.runIOS();
          require('./common').emitter().emit('ysp_toolbar_setProgress', false, 'running', 0);
      });
    }
}

function buildIOS(callback) {
    var path = require('path');
    var inputPath = path.normalize(require('./common').rootPath() + '/ios');
    var outputPath = path.normalize(require('./common').rootPath() + '/build/cache/ios');
    var zipInputPath = path.normalize(require('./common').rootPath() + '/build/cache');
    var zipOutputPath = path.normalize(require('./common').rootPath() + '/build/output/ios');
    try {
        require('ysp_ios_build').buildWithAtom(inputPath, outputPath);
        require('./common.js').createiOSZip(zipInputPath, zipOutputPath, function(zipPath) {
            callback();
        });
    } catch (e) {
        alert('buildIOS fail，info：' + e);
    } finally {}
}

function buildAndroid(callback) {
    try {
        require('./build/android_build').buildWithAtom(function() {
            callback();
        });
    } catch (e) {
        alert('buildAndroid fail，info：' + e);
    } finally {}
}
<|endoftext|>


<commit_before>var IEEE_754_BINARY_64_PRECISION = Math.pow(2, 53);
var MAX_PACKET_LENGTH            = Math.pow(2, 24) - 1;
var PacketHeader                 = require('./PacketHeader');

module.exports = Parser;
function Parser(options) {
  options = options || {};

  this._buffer            = null;
  this._longPacketBuffers = [];
  this._offset            = 0;
  this._packetEnd         = null;
  this._packetHeader      = null;
  this._packetParser      = options.packetParser || function() {};
  this._nextPacketNumber  = 0;
  this._encoding          = 'utf-8';
  this._paused            = false;
}

Parser.prototype.write = function(buffer) {
  this.append(buffer);

  while (true) {
    if (this._paused) {
      return;
    }

    if (!this._packetHeader) {
      if (this._bytesRemaining() < 4) {
        break;
      }

      this._packetHeader = new PacketHeader(
        this.parseUnsignedNumber(3),
        this.parseUnsignedNumber(1)
      );

      this._trackAndVerifyPacketNumber(this._packetHeader.number);
    }

    if (this._bytesRemaining() < this._packetHeader.length) {
      break;
    }

    this._packetEnd = this._offset + this._packetHeader.length;

    if (this._packetHeader.length === MAX_PACKET_LENGTH) {
      this._longPacketBuffers.push(this._buffer.slice(this._offset, this._packetEnd));
    } else {
      this._combineLongPacketBuffers();
      this._packetParser(this._packetHeader);
    }

    this._offset       = this._packetEnd;
    this._packetHeader = null;
    this._packetEnd    = null;
  }
};

Parser.prototype.append = function(newBuffer) {
  var oldBuffer = this._buffer;
  if (!oldBuffer) {
    this._buffer = newBuffer;
    return;
  }

  var bytesRemaining = this._bytesRemaining();
  var newLength = bytesRemaining + newBuffer.length;

  var combinedBuffer = (this._offset > newLength)
    ? oldBuffer.slice(0, newLength)
    : new Buffer(newLength);

  oldBuffer.copy(combinedBuffer, 0, this._offset);
  newBuffer.copy(combinedBuffer, bytesRemaining);

  this._buffer = combinedBuffer;
  this._offset = 0;
};

Parser.prototype.pause = function() {
  this._paused = true;
};

Parser.prototype.resume = function() {
  this._paused = false;
  // A little hacky, but does the trick of resuming the parser
  this.write(new Buffer(0));
};

Parser.prototype.peak = function() {
  return this._buffer[this._offset];
};

Parser.prototype.parseUnsignedNumber = function(bytes) {
  var bytesRead = 0;
  var value     = 0;

  while (bytesRead < bytes) {
    var byte = this._buffer[this._offset++];

    value += byte * Math.pow(256, bytesRead);

    bytesRead++;
  }

  return value;
};

Parser.prototype.parseLengthCodedString = function() {
  var length = this.parseLengthCodedNumber();

  if (length === null) {
    return null;
  }

  return this.parseString(length);
};

Parser.prototype.parseLengthCodedBuffer = function() {
  var length = this.parseLengthCodedNumber();

  if (length === null) {
    return null;
  }

  return this.parseBuffer(length);
};

Parser.prototype.parseLengthCodedNumber = function() {
  var byte = this._buffer[this._offset++];

  if (byte <= 251) {
    return (byte === 251)
      ? null
      : byte;
  }

  var length;
  if (byte === 252) {
    length = 2;
  } else if (byte === 253) {
    length = 3;
  } else if (byte === 254) {
    length = 8;
  } else {
    throw new Error('parseLengthCodedNumber: Unexpected first byte: ' + byte);
  }

  var value = 0;
  for (var bytesRead = 0; bytesRead < length; bytesRead++) {
    var byte = this._buffer[this._offset++];
    value += Math.pow(256, bytesRead) * byte;
  }

  if (value >= IEEE_754_BINARY_64_PRECISION) {
    throw new Error(
      'parseLengthCodedNumber: JS precision range exceeded, ' +
      'number is >= 53 bit: "' + value + '"'
    );
  }

  return value;
};

Parser.prototype.parseFiller = function(length) {
  return this.parseBuffer(length);
};

Parser.prototype.parseNullTerminatedBuffer = function() {
  var end      = this._nullByteOffset();
  var value    = this._buffer.slice(this._offset, end);
  this._offset = end + 1;

  return value;
};

Parser.prototype.parseNullTerminatedString = function() {
  var end      = this._nullByteOffset();
  var value    = this._buffer.toString(this._encoding, this._offset, end)
  this._offset = end + 1;

  return value;
};

Parser.prototype._nullByteOffset = function() {
  var offset = this._offset;

  while (this._buffer[offset] !== 0x00) {
    offset++;

    if (offset >= this._buffer.length) {
      throw new Error('Offset of null terminated string not found.');
    }
  }

  return offset;
};

Parser.prototype.parsePacketTerminatedString = function() {
  var length = this._packetEnd - this._offset;
  return this.parseString(length);
};

Parser.prototype.parseBuffer = function(length) {
  var buffer = this._buffer.slice(this._offset, this._offset + length);

  this._offset += length;
  return buffer;
};

Parser.prototype.parseString = function(length) {
  var offset = this._offset;
  var end = offset + length;
  var value = this._buffer.toString(this._encoding, offset, end);

  this._offset = end;
  return value;
};

Parser.prototype.reachedPacketEnd = function() {
  return this._offset === this._packetEnd;
};

Parser.prototype._bytesRemaining = function() {
  return this._buffer.length - this._offset;
};

Parser.prototype._trackAndVerifyPacketNumber = function(number) {
  if (number !== this._nextPacketNumber) {
    var err = new Error(
      'Packets out of order. Got: ' + number + ' ' +
      'Expected: ' + this._nextPacketNumber
    );

    err.code = 'PROTOCOL_PACKETS_OUT_OF_ORDER';

    throw err;
  }

  this.incrementPacketNumber();
};

Parser.prototype.incrementPacketNumber = function() {
  var currentPacketNumber = this._nextPacketNumber;
  this._nextPacketNumber = (this._nextPacketNumber + 1) % 256;

  return currentPacketNumber;
};

Parser.prototype.resetPacketNumber = function() {
  this._nextPacketNumber = 0;
};

Parser.prototype.packetLength = function() {
  return this._longPacketBuffers.reduce(function(length, buffer) {
    return length + buffer.length;
  }, this._packetHeader.length);
};

Parser.prototype._combineLongPacketBuffers = function() {
  if (!this._longPacketBuffers.length) {
    return;
  }

  var trailingPacketBytes = this._buffer.length - this._packetEnd;

  var length = this._longPacketBuffers.reduce(function(length, buffer) {
    return length + buffer.length;
  }, this._bytesRemaining());

  var combinedBuffer = new Buffer(length);

  var offset = this._longPacketBuffers.reduce(function(offset, buffer) {
    buffer.copy(combinedBuffer, offset);
    return offset + buffer.length;
  }, 0);

  this._buffer.copy(combinedBuffer, offset, this._offset);

  this._buffer            = combinedBuffer;
  this._longPacketBuffers = [];
  this._offset            = 0;
  this._packetEnd         = this._buffer.length - trailingPacketBytes;
};
<commit_msg>Fix some OOB errors on resume()<commit_after>var IEEE_754_BINARY_64_PRECISION = Math.pow(2, 53);
var MAX_PACKET_LENGTH            = Math.pow(2, 24) - 1;
var PacketHeader                 = require('./PacketHeader');

module.exports = Parser;
function Parser(options) {
  options = options || {};

  this._buffer            = null;
  this._longPacketBuffers = [];
  this._offset            = 0;
  this._packetEnd         = null;
  this._packetHeader      = null;
  this._packetParser      = options.packetParser || function() {};
  this._nextPacketNumber  = 0;
  this._encoding          = 'utf-8';
  this._paused            = false;
}

Parser.prototype.write = function(buffer) {
  this.append(buffer);

  while (true) {
    if (this._paused) {
      return;
    }

    if (!this._packetHeader) {
      if (this._bytesRemaining() < 4) {
        break;
      }

      this._packetHeader = new PacketHeader(
        this.parseUnsignedNumber(3),
        this.parseUnsignedNumber(1)
      );

      this._trackAndVerifyPacketNumber(this._packetHeader.number);
    }

    if (this._bytesRemaining() < this._packetHeader.length) {
      break;
    }

    this._packetEnd = this._offset + this._packetHeader.length;

    if (this._packetHeader.length === MAX_PACKET_LENGTH) {
      this._longPacketBuffers.push(this._buffer.slice(this._offset, this._packetEnd));
    } else {
      this._combineLongPacketBuffers();
      this._packetParser(this._packetHeader);
    }

    this._offset       = this._packetEnd;
    this._packetHeader = null;
    this._packetEnd    = null;
  }
};

Parser.prototype.append = function(newBuffer) {
  // If resume() is called, we don't pass a buffer to write()
  if (!newBuffer) {
    return;
  }

  var oldBuffer = this._buffer;
  if (!oldBuffer) {
    this._buffer = newBuffer;
    return;
  }

  var bytesRemaining = this._bytesRemaining();
  var newLength = bytesRemaining + newBuffer.length;

  var combinedBuffer = (this._offset > newLength)
    ? oldBuffer.slice(0, newLength)
    : new Buffer(newLength);

  oldBuffer.copy(combinedBuffer, 0, this._offset);
  newBuffer.copy(combinedBuffer, bytesRemaining);

  this._buffer = combinedBuffer;
  this._offset = 0;
};

Parser.prototype.pause = function() {
  this._paused = true;
};

Parser.prototype.resume = function() {
  this._paused = false;
  this.write();
};

Parser.prototype.peak = function() {
  return this._buffer[this._offset];
};

Parser.prototype.parseUnsignedNumber = function(bytes) {
  var bytesRead = 0;
  var value     = 0;

  while (bytesRead < bytes) {
    var byte = this._buffer[this._offset++];

    value += byte * Math.pow(256, bytesRead);

    bytesRead++;
  }

  return value;
};

Parser.prototype.parseLengthCodedString = function() {
  var length = this.parseLengthCodedNumber();

  if (length === null) {
    return null;
  }

  return this.parseString(length);
};

Parser.prototype.parseLengthCodedBuffer = function() {
  var length = this.parseLengthCodedNumber();

  if (length === null) {
    return null;
  }

  return this.parseBuffer(length);
};

Parser.prototype.parseLengthCodedNumber = function() {
  var byte = this._buffer[this._offset++];

  if (byte <= 251) {
    return (byte === 251)
      ? null
      : byte;
  }

  var length;
  if (byte === 252) {
    length = 2;
  } else if (byte === 253) {
    length = 3;
  } else if (byte === 254) {
    length = 8;
  } else {
    throw new Error('parseLengthCodedNumber: Unexpected first byte: ' + byte);
  }

  var value = 0;
  for (var bytesRead = 0; bytesRead < length; bytesRead++) {
    var byte = this._buffer[this._offset++];
    value += Math.pow(256, bytesRead) * byte;
  }

  if (value >= IEEE_754_BINARY_64_PRECISION) {
    throw new Error(
      'parseLengthCodedNumber: JS precision range exceeded, ' +
      'number is >= 53 bit: "' + value + '"'
    );
  }

  return value;
};

Parser.prototype.parseFiller = function(length) {
  return this.parseBuffer(length);
};

Parser.prototype.parseNullTerminatedBuffer = function() {
  var end      = this._nullByteOffset();
  var value    = this._buffer.slice(this._offset, end);
  this._offset = end + 1;

  return value;
};

Parser.prototype.parseNullTerminatedString = function() {
  var end      = this._nullByteOffset();
  var value    = this._buffer.toString(this._encoding, this._offset, end)
  this._offset = end + 1;

  return value;
};

Parser.prototype._nullByteOffset = function() {
  var offset = this._offset;

  while (this._buffer[offset] !== 0x00) {
    offset++;

    if (offset >= this._buffer.length) {
      throw new Error('Offset of null terminated string not found.');
    }
  }

  return offset;
};

Parser.prototype.parsePacketTerminatedString = function() {
  var length = this._packetEnd - this._offset;
  return this.parseString(length);
};

Parser.prototype.parseBuffer = function(length) {
  var buffer = this._buffer.slice(this._offset, this._offset + length);

  this._offset += length;
  return buffer;
};

Parser.prototype.parseString = function(length) {
  var offset = this._offset;
  var end = offset + length;
  var value = this._buffer.toString(this._encoding, offset, end);

  this._offset = end;
  return value;
};

Parser.prototype.reachedPacketEnd = function() {
  return this._offset === this._packetEnd;
};

Parser.prototype._bytesRemaining = function() {
  return this._buffer.length - this._offset;
};

Parser.prototype._trackAndVerifyPacketNumber = function(number) {
  if (number !== this._nextPacketNumber) {
    var err = new Error(
      'Packets out of order. Got: ' + number + ' ' +
      'Expected: ' + this._nextPacketNumber
    );

    err.code = 'PROTOCOL_PACKETS_OUT_OF_ORDER';

    throw err;
  }

  this.incrementPacketNumber();
};

Parser.prototype.incrementPacketNumber = function() {
  var currentPacketNumber = this._nextPacketNumber;
  this._nextPacketNumber = (this._nextPacketNumber + 1) % 256;

  return currentPacketNumber;
};

Parser.prototype.resetPacketNumber = function() {
  this._nextPacketNumber = 0;
};

Parser.prototype.packetLength = function() {
  return this._longPacketBuffers.reduce(function(length, buffer) {
    return length + buffer.length;
  }, this._packetHeader.length);
};

Parser.prototype._combineLongPacketBuffers = function() {
  if (!this._longPacketBuffers.length) {
    return;
  }

  var trailingPacketBytes = this._buffer.length - this._packetEnd;

  var length = this._longPacketBuffers.reduce(function(length, buffer) {
    return length + buffer.length;
  }, this._bytesRemaining());

  var combinedBuffer = new Buffer(length);

  var offset = this._longPacketBuffers.reduce(function(offset, buffer) {
    buffer.copy(combinedBuffer, offset);
    return offset + buffer.length;
  }, 0);

  this._buffer.copy(combinedBuffer, offset, this._offset);

  this._buffer            = combinedBuffer;
  this._longPacketBuffers = [];
  this._offset            = 0;
  this._packetEnd         = this._buffer.length - trailingPacketBytes;
};
<|endoftext|>


<commit_before>// Copyright 2014, Renasar Technologies Inc.
/* jshint: node:true */

'use strict';

var di = require('di');

module.exports = eventsProtocolFactory;

di.annotate(eventsProtocolFactory, new di.Provide('Protocol.Events'));
di.annotate(eventsProtocolFactory,
    new di.Inject(
        'Constants',
        'Services.Messenger',
        'Assert'
    )
);

function eventsProtocolFactory (Constants, messenger, assert) {
    function EventsProtocol () {
    }

    EventsProtocol.prototype.publishTftpSuccess = function (nodeId, data) {
        assert.string(nodeId);
        assert.object(data);

        return messenger.publish(
            Constants.Protocol.Exchanges.Events.Name,
            'tftp.success' + '.' + nodeId,
            data
        );
    };

    EventsProtocol.prototype.publishTftpFailure = function (nodeId, data) {
        assert.string(nodeId);
        assert.object(data);

        return messenger.publish(
            Constants.Protocol.Exchanges.Events.Name,
            'tftp.failure' + '.' + nodeId,
            data
        );
    };

    EventsProtocol.prototype.publishHttpResponse = function (nodeId, data) {
        assert.string(nodeId);
        assert.object(data);

        return messenger.publish(
            Constants.Protocol.Exchanges.Events.Name,
            'http.response' + '.' + nodeId,
            data
        );
    };

    EventsProtocol.prototype.subscribeTftpSuccess = function (nodeId, callback) {
        assert.isMongoId(nodeId);
        assert.func(callback);

        return messenger.subscribe(
            Constants.Protocol.Exchanges.Events.Name,
            'tftp.success' + '.' + nodeId,
            callback
        );
    };

    EventsProtocol.prototype.subscribeHttpResponse = function (nodeId, callback) {
        assert.isMongoId(nodeId);
        assert.func(callback);

        return messenger.subscribe(
            Constants.Protocol.Exchanges.Events.Name,
            'http.response' + '.' + nodeId,
            callback
        );
    };

    EventsProtocol.prototype.publishDhcpBoundLease = function (nodeId, data) {
        assert.string(nodeId);
        assert.object(data);

        return messenger.publish(
            Constants.Protocol.Exchanges.Events.Name,
            'dhcp.bind.success' + '.' + nodeId,
            data
        );
    };

    EventsProtocol.prototype.subscribeDhcpBoundLease = function (nodeId, callback) {
        assert.isMongoId(nodeId);
        assert.func(callback);

        return messenger.subscribe(
            Constants.Protocol.Exchanges.Events.Name,
            'dhcp.bind.success' + '.' + nodeId,
            callback
        );
    };

    EventsProtocol.prototype.publishTaskFinished = function (taskId, data) {
        assert.uuid(taskId);

        return messenger.publish(
            Constants.Protocol.Exchanges.Events.Name,
            'task.finished' + '.' + taskId,
            data || {}
        );
    };

    EventsProtocol.prototype.subscribeTaskFinished = function (taskId, callback) {
        assert.uuid(taskId);
        assert.func(callback);

        return messenger.subscribe(
            Constants.Protocol.Exchanges.Events.Name,
            'task.finished' + '.' + taskId,
            callback
        );
    };

    return new EventsProtocol();
}
<commit_msg>Add graph finished events to events protocol<commit_after>// Copyright 2014, Renasar Technologies Inc.
/* jshint: node:true */

'use strict';

var di = require('di');

module.exports = eventsProtocolFactory;

di.annotate(eventsProtocolFactory, new di.Provide('Protocol.Events'));
di.annotate(eventsProtocolFactory,
    new di.Inject(
        'Constants',
        'Services.Messenger',
        'Assert'
    )
);

function eventsProtocolFactory (Constants, messenger, assert) {
    function EventsProtocol () {
    }

    EventsProtocol.prototype.publishTftpSuccess = function (nodeId, data) {
        assert.string(nodeId);
        assert.object(data);

        return messenger.publish(
            Constants.Protocol.Exchanges.Events.Name,
            'tftp.success' + '.' + nodeId,
            data
        );
    };

    EventsProtocol.prototype.publishTftpFailure = function (nodeId, data) {
        assert.string(nodeId);
        assert.object(data);

        return messenger.publish(
            Constants.Protocol.Exchanges.Events.Name,
            'tftp.failure' + '.' + nodeId,
            data
        );
    };

    EventsProtocol.prototype.publishHttpResponse = function (nodeId, data) {
        assert.string(nodeId);
        assert.object(data);

        return messenger.publish(
            Constants.Protocol.Exchanges.Events.Name,
            'http.response' + '.' + nodeId,
            data
        );
    };

    EventsProtocol.prototype.subscribeTftpSuccess = function (nodeId, callback) {
        assert.isMongoId(nodeId);
        assert.func(callback);

        return messenger.subscribe(
            Constants.Protocol.Exchanges.Events.Name,
            'tftp.success' + '.' + nodeId,
            callback
        );
    };

    EventsProtocol.prototype.subscribeHttpResponse = function (nodeId, callback) {
        assert.isMongoId(nodeId);
        assert.func(callback);

        return messenger.subscribe(
            Constants.Protocol.Exchanges.Events.Name,
            'http.response' + '.' + nodeId,
            callback
        );
    };

    EventsProtocol.prototype.publishDhcpBoundLease = function (nodeId, data) {
        assert.string(nodeId);
        assert.object(data);

        return messenger.publish(
            Constants.Protocol.Exchanges.Events.Name,
            'dhcp.bind.success' + '.' + nodeId,
            data
        );
    };

    EventsProtocol.prototype.subscribeDhcpBoundLease = function (nodeId, callback) {
        assert.isMongoId(nodeId);
        assert.func(callback);

        return messenger.subscribe(
            Constants.Protocol.Exchanges.Events.Name,
            'dhcp.bind.success' + '.' + nodeId,
            callback
        );
    };

    EventsProtocol.prototype.publishTaskFinished = function (taskId, data) {
        assert.uuid(taskId);

        return messenger.publish(
            Constants.Protocol.Exchanges.Events.Name,
            'task.finished' + '.' + taskId,
            data || {}
        );
    };

    EventsProtocol.prototype.subscribeTaskFinished = function (taskId, callback) {
        assert.uuid(taskId);
        assert.func(callback);

        return messenger.subscribe(
            Constants.Protocol.Exchanges.Events.Name,
            'task.finished' + '.' + taskId,
            callback
        );
    };

    EventsProtocol.prototype.publishGraphFinished = function (graphid, status) {
        assert.uuid(graphid);
        assert.string(status);

        return messenger.publish(
            Constants.Protocol.Exchanges.Events.Name,
            'graph.finished' + '.' + graphid,
            { status: status }
        );
    };

    EventsProtocol.prototype.subscribeGraphFinished = function (graphid, callback) {
        assert.uuid(graphid);
        assert.func(callback);

        return messenger.subscribe(
            Constants.Protocol.Exchanges.Events.Name,
            'graph.finished' + '.' + graphid,
            function(data) {
                callback(data.data.status);
            }
        );
    };

    return new EventsProtocol();
}
<|endoftext|>


<commit_before>/*!
 * policy.js - bitcoin constants for bcoin
 * Copyright (c) 2014-2015, Fedor Indutny (MIT License)
 * Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
 * https://github.com/bcoin-org/bcoin
 */

'use strict';

/**
 * @module protocol/policy
 */

var consensus = require('./consensus');

/**
 * Maximum transaction version (policy).
 * @const {Number}
 * @default
 */

exports.MAX_TX_VERSION = 2;

/**
 * Maximum transaction base size (policy).
 * @const {Number}
 * @default
 */

exports.MAX_TX_SIZE = consensus.MAX_BLOCK_SIZE / 10;

/**
 * Maximum transaction weight (policy).
 * @const {Number}
 * @default
 */

exports.MAX_TX_WEIGHT = consensus.MAX_BLOCK_WEIGHT / 10;

/**
 * Maximum number of transaction sigops (policy).
 * @const {Number}
 * @default
 */

exports.MAX_TX_SIGOPS = consensus.MAX_BLOCK_SIGOPS / 5;

/**
 * Maximum cost of transaction sigops (policy).
 * @const {Number}
 * @default
 */

exports.MAX_TX_SIGOPS_COST = consensus.MAX_BLOCK_SIGOPS_COST / 5;

/**
 * How much weight a sigop should
 * add to virtual size (policy).
 * @const {Number}
 * @default
 */

exports.BYTES_PER_SIGOP = 20;

/**
 * Minimum relay fee rate (policy).
 * @const {Rate}
 */

exports.MIN_RELAY = 1000;

/**
 * Whether bare multisig outputs
 * should be relayed (policy).
 * @const {Boolean}
 * @default
 */

exports.BARE_MULTISIG = true;

/**
 * Priority threshold for
 * free transactions (policy).
 * @const {Number}
 * @default
 */

exports.FREE_THRESHOLD = consensus.COIN * 144 / 250;

/**
 * Max sigops per redeem script (policy).
 * @const {Number}
 * @default
 */

exports.MAX_P2SH_SIGOPS = 15;

/**
 * Max serialized nulldata size (policy).
 * @const {Number}
 * @default
 */

exports.MAX_OP_RETURN_BYTES = 83;

/**
 * Max pushdata size in nulldata (policy).
 * @const {Number}
 * @default
 */

exports.MAX_OP_RETURN = 80;

/**
 * Max p2wsh stack size. Used for
 * witness malleation checks (policy).
 * @const {Number}
 * @default
 */

exports.MAX_P2WSH_STACK = 100;

/**
 * Max p2wsh push size. Used for
 * witness malleation checks (policy).
 * @const {Number}
 * @default
 */

exports.MAX_P2WSH_PUSH = 80;

/**
 * Max serialized p2wsh size. Used for
 * witness malleation checks (policy).
 * @const {Number}
 * @default
 */

exports.MAX_P2WSH_SIZE = 3600;

/**
 * Default ancestor limit.
 * @const {Number}
 * @default
 */

exports.MEMPOOL_MAX_ANCESTORS = 25;

/**
 * Default maximum mempool size in bytes.
 * @const {Number}
 * @default
 */

exports.MEMPOOL_MAX_SIZE = 100 * 1000000;

/**
 * Time at which transactions
 * fall out of the mempool.
 * @const {Number}
 * @default
 */

exports.MEMPOOL_EXPIRY_TIME = 72 * 60 * 60;

/**
 * Maximum number of orphan transactions.
 * @const {Number}
 * @default
 */

exports.MEMPOOL_MAX_ORPHANS = 100;

/**
 * Minimum block size to create. Block will be
 * filled with free transactions until block
 * reaches this weight.
 * @const {Number}
 * @default
 */

exports.MIN_BLOCK_WEIGHT = 0;

/**
 * Maximum block weight to be mined.
 * @const {Number}
 * @default
 */

exports.MAX_BLOCK_WEIGHT = 1000000 * consensus.WITNESS_SCALE_FACTOR;

/**
 * How much of the block should be dedicated to
 * high-priority transactions (included regardless
 * of fee rate).
 * @const {Number}
 * @default
 */

exports.BLOCK_PRIORITY_WEIGHT = 0;

/**
 * Priority threshold to be reached before
 * switching to fee rate comparison.
 * @const {Number}
 * @default
 */

exports.BLOCK_PRIORITY_THRESHOLD = exports.FREE_THRESHOLD;

/**
 * Calculate minimum fee based on rate and size.
 * @param {Number?} size
 * @param {Rate?} rate - Rate of satoshi per kB.
 * @returns {Amount} fee
 */

exports.getMinFee = function getMinFee(size, rate) {
  var fee;

  if (rate == null)
    rate = exports.MIN_RELAY;

  fee = Math.floor(rate * size / 1000);

  if (fee === 0 && rate > 0)
    fee = rate;

  return fee;
};

/**
 * Calculate the minimum fee in order for the transaction
 * to be relayable, but _round to the nearest kilobyte
 * when taking into account size.
 * @param {Number?} size
 * @param {Rate?} rate - Rate of satoshi per kB.
 * @returns {Amount} fee
 */

exports.getRoundFee = function getRoundFee(size, rate) {
  var fee;

  if (rate == null)
    rate = exports.MIN_RELAY;

  fee = rate * Math.ceil(size / 1000);

  if (fee === 0 && rate > 0)
    fee = rate;

  return fee;
};

/**
 * Calculate a fee rate based on size and fees.
 * @param {Number} size
 * @param {Amount} fee
 * @returns {Rate}
 */

exports.getRate = function getRate(size, fee) {
  return Math.floor(fee * 1000 / size);
};
<commit_msg>policy: add some safety measures<commit_after>/*!
 * policy.js - bitcoin constants for bcoin
 * Copyright (c) 2014-2015, Fedor Indutny (MIT License)
 * Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
 * https://github.com/bcoin-org/bcoin
 */

'use strict';

/**
 * @module protocol/policy
 */

var assert = require('assert');
var consensus = require('./consensus');

/**
 * Maximum transaction version (policy).
 * @const {Number}
 * @default
 */

exports.MAX_TX_VERSION = 2;

/**
 * Maximum transaction base size (policy).
 * @const {Number}
 * @default
 */

exports.MAX_TX_SIZE = consensus.MAX_BLOCK_SIZE / 10;

/**
 * Maximum transaction weight (policy).
 * @const {Number}
 * @default
 */

exports.MAX_TX_WEIGHT = consensus.MAX_BLOCK_WEIGHT / 10;

/**
 * Maximum number of transaction sigops (policy).
 * @const {Number}
 * @default
 */

exports.MAX_TX_SIGOPS = consensus.MAX_BLOCK_SIGOPS / 5;

/**
 * Maximum cost of transaction sigops (policy).
 * @const {Number}
 * @default
 */

exports.MAX_TX_SIGOPS_COST = consensus.MAX_BLOCK_SIGOPS_COST / 5;

/**
 * How much weight a sigop should
 * add to virtual size (policy).
 * @const {Number}
 * @default
 */

exports.BYTES_PER_SIGOP = 20;

/**
 * Minimum relay fee rate (policy).
 * @const {Rate}
 */

exports.MIN_RELAY = 1000;

/**
 * Whether bare multisig outputs
 * should be relayed (policy).
 * @const {Boolean}
 * @default
 */

exports.BARE_MULTISIG = true;

/**
 * Priority threshold for
 * free transactions (policy).
 * @const {Number}
 * @default
 */

exports.FREE_THRESHOLD = consensus.COIN * 144 / 250;

/**
 * Max sigops per redeem script (policy).
 * @const {Number}
 * @default
 */

exports.MAX_P2SH_SIGOPS = 15;

/**
 * Max serialized nulldata size (policy).
 * @const {Number}
 * @default
 */

exports.MAX_OP_RETURN_BYTES = 83;

/**
 * Max pushdata size in nulldata (policy).
 * @const {Number}
 * @default
 */

exports.MAX_OP_RETURN = 80;

/**
 * Max p2wsh stack size. Used for
 * witness malleation checks (policy).
 * @const {Number}
 * @default
 */

exports.MAX_P2WSH_STACK = 100;

/**
 * Max p2wsh push size. Used for
 * witness malleation checks (policy).
 * @const {Number}
 * @default
 */

exports.MAX_P2WSH_PUSH = 80;

/**
 * Max serialized p2wsh size. Used for
 * witness malleation checks (policy).
 * @const {Number}
 * @default
 */

exports.MAX_P2WSH_SIZE = 3600;

/**
 * Default ancestor limit.
 * @const {Number}
 * @default
 */

exports.MEMPOOL_MAX_ANCESTORS = 25;

/**
 * Default maximum mempool size in bytes.
 * @const {Number}
 * @default
 */

exports.MEMPOOL_MAX_SIZE = 100 * 1000000;

/**
 * Time at which transactions
 * fall out of the mempool.
 * @const {Number}
 * @default
 */

exports.MEMPOOL_EXPIRY_TIME = 72 * 60 * 60;

/**
 * Maximum number of orphan transactions.
 * @const {Number}
 * @default
 */

exports.MEMPOOL_MAX_ORPHANS = 100;

/**
 * Minimum block size to create. Block will be
 * filled with free transactions until block
 * reaches this weight.
 * @const {Number}
 * @default
 */

exports.MIN_BLOCK_WEIGHT = 0;

/**
 * Maximum block weight to be mined.
 * @const {Number}
 * @default
 */

exports.MAX_BLOCK_WEIGHT = 1000000 * consensus.WITNESS_SCALE_FACTOR;

/**
 * How much of the block should be dedicated to
 * high-priority transactions (included regardless
 * of fee rate).
 * @const {Number}
 * @default
 */

exports.BLOCK_PRIORITY_WEIGHT = 0;

/**
 * Priority threshold to be reached before
 * switching to fee rate comparison.
 * @const {Number}
 * @default
 */

exports.BLOCK_PRIORITY_THRESHOLD = exports.FREE_THRESHOLD;

/**
 * Calculate minimum fee based on rate and size.
 * @param {Number?} size
 * @param {Rate?} rate - Rate of satoshi per kB.
 * @returns {Amount} fee
 */

exports.getMinFee = function getMinFee(size, rate) {
  var fee;

  if (rate == null)
    rate = exports.MIN_RELAY;

  assert(size >= 0);
  assert(rate >= 0);

  if (size === 0)
    return 0;

  fee = Math.floor(rate * size / 1000);

  if (fee === 0 && rate > 0)
    fee = rate;

  return fee;
};

/**
 * Calculate the minimum fee in order for the transaction
 * to be relayable, but _round to the nearest kilobyte
 * when taking into account size.
 * @param {Number?} size
 * @param {Rate?} rate - Rate of satoshi per kB.
 * @returns {Amount} fee
 */

exports.getRoundFee = function getRoundFee(size, rate) {
  var fee;

  if (rate == null)
    rate = exports.MIN_RELAY;

  assert(size >= 0);
  assert(rate >= 0);

  if (size === 0)
    return 0;

  fee = rate * Math.ceil(size / 1000);

  if (fee === 0 && rate > 0)
    fee = rate;

  return fee;
};

/**
 * Calculate a fee rate based on size and fees.
 * @param {Number} size
 * @param {Amount} fee
 * @returns {Rate}
 */

exports.getRate = function getRate(size, fee) {
  assert(size >= 0);
  assert(fee >= 0);

  if (size === 0)
    return 0;

  return Math.floor(fee * 1000 / size);
};
<|endoftext|>


<commit_before>'use strict';

exports = module.exports = function (options) {

    options = options || {};
    const auth0BaseUrl = `https://${options.domain}`;
    return {
        protocol: 'oauth2',
        useParamsAuth: true,
        auth: `${auth0BaseUrl}/authorize`,
        token: `${auth0BaseUrl}/oauth/token`,
        profile: function (credentials, params, get, callback) {

            get(`${auth0BaseUrl}/userinfo`, null, (profile) => {
                // https://auth0.com/docs/user-profile/normalized
                credentials.profile = {
                    id: profile.user_id,
                    email: profile.email,
                    displayName: profile.name,
                    name: {
                        first: profile.given_name,
                        last: profile.family_name
                    },
                    raw: profile
                };
                callback();
            });
        }
    };
};
<commit_msg>Validate Auth0 domain parameter<commit_after>'use strict';

const Joi = require('joi');
const Hoek = require('hoek');

exports = module.exports = function (options) {

    const validated = Joi.validate(options, Joi.object({
        domain: Joi.string().hostname().required()
    }));
    Hoek.assert(!validated.error, validated.error);
    const settings = validated.value;
    const auth0BaseUrl = `https://${settings.domain}`;
    return {
        protocol: 'oauth2',
        useParamsAuth: true,
        auth: `${auth0BaseUrl}/authorize`,
        token: `${auth0BaseUrl}/oauth/token`,
        profile: function (credentials, params, get, callback) {

            get(`${auth0BaseUrl}/userinfo`, null, (profile) => {
                // https://auth0.com/docs/user-profile/normalized
                credentials.profile = {
                    id: profile.user_id,
                    email: profile.email,
                    displayName: profile.name,
                    name: {
                        first: profile.given_name,
                        last: profile.family_name
                    },
                    raw: profile
                };
                callback();
            });
        }
    };
};
<|endoftext|>


<commit_before>var Utils     = require('./utils')
  , DataTypes = require('./data-types')

module.exports = (function() {
  var QueryInterface = function(sequelize) {
    this.sequelize = sequelize
    this.QueryGenerator = require('./dialects/' + this.sequelize.options.dialect + '/query-generator')
  }
  Utils.addEventEmitter(QueryInterface)

  QueryInterface.prototype.createTable = function(tableName, attributes, options) {
    var attributeHashes = {}

    Utils._.each(attributes, function(dataTypeOrOptions, attributeName) {
      if(Utils._.values(DataTypes).indexOf(dataTypeOrOptions) > -1)
        attributeHashes[attributeName] = { type: dataTypeOrOptions }
      else
        attributeHashes[attributeName] = dataTypeOrOptions
    })

    attributes = this.QueryGenerator.attributesToSQL(attributeHashes)

    var sql = this.QueryGenerator.createTableQuery(tableName, attributes, options)
    return queryAndEmit.call(this, sql, 'createTable')
  }

  QueryInterface.prototype.dropTable = function(tableName) {
    var sql = this.QueryGenerator.dropTableQuery(tableName)
    return queryAndEmit.call(this, sql, 'dropTable')
  }

  QueryInterface.prototype.dropAllTables = function() {
    var self = this

    return new Utils.CustomEventEmitter(function(emitter) {
      var chainer = new Utils.QueryChainer()

      self.showAllTables().success(function(tableNames) {
        tableNames.forEach(function(tableName) {
          chainer.add(self.sequelize.getQueryInterface().dropTable(tableName))
        })
        chainer
          .run()
          .success(function() {
            self.emit('dropAllTables', null)
            emitter.emit('success', null)
          })
          .error(function(err) {
            self.emit('dropAllTables', err)
            emitter.emit('failure', err)
          })
      }).error(function(err) {
        self.emit('dropAllTables', err)
        emitter.emit('failure', err)
      })
    }).run()
  }

  QueryInterface.prototype.renameTable = function(before, after) {
    var sql = this.QueryGenerator.renameTableQuery(before, after)
    return queryAndEmit.call(this, sql, 'renameTable')
  }

  QueryInterface.prototype.showAllTables = function() {
    var self = this

    return new Utils.CustomEventEmitter(function(emitter) {
      var showTablesSql = self.QueryGenerator.showTablesQuery()
      self.sequelize.query(showTablesSql, null, { raw: true }).success(function(tableNames) {
        self.emit('showAllTables', null)
        emitter.emit('success', Sequelize.Utils._.flatten(tableNames))
      }).error(function(err) {
        self.emit('showAllTables', err)
        emitter.emit('failure', err)
      })
    }).run()
  }

  QueryInterface.prototype.describeTable = function(tableName) {
    var self = this

    return new Utils.CustomEventEmitter(function(emitter) {
      self.sequelize.query('DESCRIBE `' + tableName + '`;', null, { raw: true }).success(function(data) {
        emitter.emit('success', data)
      }).error(function(err) {
        emitter.emit('failure', err)
      })
    }).run()
  }

  QueryInterface.prototype.addColumn = function(tableName, attributeName, dataTypeOrOptions) {
    var attributes = {}

    if(Utils._.values(DataTypes).indexOf(dataTypeOrOptions) > -1)
      attributes[attributeName] = { type: dataTypeOrOptions, allowNull: false }
    else
      attributes[attributeName] = dataTypeOrOptions

    var options = this.QueryGenerator.attributesToSQL(attributes)
      , sql     = this.QueryGenerator.addColumnQuery(tableName, options)

    return queryAndEmit.call(this, sql, 'addColumn')
  }

  QueryInterface.prototype.removeColumn = function(tableName, attributeName) {
    var sql = this.QueryGenerator.removeColumnQuery(tableName, attributeName)
    return queryAndEmit.call(this, sql, 'removeColumn')
  }

  QueryInterface.prototype.changeColumn = function(tableName, attributeName, dataTypeOrOptions) {
    var attributes = {}

    if(Utils._.values(DataTypes).indexOf(dataTypeOrOptions) > -1)
      attributes[attributeName] = { type: dataTypeOrOptions, allowNull: false }
    else
      attributes[attributeName] = dataTypeOrOptions

    var options = this.QueryGenerator.attributesToSQL(attributes)
      , sql     = this.QueryGenerator.changeColumnQuery(tableName, options)

    return queryAndEmit.call(this, sql, 'changeColumn')
  }

  QueryInterface.prototype.renameColumn = function(tableName, attrNameBefore, attrNameAfter) {
    var self = this

    return new Utils.CustomEventEmitter(function(emitter) {
      self.describeTable(tableName).success(function(data) {
        data = data.filter(function(h) { return h.Field == attrNameBefore })[0]

        var options =  {}

        options[attrNameAfter] = {
          type: data.Type,
          allowNull: data.Null == 'YES',
          defaultValue: data.Default
        }

        var sql = self.QueryGenerator.renameColumnQuery(tableName,
          attrNameBefore,
          self.QueryGenerator.attributesToSQL(options)
        )

        self.sequelize.query(sql).success(function() {
          self.emit('renameColumn', null)
          emitter.emit('success', null)
        }).error(function(err) {
          self.emit('renameColumn', err)
          emitter.emit('failure', err)
        })
      }).error(function(err) {
        self.emit('renameColumn', err)
        emitter.emit('failure', err)
      })
    }).run()
  }

  QueryInterface.prototype.addIndex = function(tableName, attributes, options) {
    var sql = this.QueryGenerator.addIndexQuery(tableName, attributes, options)
    return queryAndEmit.call(this, sql, 'addIndex')
  }

  QueryInterface.prototype.showIndex = function(tableName, options) {
    var sql = this.QueryGenerator.showIndexQuery(tableName, options)
    return queryAndEmit.call(this, sql, 'showIndex')
  }

  QueryInterface.prototype.removeIndex = function(tableName, indexNameOrAttributes) {
    var sql = this.QueryGenerator.removeIndexQuery(tableName, indexNameOrAttributes)
    return queryAndEmit.call(this, sql, "removeIndex")
  }

  QueryInterface.prototype.insert = function(model, tableName, values) {
    var sql = this.QueryGenerator.insertQuery(tableName, values)
    return queryAndEmit.call(this, [sql, model], 'insert', {
      success: function(obj) { obj.isNewRecord = false }
    })
  }

  QueryInterface.prototype.update = function(model, tableName, values, identifier) {
    var sql = this.QueryGenerator.updateQuery(tableName, values, identifier)
    return queryAndEmit.call(this, [sql, model], 'update')
  }

  QueryInterface.prototype.delete = function(model, tableName, identifier) {
    var sql = this.QueryGenerator.deleteQuery(tableName, identifier)
    return queryAndEmit.call(this, [sql, model], 'delete')
  }

  QueryInterface.prototype.select = function(factory, tableName, options, queryOptions) {
    var sql = this.QueryGenerator.selectQuery(tableName, options)
    return queryAndEmit.call(this, [sql, factory, queryOptions], 'select')
  }

  QueryInterface.prototype.rawSelect = function(tableName, options, attributeSelector) {
    var self = this

    if(attributeSelector == undefined)
      throw new Error('Please pass an attribute selector!')

    return new Utils.CustomEventEmitter(function(emitter) {
      var sql = self.QueryGenerator.selectQuery(tableName, options)

      self.sequelize
        .query(sql, null, { plain: true, raw: true })
        .success(function(data) {
          self.emit('rawSelect', null)
          emitter.emit('success', data[attributeSelector])
        })
        .error(function(err) {
          self.emit('rawSelect', err)
          emitter.emit('failure', err)
        })
    }).run()
  }

  // private

  var queryAndEmit = function(sqlOrQueryParams, methodName, options) {
    var self = this

    options = Utils._.extend({
      success: function(obj){},
      error: function(err){}
    }, options || {})

    return new Utils.CustomEventEmitter(function(emitter) {
      var query = null

      if(Array.isArray(sqlOrQueryParams))
        query = self.sequelize.query.apply(self.sequelize, sqlOrQueryParams)
      else
        query = self.sequelize.query(sqlOrQueryParams)

      // append the query for better testing
      emitter.query = query

      query.success(function(obj) {
        options.success && options.success(obj)
        self.emit(methodName, null)
        emitter.emit('success', obj)
      }).error(function(err) {
        options.error && options.error(err)
        self.emit(methodName, err)
        emitter.emit('failure', err)
      })
    }).run()
  }

  var query = function() {
    var args = Utils._.map(arguments, function(arg, _) { return arg })

    // add this as callee via the second argument
    if(arguments.length == 1) args.push(this)

    return this.sequelize.query.apply(this.sequelize, args)
  }

  return QueryInterface
})()
<commit_msg>removed unused private method<commit_after>var Utils     = require('./utils')
  , DataTypes = require('./data-types')

module.exports = (function() {
  var QueryInterface = function(sequelize) {
    this.sequelize = sequelize
    this.QueryGenerator = require('./dialects/' + this.sequelize.options.dialect + '/query-generator')
  }
  Utils.addEventEmitter(QueryInterface)

  QueryInterface.prototype.createTable = function(tableName, attributes, options) {
    var attributeHashes = {}

    Utils._.each(attributes, function(dataTypeOrOptions, attributeName) {
      if(Utils._.values(DataTypes).indexOf(dataTypeOrOptions) > -1)
        attributeHashes[attributeName] = { type: dataTypeOrOptions }
      else
        attributeHashes[attributeName] = dataTypeOrOptions
    })

    attributes = this.QueryGenerator.attributesToSQL(attributeHashes)

    var sql = this.QueryGenerator.createTableQuery(tableName, attributes, options)
    return queryAndEmit.call(this, sql, 'createTable')
  }

  QueryInterface.prototype.dropTable = function(tableName) {
    var sql = this.QueryGenerator.dropTableQuery(tableName)
    return queryAndEmit.call(this, sql, 'dropTable')
  }

  QueryInterface.prototype.dropAllTables = function() {
    var self = this

    return new Utils.CustomEventEmitter(function(emitter) {
      var chainer = new Utils.QueryChainer()

      self.showAllTables().success(function(tableNames) {
        tableNames.forEach(function(tableName) {
          chainer.add(self.sequelize.getQueryInterface().dropTable(tableName))
        })
        chainer
          .run()
          .success(function() {
            self.emit('dropAllTables', null)
            emitter.emit('success', null)
          })
          .error(function(err) {
            self.emit('dropAllTables', err)
            emitter.emit('failure', err)
          })
      }).error(function(err) {
        self.emit('dropAllTables', err)
        emitter.emit('failure', err)
      })
    }).run()
  }

  QueryInterface.prototype.renameTable = function(before, after) {
    var sql = this.QueryGenerator.renameTableQuery(before, after)
    return queryAndEmit.call(this, sql, 'renameTable')
  }

  QueryInterface.prototype.showAllTables = function() {
    var self = this

    return new Utils.CustomEventEmitter(function(emitter) {
      var showTablesSql = self.QueryGenerator.showTablesQuery()
      self.sequelize.query(showTablesSql, null, { raw: true }).success(function(tableNames) {
        self.emit('showAllTables', null)
        emitter.emit('success', Sequelize.Utils._.flatten(tableNames))
      }).error(function(err) {
        self.emit('showAllTables', err)
        emitter.emit('failure', err)
      })
    }).run()
  }

  QueryInterface.prototype.describeTable = function(tableName) {
    var self = this

    return new Utils.CustomEventEmitter(function(emitter) {
      self.sequelize.query('DESCRIBE `' + tableName + '`;', null, { raw: true }).success(function(data) {
        emitter.emit('success', data)
      }).error(function(err) {
        emitter.emit('failure', err)
      })
    }).run()
  }

  QueryInterface.prototype.addColumn = function(tableName, attributeName, dataTypeOrOptions) {
    var attributes = {}

    if(Utils._.values(DataTypes).indexOf(dataTypeOrOptions) > -1)
      attributes[attributeName] = { type: dataTypeOrOptions, allowNull: false }
    else
      attributes[attributeName] = dataTypeOrOptions

    var options = this.QueryGenerator.attributesToSQL(attributes)
      , sql     = this.QueryGenerator.addColumnQuery(tableName, options)

    return queryAndEmit.call(this, sql, 'addColumn')
  }

  QueryInterface.prototype.removeColumn = function(tableName, attributeName) {
    var sql = this.QueryGenerator.removeColumnQuery(tableName, attributeName)
    return queryAndEmit.call(this, sql, 'removeColumn')
  }

  QueryInterface.prototype.changeColumn = function(tableName, attributeName, dataTypeOrOptions) {
    var attributes = {}

    if(Utils._.values(DataTypes).indexOf(dataTypeOrOptions) > -1)
      attributes[attributeName] = { type: dataTypeOrOptions, allowNull: false }
    else
      attributes[attributeName] = dataTypeOrOptions

    var options = this.QueryGenerator.attributesToSQL(attributes)
      , sql     = this.QueryGenerator.changeColumnQuery(tableName, options)

    return queryAndEmit.call(this, sql, 'changeColumn')
  }

  QueryInterface.prototype.renameColumn = function(tableName, attrNameBefore, attrNameAfter) {
    var self = this

    return new Utils.CustomEventEmitter(function(emitter) {
      self.describeTable(tableName).success(function(data) {
        data = data.filter(function(h) { return h.Field == attrNameBefore })[0]

        var options =  {}

        options[attrNameAfter] = {
          type: data.Type,
          allowNull: data.Null == 'YES',
          defaultValue: data.Default
        }

        var sql = self.QueryGenerator.renameColumnQuery(tableName,
          attrNameBefore,
          self.QueryGenerator.attributesToSQL(options)
        )

        self.sequelize.query(sql).success(function() {
          self.emit('renameColumn', null)
          emitter.emit('success', null)
        }).error(function(err) {
          self.emit('renameColumn', err)
          emitter.emit('failure', err)
        })
      }).error(function(err) {
        self.emit('renameColumn', err)
        emitter.emit('failure', err)
      })
    }).run()
  }

  QueryInterface.prototype.addIndex = function(tableName, attributes, options) {
    var sql = this.QueryGenerator.addIndexQuery(tableName, attributes, options)
    return queryAndEmit.call(this, sql, 'addIndex')
  }

  QueryInterface.prototype.showIndex = function(tableName, options) {
    var sql = this.QueryGenerator.showIndexQuery(tableName, options)
    return queryAndEmit.call(this, sql, 'showIndex')
  }

  QueryInterface.prototype.removeIndex = function(tableName, indexNameOrAttributes) {
    var sql = this.QueryGenerator.removeIndexQuery(tableName, indexNameOrAttributes)
    return queryAndEmit.call(this, sql, "removeIndex")
  }

  QueryInterface.prototype.insert = function(model, tableName, values) {
    var sql = this.QueryGenerator.insertQuery(tableName, values)
    return queryAndEmit.call(this, [sql, model], 'insert', {
      success: function(obj) { obj.isNewRecord = false }
    })
  }

  QueryInterface.prototype.update = function(model, tableName, values, identifier) {
    var sql = this.QueryGenerator.updateQuery(tableName, values, identifier)
    return queryAndEmit.call(this, [sql, model], 'update')
  }

  QueryInterface.prototype.delete = function(model, tableName, identifier) {
    var sql = this.QueryGenerator.deleteQuery(tableName, identifier)
    return queryAndEmit.call(this, [sql, model], 'delete')
  }

  QueryInterface.prototype.select = function(factory, tableName, options, queryOptions) {
    var sql = this.QueryGenerator.selectQuery(tableName, options)
    return queryAndEmit.call(this, [sql, factory, queryOptions], 'select')
  }

  QueryInterface.prototype.rawSelect = function(tableName, options, attributeSelector) {
    var self = this

    if(attributeSelector == undefined)
      throw new Error('Please pass an attribute selector!')

    return new Utils.CustomEventEmitter(function(emitter) {
      var sql = self.QueryGenerator.selectQuery(tableName, options)

      self.sequelize
        .query(sql, null, { plain: true, raw: true })
        .success(function(data) {
          self.emit('rawSelect', null)
          emitter.emit('success', data[attributeSelector])
        })
        .error(function(err) {
          self.emit('rawSelect', err)
          emitter.emit('failure', err)
        })
    }).run()
  }

  // private

  var queryAndEmit = function(sqlOrQueryParams, methodName, options) {
    var self = this

    options = Utils._.extend({
      success: function(obj){},
      error: function(err){}
    }, options || {})

    return new Utils.CustomEventEmitter(function(emitter) {
      var query = null

      if(Array.isArray(sqlOrQueryParams))
        query = self.sequelize.query.apply(self.sequelize, sqlOrQueryParams)
      else
        query = self.sequelize.query(sqlOrQueryParams)

      // append the query for better testing
      emitter.query = query

      query.success(function(obj) {
        options.success && options.success(obj)
        self.emit(methodName, null)
        emitter.emit('success', obj)
      }).error(function(err) {
        options.error && options.error(err)
        self.emit(methodName, err)
        emitter.emit('failure', err)
      })
    }).run()
  }

  return QueryInterface
})()
<|endoftext|>


<commit_before>'use strict';

var bpack = require('browser-pack');
var fs = require('fs');
var path = require('path');
var xtend = require('xtend');

var preludePath = path.join(__dirname, 'prelude.js');
var prelude = fs.readFileSync(preludePath, 'utf8');

// This plugin replaces the prelude and adds a transform
var plugin = exports.plugin = function (bfy, opts) {
  var packOpts = {
    raw: true, // Added in regular Browserifiy as well
    preludePath: preludePath,
    prelude: prelude
  };

  var packer = bpack(xtend(bfy._options, packOpts));
  // Replace the 'pack' step with the new browser-pack instance
  bfy.pipeline.splice('pack', 1, packer);

  bfy.transform(require('./transform'));
};

// Maintain support for the old interface
exports.browserify = function (files) {
  console.error('You are setting up proxyquireify via the old API which will be deprecated in future versions.');
  console.error('It is recommended to use it as a browserify-plugin instead - see the example in the README.');
  return require('browserify')(files).plugin(plugin);
};
<commit_msg>replace prelude in pipeline when reset is called<commit_after>'use strict';

var bpack = require('browser-pack');
var fs = require('fs');
var path = require('path');
var xtend = require('xtend');

var preludePath = path.join(__dirname, 'prelude.js');
var prelude = fs.readFileSync(preludePath, 'utf8');

// This plugin replaces the prelude and adds a transform
var plugin = exports.plugin = function (bfy, opts) {
  var replacePrelude = function() {
    var packOpts = {
      raw: true, // Added in regular Browserifiy as well
      preludePath: preludePath,
      prelude: prelude
    };

    var packer = bpack(xtend(bfy._options, packOpts));
    // Replace the 'pack' step with the new browser-pack instance
    bfy.pipeline.splice('pack', 1, packer);
  }
  bfy.transform(require('./transform'));
  bfy.on('reset', replacePrelude);
  replacePrelude();
};

// Maintain support for the old interface
exports.browserify = function (files) {
  console.error('You are setting up proxyquireify via the old API which will be deprecated in future versions.');
  console.error('It is recommended to use it as a browserify-plugin instead - see the example in the README.');
  return require('browserify')(files).plugin(plugin);
};
<|endoftext|>