<commit_before>require('core-upgrade');
var HTML5 = require('html5');
var sys = require('sys');
var assert = require('assert');
var DOM = require('dom'); // Use env-js dom

HTML5.TreeBuilder = b = function TreeBuilder() {
	this.open_elements = [];
	this.document = new DOM.Document(DOM.DOMImplementation);
	this.activeFormattingElements = [];
}

b.prototype.reset = function() {

}

b.prototype.createElement = function (name, attributes, namespace) {
	var el = this.document.createElement(name)
	HTML5.debug('treebuilder.createElement', 'attributes', attributes);
	if(attributes) for(var i = 0; i < attributes.length; i++) {
		el.setAttribute(attributes[i].nodeName, attributes[i].nodeValue);
	}
	return el;
}

b.prototype.insert_element = function(name, attributes, namespace) {
	HTML5.debug('treebuilder.insert_element', name, attributes)
	var element = this.createElement(name, attributes, namespace);
	this.open_elements.last().appendChild(element);
	this.open_elements.push(element);
	return element;
}

b.prototype.insert_comment = function(data, parent) {
	var c = this.document.createComment(data);
	HTML5.debug('treebuilder', 'open elements at insert_comment are: ' + require('sys').inspect(this.open_elements.map(function(e) { return e.nodeName })));
	if(!parent) parent = this.open_elements.last();
	parent.appendChild(c);
}

b.prototype.insert_doctype = function (name, publicId, systemId) {
	// var dt = this.document.implementation.createDocumentType(name, publicId, systemId);
	var doctype = new DOM.DocumentType();
        doctype.nodeName = name?name:'';
        doctype.publicId = publicId?publicId:null;
        doctype.systemId = systemId?systemId:null;
	this.document.appendChild(doctype);
}

b.prototype.insert_text = function(data, parent) {
	HTML5.debug('treebuilder.insert_text', data)
	if(!parent) parent = this.open_elements.last();
	if(!this.insert_from_table || HTML5.TABLE_INSERT_MODE_ELEMENTS.indexOf(this.open_elements.last().tagName) == -1) {
		if(parent.lastChild && parent.lastChild.nodeType == DOM.Node.TEXT_NODE) {
			parent.lastChild.appendData(data);
		} else {
			var tn = this.document.createTextNode(data);
			parent.appendChild(tn);
		}
	} else {
		// We should be in the inTable phase. This means we want to do special
		// magic element rearranging.
		// FIXME
		throw(new Error("So very not implemented"));
	}
}

b.prototype.elementInScope = function(name, tableVariant) {
	if(this.open_elements.length == 0) return false;
	for(var i = this.open_elements.length - 1; i >= 0; i--) {
		if(this.open_elements[i].tagName == name) return true
		else if(this.open_elements[i].tagName == 'table') return false
		else if(!tableVariant && HTML5.SCOPING_ELEMENTS.indexOf(this.open_elements[i].tagName) != -1) return false
		else if(this.open_elements[i].tagName == 'html') return false;
	}
	return false;
}

b.prototype.generateImpliedEndTags = function (exclude) {
	//HTML5.debug('implied end tags with ' + sys.inspect(this.open_elements.map(function(el) { return el.tagName })));
	var name = this.open_elements.last().tagName;
	if(['dd', 'dt', 'li', 'p', 'td', 'th', 'tr'].indexOf(name) != -1 && name != exclude) {
		var p  = this.open_elements.pop();
		this.generateImpliedEndTags(exclude);
	}
}

b.prototype.reconstructActiveFormattingElements = function() {
	HTML5.debug('treebuilder.reconstructActiveFormattingElements', this.activeFormattingElements.map(function(e) { return e.tagName }));
	// Within this algorithm the order of steps decribed in the specification
	// is not quite the same as the order of steps in the code. It should still
	// do the same though.

	// Step 1: stop if there's nothing to do
	if(this.activeFormattingElements.length == 0) return;

	// Step 2 and 3: start with the last element
	var i = this.activeFormattingElements.length - 1;
	var entry = this.activeFormattingElements[i];
	if(entry == HTML5.Marker || this.open_elements.indexOf(entry) != -1) return;

	while(!(entry == HTML5.Marker || this.open_elements.indexOf(entry) != -1)) {
		i -= 1;
		entry = this.activeFormattingElements[i];
		if(!entry) break;
	}

	while(true) {
		i += 1;
		var clone = this.activeFormattingElements[i].cloneNode();

		var element = this.insert_element(clone.tagName, clone.attributes);

		this.activeFormattingElements[i] = element;

		if(element == this.activeFormattingElements.last()) break;
	}

	HTML5.debug('treebuilder.reconstructActiveFormattingElements', 'open tags are ' + HTML5.dumpTagStack(this.open_elements));
}

b.prototype.elementInActiveFormattingElements = function(name) {
	var els = this.activeFormattingElements;
	for(var i = els.length - 1; i >= 0; i--) {
		if(els[i] == HTML5.Marker) break;
		if(els[i].tagName == name) return els[i];
	}
	return false;
}

b.prototype.reparentChildren = function(o, n) {
	while(o.childNodes.length > 0) {
		var el = o.removeChild(o.childNodes[0]);
		n.appendChild(el);
	}
}

b.prototype.clearActiveFormattingElements = function() {
	while(!(this.activeFormattingElements.length == 0 || this.activeFormattingElements.pop() == HTML5.Marker));
}

b.prototype.getFragment = function() {
	// assert.ok(this.parser.inner_html)
	var fragment = this.document.createDocumentFragment()
	this.reparentChildren(this.open_elements[1], fragment)
	return fragment
}
<commit_msg>- don't strip off two layers from fragment parses<commit_after>require('core-upgrade');
var HTML5 = require('html5');
var sys = require('sys');
var assert = require('assert');
var DOM = require('dom'); // Use env-js dom

HTML5.TreeBuilder = b = function TreeBuilder() {
	this.open_elements = [];
	this.document = new DOM.Document(DOM.DOMImplementation);
	this.activeFormattingElements = [];
}

b.prototype.reset = function() {

}

b.prototype.createElement = function (name, attributes, namespace) {
	var el = this.document.createElement(name)
	HTML5.debug('treebuilder.createElement', 'attributes', attributes);
	if(attributes) for(var i = 0; i < attributes.length; i++) {
		el.setAttribute(attributes[i].nodeName, attributes[i].nodeValue);
	}
	return el;
}

b.prototype.insert_element = function(name, attributes, namespace) {
	HTML5.debug('treebuilder.insert_element', name, attributes)
	var element = this.createElement(name, attributes, namespace);
	this.open_elements.last().appendChild(element);
	this.open_elements.push(element);
	return element;
}

b.prototype.insert_comment = function(data, parent) {
	var c = this.document.createComment(data);
	HTML5.debug('treebuilder', 'open elements at insert_comment are: ' + require('sys').inspect(this.open_elements.map(function(e) { return e.nodeName })));
	if(!parent) parent = this.open_elements.last();
	parent.appendChild(c);
}

b.prototype.insert_doctype = function (name, publicId, systemId) {
	// var dt = this.document.implementation.createDocumentType(name, publicId, systemId);
	var doctype = new DOM.DocumentType();
        doctype.nodeName = name?name:'';
        doctype.publicId = publicId?publicId:null;
        doctype.systemId = systemId?systemId:null;
	this.document.appendChild(doctype);
}

b.prototype.insert_text = function(data, parent) {
	HTML5.debug('treebuilder.insert_text', data)
	if(!parent) parent = this.open_elements.last();
	if(!this.insert_from_table || HTML5.TABLE_INSERT_MODE_ELEMENTS.indexOf(this.open_elements.last().tagName) == -1) {
		if(parent.lastChild && parent.lastChild.nodeType == DOM.Node.TEXT_NODE) {
			parent.lastChild.appendData(data);
		} else {
			var tn = this.document.createTextNode(data);
			parent.appendChild(tn);
		}
	} else {
		// We should be in the inTable phase. This means we want to do special
		// magic element rearranging.
		// FIXME
		throw(new Error("So very not implemented"));
	}
}

b.prototype.elementInScope = function(name, tableVariant) {
	if(this.open_elements.length == 0) return false;
	for(var i = this.open_elements.length - 1; i >= 0; i--) {
		if(this.open_elements[i].tagName == name) return true
		else if(this.open_elements[i].tagName == 'table') return false
		else if(!tableVariant && HTML5.SCOPING_ELEMENTS.indexOf(this.open_elements[i].tagName) != -1) return false
		else if(this.open_elements[i].tagName == 'html') return false;
	}
	return false;
}

b.prototype.generateImpliedEndTags = function (exclude) {
	//HTML5.debug('implied end tags with ' + sys.inspect(this.open_elements.map(function(el) { return el.tagName })));
	var name = this.open_elements.last().tagName;
	if(['dd', 'dt', 'li', 'p', 'td', 'th', 'tr'].indexOf(name) != -1 && name != exclude) {
		var p  = this.open_elements.pop();
		this.generateImpliedEndTags(exclude);
	}
}

b.prototype.reconstructActiveFormattingElements = function() {
	HTML5.debug('treebuilder.reconstructActiveFormattingElements', this.activeFormattingElements.map(function(e) { return e.tagName }));
	// Within this algorithm the order of steps decribed in the specification
	// is not quite the same as the order of steps in the code. It should still
	// do the same though.

	// Step 1: stop if there's nothing to do
	if(this.activeFormattingElements.length == 0) return;

	// Step 2 and 3: start with the last element
	var i = this.activeFormattingElements.length - 1;
	var entry = this.activeFormattingElements[i];
	if(entry == HTML5.Marker || this.open_elements.indexOf(entry) != -1) return;

	while(!(entry == HTML5.Marker || this.open_elements.indexOf(entry) != -1)) {
		i -= 1;
		entry = this.activeFormattingElements[i];
		if(!entry) break;
	}

	while(true) {
		i += 1;
		var clone = this.activeFormattingElements[i].cloneNode();

		var element = this.insert_element(clone.tagName, clone.attributes);

		this.activeFormattingElements[i] = element;

		if(element == this.activeFormattingElements.last()) break;
	}

	HTML5.debug('treebuilder.reconstructActiveFormattingElements', 'open tags are ' + HTML5.dumpTagStack(this.open_elements));
}

b.prototype.elementInActiveFormattingElements = function(name) {
	var els = this.activeFormattingElements;
	for(var i = els.length - 1; i >= 0; i--) {
		if(els[i] == HTML5.Marker) break;
		if(els[i].tagName == name) return els[i];
	}
	return false;
}

b.prototype.reparentChildren = function(o, n) {
	while(o.childNodes.length > 0) {
		var el = o.removeChild(o.childNodes[0]);
		n.appendChild(el);
	}
}

b.prototype.clearActiveFormattingElements = function() {
	while(!(this.activeFormattingElements.length == 0 || this.activeFormattingElements.pop() == HTML5.Marker));
}

b.prototype.getFragment = function() {
	// assert.ok(this.parser.inner_html)
	var fragment = this.document.createDocumentFragment()
	this.reparentChildren(this.open_elements[0], fragment)
	return fragment
}
<|endoftext|>


<commit_before>//copy from showdown/table, removed styles
var table = function(context) {
  return function(converter) {
    var tables = {}, filter;
    tables.th = function(header){
      if (header.trim() === "") { return "";}
      var id = header.trim().replace(/ /g, '_').toLowerCase();
      return '' + header + '	';
    };
    tables.td = function(cell) {
      return '' + converter.makeHtml(cell) + '	';
    };
    tables.ths = function(){
      var out = "", i = 0, hs = [].slice.apply(arguments);
      for (i;i<hs.length;i+=1) {
        out += tables.th(hs[i]) + '\n';
      }
      return out;
    };
    tables.tds = function(){
      var out = "", i = 0, ds = [].slice.apply(arguments);
      for (i;i<ds.length;i+=1) {
        out += tables.td(ds[i]) + '\n';
      }
      return out;
    };
    tables.thead = function() {
      var out, i = 0, hs = [].slice.apply(arguments);
      out = "
\n";
      out += "
\n";
      out += tables.ths.apply(this, hs);
      out += "
\n";
      out += "
\n";
      return out;
    };
    tables.tr = function() {
      var out, i = 0, cs = [].slice.apply(arguments);
      out = "
\n";
      out += tables.tds.apply(this, cs);
      out += "
\n";
      return out;
    };
    filter = function(text) {
      var i=0, lines = text.split('\n'), tbl = [], line, hs, rows, out = [];
      for (i; i<lines.length;i+=1) {
        line = lines[i];
        // looks like a table heading
        if (line.trim().match(/^[|]{1}.*[|]{1}$/)) {
          line = line.trim();
          tbl.push('
');
          hs = line.substring(1, line.length -1).split('|');
          tbl.push(tables.thead.apply(this, hs));
          line = lines[++i];
          if (!line.trim().match(/^[|]{1}[\-=| ]+[|]{1}$/)) {
            // not a table rolling back
            line = lines[--i];
          }
          else {
            line = lines[++i];
            tbl.push('
');
            while (line.trim().match(/^[|]{1}.*[|]{1}$/)) {
              line = line.trim();
              tbl.push(tables.tr.apply(this, line.substring(1, line.length -1).split('|')));
              line = lines[++i];
            }
            tbl.push('
');
            tbl.push('
');
            // we are done with this table and we move along
            out.push(tbl.join('\n'));
            continue;
          }
        }
        out.push(line);
      }
      return out.join('\n');
    };
    return [
    {
      type: 'lang',
      filter: filter
    }
    ];
  };
};

var js = function(context) {
    return function(converter) {
      return [
          {
            type    : 'lang',
            regex   : '(@{2})(.*?)(@{2})',
            replace : function(match, prefix, content, suffix) {
              with(context) {
                try {
                  return eval(content);
                } catch (e) {
                  return 'ERROR: ' + e.message + '';
                }
              }
            }
          }
      ];
    };
};

module.exports = [table, js];<commit_msg>Fixed bug in extensions.js<commit_after>//copy from showdown/table, removed styles
var table = function(context) {
  return function(converter) {
    var tables = {}, filter;
    tables.th = function(header){
      if (header.trim() === "") { return "";}
      var id = header.trim().replace(/ /g, '_').toLowerCase();
      return '' + header + '	';
    };
    tables.td = function(cell) {
      return '' + converter.makeHtml(cell) + '	';
    };
    tables.ths = function(){
      var out = "", i = 0, hs = [].slice.apply(arguments);
      for (i;i<hs.length;i+=1) {
        out += tables.th(hs[i]) + '\n';
      }
      return out;
    };
    tables.tds = function(){
      var out = "", i = 0, ds = [].slice.apply(arguments);
      for (i;i<ds.length;i+=1) {
        out += tables.td(ds[i]) + '\n';
      }
      return out;
    };
    tables.thead = function() {
      var out, i = 0, hs = [].slice.apply(arguments);
      out = "
\n";
      out += "
\n";
      out += tables.ths.apply(this, hs);
      out += "
\n";
      out += "
\n";
      return out;
    };
    tables.tr = function() {
      var out, i = 0, cs = [].slice.apply(arguments);
      out = "
\n";
      out += tables.tds.apply(this, cs);
      out += "
\n";
      return out;
    };
    filter = function(text) {
      var i=0, lines = text.split('\n'), tbl = [], line, hs, rows, out = [];
      for(i; i<lines.length;i+=1) {
        line = lines[i];
        // looks like a table heading
        if (line.trim().match(/^[|]{1}.*[|]{1}$/)) {
          line = line.trim();
          tbl.push('
');
          hs = line.substring(1, line.length -1).split('|');
          tbl.push(tables.thead.apply(this, hs));
          line = lines[++i];
          if (!line.trim().match(/^[|]{1}[\-=| ]+[|]{1}$/)) {
            // not a table rolling back
            line = lines[--i];
          }
          else {
            line = lines[++i];
            tbl.push('
');
            while (line.trim().match(/^[|]{1}.*[|]{1}$/)) {
              line = line.trim();
              tbl.push(tables.tr.apply(this, line.substring(1, line.length -1).split('|')));
              line = lines[++i];
            }
            tbl.push('
');
            tbl.push('
');
            // we are done with this table and we move along
            out.push(tbl.join('\n'));
            tbl = [];
            continue;
          }
        }
        out.push(line);
      }
      return out.join('\n');
    };
    return [
    {
      type: 'lang',
      filter: filter
    }
    ];
  };
};

var js = function(context) {
    return function(converter) {
      return [
          {
            type    : 'lang',
            regex   : '(@{2})(.*?)(@{2})',
            replace : function(match, prefix, content, suffix) {
              with(context) {
                try {
                  return eval(content);
                } catch (e) {
                  return 'ERROR: ' + e.message + '';
                }
              }
            }
          }
      ];
    };
};

module.exports = [table, js];<|endoftext|>


<commit_before>/*jshint esversion:6, node:true*/
'use strict';

var inSubnet = require('insubnet');

function firewall(socket, config, next){
    if(firewall.block(socket, config)){
        return next('firewall-ip');
    }
    next();
}

firewall._policy = 'ACCEPT';

firewall.policy = function(policy){
    firewall._policy = policy;
};

firewall.block = function $firewall(socket, config){
    //TODO: should we have a policy here?
    //we have no firewall defined in config, should
    //we make it so that in production we always need
    //an ip?!!
    if(!config.firewall){
        return false;
    }

    //extend(firewall, config);
    var valid = false;

    var toIPv4 = function(addr) {
        var parts = String(addr).split(":");
        return parts[parts.length - 1];
    };

    var ip = socket.remoteAddress;
    if(socket.remoteFamily === 'IPv6'){
        ip = toIPv4(ip);
    }

    //this should be based on policy
    if(!firewall.isValidIp(ip)) {
        return true;
    }

    var matches = [], match;
    config.firewall.rules.map(function(rule){
        match = inSubnet.Auto(ip, rule.ip, rule.subnet || 32);
        if(match){
            matches.push(rule);
        }
    });

    if(matches.length === 0){
        valid = firewall._policy === 'ACCEPT' ? false : true;
        return valid;
    }

    var rule = matches[0];
    valid = (rule.rule === 'ACCEPT') ? false : true;

    return valid;
};

firewall.isValidIp = function(ip) {
  return ((/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(ip)));
};

module.exports = firewall;
<commit_msg>clean up format<commit_after>'use strict';

const inSubnet = require('insubnet');

function firewall(socket, config, next) {
    if (firewall.block(socket, config)) {
        return next('firewall-ip');
    }
    next();
}

firewall._policy = 'ACCEPT';

firewall.policy = function (policy) {
    firewall._policy = policy;
};

firewall.block = function $firewall(socket, config) {
    //TODO: should we have a policy here?
    //we have no firewall defined in config, should
    //we make it so that in production we always need
    //an ip?!!
    if (!config.firewall) {
        return false;
    }

    //extend(firewall, config);
    let valid = false;

    const toIPv4 = function (addr) {
        var parts = String(addr).split(':');
        return parts[parts.length - 1];
    };

    let ip = socket.remoteAddress;
    if (socket.remoteFamily === 'IPv6') {
        ip = toIPv4(ip);
    }

    //this should be based on policy
    if (!firewall.isValidIp(ip)) {
        return true;
    }

    let matches = [], match;

    config.firewall.rules.map(function (rule) {
        match = inSubnet.Auto(ip, rule.ip, rule.subnet || 32);
        if (match) {
            matches.push(rule);
        }
    });

    if (matches.length === 0) {
        valid = firewall._policy === 'ACCEPT' ? false : true;
        return valid;
    }

    const rule = matches[0];

    valid = (rule.rule === 'ACCEPT') ? false : true;

    return valid;
};

firewall.isValidIp = function (ip) {
    return ((/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(ip)));
};

module.exports = firewall;
<|endoftext|>


<commit_before>/**
 * Created with IntelliJ IDEA.
 * User: paulomcnally
 * Date: 10/30/13
 * Time: 8:53 PM
 * To change this template use File | Settings | File Templates.
 */

var crypto = require('crypto');
var mssql = require('mssql');
var Memcached = require('memcached');
var memcached;
var debug = false;

function getHash( value ){
    return crypto.createHash('md5').update(value).digest("hex");
}

/**
 * @param boolean
 */
exports.debug = function( boolean ){
    debug = boolean;
}

/**
 * @param value
 * @description Set server or servers memcached
 */
exports.setMemcachedServers = function( value ){
    memcached = new Memcached( value );

}

/**
 * @param query - String
 * @param connection - String
 * @param cache - Boolean
 * @param lifetime - Int
 * @param callback - function
 * @description Simple query to Microsoft SQL Server with or without memcached
 */

exports.query = function( query, connection, cache, lifetime, callback ){

    this.demo = function demo(){
        console.log('Esto es una demo');
    }

    function out( paramQuery, paramConnection, paramCache, paramLifetime, functionCallback ){

        // validate cache and lifetime params
        if(typeof(paramCache)==='undefined'){
            paramCache = false;
        }

        if(typeof(paramLifetime)==='undefined'){
            paramLifetime = 86400; // one day
        }

        // validating cache or not cache

        if( paramCache ){

            if( debug ){
                console.log( 'Memcached enabled' );
            }

            // create a hash by query
            var key = getHash( paramQuery );

            if( debug ){
                console.log( 'Memcached key: ' + key );
            }

            memcached.get( key, function( errGet, memcachedData ) {
                if( errGet ){

                    if( debug ){
                        console.log( 'Memcached errGet: ' + errGet );
                    }

                    functionCallback( errGet, null );
                }
                else{
                    if( memcachedData ){

                        if( debug ){
                            console.log( 'Result from Memcached' );
                        }

                        // get data from memcached
                        functionCallback( null, memcachedData );
                    }
                    else{
                        // get data from microsoft sql server
                        var connection = new mssql.Connection( paramConnection, function( connectionError ){
                            if( connectionError ){

                                if( debug ){
                                    console.log( 'Sql connectionError: ' + connectionError );
                                }

                                functionCallback( connectionError, null );
                            }
                            else{

                                if( debug ){
                                    console.log( 'Sql Connection Open' );
                                }

                                var request = connection.request();
                                request.query( paramQuery, function( queryError, recordset ) {
                                    if( queryError ){

                                        if( debug ){
                                            console.log( 'Sql queryError: ' + queryError );
                                        }

                                        functionCallback( queryError, null );
                                    }
                                    else{
                                        memcached.set( key, recordset, paramLifetime, function ( errSet ) {
                                            if( errSet ){

                                                if( debug ){
                                                    console.log( 'Memcached errSet: ' + errSet );
                                                }

                                                functionCallback( errSet, null );
                                            }
                                            else{

                                                if( debug ){
                                                    console.log( 'Result from Sql Server' );
                                                }

                                                functionCallback( null, recordset );

                                                if( debug ){
                                                    console.log( 'Sql Connection Close' );
                                                }

                                                connection.close();
                                            }
                                        });
                                    }
                                });
                            }
                        });
                    }
                }
            });

        }
        else{
            if( debug ){
                console.log( 'Memcached disabled' );
            }

            // get data from microsoft sql server
            // get data from microsoft sql server
            var connection = new mssql.Connection( paramConnection, function( connectionError ){
                if( connectionError ){

                    if( debug ){
                        console.log( 'Sql connectionError: ' + connectionError );
                    }

                    functionCallback( connectionError, null );
                }
                else{

                    if( debug ){
                        console.log( 'Sql Connection Open' );
                    }

                    var request = connection.request();
                    request.query( paramQuery, function( queryError, recordset ) {
                        if( queryError ){

                            if( debug ){
                                console.log( 'Sql queryError: ' + queryError );
                            }

                            functionCallback( queryError, null );
                        }
                        else{
                            if( debug ){
                                console.log( 'Result from Sql Server' );
                            }

                            functionCallback( null, recordset );

                            if( debug ){
                                console.log( 'Sql Connection Close' );
                            }

                            connection.close();
                        }
                    });
                }
            });
        }
    }

    out( query, connection, cache, lifetime, callback );
}

<commit_msg>Changes<commit_after>/**
 * Created with IntelliJ IDEA.
 * User: paulomcnally
 * Date: 10/30/13
 * Time: 8:53 PM
 * To change this template use File | Settings | File Templates.
 */

var crypto = require('crypto');
var mssql = require('mssql');
var Memcached = require('memcached');
var memcached;
var debug = false;

function getHash( value ){
    return crypto.createHash('md5').update(value).digest("hex");
}

/**
 * @param boolean
 */
exports.debug = function( boolean ){
    debug = boolean;
}

/**
 * @param value
 * @description Set server or servers memcached
 */
exports.setMemcachedServers = function( value ){
    memcached = new Memcached( value );

}

/**
 * @param query - String
 * @param connection - String
 * @param cache - Boolean
 * @param lifetime - Int
 * @param callback - function
 * @description Simple query to Microsoft SQL Server with or without memcached
 */

exports.query = function( query, connection, cache, lifetime, callback ){
    var parent = this;

    parent.success = null;

    parent.out = function( paramQuery, paramConnection, paramCache, paramLifetime, functionCallback ){

         var culito = 'ss';

        // validate cache and lifetime params
        if(typeof(paramCache)==='undefined'){
            paramCache = false;
        }

        if(typeof(paramLifetime)==='undefined'){
            paramLifetime = 86400; // one day
        }

        // validating cache or not cache

        if( paramCache ){

            if( debug ){
                console.log( 'Memcached enabled' );
            }

            // create a hash by query
            var key = getHash( paramQuery );

            if( debug ){
                console.log( 'Memcached key: ' + key );
            }

            memcached.get( key, function( errGet, memcachedData ) {
                if( errGet ){

                    if( debug ){
                        console.log( 'Memcached errGet: ' + errGet );
                    }

                    functionCallback( errGet, null );
                }
                else{
                    if( memcachedData ){

                        if( debug ){
                            console.log( 'Result from Memcached' );
                        }

                        // get data from memcached
                        functionCallback( null, memcachedData );
                    }
                    else{
                        // get data from microsoft sql server
                        var connection = new mssql.Connection( paramConnection, function( connectionError ){
                            if( connectionError ){

                                if( debug ){
                                    console.log( 'Sql connectionError: ' + connectionError );
                                }

                                functionCallback( connectionError, null );
                            }
                            else{

                                if( debug ){
                                    console.log( 'Sql Connection Open' );
                                }

                                var request = connection.request();
                                request.query( paramQuery, function( queryError, recordset ) {
                                    if( queryError ){

                                        if( debug ){
                                            console.log( 'Sql queryError: ' + queryError );
                                        }

                                        functionCallback( queryError, null );
                                    }
                                    else{
                                        memcached.set( key, recordset, paramLifetime, function ( errSet ) {
                                            if( errSet ){

                                                if( debug ){
                                                    console.log( 'Memcached errSet: ' + errSet );
                                                }

                                                functionCallback( errSet, null );
                                            }
                                            else{

                                                if( debug ){
                                                    console.log( 'Result from Sql Server' );
                                                }

                                                functionCallback( null, recordset );

                                                if( debug ){
                                                    console.log( 'Sql Connection Close' );
                                                }

                                                connection.close();
                                            }
                                        });
                                    }
                                });
                            }
                        });
                    }
                }
            });

        }
        else{
            if( debug ){
                console.log( 'Memcached disabled' );
            }

            // get data from microsoft sql server
            // get data from microsoft sql server
            var connection = new mssql.Connection( paramConnection, function( connectionError ){
                if( connectionError ){

                    if( debug ){
                        console.log( 'Sql connectionError: ' + connectionError );
                    }

                    functionCallback( connectionError, null );
                }
                else{

                    if( debug ){
                        console.log( 'Sql Connection Open' );
                    }

                    var request = connection.request();
                    request.query( paramQuery, function( queryError, recordset ) {
                        if( queryError ){

                            if( debug ){
                                console.log( 'Sql queryError: ' + queryError );
                            }

                            functionCallback( queryError, null );
                        }
                        else{
                            if( debug ){
                                console.log( 'Result from Sql Server' );
                            }

                            console.log( recordset );

                            culito =  recordset;

                            functionCallback( null, recordset );

                            if( debug ){
                                console.log( 'Sql Connection Close' );
                            }

                            connection.close();
                        }
                    });
                }
            });
        }

        parent.success = culito;
    }

    parent.out( query, connection, cache, lifetime, callback );
}

<|endoftext|>


<commit_before>/*eslint no-invalid-this: 0*/ // eslint doesn't understand Promise.coroutine wrapping
"use strict";
const ircFormatting = require("../irc/formatting");
const log = require("../logging").get("MatrixAction");
const ContentRepo = require("matrix-appservice-bridge").ContentRepo;
const escapeStringRegexp = require('escape-string-regexp');
const Promise = require("bluebird");

const ACTION_TYPES = ["message", "emote", "topic", "notice", "file", "image", "video", "audio"];
const EVENT_TO_TYPE = {
    "m.room.message": "message",
    "m.room.topic": "topic"
};
const MSGTYPE_TO_TYPE = {
    "m.emote": "emote",
    "m.notice": "notice",
    "m.image": "image",
    "m.video": "video",
    "m.audio": "audio",
    "m.file": "file"
};

const PILL_MIN_LENGTH_TO_MATCH = 4;
const MAX_MATCHES = 5;

function MatrixAction(type, text, htmlText, timestamp) {
    if (ACTION_TYPES.indexOf(type) === -1) {
        throw new Error("Unknown MatrixAction type: " + type);
    }
    this.type = type;
    this.text = text;
    this.htmlText = htmlText;
    this.ts = timestamp || 0;
}

MatrixAction.prototype.formatMentions = Promise.coroutine(function*(nickUserIdMap, intent) {
    const regexString = "(" +
        Object.keys(nickUserIdMap).map((value) => escapeStringRegexp(value)).join("|")
        + ")";
    const usersRegex = MentionRegex(regexString);
    const matched = new Set(); // lowercased nicknames we have matched already.
    let match;
    for (let i = 0; i < MAX_MATCHES && (match = usersRegex.exec(this.text)) !== null; i++) {
        let matchName = match[2];
        // Deliberately have a minimum length to match on,
        // so we don't match smaller nicks accidentally.
        if (matchName.length < PILL_MIN_LENGTH_TO_MATCH || matched.has(matchName.toLowerCase())) {
            continue;
        }
        let userId = nickUserIdMap[matchName];
        if (userId === undefined) {
            // We might need to search case-insensitive.
            const nick = Object.keys(nickUserIdMap).find((n) =>
                n.toLowerCase() === matchName.toLowerCase()
            );
            if (nick === undefined) {
                continue;
            }
            userId = nickUserIdMap[nick];
            matchName = nick;
        }
        // If this message is not HTML, we should make it so.
        if (this.htmlText === undefined) {
            // This looks scary and unsafe, but further down we check
            // if `text` contains any HTML and escape + set `htmlText` appropriately.
            this.htmlText = this.text;
        }
        userId = ircFormatting.escapeHtmlChars(userId);

        /* Due to how Riot and friends do push notifications,
           we need the plain text to match something.*/
        let identifier;
        try {
            identifier = yield intent.getProfileInfo(userId, 'displayname', true).displayname;
        }
        catch (e) {
            // This shouldn't happen, but let's not fail to match if so.
        }

        if (identifier === undefined) {
            // Fallback to userid.
            identifier = userId.substr(1, userId.indexOf(":")-1)
        }

        const regex = MentionRegex(escapeStringRegexp(matchName));
        this.htmlText = this.htmlText.replace(regex,
`$1<a href="https://matrix.to/#/${userId}">${ircFormatting.escapeHtmlChars(identifier)}</a>`
        );
        this.text = this.text.replace(regex, `$1${identifier}`);
        // Don't match this name twice, we've already replaced all entries.
        matched.add(matchName.toLowerCase());
    }
});

MatrixAction.fromEvent = function(client, event, mediaUrl) {
    event.content = event.content || {};
    let type = EVENT_TO_TYPE[event.type] || "message"; // mx event type to action type
    let text = event.content.body;
    let htmlText = null;

    if (event.type === "m.room.topic") {
        text = event.content.topic;
    }
    else if (event.type === "m.room.message") {
        if (event.content.format === "org.matrix.custom.html") {
            htmlText = event.content.formatted_body;
        }
        if (MSGTYPE_TO_TYPE[event.content.msgtype]) {
            type = MSGTYPE_TO_TYPE[event.content.msgtype];
        }
        if (["m.image", "m.file", "m.video", "m.audio"].indexOf(event.content.msgtype) !== -1) {
            var fileSize = "";
            if (event.content.info && event.content.info.size &&
                    typeof event.content.info.size === "number") {
                fileSize = " (" + Math.round(event.content.info.size / 1024) + "KB)";
            }

            // By default assume that the media server = client homeserver
            if (!mediaUrl) {
                mediaUrl = client.getHomeserverUrl();
            }

            const url = ContentRepo.getHttpUriForMxc(mediaUrl, event.content.url);
            text = `${event.content.body}${fileSize} < ${url} >`;
        }
    }
    return new MatrixAction(type, text, htmlText, event.origin_server_ts);
};
MatrixAction.fromIrcAction = function(ircAction) {
    switch (ircAction.type) {
        case "message":
        case "emote":
        case "notice":
            let htmlText = ircFormatting.ircToHtml(ircAction.text);
            return new MatrixAction(
                ircAction.type,
                ircFormatting.stripIrcFormatting(ircAction.text),
                // only set HTML text if we think there is HTML, else the bridge
                // will send everything as HTML and never text only.
                ircAction.text !== htmlText ? htmlText : undefined
            );
        case "topic":
            return new MatrixAction("topic", ircAction.text);
        default:
            log.error("MatrixAction.fromIrcAction: Unknown action: %s", ircAction.type);
            return null;
    }
};

function MentionRegex(matcher) {
    const WORD_BOUNDARY = "^|\:|\#|```|\\s|$|,";
    return new RegExp(
        `(${WORD_BOUNDARY})(@?(${matcher}))(?=${WORD_BOUNDARY})`,
        "igmu"
    );
}

module.exports = MatrixAction;
<commit_msg>Trailing spaces have been neutralised<commit_after>/*eslint no-invalid-this: 0*/ // eslint doesn't understand Promise.coroutine wrapping
"use strict";
const ircFormatting = require("../irc/formatting");
const log = require("../logging").get("MatrixAction");
const ContentRepo = require("matrix-appservice-bridge").ContentRepo;
const escapeStringRegexp = require('escape-string-regexp');
const Promise = require("bluebird");

const ACTION_TYPES = ["message", "emote", "topic", "notice", "file", "image", "video", "audio"];
const EVENT_TO_TYPE = {
    "m.room.message": "message",
    "m.room.topic": "topic"
};
const MSGTYPE_TO_TYPE = {
    "m.emote": "emote",
    "m.notice": "notice",
    "m.image": "image",
    "m.video": "video",
    "m.audio": "audio",
    "m.file": "file"
};

const PILL_MIN_LENGTH_TO_MATCH = 4;
const MAX_MATCHES = 5;

function MatrixAction(type, text, htmlText, timestamp) {
    if (ACTION_TYPES.indexOf(type) === -1) {
        throw new Error("Unknown MatrixAction type: " + type);
    }
    this.type = type;
    this.text = text;
    this.htmlText = htmlText;
    this.ts = timestamp || 0;
}

MatrixAction.prototype.formatMentions = Promise.coroutine(function*(nickUserIdMap, intent) {
    const regexString = "(" +
        Object.keys(nickUserIdMap).map((value) => escapeStringRegexp(value)).join("|")
        + ")";
    const usersRegex = MentionRegex(regexString);
    const matched = new Set(); // lowercased nicknames we have matched already.
    let match;
    for (let i = 0; i < MAX_MATCHES && (match = usersRegex.exec(this.text)) !== null; i++) {
        let matchName = match[2];
        // Deliberately have a minimum length to match on,
        // so we don't match smaller nicks accidentally.
        if (matchName.length < PILL_MIN_LENGTH_TO_MATCH || matched.has(matchName.toLowerCase())) {
            continue;
        }
        let userId = nickUserIdMap[matchName];
        if (userId === undefined) {
            // We might need to search case-insensitive.
            const nick = Object.keys(nickUserIdMap).find((n) =>
                n.toLowerCase() === matchName.toLowerCase()
            );
            if (nick === undefined) {
                continue;
            }
            userId = nickUserIdMap[nick];
            matchName = nick;
        }
        // If this message is not HTML, we should make it so.
        if (this.htmlText === undefined) {
            // This looks scary and unsafe, but further down we check
            // if `text` contains any HTML and escape + set `htmlText` appropriately.
            this.htmlText = this.text;
        }
        userId = ircFormatting.escapeHtmlChars(userId);

        /* Due to how Riot and friends do push notifications,
           we need the plain text to match something.*/
        let identifier;
        try {
            identifier = yield intent.getProfileInfo(userId, 'displayname', true).displayname;
        }
        catch (e) {
            // This shouldn't happen, but let's not fail to match if so.
        }

        if (identifier === undefined) {
            // Fallback to userid.
            identifier = userId.substr(1, userId.indexOf(":")-1)
        }

        const regex = MentionRegex(escapeStringRegexp(matchName));
        this.htmlText = this.htmlText.replace(regex,
`$1<a href="https://matrix.to/#/${userId}">${ircFormatting.escapeHtmlChars(identifier)}</a>`
        );
        this.text = this.text.replace(regex, `$1${identifier}`);
        // Don't match this name twice, we've already replaced all entries.
        matched.add(matchName.toLowerCase());
    }
});

MatrixAction.fromEvent = function(client, event, mediaUrl) {
    event.content = event.content || {};
    let type = EVENT_TO_TYPE[event.type] || "message"; // mx event type to action type
    let text = event.content.body;
    let htmlText = null;

    if (event.type === "m.room.topic") {
        text = event.content.topic;
    }
    else if (event.type === "m.room.message") {
        if (event.content.format === "org.matrix.custom.html") {
            htmlText = event.content.formatted_body;
        }
        if (MSGTYPE_TO_TYPE[event.content.msgtype]) {
            type = MSGTYPE_TO_TYPE[event.content.msgtype];
        }
        if (["m.image", "m.file", "m.video", "m.audio"].indexOf(event.content.msgtype) !== -1) {
            var fileSize = "";
            if (event.content.info && event.content.info.size &&
                    typeof event.content.info.size === "number") {
                fileSize = " (" + Math.round(event.content.info.size / 1024) + "KB)";
            }

            // By default assume that the media server = client homeserver
            if (!mediaUrl) {
                mediaUrl = client.getHomeserverUrl();
            }

            const url = ContentRepo.getHttpUriForMxc(mediaUrl, event.content.url);
            text = `${event.content.body}${fileSize} < ${url} >`;
        }
    }
    return new MatrixAction(type, text, htmlText, event.origin_server_ts);
};
MatrixAction.fromIrcAction = function(ircAction) {
    switch (ircAction.type) {
        case "message":
        case "emote":
        case "notice":
            let htmlText = ircFormatting.ircToHtml(ircAction.text);
            return new MatrixAction(
                ircAction.type,
                ircFormatting.stripIrcFormatting(ircAction.text),
                // only set HTML text if we think there is HTML, else the bridge
                // will send everything as HTML and never text only.
                ircAction.text !== htmlText ? htmlText : undefined
            );
        case "topic":
            return new MatrixAction("topic", ircAction.text);
        default:
            log.error("MatrixAction.fromIrcAction: Unknown action: %s", ircAction.type);
            return null;
    }
};

function MentionRegex(matcher) {
    const WORD_BOUNDARY = "^|\:|\#|```|\\s|$|,";
    return new RegExp(
        `(${WORD_BOUNDARY})(@?(${matcher}))(?=${WORD_BOUNDARY})`,
        "igmu"
    );
}

module.exports = MatrixAction;
<|endoftext|>


<commit_before>'use strict';
var BucketQuery = function (bucket, matches, options) {
  return {
    bucket: bucket,
    matches: matches,
    isTruncated: false,
    marker: options.marker,
    prefix: options.prefix,
    maxKeys: options.maxKeys,
    delimiter: options.delimiter
  };
};
module.exports = BucketQuery;<commit_msg>Pass options to create a s3rver instance instead of multiple arguments. Update tests client instansiation and docs to reflect this<commit_after><|endoftext|>


<commit_before>/*
 * Copyright 2017 Teppo Kurki <teppo.kurki@iki.fi>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const debug = require("debug")("signalk-server:interfaces:charts");
const Promise = require("bluebird");
const fs = Promise.promisifyAll(require("fs"));
const MBTiles = require("@mapbox/mbtiles");
const _ = require('lodash');

const pathPrefix = "/signalk";
const versionPrefix = "/v1";
const apiPathPrefix = pathPrefix + versionPrefix + "/api/";
const parseStringAsync = Promise.promisify(require("xml2js").parseString);
const path = require("path");
const chartBaseDir = path.join(__dirname, "..", "..", "public", "mapcache");

const chartProviders = {};
loadCharts();

module.exports = function(app) {
  const api = {};

  api.start = function() {
    debug("Starting charts interface");

    app.get(apiPathPrefix + "resources/charts/*", (req, res, next) => {
      loadCharts(app, req).then(charts => {
        var parts = req.path.split("/");
        var chart_parts = parts.slice(6);

        if (typeof charts[chart_parts[0]] !== "undefined") {
          res.json(charts[chart_parts[0]]);
        } else {
          res.status(404).send("Not found");
        }
      });
    });

    app.get(apiPathPrefix + "resources/charts", (req, res, next) => {
      loadCharts(app, req)
        .then(charts => {
          res.json(charts);
        })
        .catch(err => {
          console.error(err.message);
          res.json({});
        });
    });

    app.get("/charts/:map/:z/:x/:y", (req, res) => {
      const { map, z, x, y } = req.params;
      const provider = chartProviders[map];
      if (!provider) {
        res.sendStatus(404);
        return;
      }
      provider.getTile(z, x, y, (err, tile, headers) => {
        if (err && err.message && err.message === "Tile does not exist") {
          res.sendStatus(404);
        } else if (err) {
          console.error(`Error fetching tile ${map}/${z}/${x}/${y}:`, err);
          res.sendStatus(500);
        } else {
          headers["Cache-Control"] = "public, max-age=7776000"; // 90 days
          res.writeHead(200, headers);
          res.end(tile);
        }
      });
    });
  };

  api.stop = function() {};

  return api;
};

function loadCharts(app, req) {
  return fs
    .readdirAsync(chartBaseDir)
    .then(files => {
      return Promise.props(
        files.reduce((result, file) => {
          result[file] = fs
            .statAsync(path.join(chartBaseDir, file))
            .then(stat => {
              if (stat.isDirectory()) {
                return directoryToMapInfo(file);
              } else {
                return fileToMapInfo(file);
              }
            })
            .catch(err => {
              console.error(err + " " + file);
              return undefined;
            });
          return result;
        }, {})
      );
    })
    .catch(err => {
      console.error("Error reading " + chartBaseDir);
      return {};
    });
}

function directoryToMapInfo(dir) {
  const resourceFile = path.join(chartBaseDir, dir, 'tilemapresource.xml');
  return fs
    .readFileAsync(resourceFile)
    .then(resXml => {
      return parseStringAsync(resXml);
    })
    .then(parsed => {
      const result = parsed.TileMap;
      var scale = "250000";
      if (typeof result.Metadata !== "undefined") {
        var metaScale = result.Metadata[0]["$"].scale;
        if (typeof metaScale !== "undefined") scale = metaScale;
      }

      return {
        identifier: dir,
        name: result.Title[0],
        description: result.Title[0],
        tilemapUrl: "/mapcache/" + dir,
        scale: parseInt(scale)
      };
    })
    .catch(err => {
      console.error("Error reading " + resourceFile + " " + err.message);
      return undefined;
    });
}

function fileToMapInfo(file) {
  return new Promise((resolve, reject) => {
    new MBTiles(path.join(chartBaseDir, file), (err, mbtiles) => {
      if (err) {
        reject(err);
      }
      mbtiles.getInfo((err, mbtilesData) => {
        if (err) {
          reject(err);
        }
        if (_.isUndefined(mbtilesData) || _.isUndefined(mbtilesData.name)) {
          resolve(undefined);
        }
        chartProviders[file] = mbtiles;
        resolve({
          identifier: file,
          name: mbtilesData.name,
          description: mbtilesData.description,
          bounds: mbtilesData.bounds,
          minzoom: mbtilesData.minzoom,
          maxzoom: mbtilesData.maxzoom,
          format: mbtilesData.format,
          tilemapUrl: "/charts/" + file + "/{z}/{x}/{y}",
          type: "tilelayer",
          scale: "250000"
        });
      });
    });
  });
}
<commit_msg>fix: add return statements<commit_after>/*
 * Copyright 2017 Teppo Kurki <teppo.kurki@iki.fi>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const debug = require("debug")("signalk-server:interfaces:charts");
const Promise = require("bluebird");
const fs = Promise.promisifyAll(require("fs"));
const MBTiles = require("@mapbox/mbtiles");
const _ = require('lodash');

const pathPrefix = "/signalk";
const versionPrefix = "/v1";
const apiPathPrefix = pathPrefix + versionPrefix + "/api/";
const parseStringAsync = Promise.promisify(require("xml2js").parseString);
const path = require("path");
const chartBaseDir = path.join(__dirname, "..", "..", "public", "mapcache");

const chartProviders = {};
loadCharts();

module.exports = function(app) {
  const api = {};

  api.start = function() {
    debug("Starting charts interface");

    app.get(apiPathPrefix + "resources/charts/*", (req, res, next) => {
      loadCharts(app, req).then(charts => {
        var parts = req.path.split("/");
        var chart_parts = parts.slice(6);

        if (typeof charts[chart_parts[0]] !== "undefined") {
          res.json(charts[chart_parts[0]]);
        } else {
          res.status(404).send("Not found");
        }
      });
    });

    app.get(apiPathPrefix + "resources/charts", (req, res, next) => {
      loadCharts(app, req)
        .then(charts => {
          res.json(charts);
        })
        .catch(err => {
          console.error(err.message);
          res.json({});
        });
    });

    app.get("/charts/:map/:z/:x/:y", (req, res) => {
      const { map, z, x, y } = req.params;
      const provider = chartProviders[map];
      if (!provider) {
        res.sendStatus(404);
        return;
      }
      provider.getTile(z, x, y, (err, tile, headers) => {
        if (err && err.message && err.message === "Tile does not exist") {
          res.sendStatus(404);
        } else if (err) {
          console.error(`Error fetching tile ${map}/${z}/${x}/${y}:`, err);
          res.sendStatus(500);
        } else {
          headers["Cache-Control"] = "public, max-age=7776000"; // 90 days
          res.writeHead(200, headers);
          res.end(tile);
        }
      });
    });
  };

  api.stop = function() {};

  return api;
};

function loadCharts(app, req) {
  return fs
    .readdirAsync(chartBaseDir)
    .then(files => {
      return Promise.props(
        files.reduce((result, file) => {
          result[file] = fs
            .statAsync(path.join(chartBaseDir, file))
            .then(stat => {
              if (stat.isDirectory()) {
                return directoryToMapInfo(file);
              } else {
                return fileToMapInfo(file);
              }
            })
            .catch(err => {
              console.error(err + " " + file);
              return undefined;
            });
          return result;
        }, {})
      );
    })
    .catch(err => {
      console.error("Error reading " + chartBaseDir);
      return {};
    });
}

function directoryToMapInfo(dir) {
  const resourceFile = path.join(chartBaseDir, dir, 'tilemapresource.xml');
  return fs
    .readFileAsync(resourceFile)
    .then(resXml => {
      return parseStringAsync(resXml);
    })
    .then(parsed => {
      const result = parsed.TileMap;
      var scale = "250000";
      if (typeof result.Metadata !== "undefined") {
        var metaScale = result.Metadata[0]["$"].scale;
        if (typeof metaScale !== "undefined") scale = metaScale;
      }

      return {
        identifier: dir,
        name: result.Title[0],
        description: result.Title[0],
        tilemapUrl: "/mapcache/" + dir,
        scale: parseInt(scale)
      };
    })
    .catch(err => {
      console.error("Error reading " + resourceFile + " " + err.message);
      return undefined;
    });
}

function fileToMapInfo(file) {
  return new Promise((resolve, reject) => {
    new MBTiles(path.join(chartBaseDir, file), (err, mbtiles) => {
      if (err) {
        reject(err);
        return;
      }
      mbtiles.getInfo((err, mbtilesData) => {
        if (err) {
          reject(err);
          return;
        }
        if (_.isUndefined(mbtilesData) || _.isUndefined(mbtilesData.name)) {
          resolve(undefined);
          return;
        }
        chartProviders[file] = mbtiles;
        resolve({
          identifier: file,
          name: mbtilesData.name,
          description: mbtilesData.description,
          bounds: mbtilesData.bounds,
          minzoom: mbtilesData.minzoom,
          maxzoom: mbtilesData.maxzoom,
          format: mbtilesData.format,
          tilemapUrl: "/charts/" + file + "/{z}/{x}/{y}",
          type: "tilelayer",
          scale: "250000"
        });
      });
    });
  });
}
<|endoftext|>


<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, 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 ' + rid + ' 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 ' + rid + ' 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;
<commit_msg>Support for relative Location: redirects<commit_after>/*!
 * node.io
 * Copyright(c) 2010 Chris O'Hara <cohara87@gmail.com>
 * MIT Licensed
 */

var http = require('http'),
    resolve = require('url').resolve,
    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 ' + rid + ' 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 ' + rid + ' 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);
                    var location = resolve(resource, response.headers.location);
                    self.doRequest(method, 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>/**
 * matrix.js
 * http://github.com/sjkaliski/numbers.js
 *
 * Copyright 2012 Stephen Kaliski
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var numbers = require('../numbers');
var basic = numbers.basic;

var Complex = function (re, im) {
  this.re = re;
  this.im = im;
  this.r  = this.magnitude();
  this.t  = this.phase(); // theta = t = arg(z)
};

/**
 * Add a complex number to this one.
 *
 * @param {Complex} Number to add.
 * @return {Complex} New complex number (sum).
 */
Complex.prototype.add = function(addend) {
  return new Complex(this.re + addend.re, this.im + addend.im);
};

/**
 * Subtract a complex number from this one.
 *
 * @param {Complex} Number to subtract.
 * @return {Complex} New complex number (difference).
 */
Complex.prototype.subtract = function (subtrahend) {
  return new Complex(this.re - subtrahend.re, this.im - subtrahend.im);
};

/**
 * Multiply a complex number with this one.
 *
 * @param {Complex} Number to multiply by.
 * @return {Complex} New complex number (product).
 */
Complex.prototype.multiply = function (multiplier) {
  var re = this.re * multiplier.re - this.im * multiplier.im;
  var im = this.im * multiplier.re + this.re * multiplier.im;

  return new Complex(re, im);
};

/**
 * Divide this number with another complex number.
 *
 * @param {Complex} Divisor.
 * @return {Complex} New complex number (quotient).
 */
Complex.prototype.divide = function (divisor) {
  var denominator = divisor.re * divisor.re + divisor.im * divisor.im;
  var re = (this.re * divisor.re + this.im * divisor.im) / denominator;
  var im = (this.im * divisor.re - this.re * divisor.im) / denominator;

  return new Complex(re,im);
};

/**
 * Get the magnitude of this number.
 *
 * @return {Number} Magnitude.
 */
Complex.prototype.magnitude = function () {
  return Math.sqrt(this.re * this.re + this.im * this.im);
};

/**
 * Get the phase of this number.
 *
 * @return {Number} Phase.
 */
Complex.prototype.phase = function () {
  return Math.atan2(this.im, this.re);
};

/**
 * Conjugate the imaginary part
 *
 * @return {Complex} Conjugated number
 */
Complex.prototype.conjugate = function () {
  return new Complex(this.re, -1 * this.im);
};

/**
 * Raises this complex number to the nth power.
 *
 * @param {number} power to raise this complex number to.
 * @return {Complex} the nth power of this complex number.
 */
Complex.prototype.pow = function(n) {
  var constant = Math.pow(this.magnitude(), n);

  return new Complex(constant * Math.cos(n * this.phase()), constant * Math.sin(n * this.phase()));
};

/**
 * Find all the nth roots of this complex number.
 *
 * @param {Number} root of this complex number to take.
 * @return {Array} an array of size n with the roots of this complex number.
 */
Complex.prototype.roots = function(n) {
  var result = new Array(n);

  for(var i = 0; i < n; i++) {
    var theta = (this.phase() + 2*Math.PI*i) / n;
    var radiusConstant = Math.pow(this.magnitude(), 1/n);
    result[i] = (new Complex(radiusConstant * Math.cos(theta), radiusConstant * Math.sin(theta)))
  }

  return result;
};

/**
 * Raises this complex number to given complex power.
 *
 * @param complexN the complex number to raise this complex number to.
 * @return {Complex} this complex number raised to the given complex number.
 */
Complex.prototype.complexPow = function(complexN) {
  var realSqPlusImSq =  Math.pow(this.re, 2) + Math.pow(this.im, 2);
  var multiplier = Math.pow(realSqPlusImSq, complexN.re/2) * Math.pow(Math.E, -complexN.im * this.phase());
  var theta = complexN.re * this.phase() + .5 * complexN.im * Math.log(realSqPlusImSq);

  return new Complex(multiplier * Math.cos(theta), multiplier * Math.sin(theta));
};

/**
 * Returns the sine of this complex number.
 *
 * @return {Complex} the sine of this complex number.
 */
Complex.prototype.sin = function() {
  var E = new Complex(Math.E, 0);
  var i = new Complex(0, 1);
  var negativeI = new Complex(0, -1);
  var numerator = E.complexPow(i.multiply(this)).subtract(E.complexPow(negativeI.multiply(this)));

  return numerator.divide(new Complex(0, 2));
};

/**
 * Returns the cosine of this complex number.
 *
 * @return {Complex} the cosine of this complex number.
 */
Complex.prototype.cos = function() {
  var E = new Complex(Math.E, 0);
  var i = new Complex(0, 1);
  var negativeI = new Complex(0, -1);
  var numerator = E.complexPow(i.multiply(this)).add(E.complexPow(negativeI.multiply(this)));

  return numerator.divide(new Complex(2, 0));
};

/**
 * Returns the tangent of this complex number.
 *
 * @return {Complex} the cosine of this complex number.
 */
Complex.prototype.tan = function() {
  return this.sin().divide(this.cos());
};

/**
 * Checks for equality between this complex number and another
 * within a given range defined by epsilon.
 *
 * @param {Complex} complex number to check this number against.
 * @param {Number} epsilon
 * @return {boolean} true if equal within epsilon, false otherwise
 */
Complex.prototype.equals = function(complex, epsilon) {
  return basic.numbersEqual(this.re, complex.re, epsilon) &&
         basic.numbersEqual(this.im, complex.im, epsilon);
};

module.exports = Complex;
<commit_msg>move method<commit_after>/**
 * matrix.js
 * http://github.com/sjkaliski/numbers.js
 *
 * Copyright 2012 Stephen Kaliski
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var numbers = require('../numbers');
var basic = numbers.basic;

var Complex = function (re, im) {
  this.re = re;
  this.im = im;
  this.r  = this.magnitude();
  this.t  = this.phase(); // theta = t = arg(z)
};

/**
 * Add a complex number to this one.
 *
 * @param {Complex} Number to add.
 * @return {Complex} New complex number (sum).
 */
Complex.prototype.add = function(addend) {
  return new Complex(this.re + addend.re, this.im + addend.im);
};

/**
 * Subtract a complex number from this one.
 *
 * @param {Complex} Number to subtract.
 * @return {Complex} New complex number (difference).
 */
Complex.prototype.subtract = function (subtrahend) {
  return new Complex(this.re - subtrahend.re, this.im - subtrahend.im);
};

/**
 * Multiply a complex number with this one.
 *
 * @param {Complex} Number to multiply by.
 * @return {Complex} New complex number (product).
 */
Complex.prototype.multiply = function (multiplier) {
  var re = this.re * multiplier.re - this.im * multiplier.im;
  var im = this.im * multiplier.re + this.re * multiplier.im;

  return new Complex(re, im);
};

/**
 * Divide this number with another complex number.
 *
 * @param {Complex} Divisor.
 * @return {Complex} New complex number (quotient).
 */
Complex.prototype.divide = function (divisor) {
  var denominator = divisor.re * divisor.re + divisor.im * divisor.im;
  var re = (this.re * divisor.re + this.im * divisor.im) / denominator;
  var im = (this.im * divisor.re - this.re * divisor.im) / denominator;

  return new Complex(re,im);
};

/**
 * Get the magnitude of this number.
 *
 * @return {Number} Magnitude.
 */
Complex.prototype.magnitude = function () {
  return Math.sqrt(this.re * this.re + this.im * this.im);
};

/**
 * Get the phase of this number.
 *
 * @return {Number} Phase.
 */
Complex.prototype.phase = function () {
  return Math.atan2(this.im, this.re);
};

/**
 * Conjugate the imaginary part
 *
 * @return {Complex} Conjugated number
 */
Complex.prototype.conjugate = function () {
  return new Complex(this.re, -1 * this.im);
};

/**
 * Raises this complex number to the nth power.
 *
 * @param {number} power to raise this complex number to.
 * @return {Complex} the nth power of this complex number.
 */
Complex.prototype.pow = function(n) {
  var constant = Math.pow(this.magnitude(), n);

  return new Complex(constant * Math.cos(n * this.phase()), constant * Math.sin(n * this.phase()));
};

/**
 * Raises this complex number to given complex power.
 *
 * @param complexN the complex number to raise this complex number to.
 * @return {Complex} this complex number raised to the given complex number.
 */
Complex.prototype.complexPow = function(complexN) {
  var realSqPlusImSq =  Math.pow(this.re, 2) + Math.pow(this.im, 2);
  var multiplier = Math.pow(realSqPlusImSq, complexN.re/2) * Math.pow(Math.E, -complexN.im * this.phase());
  var theta = complexN.re * this.phase() + .5 * complexN.im * Math.log(realSqPlusImSq);

  return new Complex(multiplier * Math.cos(theta), multiplier * Math.sin(theta));
};

/**
 * Find all the nth roots of this complex number.
 *
 * @param {Number} root of this complex number to take.
 * @return {Array} an array of size n with the roots of this complex number.
 */
Complex.prototype.roots = function(n) {
  var result = new Array(n);

  for(var i = 0; i < n; i++) {
    var theta = (this.phase() + 2*Math.PI*i) / n;
    var radiusConstant = Math.pow(this.magnitude(), 1/n);

    result[i] = (new Complex(radiusConstant * Math.cos(theta), radiusConstant * Math.sin(theta)))
  }

  return result;
};

/**
 * Returns the sine of this complex number.
 *
 * @return {Complex} the sine of this complex number.
 */
Complex.prototype.sin = function() {
  var E = new Complex(Math.E, 0);
  var i = new Complex(0, 1);
  var negativeI = new Complex(0, -1);
  var numerator = E.complexPow(i.multiply(this)).subtract(E.complexPow(negativeI.multiply(this)));

  return numerator.divide(new Complex(0, 2));
};

/**
 * Returns the cosine of this complex number.
 *
 * @return {Complex} the cosine of this complex number.
 */
Complex.prototype.cos = function() {
  var E = new Complex(Math.E, 0);
  var i = new Complex(0, 1);
  var negativeI = new Complex(0, -1);
  var numerator = E.complexPow(i.multiply(this)).add(E.complexPow(negativeI.multiply(this)));

  return numerator.divide(new Complex(2, 0));
};

/**
 * Returns the tangent of this complex number.
 *
 * @return {Complex} the cosine of this complex number.
 */
Complex.prototype.tan = function() {
  return this.sin().divide(this.cos());
};

/**
 * Checks for equality between this complex number and another
 * within a given range defined by epsilon.
 *
 * @param {Complex} complex number to check this number against.
 * @param {Number} epsilon
 * @return {boolean} true if equal within epsilon, false otherwise
 */
Complex.prototype.equals = function(complex, epsilon) {
  return basic.numbersEqual(this.re, complex.re, epsilon) &&
         basic.numbersEqual(this.im, complex.im, epsilon);
};

module.exports = Complex;
<|endoftext|>