<commit_before>var mapnik = require('mapnik');
var zlib = require('zlib');
var path = require('path');
var util = require('util');
var crypto = require('crypto');

module.exports = Vector;

function Task() {
    this.err = null;
    this.headers = {};
    this.access = +new Date;
    this.done;
    this.body;
    return;
};
util.inherits(Task, require('events').EventEmitter);

function Vector(uri, callback) {
    if (!uri.backend) return callback && callback(new Error('No datatile backend'));
    if (!uri.xml) return callback && callback(new Error('No xml'));

    this._uri = uri;
    this._scale = uri.scale || 1;
    this._format = uri.format || 'png8:m=h';
    this._maxAge = typeof uri.maxAge === 'number' ? uri.maxAge : 300e3;
    this._deflate = typeof uri.deflate === 'boolean' ? uri.deflate : true;
    this._reap = typeof uri.reap === 'number' ? uri.reap : 60e3;
    this._base = path.resolve(uri.base || __dirname);

    if (callback) this.once('open', callback);

    this.update(uri, function(err) {
        this.emit('open', err, this);
    }.bind(this));
};
util.inherits(Vector, require('events').EventEmitter);

// Helper for callers to ensure source is open. This is not built directly
// into the constructor because there is no good auto cache-keying system
// for these tile sources (ie. sharing/caching is best left to the caller).
Vector.prototype.open = function(callback) {
    if (this._map) return callback(null, this);
    this.once('open', callback);
};

// Allows in-place update of XML/backends.
Vector.prototype.update = function(opts, callback) {
    // Scale.
    if (opts.scale && this._scale !== opts.scale) {
        this._scale = opts.scale;
    }
    // If the backend has changed, the datatile cache must be cleared.
    if (opts.backend && this._backend !== opts.backend) {
        opts.backend._vectorCache = {};
        this._backend = opts.backend;
        delete this._minzoom;
        delete this._maxzoom;
        delete this._maskLevel;
    }
    // If the XML has changed update the map.
    if (opts.xml && this._xml !== opts.xml) {
        var map = new mapnik.Map(256,256);
        map.fromString(opts.xml, {
            strict: false,
            base: this._base + '/'
        }, function(err) {
            delete this._info;
            map.bufferSize = 256 * this._scale;
            this._xml = opts.xml;
            this._map = map;
            this._md5 = crypto.createHash('md5').update(opts.xml).digest('hex');
            return callback(err);
        }.bind(this));
        return;
    }
    return callback();
};

// Wrapper around backend.getTile that implements a "locking" cache.
Vector.prototype.sourceTile = function(backend, z, x, y, callback) {
    var source = this;
    var now = +new Date;
    var key = z + '/' + x + '/' + y;
    var cache = backend._vectorCache[key];

    // Reap cached vector tiles with stale access times on an interval.
    if (source._reap && !backend._vectorTimeout) backend._vectorTimeout = setTimeout(function() {
        var now = +new Date;
        Object.keys(backend._vectorCache).forEach(function(key) {
            if ((now - backend._vectorCache[key].access) < source._maxAge) return;
            delete backend._vectorCache[key];
        });
        delete backend._vectorTimeout;
    }, source._reap);

    // Expire cached tiles when they are past maxAge.
    if (cache && (now-cache.access) >= source._maxAge) cache = false;

    // Return cache if finished.
    if (cache && cache.done) {
        cache.access = now;
        return callback(null, cache.body, cache.headers);
    // Otherwise add listener if task is in progress.
    } else if (cache) {
        return cache.once('done', callback);
    }

    var task = new Task();
    task.once('done', callback);

    var done = function(err, body, headers) {
        if (err) delete backend._vectorCache[key];
        task.done = true;
        task.body = body;
        task.headers = headers;
        task.emit('done', err, body, headers);
    };
    backend._vectorCache[key] = task;
    backend.getTile(z, x, y, function(err, body, headers) {
        if (err) return done(err);

        // If the source vector tiles are not using deflate, we're done.
        if (!source._deflate) return done(err, body, headers);

        // Otherwise, inflate the data.
        zlib.inflate(body, function(err, body) { return done(err, body, headers); });
    });
};

Vector.prototype.drawTile = function(bz, bx, by, z, x, y, format, callback) {
    var source = this;
    source.sourceTile(this._backend, bz, bx, by, function(err, data, head) {
        if (err && err.message !== 'Tile does not exist')
            return callback(err);

        if (err && source._maskLevel && bz > source._maskLevel)
            return callback(err);

        var datatile = new mapnik.DataTile(bz, bx, by);
        datatile.setData(data || new Buffer(0), function(err, success) {
            var opts = {z:z, x:x, y:y, scale:source._scale};
            datatile.render(source._map, new mapnik.Image(256,256), opts, function(err, image) {
                if (err) return callback(err);
                image.encode(format, {}, function(err, buffer) {
                    if (err) return callback(err);
                    var headers = {};
                    headers['Content-Type'] = format.indexOf('jpeg') === 0
                        ? 'image/jpeg'
                        : 'image/png';
                    headers['ETag'] = JSON.stringify(crypto.createHash('md5')
                        .update(source._scale + source._md5 + (head && head['ETag'] || (z+','+x+','+y)))
                        .digest('hex'));
                    return callback(null, buffer, headers);
                });
            });
        });
    });
};

Vector.prototype.getTile = function(z, x, y, callback) {
    if (!this._map) return callback(new Error('Tilesource not loaded'));

    // Lazy load min/maxzoom/maskLevel info.
    if (this._maxzoom === undefined) return this._backend.getInfo(function(err, info) {
        if (err) return callback(err);

        this._minzoom = info.minzoom || 0;
        this._maxzoom = info.maxzoom || 22;

        // @TODO massive hack to avoid conflict with tilelive-s3's
        // interpretation of 'maskLevel' key. Fix this by removing
        // masking entirely from the next version of tilelive-s3.
        if (this._backend.data && this._backend.data.maskLevel) {
            this._backend.data._maskLevel = this._backend.data.maskLevel;
            delete this._backend.data.maskLevel;
        }
        if (this._backend.data && this._backend.data._maskLevel) {
            this._maskLevel = this._backend.data._maskLevel;
        }
        // Support specifying maskLevel in other sources (mbtiles).
        if (info.maskLevel) {
            this._maskLevel = parseInt(info.maskLevel, 10);
        }

        return this.getTile(z, x, y, callback);
    }.bind(this));

    // If scale > 1 adjusts source data zoom level inversely.
    // scale 2x => z-1, scale 4x => z-2, scale 8x => z-3, etc.
    var d = Math.round(Math.log(this._scale)/Math.log(2));
    var bz = (z - d) > this._minzoom ? z - d : this._minzoom;
    var bx = Math.floor(x / Math.pow(2, z - bz));
    var by = Math.floor(y / Math.pow(2, z - bz));

    // Overzooming support.
    if (bz > this._maxzoom) {
        bz = this._maxzoom;
        bx = Math.floor(x / Math.pow(2, z - this._maxzoom));
        by = Math.floor(y / Math.pow(2, z - this._maxzoom));
    }

    // Hack around tilelive API - allow params to be passed per request
    // as attributes of the callback function.
    var format = callback.format || this._format;

    // For nonmasked sources or bz within the maskrange attempt 1 draw.
    if (!this._maskLevel || bz <= this._maskLevel)
        return this.drawTile(bz,bx,by,z,x,y,format,callback);

    // Above the maskLevel errors should attempt a second draw using the mask.
    this.drawTile(bz,bx,by,z,x,y,format,function(err, buffer, headers) {
        if (!err) return callback(err, buffer, headers);
        if (err && err.message !== 'Tile does not exist') return callback(err);
        bz = this._maskLevel;
        bx = Math.floor(x / Math.pow(2, z - this._maskLevel));
        by = Math.floor(y / Math.pow(2, z - this._maskLevel));
        this.drawTile(bz, bx, by, z, x, y, format, callback);
    }.bind(this));
};

// @TODO
Vector.prototype.getGrid = function(z, x, y, callback) {
    return callback(new Error('Grid does not exist'));
};

Vector.prototype.getInfo = function(callback) {
    if (!this._map) return callback(new Error('Tilesource not loaded'));
    if (this._info) return callback(null, this._info);

    var params = this._map.parameters;
    this._info = Object.keys(params).reduce(function(memo, key) {
        switch (key) {
        case 'bounds':
        case 'center':
            memo[key] = params[key].split(',').map(function(v) { return parseFloat(v) });
            break;
        case 'minzoom':
        case 'maxzoom':
            memo[key] = parseInt(params[key], 10);
            break;
        default:
            memo[key] = params[key];
            break;
        }
        return memo;
    }, {});
    return callback(null, this._info);
};

<commit_msg>Add grid rendering support.<commit_after>var mapnik = require('mapnik');
var zlib = require('zlib');
var path = require('path');
var util = require('util');
var crypto = require('crypto');

module.exports = Vector;

function Task() {
    this.err = null;
    this.headers = {};
    this.access = +new Date;
    this.done;
    this.body;
    return;
};
util.inherits(Task, require('events').EventEmitter);

function Vector(uri, callback) {
    if (!uri.backend) return callback && callback(new Error('No datatile backend'));
    if (!uri.xml) return callback && callback(new Error('No xml'));

    this._uri = uri;
    this._scale = uri.scale || 1;
    this._format = uri.format || 'png8:m=h';
    this._maxAge = typeof uri.maxAge === 'number' ? uri.maxAge : 300e3;
    this._deflate = typeof uri.deflate === 'boolean' ? uri.deflate : true;
    this._reap = typeof uri.reap === 'number' ? uri.reap : 60e3;
    this._base = path.resolve(uri.base || __dirname);

    if (callback) this.once('open', callback);

    this.update(uri, function(err) {
        this.emit('open', err, this);
    }.bind(this));
};
util.inherits(Vector, require('events').EventEmitter);

// Helper for callers to ensure source is open. This is not built directly
// into the constructor because there is no good auto cache-keying system
// for these tile sources (ie. sharing/caching is best left to the caller).
Vector.prototype.open = function(callback) {
    if (this._map) return callback(null, this);
    this.once('open', callback);
};

// Allows in-place update of XML/backends.
Vector.prototype.update = function(opts, callback) {
    // Scale.
    if (opts.scale && this._scale !== opts.scale) {
        this._scale = opts.scale;
    }
    // If the backend has changed, the datatile cache must be cleared.
    if (opts.backend && this._backend !== opts.backend) {
        opts.backend._vectorCache = {};
        this._backend = opts.backend;
        delete this._minzoom;
        delete this._maxzoom;
        delete this._maskLevel;
    }
    // If the XML has changed update the map.
    if (opts.xml && this._xml !== opts.xml) {
        var map = new mapnik.Map(256,256);
        map.fromString(opts.xml, {
            strict: false,
            base: this._base + '/'
        }, function(err) {
            delete this._info;
            map.bufferSize = 256 * this._scale;
            this._xml = opts.xml;
            this._map = map;
            this._md5 = crypto.createHash('md5').update(opts.xml).digest('hex');
            return callback(err);
        }.bind(this));
        return;
    }
    return callback();
};

// Wrapper around backend.getTile that implements a "locking" cache.
Vector.prototype.sourceTile = function(backend, z, x, y, callback) {
    var source = this;
    var now = +new Date;
    var key = z + '/' + x + '/' + y;
    var cache = backend._vectorCache[key];

    // Reap cached vector tiles with stale access times on an interval.
    if (source._reap && !backend._vectorTimeout) backend._vectorTimeout = setTimeout(function() {
        var now = +new Date;
        Object.keys(backend._vectorCache).forEach(function(key) {
            if ((now - backend._vectorCache[key].access) < source._maxAge) return;
            delete backend._vectorCache[key];
        });
        delete backend._vectorTimeout;
    }, source._reap);

    // Expire cached tiles when they are past maxAge.
    if (cache && (now-cache.access) >= source._maxAge) cache = false;

    // Return cache if finished.
    if (cache && cache.done) {
        cache.access = now;
        return callback(null, cache.body, cache.headers);
    // Otherwise add listener if task is in progress.
    } else if (cache) {
        return cache.once('done', callback);
    }

    var task = new Task();
    task.once('done', callback);

    var done = function(err, body, headers) {
        if (err) delete backend._vectorCache[key];
        task.done = true;
        task.body = body;
        task.headers = headers;
        task.emit('done', err, body, headers);
    };
    backend._vectorCache[key] = task;
    backend.getTile(z, x, y, function(err, body, headers) {
        if (err) return done(err);

        // If the source vector tiles are not using deflate, we're done.
        if (!source._deflate) return done(err, body, headers);

        // Otherwise, inflate the data.
        zlib.inflate(body, function(err, body) { return done(err, body, headers); });
    });
};

Vector.prototype.drawTile = function(bz, bx, by, z, x, y, format, callback) {
    var source = this;
    source.sourceTile(this._backend, bz, bx, by, function(err, data, head) {
        if (err && err.message !== 'Tile does not exist')
            return callback(err);

        if (err && source._maskLevel && bz > source._maskLevel)
            return callback(format === 'utf' ? new Error('Grid does not exist') : err);

        var datatile = new mapnik.DataTile(bz, bx, by);
        datatile.setData(data || new Buffer(0), function(err, success) {
            var opts = {z:z, x:x, y:y, scale:source._scale};
            if (format === 'utf') {
                var surface = new mapnik.Grid(256,256);
                opts.layer = source._map.parameters.interactivity_layer;
                opts.fields = source._map.parameters.interactivity_fields.split(',');
            } else {
                var surface = new mapnik.Image(256,256);
            }
            datatile.render(source._map, surface, opts, function(err, image) {
                if (err) return callback(err);
                image.encode(format, {}, function(err, buffer) {
                    if (err) return callback(err);
                    var headers = {};
                    headers['Content-Type'] = format.indexOf('utf') === 0
                        ? 'application/json'
                        : format.indexOf('jpeg') === 0
                        ? 'image/jpeg'
                        : 'image/png';
                    headers['ETag'] = JSON.stringify(crypto.createHash('md5')
                        .update(source._scale + source._md5 + (head && head['ETag'] || (z+','+x+','+y)))
                        .digest('hex'));
                    return callback(null, buffer, headers);
                });
            });
        });
    });
};

Vector.prototype.getTile = function(z, x, y, callback) {
    if (!this._map) return callback(new Error('Tilesource not loaded'));

    // Lazy load min/maxzoom/maskLevel info.
    if (this._maxzoom === undefined) return this._backend.getInfo(function(err, info) {
        if (err) return callback(err);

        this._minzoom = info.minzoom || 0;
        this._maxzoom = info.maxzoom || 22;

        // @TODO massive hack to avoid conflict with tilelive-s3's
        // interpretation of 'maskLevel' key. Fix this by removing
        // masking entirely from the next version of tilelive-s3.
        if (this._backend.data && this._backend.data.maskLevel) {
            this._backend.data._maskLevel = this._backend.data.maskLevel;
            delete this._backend.data.maskLevel;
        }
        if (this._backend.data && this._backend.data._maskLevel) {
            this._maskLevel = this._backend.data._maskLevel;
        }
        // Support specifying maskLevel in other sources (mbtiles).
        if (info.maskLevel) {
            this._maskLevel = parseInt(info.maskLevel, 10);
        }

        return this.getTile(z, x, y, callback);
    }.bind(this));

    // If scale > 1 adjusts source data zoom level inversely.
    // scale 2x => z-1, scale 4x => z-2, scale 8x => z-3, etc.
    var d = Math.round(Math.log(this._scale)/Math.log(2));
    var bz = (z - d) > this._minzoom ? z - d : this._minzoom;
    var bx = Math.floor(x / Math.pow(2, z - bz));
    var by = Math.floor(y / Math.pow(2, z - bz));

    // Overzooming support.
    if (bz > this._maxzoom) {
        bz = this._maxzoom;
        bx = Math.floor(x / Math.pow(2, z - this._maxzoom));
        by = Math.floor(y / Math.pow(2, z - this._maxzoom));
    }

    // Hack around tilelive API - allow params to be passed per request
    // as attributes of the callback function.
    var format = callback.format || this._format;

    // For nonmasked sources or bz within the maskrange attempt 1 draw.
    if (!this._maskLevel || bz <= this._maskLevel)
        return this.drawTile(bz,bx,by,z,x,y,format,callback);

    // Above the maskLevel errors should attempt a second draw using the mask.
    this.drawTile(bz,bx,by,z,x,y,format,function(err, buffer, headers) {
        if (!err) return callback(err, buffer, headers);
        if (err && err.message !== 'Tile does not exist') return callback(err);
        bz = this._maskLevel;
        bx = Math.floor(x / Math.pow(2, z - this._maskLevel));
        by = Math.floor(y / Math.pow(2, z - this._maskLevel));
        this.drawTile(bz, bx, by, z, x, y, format, callback);
    }.bind(this));
};

Vector.prototype.getGrid = function(z, x, y, callback) {
    if (!this._map) return callback(new Error('Tilesource not loaded'));
    if (!this._map.parameters.interactivity_layer) return callback(new Error('Tilesource has no interactivity_layer'));
    if (!this._map.parameters.interactivity_fields) return callback(new Error('Tilesource has no interactivity_fields'));
    callback.format = 'utf';
    return this.getTile(z, x, y, callback);
};

Vector.prototype.getInfo = function(callback) {
    if (!this._map) return callback(new Error('Tilesource not loaded'));
    if (this._info) return callback(null, this._info);

    var params = this._map.parameters;
    this._info = Object.keys(params).reduce(function(memo, key) {
        switch (key) {
        case 'bounds':
        case 'center':
            memo[key] = params[key].split(',').map(function(v) { return parseFloat(v) });
            break;
        case 'minzoom':
        case 'maxzoom':
            memo[key] = parseInt(params[key], 10);
            break;
        default:
            memo[key] = params[key];
            break;
        }
        return memo;
    }, {});
    return callback(null, this._info);
};

<|endoftext|>


<commit_before>/* global require, exports */

const { PageMod } = require('sdk/page-mod');
const self = require('sdk/self');
const service = require('sdk/preferences/service');

const pkg = require('./package.json');

const PREFS = {
  // Enables WebVR. Not needed for Nightly, but we need to keep for other versions.
  'dom.vr.enabled': true,

  // Disables e10s (multi-process in Nightly).
  'browser.tabs.remote.autostart.2': false,

  // Enables pose prediction (for Nightly).
  'dom.vr.poseprediction.enabled': true,

  // Improves frame rate for Oculus DK2 but will break things for HMDs that
  // run at other refresh rates (e.g, 60, 90).
  'layout.frame_rate': 75,

  // Increases animation preformance.
  'layout.frame_rate.precise': true,

  // Enables mirroring. It's confusing otherwise, if you're not looking at your Rift.
  'gfx.vr.mirror-textures': true
};

function setDefaultPrefs () {
  Object.keys(PREFS).forEach(function (key) {
    service.set(key, PREFS[key]);
  });
}

function revertPrefs () {
  Object.keys(PREFS).forEach(function (key) {
    service.reset(key);
  });
}

function stringifyMsg (type, data) {
  return JSON.stringify({
    type: type,
    data: data
  });
}

function sendMsg (worker, type, data) {
  worker.port.emit('msg', stringifyMsg(type, data));
}

function startListening (worker) {
  sendMsg(worker, 'version', pkg.version);
}

PageMod({
  include: '*',
  contentScriptFile: self.data.url('content-script.js'),
  contentScriptWhen: 'ready',
  onAttach: startListening
});

// Covers startup, install, upgrade, downgrade, enable.
exports.main = setDefaultPrefs;

// Covers uninstall, disable, shutdown, downgrade, upgrade.
exports.onUnload = revertPrefs;
<commit_msg>fix prefs and force restart (fixes #32 and #33)<commit_after>/* global require, exports */

const { Cc, Ci, Cu, Cm } = require('chrome');
const { PageMod } = require('sdk/page-mod');
const self = require('sdk/self');
const prefs = require('sdk/preferences/service');

Cu.import('resource://gre/modules/Services.jsm');

const pkg = require('./package.json');

const PREFS = {
  // Enables WebVR. Not needed for Nightly, but we need to keep for other versions.
  'dom.vr.enabled': true,

  // Disables e10s (multi-process in Nightly).
  'browser.tabs.remote.autostart.2': false,

  // Enables pose prediction (for Nightly).
  'dom.vr.poseprediction.enabled': true,

  // Improves frame rate for Oculus DK2 but will break things for HMDs that
  // run at other refresh rates (e.g, 60, 90).
  'layout.frame_rate': 0,

  // Increases animation preformance.
  'layout.frame_rate.precise': true,

  // Enables mirroring. It's confusing otherwise, if you're not looking at your Rift.
  'gfx.vr.mirror-textures': true
};

function setDefaultPrefs () {
  var needsReset = false;

  Object.keys(PREFS).forEach(function (key) {
    if (prefs.get(key) === PREFS[key]) { return; }
    prefs.set(key, PREFS[key]);
    needsReset = true;
  });

  if (!needsReset) { return; }

  var title = 'Restart Required';
  var msg = 'Installing the WebVR Plus add-on for the first time requires a restart. Restart now?';
  let shouldProceed = Services.prompt.confirm(null, title, msg);
  if (!shouldProceed) { return; }

  let cancelQuit = Cc['@mozilla.org/supports-PRBool;1'].createInstance(Ci.nsISupportsPRBool);
  Services.obs.notifyObservers(cancelQuit, 'quit-application-requested', 'restart');
  shouldProceed = !cancelQuit.data;
  if (!shouldProceed) { return; }

  Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit |  Ci.nsIAppStartup.eRestart);
}

function revertPrefs () {
  Object.keys(PREFS).forEach(function (key) {
    prefs.reset(key);
  });
}

function stringifyMsg (type, data) {
  return JSON.stringify({
    type: type,
    data: data
  });
}

function sendMsg (worker, type, data) {
  worker.port.emit('msg', stringifyMsg(type, data));
}

function startListening (worker) {
  sendMsg(worker, 'version', pkg.version);
}

PageMod({
  include: '*',
  contentScriptFile: self.data.url('content-script.js'),
  contentScriptWhen: 'ready',
  onAttach: startListening
});

// Covers startup, install, upgrade, downgrade, enable.
exports.main = function (opts) {
  if (opts.loadReason === 'startup') { return; }
  setDefaultPrefs();
};

// Covers uninstall, disable, shutdown, downgrade, upgrade.
exports.onUnload = function (reason) {
  if (reason === 'shutdown') { return; }
  revertPrefs();
};
<|endoftext|>


<commit_before>var Service, Characteristic;
var request = require("request");
var pollingtoevent = require('polling-to-event');

module.exports = function(homebridge){
	Service = homebridge.hap.Service;
	Characteristic = homebridge.hap.Characteristic;
	homebridge.registerAccessory("homebridge-http-advanced", "Http-advanced", HttpAdvancedAccessory);
}

function HttpAdvancedAccessory(log, config) {
  this.log = log;

 	// url info
	this.on_url                 = config["on_url"];
	this.on_body                = config["on_body"];
	this.off_url                = config["off_url"];
	this.off_body               = config["off_body"];
	this.lock_url               = config["lock_url"];
	this.lock_body              = config["lock_body"];
	this.unlock_url             = config["unlock_url"]  			|| this.lock_url;
	this.unlock_body            = config["unlock_body"] 			|| this.lock_body;
	this.status_url             = config["status_url"];
	this.brightness_url         = config["brightness_url"];
	this.brightnesslvl_url      = config["brightnesslvl_url"];
	this.http_method            = config["http_method"] 	  	 	|| "GET";
	this.http_brightness_method = config["http_brightness_method"] 	|| this.http_method;
	this.http_lock_method       = config["http_lock_method"] 	 	|| this.http_method;
	this.username               = config["username"] 	  	 	 	|| "";
	this.password               = config["password"] 	  	 	 	|| "";
	this.sendimmediately        = config["sendimmediately"] 	 	|| "";
	this.service                = config["service"] 	  	 	 	|| "Switch";
	this.name                   = config["name"];
	this.brightnessHandling     = config["brightnessHandling"] 	 	|| "no";
	this.switchHandling 	    = config["switchHandling"] 		 	|| "no";

	this.state = false;

	this.currentlevel = 0;
    	var that = this;

	// Status Polling
	if ((this.status_url && this.switchHandling =="realtime") || (this.service=="Smoke" || this.service=="Motion")) {
		var powerurl = this.status_url;
		var statusemitter = pollingtoevent(function(done) {
	        	that.httpRequest(powerurl, "", "GET", that.username, that.password, that.sendimmediately, function(error, response, body) {
            		if (error) {
                		that.log('HTTP get power function failed: %s', error.message);
		                callback(error);
            		} else {
				done(null, body);
            		}
        		})
    	}, {longpolling:true,interval:300,longpollEventName:"statuspoll"});

	statusemitter.on("statuspoll", function(data) {
        	var binaryState = parseInt(data);
	    	that.state = binaryState > 0;
		that.log(that.service, "received data:"+that.status_url, "state is currently", binaryState);

		switch (that.service) {
			case "Switch":
				if (that.switchService ) {
					that.switchService .getCharacteristic(Characteristic.On)
					.setValue(that.state);
				}
				break;
			case "Light":
				if (that.lightbulbService) {
					that.lightbulbService.getCharacteristic(Characteristic.On)
					.setValue(that.state);
				}
				break;
			case "Smoke":
				if (that.smokeService) {
					that.smokeService.getCharacteristic(Characteristic.SmokeDetected)
					.setValue(that.state);
				}
				break;
			case "Motion":
				if (that.motionService) {
					that.motionService.getCharacteristic(Characteristic.MotionDetected)
					.setValue(that.state);
				}
			break;
			}
    });

}
	// Brightness Polling
	if (this.brightnesslvl_url && this.brightnessHandling =="realtime") {
		var brightnessurl = this.brightnesslvl_url;
		var levelemitter = pollingtoevent(function(done) {
	        	that.httpRequest(brightnessurl , "", "GET", that.username, that.password, that.sendimmediately, function(error, response, responseBody) {
            		if (error) {
                			that.log('HTTP get power function failed: %s', error.message);
							return;
            		} else {
						done(null, responseBody);
            		}
        		})
    	}, {longpolling:true,interval:2000,longpollEventName:"levelpoll"});

		levelemitter.on("levelpoll", function(data) {
			that.currentlevel = parseInt(data);

			if (that.lightbulbService) {
				that.log(that.service, "received data:"+that.brightnesslvl_url, "level is currently", that.currentlevel);
				that.lightbulbService.getCharacteristic(Characteristic.Brightness)
				.setValue(that.currentlevel);
			}
    	});
	}
}

HttpAdvancedAccessory.prototype = {

	httpRequest: function(url, body, method, username, password, sendimmediately, callback) {
		request({
			url: url,
			body: body,
			method: method,
			rejectUnauthorized: false,
			auth: {
				user: username,
				pass: password,
				sendImmediately: sendimmediately
			}
		},
		function(error, response, body) {
			callback(error, response, body)
		})
	},
	getStatusState: function(callback) {
		if (!this.status_url) {
    			this.log.warn("Ignoring request; No status url defined.");
	    		callback(new Error("No status url defined."));
	    		return;
   		 }

    	var service = this.service;
		var url = this.status_url;
    	this.log("Getting" , service , "state");

    	this.httpRequest(url, "", "GET", this.username, this.password, this.sendimmediately, function(error, response, responseBody) {
			if (error) {
				this.log('HTTP get power function failed: %s', error.message);
				callback(error);
			} else {
				var binaryState = parseInt(responseBody);
				var powerOn = binaryState > 0;
				this.log(service, "state is currently", binaryState);
				callback(null, powerOn);
			}
	    }.bind(this));
	  },

	setPowerState: function(powerOn, callback) {
		var url;
		var body;

		if (!this.on_url || !this.off_url) {
			this.log.warn("Ignoring request; No power url defined.");
			callback(new Error("No power url defined."));
			return;
		}

		if (powerOn) {
			url = this.on_url;
			body = this.on_body;
			this.log("Setting power state to on");
		} else {
			url = this.off_url;
			body = this.off_body;
			this.log("Setting power state to off");
		}

		this.httpRequest(url, body, this.http_method, this.username, this.password, this.sendimmediately, function(error, response, responseBody) {
			if (error) {
				this.log('HTTP set power function failed: %s', error.message);
				callback(error);
			} else {
				this.log('HTTP set power function succeeded!');
				callback();
			}
		}.bind(this));
	},

	getLockCurrentState: function(callback){
		this.log("getLockCurrentState");
		callback(null, 1); //Not possible with my setup
	},
	setLockCurrentState: function(callback){
		this.log("setLockCurrentState");
		callback(null, 1); //Not possible with my setup
	},
	getLockTargetState: function(callback){
		this.log("getLockTargetState");
		callback(null, 1); //Not possible with my setup
	},

	setLockTargetState: function(powerOn,callback) {
		var url;
		var body;

		if (!this.unlock_url || !this.lock_url) {
			this.log.warn("Ignoring request; No Door url defined.");
			callback(new Error("No Door url defined."));
		    return;
		}

	    if (powerOn) {
			url = this.lock_url;
			body = this.lock_body;
			this.log("Locking Door");
	    } else {
      		url = this.unlock_url;
            body = this.unlock_body;
      		this.log("Unlocking Door");
	    }
		this.httpRequest(url, body, this.http_method, this.username, this.password, this.sendimmediately, function(error, response, responseBody) {
			if (error) {
				this.log('HTTP Door function failed: %s', error.message);
				callback(error);
			} else {
				this.log('HTTP Door function succeeded!');
				callback();
			}
		}.bind(this));
	},

	getBrightness: function(callback) {
		if (!this.brightnesslvl_url) {
			this.log.warn("Ignoring request; No brightness level url defined.");
			callback(new Error("No brightness level url defined."));
			return;
		}
		var url = this.brightnesslvl_url;
		this.log("Getting Brightness level");

		this.httpRequest(url, "", "GET", this.username, this.password, this.sendimmediately, function(error, response, responseBody) {
			if (error) {
				this.log('HTTP get brightness function failed: %s', error.message);
				callback(error);
			} else {
				var level = parseInt(responseBody);
				this.log("brightness state is currently %s", level);
				callback(null, level);
			}
		}.bind(this));
	},

	setBrightness: function(level, callback) {

		if (!this.brightness_url) {
			this.log.warn("Ignoring request; No brightness url defined.");
			callback(new Error("No brightness url defined."));
			return;
		}
		if (!this.on_url || !this.off_url) {
			this.log.warn("Ignoring request; No power url defined.");
			callback(new Error("No power url defined."));
			return;
		}

		var url = this.brightness_url.replace("%b", level)

		this.log("Setting brightness to %s", level);

		this.httpRequest(url, "", this.http_brightness_method, this.username, this.password, this.sendimmediately, function(error, response, body) {
			if (error) {
				this.log('HTTP brightness function failed: %s', error);
				callback(error);
			} else {
				this.log('HTTP brightness function succeeded!');
				callback();
			}
		}.bind(this));
	},

  identify: function(callback) {
    this.log("Identify requested!");
    callback(); // success
  },

  getServices: function() {
	var that = this;

    var informationService = new Service.AccessoryInformation();

    informationService
    .setCharacteristic(Characteristic.Manufacturer, "HTTP Manufacturer")
    .setCharacteristic(Characteristic.Model, "HTTP Model")
    .setCharacteristic(Characteristic.SerialNumber, "HTTP Serial Number");

	switch (this.service) {
		case "Switch":
			this.switchService = new Service.Switch(this.name);
			switch (this.switchHandling) {
				case "yes":
					this.switchService
					.getCharacteristic(Characteristic.On)
					.on('get', this.getStatusState.bind(this))
					.on('set', this.setPowerState.bind(this));
					return [this.switchService];
					break;
				case "realtime":
					this.switchService
					.getCharacteristic(Characteristic.On)
					.on('get', function(callback) {callback(null, that.state)})
					.on('set', this.setPowerState.bind(this));
					return [this.switchService];
					break;
				default	:
					this.switchService
					.getCharacteristic(Characteristic.On)
					.on('set', this.setPowerState.bind(this));
					return [this.switchService];
					break;}
		case "Light":
			this.lightbulbService = new Service.Lightbulb(this.name);
			switch (this.switchHandling) {

			case "yes" :
				this.lightbulbService
				.getCharacteristic(Characteristic.On)
				.on('get', this.getStatusState.bind(this))
				.on('set', this.setPowerState.bind(this));
				break;
			case "realtime":
				this.lightbulbService
				.getCharacteristic(Characteristic.On)
				.on('get', function(callback) {callback(null, that.state)})
				.on('set', this.setPowerState.bind(this));
				break;
			default:
				this.lightbulbService
				.getCharacteristic(Characteristic.On)
				.on('set', this.setPowerState.bind(this));
				break;
			}

			if (this.brightnessHandling == "realtime") {
				this.lightbulbService
				.addCharacteristic(new Characteristic.Brightness())
				.on('get', function(callback) {callback(null, that.currentlevel)})
				.on('set', this.setBrightness.bind(this));
			} else if (this.brightnessHandling == "yes") {
				this.lightbulbService
				.addCharacteristic(new Characteristic.Brightness())
				.on('get', this.getBrightness.bind(this))
				.on('set', this.setBrightness.bind(this));
			}

			return [informationService, this.lightbulbService];
			break;
		case "Door":
			var lockService = new Service.LockMechanism(this.name);

			lockService
			.getCharacteristic(Characteristic.LockCurrentState)
			.on('get', this.getLockCurrentState.bind(this))
			.on('set', this.setLockCurrentState.bind(this));

			lockService
			.getCharacteristic(Characteristic.LockTargetState)
			.on('get', this.getLockTargetState.bind(this))
			.on('set', this.setLockTargetState.bind(this));

			return [lockService];
			break;
		case "Smoke":
			this.smokeService = new Service.SmokeSensor(this.name);
			this.switchHandling=="realtime";

			this.smokeService
			.getCharacteristic(Characteristic.SmokeDetected)
			.on('get', function(callback) {callback(null, that.state)});

			return [this.smokeService];
		case "Motion":
			this.motionService = new Service.MotionSensor(this.name);
			this.switchHandling=="realtime";
			this.motionService
			.getCharacteristic(Characteristic.MotionDetected)
			.on('get', function(callback) {callback(null, that.state)});

			return [this.motionService];
			break;
	}
  }
};
<commit_msg>fixed lock http method<commit_after>var Service, Characteristic;
var request = require("request");
var pollingtoevent = require('polling-to-event');

module.exports = function(homebridge){
	Service = homebridge.hap.Service;
	Characteristic = homebridge.hap.Characteristic;
	homebridge.registerAccessory("homebridge-http-advanced", "Http-advanced", HttpAdvancedAccessory);
}

function HttpAdvancedAccessory(log, config) {
  this.log = log;

 	// url info
	this.on_url                 = config["on_url"];
	this.on_body                = config["on_body"];
	this.off_url                = config["off_url"];
	this.off_body               = config["off_body"];
	this.lock_url               = config["lock_url"];
	this.lock_body              = config["lock_body"];
	this.unlock_url             = config["unlock_url"]  			|| this.lock_url;
	this.unlock_body            = config["unlock_body"] 			|| this.lock_body;
	this.status_url             = config["status_url"];
	this.brightness_url         = config["brightness_url"];
	this.brightnesslvl_url      = config["brightnesslvl_url"];
	this.http_method            = config["http_method"] 	  	 	|| "GET";
	this.http_brightness_method = config["http_brightness_method"] 	|| this.http_method;
	this.http_lock_method       = config["http_lock_method"] 	 	|| this.http_method;
	this.username               = config["username"] 	  	 	 	|| "";
	this.password               = config["password"] 	  	 	 	|| "";
	this.sendimmediately        = config["sendimmediately"] 	 	|| "";
	this.service                = config["service"] 	  	 	 	|| "Switch";
	this.name                   = config["name"];
	this.brightnessHandling     = config["brightnessHandling"] 	 	|| "no";
	this.switchHandling 	    = config["switchHandling"] 		 	|| "no";

	this.state = false;

	this.currentlevel = 0;
    	var that = this;

	// Status Polling
	if ((this.status_url && this.switchHandling =="realtime") || (this.service=="Smoke" || this.service=="Motion")) {
		var powerurl = this.status_url;
		var statusemitter = pollingtoevent(function(done) {
	        	that.httpRequest(powerurl, "", "GET", that.username, that.password, that.sendimmediately, function(error, response, body) {
            		if (error) {
                		that.log('HTTP get power function failed: %s', error.message);
		                callback(error);
            		} else {
				done(null, body);
            		}
        		})
    	}, {longpolling:true,interval:300,longpollEventName:"statuspoll"});

	statusemitter.on("statuspoll", function(data) {
        	var binaryState = parseInt(data);
	    	that.state = binaryState > 0;
		that.log(that.service, "received data:"+that.status_url, "state is currently", binaryState);

		switch (that.service) {
			case "Switch":
				if (that.switchService ) {
					that.switchService .getCharacteristic(Characteristic.On)
					.setValue(that.state);
				}
				break;
			case "Light":
				if (that.lightbulbService) {
					that.lightbulbService.getCharacteristic(Characteristic.On)
					.setValue(that.state);
				}
				break;
			case "Smoke":
				if (that.smokeService) {
					that.smokeService.getCharacteristic(Characteristic.SmokeDetected)
					.setValue(that.state);
				}
				break;
			case "Motion":
				if (that.motionService) {
					that.motionService.getCharacteristic(Characteristic.MotionDetected)
					.setValue(that.state);
				}
			break;
			}
    });

}
	// Brightness Polling
	if (this.brightnesslvl_url && this.brightnessHandling =="realtime") {
		var brightnessurl = this.brightnesslvl_url;
		var levelemitter = pollingtoevent(function(done) {
	        	that.httpRequest(brightnessurl , "", "GET", that.username, that.password, that.sendimmediately, function(error, response, responseBody) {
            		if (error) {
                			that.log('HTTP get power function failed: %s', error.message);
							return;
            		} else {
						done(null, responseBody);
            		}
        		})
    	}, {longpolling:true,interval:2000,longpollEventName:"levelpoll"});

		levelemitter.on("levelpoll", function(data) {
			that.currentlevel = parseInt(data);

			if (that.lightbulbService) {
				that.log(that.service, "received data:"+that.brightnesslvl_url, "level is currently", that.currentlevel);
				that.lightbulbService.getCharacteristic(Characteristic.Brightness)
				.setValue(that.currentlevel);
			}
    	});
	}
}

HttpAdvancedAccessory.prototype = {

	httpRequest: function(url, body, method, username, password, sendimmediately, callback) {
		request({
			url: url,
			body: body,
			method: method,
			rejectUnauthorized: false,
			auth: {
				user: username,
				pass: password,
				sendImmediately: sendimmediately
			}
		},
		function(error, response, body) {
			callback(error, response, body)
		})
	},
	getStatusState: function(callback) {
		if (!this.status_url) {
    			this.log.warn("Ignoring request; No status url defined.");
	    		callback(new Error("No status url defined."));
	    		return;
   		 }

    	var service = this.service;
		var url = this.status_url;
    	this.log("Getting" , service , "state");

    	this.httpRequest(url, "", "GET", this.username, this.password, this.sendimmediately, function(error, response, responseBody) {
			if (error) {
				this.log('HTTP get power function failed: %s', error.message);
				callback(error);
			} else {
				var binaryState = parseInt(responseBody);
				var powerOn = binaryState > 0;
				this.log(service, "state is currently", binaryState);
				callback(null, powerOn);
			}
	    }.bind(this));
	  },

	setPowerState: function(powerOn, callback) {
		var url;
		var body;

		if (!this.on_url || !this.off_url) {
			this.log.warn("Ignoring request; No power url defined.");
			callback(new Error("No power url defined."));
			return;
		}

		if (powerOn) {
			url = this.on_url;
			body = this.on_body;
			this.log("Setting power state to on");
		} else {
			url = this.off_url;
			body = this.off_body;
			this.log("Setting power state to off");
		}

		this.httpRequest(url, body, this.http_method, this.username, this.password, this.sendimmediately, function(error, response, responseBody) {
			if (error) {
				this.log('HTTP set power function failed: %s', error.message);
				callback(error);
			} else {
				this.log('HTTP set power function succeeded!');
				callback();
			}
		}.bind(this));
	},

	getLockCurrentState: function(callback){
		this.log("getLockCurrentState");
		callback(null, 1); //Not possible with my setup
	},
	setLockCurrentState: function(callback){
		this.log("setLockCurrentState");
		callback(null, 1); //Not possible with my setup
	},
	getLockTargetState: function(callback){
		this.log("getLockTargetState");
		callback(null, 1); //Not possible with my setup
	},

	setLockTargetState: function(powerOn,callback) {
		var url;
		var body;

		if (!this.unlock_url || !this.lock_url) {
			this.log.warn("Ignoring request; No Door url defined.");
			callback(new Error("No Door url defined."));
		    return;
		}

	    if (powerOn) {
			url = this.lock_url;
			body = this.lock_body;
			this.log("Locking Door");
	    } else {
      		url = this.unlock_url;
            body = this.unlock_body;
      		this.log("Unlocking Door");
	    }
		this.httpRequest(url, body, this.http_lock_method, this.username, this.password, this.sendimmediately, function(error, response, responseBody) {
			if (error) {
				this.log('HTTP Door function failed: %s', error.message);
				callback(error);
			} else {
				this.log('HTTP Door function succeeded!');
				callback();
			}
		}.bind(this));
	},

	getBrightness: function(callback) {
		if (!this.brightnesslvl_url) {
			this.log.warn("Ignoring request; No brightness level url defined.");
			callback(new Error("No brightness level url defined."));
			return;
		}
		var url = this.brightnesslvl_url;
		this.log("Getting Brightness level");

		this.httpRequest(url, "", "GET", this.username, this.password, this.sendimmediately, function(error, response, responseBody) {
			if (error) {
				this.log('HTTP get brightness function failed: %s', error.message);
				callback(error);
			} else {
				var level = parseInt(responseBody);
				this.log("brightness state is currently %s", level);
				callback(null, level);
			}
		}.bind(this));
	},

	setBrightness: function(level, callback) {

		if (!this.brightness_url) {
			this.log.warn("Ignoring request; No brightness url defined.");
			callback(new Error("No brightness url defined."));
			return;
		}
		if (!this.on_url || !this.off_url) {
			this.log.warn("Ignoring request; No power url defined.");
			callback(new Error("No power url defined."));
			return;
		}

		var url = this.brightness_url.replace("%b", level)

		this.log("Setting brightness to %s", level);

		this.httpRequest(url, "", this.http_brightness_method, this.username, this.password, this.sendimmediately, function(error, response, body) {
			if (error) {
				this.log('HTTP brightness function failed: %s', error);
				callback(error);
			} else {
				this.log('HTTP brightness function succeeded!');
				callback();
			}
		}.bind(this));
	},

  identify: function(callback) {
    this.log("Identify requested!");
    callback(); // success
  },

  getServices: function() {
	var that = this;

    var informationService = new Service.AccessoryInformation();

    informationService
    .setCharacteristic(Characteristic.Manufacturer, "HTTP Manufacturer")
    .setCharacteristic(Characteristic.Model, "HTTP Model")
    .setCharacteristic(Characteristic.SerialNumber, "HTTP Serial Number");

	switch (this.service) {
		case "Switch":
			this.switchService = new Service.Switch(this.name);
			switch (this.switchHandling) {
				case "yes":
					this.switchService
					.getCharacteristic(Characteristic.On)
					.on('get', this.getStatusState.bind(this))
					.on('set', this.setPowerState.bind(this));
					return [this.switchService];
					break;
				case "realtime":
					this.switchService
					.getCharacteristic(Characteristic.On)
					.on('get', function(callback) {callback(null, that.state)})
					.on('set', this.setPowerState.bind(this));
					return [this.switchService];
					break;
				default	:
					this.switchService
					.getCharacteristic(Characteristic.On)
					.on('set', this.setPowerState.bind(this));
					return [this.switchService];
					break;}
		case "Light":
			this.lightbulbService = new Service.Lightbulb(this.name);
			switch (this.switchHandling) {

			case "yes" :
				this.lightbulbService
				.getCharacteristic(Characteristic.On)
				.on('get', this.getStatusState.bind(this))
				.on('set', this.setPowerState.bind(this));
				break;
			case "realtime":
				this.lightbulbService
				.getCharacteristic(Characteristic.On)
				.on('get', function(callback) {callback(null, that.state)})
				.on('set', this.setPowerState.bind(this));
				break;
			default:
				this.lightbulbService
				.getCharacteristic(Characteristic.On)
				.on('set', this.setPowerState.bind(this));
				break;
			}

			if (this.brightnessHandling == "realtime") {
				this.lightbulbService
				.addCharacteristic(new Characteristic.Brightness())
				.on('get', function(callback) {callback(null, that.currentlevel)})
				.on('set', this.setBrightness.bind(this));
			} else if (this.brightnessHandling == "yes") {
				this.lightbulbService
				.addCharacteristic(new Characteristic.Brightness())
				.on('get', this.getBrightness.bind(this))
				.on('set', this.setBrightness.bind(this));
			}

			return [informationService, this.lightbulbService];
			break;
		case "Door":
			var lockService = new Service.LockMechanism(this.name);

			lockService
			.getCharacteristic(Characteristic.LockCurrentState)
			.on('get', this.getLockCurrentState.bind(this))
			.on('set', this.setLockCurrentState.bind(this));

			lockService
			.getCharacteristic(Characteristic.LockTargetState)
			.on('get', this.getLockTargetState.bind(this))
			.on('set', this.setLockTargetState.bind(this));

			return [lockService];
			break;
		case "Smoke":
			this.smokeService = new Service.SmokeSensor(this.name);
			this.switchHandling=="realtime";

			this.smokeService
			.getCharacteristic(Characteristic.SmokeDetected)
			.on('get', function(callback) {callback(null, that.state)});

			return [this.smokeService];
		case "Motion":
			this.motionService = new Service.MotionSensor(this.name);
			this.switchHandling=="realtime";
			this.motionService
			.getCharacteristic(Characteristic.MotionDetected)
			.on('get', function(callback) {callback(null, that.state)});

			return [this.motionService];
			break;
	}
  }
};
<|endoftext|>


<commit_before>const getJSON = require('get-json');
const unique = require('array-unique');

/** URL of the Overpass API being used */
const overpass = 'http://overpass-api.de/api/interpreter?data=';

/**
 * Validation checks for fromLocation params
 * @param {Number} lat - Latitude of centre location.
 * @param {Number} long - Longitude of centre location.
 * @param {Number} distance - Radius distance in metres.
 * @returns {Error} - Error object if validation fails, null otherwise
 */
function validateFromLocation(lat, long, distance) {
  if (typeof lat !== 'number' || typeof long !== 'number' || typeof distance !== 'number') {
    return new Error('Lat, Long, and Distance must be numbers');
  }

  if (Math.abs(lat) > 90) {
    return Error('Latitude must be between -90 and 90');
  }

  if (Math.abs(long) > 180) {
    return Error('Longitude must be between -180 and 180');
  }

  if (distance < 0) {
    return Error('Distance must be greater than 0');
  }

  return null;
}

/**
 * Get all road names within a specified distance from a location.
 * @param {Number} lat - Latitude of centre location.
 * @param {Number} long - Longitude of centre location.
 * @param {Number} distance - Radius distance in metres.
 * @param {Function} callback - callback(err, data)
 * @returns {Array} - Array of road names, use callback.
 */
function fromLocation(lat, long, distance, callback) {
  const query = `[out:json]; way["highway"](around:${distance},${lat},${long}); out;`;

  const validationError = validateFromLocation(lat, long, distance);

  if (validationError) {
    return callback(validationError, null);
  }

  return getJSON(`${overpass}${query}`, (err, result) => {
    if (err) return callback(err, null);

    let roads = [];
    result.elements.forEach(element => roads.push(element.tags.name));
    roads = unique(roads);

    return callback(null, roads);
  });
}

module.exports = { fromLocation };
<commit_msg>Implement bounding box functionality<commit_after>const getJSON = require('get-json');
const unique = require('array-unique');

/** URL of the Overpass API being used */
const overpass = 'http://overpass-api.de/api/interpreter?data=';

/**
 * Validation checks for fromLocation params
 *
 * @param {Number} lat - Latitude of centre location.
 * @param {Number} long - Longitude of centre location.
 * @param {Number} distance - Radius distance in metres.
 * @returns {Error} - Error object if validation fails, null otherwise
 */
function validateFromLocation(lat, long, distance) {
  if (typeof lat !== 'number' || typeof long !== 'number' || typeof distance !== 'number') {
    return new Error('Lat, Long, and Distance must be numbers');
  }

  if (Math.abs(lat) > 90) {
    return Error('Latitude must be between -90 and 90');
  }

  if (Math.abs(long) > 180) {
    return Error('Longitude must be between -180 and 180');
  }

  if (distance < 0) {
    return Error('Distance must be greater than 0');
  }

  return null;
}

/**
 * Validation checks for boundingBox params
 *
 * @param {any} northLat - the north latitude of the bounding box.
 * @param {any} eastLong - the east longitude of the bounding box.
 * @param {any} southLat - the south latitude of the bounding box.
 * @param {any} westLong - the west longitude of the bounding box.
 * @returns {Error} - Error object if validation fails, null otherwise
 */
function validateBoundingBox(northLat, eastLong, southLat, westLong) {
  if (typeof northLat !== 'number' || typeof eastLong !== 'number' || typeof southLat !== 'number' || typeof westLong !== 'number') {
    return new Error('northLat, eastLong, southLat and westLong must all be numbers.');
  }

  if (northLat < southLat) {
    return new Error('northLat must be greater than southLat.');
  }

  // The western limit is higher than the eastern limit if and only if the query surpasses
  // the longitude ±180.0 degrees with a bounding box passing through the Antimeridian

  return null;
}

/**
 * Get all road names within a specified distance from a location.
 *
 * @param {Number} lat - Latitude of centre location.
 * @param {Number} long - Longitude of centre location.
 * @param {Number} distance - Radius distance in metres.
 * @param {Function} callback - callback(err, data)
 * @returns {Array} - Array of road names, use callback.
 */
function fromLocation(lat, long, distance, callback) {
  const query = `[out:json]; way["highway"](around:${distance},${lat},${long}); out;`;

  const validationError = validateFromLocation(lat, long, distance);

  if (validationError) {
    return callback(validationError, null);
  }

  return getJSON(`${overpass}${query}`, (err, result) => {
    if (err) return callback(err, null);

    let roads = [];
    result.elements.forEach(element => roads.push(element.tags.name));
    roads = unique(roads);

    return callback(null, roads);
  });
}

/**
 * Get all road names within a bounding box.
 *
 * @param {any} northLat - the north latitude of the bounding box.
 * @param {any} eastLong - the east longitude of the bounding box.
 * @param {any} southLat - the south latitude of the bounding box.
 * @param {any} westLong - the west longitude of the bounding box.
 * @param {Function} callback - callback(err, data)
 * @returns {Array} - Array of road names, use callback.
 */
function boundingBox(northLat, eastLong, southLat, westLong, callback) {
  // Overpass expects (S, W, N, E)
  const query = `[out:json]; way["highway"](${southLat}, ${westLong}, ${northLat}, ${eastLong}); out;`;

  const validationError = validateBoundingBox(northLat, eastLong, southLat, westLong);

  if (validationError) {
    return callback(validationError, null);
  }

  return getJSON(`${overpass}${query}`, (err, result) => {
    if (err) return callback(err, null);

    let roads = [];

    result.elements.forEach((element) => {
      if (element.tags.name !== undefined) {
        roads.push(element.tags.name);
      }
    });

    roads = unique(roads);

    return callback(null, roads);
  });
}

module.exports = {

  fromLocation,

  boundingBox,

};
<|endoftext|>


<commit_before>var _         = require('underscore'),
    ginga     = require('ginga'),
    params    = ginga.params;

function semaphore(n){
  if(!(this instanceof semaphore))
    return new semaphore(n);
  this._q = [];
  this._taken = 0;
  this._n = n || 1;
}
var s = semaphore.prototype;
s.take = function(fn){
  if(this._taken < this._n){
    this._taken++;
    process.nextTick(fn);
  }else
    this._q.push(fn);
  return this;
};
s.leave = function(){
  if(this._q.length > 0){
    process.nextTick(this._q.shift());
  }else{
    if(this._taken === 0)
      throw new Error('leave called too many times.');
    this._taken--;
  }
  return this;
};

function start(fn, err){
  var self = this;
  if(this.length > 0 && !err){
    //todo: prepare nested queue
    this.shift()(function(err){
      process.nextTick(start.bind(self, fn, err));
    });
  }else{
    fn(err);
  }
}

module.exports = function( db ){

  var count = 0, map = {};

  function mutual(hash){
    map[hash] = map[hash] || semaphore(1);
    return map[hash];
  }

  function Transaction(options){
    this.db = db;
    this.options = options;
    this._id = count;
    count++;

    this._released = false;

    this._wait = {};
    this._taken = {};
    this._map = {};
    this._batch = [];

    this._q = [];
    this.defer = Array.prototype.push.bind(this._q);

    // this._deps = {};
  }

  function pre(ctx, next){
    //options object
    ctx.options = _.defaults({}, ctx.params.opts, this.options);

    //check sublevel
    if(ctx.options && ctx.options.prefix &&
      typeof ctx.options.prefix.sublevel === 'function')
      ctx.prefix = ctx.options.prefix;

    //key + sublevel prefix hash
    ctx.hash = JSON.stringify(
      ctx.prefix ? [ctx.prefix.prefix(), ctx.params.key] : ctx.params.key
    );

    next();
  }
  function lock(ctx, next, end){
    var self = this;

    if(this._released)
      return next(new Error('Transaction has already been committed/rollback.'));

    var plan = 0;
    function invoke(){
      plan--; if(plan === 0) next();
    }

    if(!this._wait[ctx.hash]){
      //gain mutually exclusive access for transaction

      var mu = mutual(ctx.hash);
      plan++;
      mu.take(function(){
        if(self._released){
          mu.leave();
          return;
        }
        self._taken[ctx.hash] = true;
        invoke();
      });
      this._wait[ctx.hash] = semaphore(1);
    }
    var wait = this._wait[ctx.hash];

    plan++;
    wait.take(invoke);

    end(function(err){
      if(err && !err.notFound){
        //Error that abort transaction
        self.rollback();
        return;
      }
      wait.leave(); //relase wait
    });
  }

  function get(ctx, done){
    if(ctx.hash in this._map){
      done(null, this._map[ctx.hash]);
      return;
    }
    var self = this;

    (ctx.prefix || db).get(ctx.params.key, _.defaults(
      {}, ctx.params.opts, this.options
    ), function(err, val){
      self._map[ctx.hash] = val;
      done(err, val);
    });
  }

  function put(ctx, done){
    this._batch.push(_.defaults({
      type: 'put',
      key: ctx.params.key,
      value: ctx.params.value
    }, ctx.options));

    this._map[ctx.hash] = ctx.params.value;

    done(null);
  }

  function del(ctx, done){
    this._batch.push(_.defaults({
      type: 'del',
      key: ctx.params.key
    }, ctx.options));

    this._map[ctx.hash] = undefined;

    done(null);
  }

  function commit(ctx, next, end){
    var self = this;

    var plan = 0;
    function invoke(){
      plan--;
      if(plan === 0)
        db.batch(self._batch, function(err, res){
          if(err) next(err);
          else next();
        });
    }

    start.call(this._q, function(err){
      if(err)
        return next(err);
      plan = _.size(self._wait);
      _.invoke(self._wait, 'take', invoke);
    });

    end(function(err){
      //rollback on commit error
      if(err)
        self.rollback();
    });
  }

  //release after rollback, commit
  function release(ctx, done){
    this._released = true;

    _.each(this._taken, function(t, hash){
      mutual(hash).leave();
    });

    delete this._wait;
    delete this._taken;
    delete this._map;
    delete this._batch;
    done(null);
  }

  ginga(Transaction.prototype)
    .define('get', params('key','opts?'), pre, lock, get)
    .define('put', params('key','value','opts?'), pre, lock, put)
    .define('del', params('key','opts?'), pre, lock, del)
    .define('rollback', release)
    .define('commit', commit, release);

  db.transaction = db.transaction || function(options){
    return new Transaction(options);
  };
  return db;
};
<commit_msg>prepare custom queue<commit_after>var _         = require('underscore'),
    ginga     = require('ginga'),
    params    = ginga.params;

function semaphore(n){
  if(!(this instanceof semaphore))
    return new semaphore(n);
  this._q = [];
  this._taken = 0;
  this._n = n || 1;
}
var s = semaphore.prototype;
s.take = function(fn){
  if(this._taken < this._n){
    this._taken++;
    process.nextTick(fn);
  }else
    this._q.push(fn);
  return this;
};
s.leave = function(){
  if(this._q.length > 0){
    process.nextTick(this._q.shift());
  }else{
    if(this._taken === 0)
      throw new Error('leave called too many times.');
    this._taken--;
  }
  return this;
};

function queue(){
  if(!(this instanceof queue))
    return new queue();
  this._q = [];
}
var q = queue.prototype;
q.defer = function(fn){
  this._q.push(fn);
};
q.start = function(fn, err){
  var self = this;
  if(this._q.length > 0 && !err){
    //todo: prepare nested queue
    this._q.shift()(function(err){
      process.nextTick(self.start.bind(self, fn, err));
    });
  }else{
    fn(err);
  }
};

module.exports = function( db ){

  var count = 0, map = {};

  function mutual(hash){
    map[hash] = map[hash] || semaphore(1);
    return map[hash];
  }

  function Transaction(options){
    this.db = db;
    this.options = options;
    this._id = count;
    count++;

    this._released = false;

    this._wait = {};
    this._taken = {};
    this._map = {};
    this._batch = [];

    this._q = queue();
    this.defer = this._q.defer.bind(this._q);

    // this._deps = {};
  }

  function pre(ctx, next){
    //options object
    ctx.options = _.defaults({}, ctx.params.opts, this.options);

    //check sublevel
    if(ctx.options && ctx.options.prefix &&
      typeof ctx.options.prefix.sublevel === 'function')
      ctx.prefix = ctx.options.prefix;

    //key + sublevel prefix hash
    ctx.hash = JSON.stringify(
      ctx.prefix ? [ctx.prefix.prefix(), ctx.params.key] : ctx.params.key
    );

    next();
  }
  function lock(ctx, next, end){
    var self = this;

    if(this._released)
      return next(new Error('Transaction has already been committed/rollback.'));

    var plan = 0;
    function invoke(){
      plan--; if(plan === 0) next();
    }

    if(!this._wait[ctx.hash]){
      //gain mutually exclusive access for transaction

      var mu = mutual(ctx.hash);
      plan++;
      mu.take(function(){
        if(self._released){
          mu.leave();
          return;
        }
        self._taken[ctx.hash] = true;
        invoke();
      });
      this._wait[ctx.hash] = semaphore(1);
    }
    var wait = this._wait[ctx.hash];

    plan++;
    wait.take(invoke);

    end(function(err){
      if(err && !err.notFound){
        //Error that abort transaction
        self.rollback();
        return;
      }
      wait.leave(); //relase wait
    });
  }

  function get(ctx, done){
    if(ctx.hash in this._map){
      done(null, this._map[ctx.hash]);
      return;
    }
    var self = this;

    (ctx.prefix || db).get(ctx.params.key, _.defaults(
      {}, ctx.params.opts, this.options
    ), function(err, val){
      self._map[ctx.hash] = val;
      done(err, val);
    });
  }

  function put(ctx, done){
    this._batch.push(_.defaults({
      type: 'put',
      key: ctx.params.key,
      value: ctx.params.value
    }, ctx.options));

    this._map[ctx.hash] = ctx.params.value;

    done(null);
  }

  function del(ctx, done){
    this._batch.push(_.defaults({
      type: 'del',
      key: ctx.params.key
    }, ctx.options));

    this._map[ctx.hash] = undefined;

    done(null);
  }

  function commit(ctx, next, end){
    var self = this;

    var plan = 0;
    function invoke(){
      plan--;
      if(plan === 0)
        db.batch(self._batch, function(err, res){
          if(err) next(err);
          else next();
        });
    }

    this._q.start(function(err){
      if(err)
        return next(err);
      plan = _.size(self._wait);
      _.invoke(self._wait, 'take', invoke);
    });

    end(function(err){
      //rollback on commit error
      if(err)
        self.rollback();
    });
  }

  //release after rollback, commit
  function release(ctx, done){
    this._released = true;

    _.each(this._taken, function(t, hash){
      mutual(hash).leave();
    });

    delete this._wait;
    delete this._taken;
    delete this._map;
    delete this._batch;
    done(null);
  }

  ginga(Transaction.prototype)
    .define('get', params('key','opts?'), pre, lock, get)
    .define('put', params('key','value','opts?'), pre, lock, put)
    .define('del', params('key','opts?'), pre, lock, del)
    .define('rollback', release)
    .define('commit', commit, release);

  db.transaction = db.transaction || function(options){
    return new Transaction(options);
  };
  return db;
};
<|endoftext|>


<commit_before>"use strict";

module.exports = CSSselect;

var Pseudos     = require("./lib/pseudos.js"),
    DomUtils    = require("domutils"),
    findOne     = DomUtils.findOne,
    findAll     = DomUtils.findAll,
    getChildren = DomUtils.getChildren,
    falseFunc   = require("./lib/basefunctions.js").falseFunc,
    compile     = require("./lib/compile.js");

function selectAll(query, elems){
	if(typeof query !== "function") query = compile(query);
	if(!Array.isArray(elems)) elems = getChildren(elems);
	return query === falseFunc ? [] : findAll(query, elems);
}

function selectOne(query, elems){
	if(typeof query !== "function") query = compile(query);
	if(!Array.isArray(elems)) elems = getChildren(elems);
	return query === falseFunc ? null : findOne(query, elems);
}

function is(elem, query){
	return (typeof query === "function" ? query : compile(query))(elem);
}

/*
	the exported interface
*/
function CSSselect(query, elems){
	return selectAll(query, elems);
}

CSSselect.compile = compile;
CSSselect.filters = Pseudos.filters;
CSSselect.pseudos = Pseudos.pseudos;

CSSselect.selectAll = selectAll;
CSSselect.selectOne = selectOne;

CSSselect.is = is;

//legacy methods (might be removed)
CSSselect.parse = compile;
CSSselect.iterate = selectAll;
<commit_msg>[index] when no elements are passed, return an empty result set<commit_after>"use strict";

module.exports = CSSselect;

var Pseudos     = require("./lib/pseudos.js"),
    DomUtils    = require("domutils"),
    findOne     = DomUtils.findOne,
    findAll     = DomUtils.findAll,
    getChildren = DomUtils.getChildren,
    falseFunc   = require("./lib/basefunctions.js").falseFunc,
    compile     = require("./lib/compile.js");

function selectAll(query, elems){
	if(typeof query !== "function") query = compile(query);
	if(!Array.isArray(elems)) elems = getChildren(elems);
	return (!elems || query === falseFunc) ? [] : findAll(query, elems);
}

function selectOne(query, elems){
	if(typeof query !== "function") query = compile(query);
	if(!Array.isArray(elems)) elems = getChildren(elems);
	return (!elems || query === falseFunc) ? null : findOne(query, elems);
}

function is(elem, query){
	return (typeof query === "function" ? query : compile(query))(elem);
}

/*
	the exported interface
*/
function CSSselect(query, elems){
	return selectAll(query, elems);
}

CSSselect.compile = compile;
CSSselect.filters = Pseudos.filters;
CSSselect.pseudos = Pseudos.pseudos;

CSSselect.selectAll = selectAll;
CSSselect.selectOne = selectOne;

CSSselect.is = is;

//legacy methods (might be removed)
CSSselect.parse = compile;
CSSselect.iterate = selectAll;
<|endoftext|>


<commit_before>'use strict';
const execa = require('execa');
const lcid = require('lcid');

const defaultOptions = {spawn: true};
const defaultLocale = 'en-US';

async function getStdOut(command, args) {
	return (await execa(command, args)).stdout;
}

function getStdOutSync(command, args) {
	return execa.sync(command, args).stdout;
}

function getEnvLocale(env = process.env) {
	return env.LC_ALL || env.LC_MESSAGES || env.LANG || env.LANGUAGE;
}

function parseLocale(string) {
	const env = {};
	for (const definition of string.split('\n')) {
		const [key, value] = definition.split('=');
		env[key] = value.replace(/^"|"$/g, '');
	}

	return getEnvLocale(env);
}

function getLocale(string) {
	return (string && string.replace(/[.:].*/, ''));
}

async function getLocales() {
	return getStdOut('locale', ['-a']);
}

function getLocalesSync() {
	return getStdOutSync('locale', ['-a']);
}

function getSupportedLocale(locale, locales = '') {
	return locales.includes(locale) ? locale : defaultLocale;
}

async function getAppleLocale() {
	const results = await Promise.all([
		getStdOut('defaults', ['read', '-globalDomain', 'AppleLocale']),
		getLocales()
	]);

	return getSupportedLocale(results[0], results[1]);
}

function getAppleLocaleSync() {
	return getSupportedLocale(
		getStdOutSync('defaults', ['read', '-globalDomain', 'AppleLocale']),
		getLocalesSync()
	);
}

async function getUnixLocale() {
	return getLocale(parseLocale(await getStdOut('locale')));
}

function getUnixLocaleSync() {
	return getLocale(parseLocale(getStdOutSync('locale')));
}

async function getWinLocale() {
	const stdout = await getStdOut('wmic', ['os', 'get', 'locale']);
	const lcidCode = Number.parseInt(stdout.replace('Locale', ''), 16);

	return lcid.from(lcidCode);
}

function getWinLocaleSync() {
	const stdout = getStdOutSync('wmic', ['os', 'get', 'locale']);
	const lcidCode = Number.parseInt(stdout.replace('Locale', ''), 16);

	return lcid.from(lcidCode);
}

function normalise(input) {
	return input.replace(/_/, '-');
}

// Uses a map as a simple memoization technique without having to import `mem`
const asyncCache = new Map();

module.exports = async (options = defaultOptions) => {
	if (asyncCache.has(options.spawn)) {
		return asyncCache.get(options.spawn);
	}

	let locale;

	try {
		const envLocale = getEnvLocale();

		if (envLocale || options.spawn === false) {
			locale = getLocale(envLocale);
		} else if (process.platform === 'win32') {
			locale = await getWinLocale();
		} else if (process.platform === 'darwin') {
			locale = await getAppleLocale();
		} else {
			locale = await getUnixLocale();
		}
	} catch {}

	const normalised = normalise(locale || defaultLocale);
	asyncCache.set(options.spawn, normalised);
	return normalised;
};

const syncCache = new Map();

module.exports.sync = (options = defaultOptions) => {
	if (syncCache.has(options.spawn)) {
		return syncCache.get(options.spawn);
	}

	let locale;
	try {
		const envLocale = getEnvLocale();

		if (envLocale || options.spawn === false) {
			locale = getLocale(envLocale);
		} else if (process.platform === 'win32') {
			locale = getWinLocaleSync();
		} else if (process.platform === 'darwin') {
			locale = getAppleLocaleSync();
		} else {
			locale = getUnixLocaleSync();
		}
	} catch {}

	const normalised = normalise(locale || defaultLocale);
	syncCache.set(options.spawn, normalised);
	return normalised;
};
<commit_msg>Single cache map (#49)<commit_after>'use strict';
const execa = require('execa');
const lcid = require('lcid');

const defaultOptions = {spawn: true};
const defaultLocale = 'en-US';

async function getStdOut(command, args) {
	return (await execa(command, args)).stdout;
}

function getStdOutSync(command, args) {
	return execa.sync(command, args).stdout;
}

function getEnvLocale(env = process.env) {
	return env.LC_ALL || env.LC_MESSAGES || env.LANG || env.LANGUAGE;
}

function parseLocale(string) {
	const env = {};
	for (const definition of string.split('\n')) {
		const [key, value] = definition.split('=');
		env[key] = value.replace(/^"|"$/g, '');
	}

	return getEnvLocale(env);
}

function getLocale(string) {
	return (string && string.replace(/[.:].*/, ''));
}

async function getLocales() {
	return getStdOut('locale', ['-a']);
}

function getLocalesSync() {
	return getStdOutSync('locale', ['-a']);
}

function getSupportedLocale(locale, locales = '') {
	return locales.includes(locale) ? locale : defaultLocale;
}

async function getAppleLocale() {
	const results = await Promise.all([
		getStdOut('defaults', ['read', '-globalDomain', 'AppleLocale']),
		getLocales()
	]);

	return getSupportedLocale(results[0], results[1]);
}

function getAppleLocaleSync() {
	return getSupportedLocale(
		getStdOutSync('defaults', ['read', '-globalDomain', 'AppleLocale']),
		getLocalesSync()
	);
}

async function getUnixLocale() {
	return getLocale(parseLocale(await getStdOut('locale')));
}

function getUnixLocaleSync() {
	return getLocale(parseLocale(getStdOutSync('locale')));
}

async function getWinLocale() {
	const stdout = await getStdOut('wmic', ['os', 'get', 'locale']);
	const lcidCode = Number.parseInt(stdout.replace('Locale', ''), 16);

	return lcid.from(lcidCode);
}

function getWinLocaleSync() {
	const stdout = getStdOutSync('wmic', ['os', 'get', 'locale']);
	const lcidCode = Number.parseInt(stdout.replace('Locale', ''), 16);

	return lcid.from(lcidCode);
}

function normalise(input) {
	return input.replace(/_/, '-');
}

const cache = new Map();

module.exports = async (options = defaultOptions) => {
	if (cache.has(options.spawn)) {
		return cache.get(options.spawn);
	}

	let locale;

	try {
		const envLocale = getEnvLocale();

		if (envLocale || options.spawn === false) {
			locale = getLocale(envLocale);
		} else if (process.platform === 'win32') {
			locale = await getWinLocale();
		} else if (process.platform === 'darwin') {
			locale = await getAppleLocale();
		} else {
			locale = await getUnixLocale();
		}
	} catch {}

	const normalised = normalise(locale || defaultLocale);
	cache.set(options.spawn, normalised);
	return normalised;
};

module.exports.sync = (options = defaultOptions) => {
	if (cache.has(options.spawn)) {
		return cache.get(options.spawn);
	}

	let locale;
	try {
		const envLocale = getEnvLocale();

		if (envLocale || options.spawn === false) {
			locale = getLocale(envLocale);
		} else if (process.platform === 'win32') {
			locale = getWinLocaleSync();
		} else if (process.platform === 'darwin') {
			locale = getAppleLocaleSync();
		} else {
			locale = getUnixLocaleSync();
		}
	} catch {}

	const normalised = normalise(locale || defaultLocale);
	cache.set(options.spawn, normalised);
	return normalised;
};
<|endoftext|>


<commit_before>function app(){
	this.name = "new app";
	this.title= "sfmaster1";
	this.url  = "http://jqueryegitimseti.com/";
	this.title2= "testıser95";
}

app.prototype.new = function() {
	console.log(newUser);
}

app.prototype.write = function(options) {
	console.log(options.text);
};

app.prototype.meet = function() {
	console.log(obj);
}

app.prototype.read = function () {
	console.log(options.url);
};

app.prototype.hide = function () {
	console.log(options.hide);
}

$.fn.jQuery = function(arg) {
	arg = () > ||;
}

$.fn.testuser = function(arg) {
	arg = () < ll;
}
<commit_msg>edit the index file<commit_after>function app(){
	this.name = "new app";
	this.title= "sfmaster1";
	this.url  = "http://jqueryegitimseti.com/";
	this.title2= "testiser95";
}

app.prototype.new = function() {
	console.log(newUser);
}

app.prototype.write = function(options) {
	console.log(options.text);
};

app.prototype.meet = function() {
	console.log(obj);
}

app.prototype.read = function () {
	console.log(options.url);
};

app.prototype.hide = function () {
	console.log(options.hide);
}

$.fn.jQuery = function(arg) {
	arg = () > ||;
}

$.fn.testuser = function(arg) {
	arg = () < ll;
}
<|endoftext|>


<commit_before>var getGL = require('webgl-context');

module.exports = function(opts) {
    if (!opts || (!opts.vertex || !opts.fragment))
        throw "must specify 'vertex' and 'fragment' source";
    var vertSource = (opts.vertex).trim();
    var fragSource = (opts.fragment).trim();

    var gl = opts.gl;
    if (!gl) {
        gl = getGL();
        if (!gl)
            throw new Error("WebGL not supported -- try another browser");
    }
    return compile(gl, vertSource, fragSource, opts.attributeLocations, opts.verbose);
};

//Compiles the shaders, throwing an error if the program was invalid.
function compile(gl, vertSource, fragSource, attribs, verbose) {
    var log = "";

    var vert = loadShader(gl, gl.VERTEX_SHADER, vertSource, verbose);
    var frag = loadShader(gl, gl.FRAGMENT_SHADER, fragSource, verbose);

    var vertShader = vert.shader;
    var fragShader = frag.shader;

    log += vert.log + "\n" + frag.log;

    var program = gl.createProgram();

    gl.attachShader(program, vertShader);
    gl.attachShader(program, fragShader);

    //TODO: Chrome seems a bit buggy with attribute bindings...
    if (attribs) {
        for (var key in attribs) {
            if (attribs.hasOwnProperty(key)) {
                gl.bindAttribLocation(program, Math.floor(attribs[key]), key);
            }
        }
    }

    gl.linkProgram(program);

    log += gl.getProgramInfoLog(program) || "";

    if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
        if (verbose)
            console.warn("Problematic shaders:\nVERTEX_SHADER:\n"+addLineNumbers(vertSource)
                    +"\n\nFRAGMENT_SHADER:\n"+addLineNumbers(fragSource));

        //delete before throwing error
        gl.detachShader(program, vertShader);
        gl.detachShader(program, fragShader);
        gl.deleteShader(vertShader);
        gl.deleteShader(fragShader);

        throw new Error("Error linking the shader program:\n" + log);

    }
    return {
        program: program,
        vertex: vertShader,
        fragment: fragShader,
        log: log.trim()
    };
}

function loadShader(gl, type, source, verbose) {
    var shader = gl.createShader(type);
    if (!shader) //should not occur...
        return -1;

    gl.shaderSource(shader, source);
    gl.compileShader(shader);

    //we do this so the user knows which shader has the error
    var typeStr = (type === gl.VERTEX_SHADER) ? "vertex" : "fragment";

    var logResult = gl.getShaderInfoLog(shader) || "";

    //Chrome will just print "Uncaught error object" if the Error.message
    //is longer than 250 chars... WTF!
    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS) ) {
        if (verbose)
            console.warn( "Problematic "+typeStr+" shader:\n" + addLineNumbers(source) );
        throw new Error("Could not compile "+typeStr+" shader:\n"+logResult);
    }
    if (!shader)
        throw new Error("gl.createShader returned 0 for "+typeStr+" shader.\n"+logResult);
    return {
        shader: shader,
        log: logResult
    };
}

function addLineNumbers( string ) {
    var lines = string.split( '\n' );
    for ( var i = 0; i < lines.length; i ++ ) {
        lines[ i ] = ( i + 1 ) + ': ' + lines[ i ];
    }
    return lines.join( '\n' );
}<commit_msg>verbose now prints error messages since sometimes they were getting truncated in Chrome<commit_after>var getGL = require('webgl-context');

module.exports = function(opts) {
    if (!opts || (!opts.vertex || !opts.fragment))
        throw "must specify 'vertex' and 'fragment' source";
    var vertSource = (opts.vertex).trim();
    var fragSource = (opts.fragment).trim();

    var gl = opts.gl;
    if (!gl) {
        gl = getGL();
        if (!gl)
            throw new Error("WebGL not supported -- try another browser");
    }
    return compile(gl, vertSource, fragSource, opts.attributeLocations, opts.verbose);
};

//Compiles the shaders, throwing an error if the program was invalid.
function compile(gl, vertSource, fragSource, attribs, verbose) {
    var log = "";

    var vert = loadShader(gl, gl.VERTEX_SHADER, vertSource, verbose);
    var frag = loadShader(gl, gl.FRAGMENT_SHADER, fragSource, verbose);

    var vertShader = vert.shader;
    var fragShader = frag.shader;

    log += vert.log + "\n" + frag.log;

    var program = gl.createProgram();

    gl.attachShader(program, vertShader);
    gl.attachShader(program, fragShader);

    //TODO: Chrome seems a bit buggy with attribute bindings...
    if (attribs) {
        for (var key in attribs) {
            if (attribs.hasOwnProperty(key)) {
                gl.bindAttribLocation(program, Math.floor(attribs[key]), key);
            }
        }
    }

    gl.linkProgram(program);

    log += gl.getProgramInfoLog(program) || "";

    if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
        if (verbose) {
            console.error("Shader error:\n"+log);
            console.error("Problematic shaders:\nVERTEX_SHADER:\n"+addLineNumbers(vertSource)
                    +"\n\nFRAGMENT_SHADER:\n"+addLineNumbers(fragSource));
        }
        //delete before throwing error
        gl.detachShader(program, vertShader);
        gl.detachShader(program, fragShader);
        gl.deleteShader(vertShader);
        gl.deleteShader(fragShader);

        throw new Error("Error linking the shader program:\n" + log);

    }
    return {
        program: program,
        vertex: vertShader,
        fragment: fragShader,
        log: log.trim()
    };
}

function loadShader(gl, type, source, verbose) {
    var shader = gl.createShader(type);
    if (!shader) //should not occur...
        return -1;

    gl.shaderSource(shader, source);
    gl.compileShader(shader);

    //we do this so the user knows which shader has the error
    var typeStr = (type === gl.VERTEX_SHADER) ? "vertex" : "fragment";

    var logResult = gl.getShaderInfoLog(shader) || "";

    //Chrome will just print "Uncaught error object" if the Error.message
    //is longer than 250 chars... WTF!
    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS) ) {
        if (verbose) {
            console.error("Shader error:\n"+log);
            console.error( "Problematic "+typeStr+" shader:\n" + addLineNumbers(source) );
        }
        throw new Error("Could not compile "+typeStr+" shader:\n"+logResult);
    }
    if (!shader)
        throw new Error("gl.createShader returned 0 for "+typeStr+" shader.\n"+logResult);
    return {
        shader: shader,
        log: logResult
    };
}

function addLineNumbers( string ) {
    var lines = string.split( '\n' );
    for ( var i = 0; i < lines.length; i ++ ) {
        lines[ i ] = ( i + 1 ) + ': ' + lines[ i ];
    }
    return lines.join( '\n' );
}<|endoftext|>


<commit_before>var hypercore = require('hypercore')
var level = require('level')
var path = require('path')
var storage = require('random-access-file')
var encoding = require('hyperdrive-encoding')
var subleveldown = require('subleveldown')
var collect = require('stream-collector')
var eos = require('end-of-stream')
var events = require('events')
var datKeyAs = require('dat-key-as')
var thunky = require('thunky')

module.exports = create

function create (dir) {
  if (!dir) dir = '.'

  var db = level(path.join(dir, 'db'))
  var misc = subleveldown(db, 'misc', {valueEncoding: 'binary'})
  var keys = subleveldown(db, 'added-keys', {valueEncoding: 'binary'})
  var core = hypercore(db)
  var opened = {}
  var that = new events.EventEmitter()

  that.db = db
  that.discoveryKey = hypercore.discoveryKey
  that.core = core
  that.list = list
  that.add = add
  that.remove = remove
  that.get = get
  that.replicate = replicate

  that.changes = thunky(function (cb) {
    misc.get('changes', function (_, key) {
      var feed = core.createFeed(key)

      if (key) return open()
      misc.put('changes', feed.key, open)

      function open (err) {
        if (err) return cb(err)
        feed.open(function (err) {
          if (err) return cb(err)
          cb(null, feed)
        })
      }
    })
  })

  return that

  function list (cb) {
    return collect(keys.createValueStream(), cb)
  }

  function append (change) {
    that.changes(function (_, feed) {
      if (feed && feed.secretKey) feed.append(JSON.stringify(change) + '\n')
    })
  }

  function cleanup (feed, stream) {
    var hex = feed.discoveryKey.toString('hex')
    opened[hex] = (opened[hex] || 0) + 1

    if (stream.destroyed) return close()
    eos(stream, close)

    function close () {
      if (--opened[hex]) return
      feed.close()
    }
  }

  function replicate (opts) {
    if (!opts) opts = {}

    var stream = core.replicate()

    stream.setTimeout(5000, stream.destroy)
    stream.setMaxListeners(0)
    stream.on('open', onopen)

    if (!opts.passive) {
      that.list().on('data', function (key) {
        open(key, true, stream)
      })
    }

    function onopen (disc) {
      that.changes(function (_, feed) {
        if (feed && feed.discoveryKey.toString('hex') === disc.toString('hex')) {
          feed.replicate({stream: stream})
          return
        }

        keys.get(disc.toString('hex'), function (err, key) {
          if (err) return // ignore errors
          open(key, true, stream)
        })
      })
    }

    return stream
  }

  function add (key, cb) {
    key = datKeyAs.buf(key)
    that.emit('add', key)

    var hex = hypercore.discoveryKey(key).toString('hex')
    keys.get(hex, function (err) {
      if (!err) return cb()
      keys.put(hex, key, cb)
      append({type: 'add', key: key.toString('hex')})
    })
  }

  function remove (key, cb) {
    key = datKeyAs.buf(key)
    that.emit('remove', key)
    var hex = hypercore.discoveryKey(key).toString('hex')
    keys.get(hex, function (err) {
      if (err) return cb()
      keys.del(hex, cb)
      append({type: 'remove', key: key.toString('hex')})
    })
  }

  function get (key, cb) {
    key = datKeyAs.buf(key)
    var discKey = hypercore.discoveryKey(key).toString('hex')
    keys.get(discKey, function (err, key) {
      if (err) return cb(err) // no key found

      key = datKeyAs.str(key)
      var feed = core.createFeed(key, {
        storage: storage(path.join(dir, 'data', key.slice(0, 2), key.slice(2) + '.data'))
      })
      feed.get(0, function (err, data) {
        if (err) return cb(err)
        var content = hyperdriveFeedKey(data)
        if (content || !feed.blocks) return done(content)
        feed.get(feed.blocks - 1, function (err, data) {
          if (err) return cb(err)
          done(hyperdriveFeedKey(data))
        })
      })

      function done (contentKey) {
        opened[discKey] = (opened[discKey] || 0) + 1
        if (!contentKey) return cb(null, feed)

        contentKey = datKeyAs.str(contentKey)
        var contentFeed = core.createFeed(contentKey, {
          storage: storage(path.join(dir, 'data', contentKey.slice(0, 2), contentKey.slice(2) + '.data'))
        })
        var contentDiscKey = hypercore.discoveryKey(contentKey).toString('hex')
        opened[contentDiscKey] = (opened[contentDiscKey] || 0) + 1

        cb(null, feed, contentFeed)
      }
    })
  }

  function open (key, maybeContent, stream) {
    key = datKeyAs.str(key)

    var feed = core.createFeed(key, {
      storage: storage(path.join(dir, 'data', key.slice(0, 2), key.slice(2) + '.data'))
    })

    feed.replicate({stream: stream})

    if (!feed.firstDownload) {
      var downloaded = false

      feed.firstDownload = true
      feed.once('download', function () {
        downloaded = true
      })
      feed.once('download-finished', function () {
        if (downloaded) that.emit('archived', feed.key, feed)
      })
    }

    cleanup(feed, stream)

    if (!maybeContent) return feed

    feed.get(0, function (err, data) {
      if (!decodeContent(err, data) && feed.blocks) feed.get(feed.blocks - 1, decodeContent)
    })

    return feed

    function decodeContent (err, data) {
      if (err) return false
      var content = hyperdriveFeedKey(data)
      if (!content) return false
      open(content, false, stream)
      return true
    }
  }
}

function hyperdriveFeedKey (data) {
  try {
    var index = encoding.decode(data)
    if (index.type !== 'index') return null
    if (!index.content || index.content.length !== 32) return null
    return index.content
  } catch (err) {
    return null
  }
}
<commit_msg>fix fd leak on parallel download. fixes #2<commit_after>var hypercore = require('hypercore')
var level = require('level')
var path = require('path')
var storage = require('random-access-file')
var encoding = require('hyperdrive-encoding')
var subleveldown = require('subleveldown')
var collect = require('stream-collector')
var eos = require('end-of-stream')
var events = require('events')
var datKeyAs = require('dat-key-as')
var thunky = require('thunky')

module.exports = create

function create (dir) {
  if (!dir) dir = '.'

  var db = level(path.join(dir, 'db'))
  var misc = subleveldown(db, 'misc', {valueEncoding: 'binary'})
  var keys = subleveldown(db, 'added-keys', {valueEncoding: 'binary'})
  var core = hypercore(db)
  var opened = {}
  var that = new events.EventEmitter()

  that.db = db
  that.discoveryKey = hypercore.discoveryKey
  that.core = core
  that.list = list
  that.add = add
  that.remove = remove
  that.get = get
  that.replicate = replicate

  that.changes = thunky(function (cb) {
    misc.get('changes', function (_, key) {
      var feed = core.createFeed(key)

      if (key) return open()
      misc.put('changes', feed.key, open)

      function open (err) {
        if (err) return cb(err)
        feed.open(function (err) {
          if (err) return cb(err)
          cb(null, feed)
        })
      }
    })
  })

  return that

  function list (cb) {
    return collect(keys.createValueStream(), cb)
  }

  function append (change) {
    that.changes(function (_, feed) {
      if (feed && feed.secretKey) feed.append(JSON.stringify(change) + '\n')
    })
  }

  function cleanup (feed, stream) {
    var hex = feed.discoveryKey.toString('hex')
    var old = opened[hex]

    if (stream.destroyed) return close()
    eos(stream, close)

    function close () {
      if (--old.cnt) return
      old.feed = null
      feed.close()
    }
  }

  function replicate (opts) {
    if (!opts) opts = {}

    var stream = core.replicate()

    stream.setTimeout(5000, stream.destroy)
    stream.setMaxListeners(0)
    stream.on('open', onopen)

    if (!opts.passive) {
      that.list().on('data', function (key) {
        open(key, true, stream)
      })
    }

    function onopen (disc) {
      that.changes(function (_, feed) {
        if (feed && feed.discoveryKey.toString('hex') === disc.toString('hex')) {
          feed.replicate({stream: stream})
          return
        }

        keys.get(disc.toString('hex'), function (err, key) {
          if (err) return // ignore errors
          open(key, true, stream)
        })
      })
    }

    return stream
  }

  function add (key, cb) {
    key = datKeyAs.buf(key)
    that.emit('add', key)

    var hex = hypercore.discoveryKey(key).toString('hex')
    keys.get(hex, function (err) {
      if (!err) return cb()
      keys.put(hex, key, cb)
      append({type: 'add', key: key.toString('hex')})
    })
  }

  function remove (key, cb) {
    key = datKeyAs.buf(key)
    that.emit('remove', key)
    var hex = hypercore.discoveryKey(key).toString('hex')
    keys.get(hex, function (err) {
      if (err) return cb()
      keys.del(hex, cb)
      append({type: 'remove', key: key.toString('hex')})
    })
  }

  function get (key, cb) {
    key = datKeyAs.buf(key)
    var discKey = hypercore.discoveryKey(key).toString('hex')
    keys.get(discKey, function (err, key) {
      if (err) return cb(err) // no key found

      key = datKeyAs.str(key)
      var feed = core.createFeed(key, {
        storage: storage(path.join(dir, 'data', key.slice(0, 2), key.slice(2) + '.data'))
      })
      feed.get(0, function (err, data) {
        if (err) return cb(err)
        var content = hyperdriveFeedKey(data)
        if (content || !feed.blocks) return done(content)
        feed.get(feed.blocks - 1, function (err, data) {
          if (err) return cb(err)
          done(hyperdriveFeedKey(data))
        })
      })

      function done (contentKey) {
        opened[discKey] = (opened[discKey] || 0) + 1
        if (!contentKey) return cb(null, feed)

        contentKey = datKeyAs.str(contentKey)
        var contentFeed = core.createFeed(contentKey, {
          storage: storage(path.join(dir, 'data', contentKey.slice(0, 2), contentKey.slice(2) + '.data'))
        })
        var contentDiscKey = hypercore.discoveryKey(contentKey).toString('hex')
        opened[contentDiscKey] = (opened[contentDiscKey] || 0) + 1

        cb(null, feed, contentFeed)
      }
    })
  }

  function open (key, maybeContent, stream) {
    key = datKeyAs.str(key)

    var hex = that.discoveryKey(new Buffer(key, 'hex')).toString('hex')
    var old = opened[hex] || {feed: null, cnt: 0}
    var feed = old.feed

    opened[hex] = old

    if (!feed) {
      old.feed = feed = core.createFeed(key, {
        storage: storage(path.join(dir, 'data', key.slice(0, 2), key.slice(2) + '.data'))
      })
    }

    old.cnt++
    feed.replicate({stream: stream})

    if (!feed.firstDownload) {
      var downloaded = false

      feed.firstDownload = true
      feed.once('download', function () {
        downloaded = true
      })
      feed.once('download-finished', function () {
        if (downloaded) that.emit('archived', feed.key, feed)
      })
    }

    cleanup(feed, stream)

    if (!maybeContent) return feed

    feed.get(0, function (err, data) {
      if (!decodeContent(err, data) && feed.blocks) feed.get(feed.blocks - 1, decodeContent)
    })

    return feed

    function decodeContent (err, data) {
      if (err) return false
      var content = hyperdriveFeedKey(data)
      if (!content) return false
      open(content, false, stream)
      return true
    }
  }
}

function hyperdriveFeedKey (data) {
  try {
    var index = encoding.decode(data)
    if (index.type !== 'index') return null
    if (!index.content || index.content.length !== 32) return null
    return index.content
  } catch (err) {
    return null
  }
}
<|endoftext|>


<commit_before>var level = require('level')
  , s3sync = require('s3-sync')
  , readdirp = require('readdirp')

var public_dir = hexo.config.public_dir || './public';

hexo.extend.deployer.register('s3', function (args, callback) {
  var config = hexo.config.deploy;

  config.aws_key = config.aws_key || process.env.AWS_KEY;
  config.aws_secret = config.aws_secret || process.env.AWS_SECRET;

  if (!config.bucket || !config.aws_key || !config.aws_secret){
    var help = [
      'You should configure deployment settings in _config.yml first!',
      '',
      'Example:',
      '  deploy:',
      '    type: s3',
      '    bucket: <bucket>',
      '    [aws_key]: <aws_key>        # Optional, if provided as environment variable',
      '    [aws_secret]: <aws_secret>  # Optional, if provided as environment variable',
      '    [concurrency]: <concurrency>',
      '    [region]: <region>          # See https://github.com/LearnBoost/knox#region',
      '',
      'For more help, you can check the docs: ' + 'https://github.com/joshstrange/hexo-deployer-s3'
    ];

    console.log(help.join('\n'));
    return callback();
  }

  var files = readdirp({
      root: public_dir,
      entryType: 'both'
  });

  if(!config.concurrency)
  {
    config.concurrency = 8;
  }

  // Takes the same options arguments as `knox`,
  // plus some additional options listed above
  var uploader = s3sync({
      key: config.aws_key
    , secret: config.aws_secret
    , bucket: config.bucket
    , concurrency: config.concurrency
    , region: config.region
  }).on('data', function(file) {
    console.log(file.fullPath + ' -> ' + file.url)
  }).on('end', function() {
    console.log('Done!');
    callback();
  });

  files.pipe(uploader);

});
<commit_msg>Add some file upload error handling<commit_after>var level = require('level')
  , s3sync = require('s3-sync')
  , readdirp = require('readdirp')

var public_dir = hexo.config.public_dir || './public';

hexo.extend.deployer.register('s3', function (args, callback) {
  var config = hexo.config.deploy;

  config.aws_key = config.aws_key || process.env.AWS_KEY;
  config.aws_secret = config.aws_secret || process.env.AWS_SECRET;

  if (!config.bucket || !config.aws_key || !config.aws_secret){
    var help = [
      'You should configure deployment settings in _config.yml first!',
      '',
      'Example:',
      '  deploy:',
      '    type: s3',
      '    bucket: <bucket>',
      '    [aws_key]: <aws_key>        # Optional, if provided as environment variable',
      '    [aws_secret]: <aws_secret>  # Optional, if provided as environment variable',
      '    [concurrency]: <concurrency>',
      '    [region]: <region>          # See https://github.com/LearnBoost/knox#region',
      '',
      'For more help, you can check the docs: ' + 'https://github.com/joshstrange/hexo-deployer-s3'
    ];

    console.log(help.join('\n'));
    return callback();
  }

  var files = readdirp({
      root: public_dir,
      entryType: 'both'
  });

  if(!config.concurrency)
  {
    config.concurrency = 8;
  }

  // Takes the same options arguments as `knox`,
  // plus some additional options listed above
  var uploader = s3sync({
      key: config.aws_key
    , secret: config.aws_secret
    , bucket: config.bucket
    , concurrency: config.concurrency
    , region: config.region
  }).on('data', function(file) {
    console.log(file.fullPath + ' -> ' + file.url)
  }).on('end', function() {
    console.log('Done!');
    callback();
  }).on('fail', function(err) {
    console.log(err)
  });

  files.pipe(uploader);

});
<|endoftext|>