<commit_before>/*
Copyright (c) 2011, Rob Ellis, Chris Umbel

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

var _ = require("underscore")._,
    Tokenizer = require('../tokenizers/regexp_tokenizer').WordTokenizer,
    tokenizer = new Tokenizer(),
    stopwords = require('../util/stopwords').words,
    fs = require('fs');

function buildDocument(text, key) {
    var stopOut;

    if(typeof text === 'string') {
        text = tokenizer.tokenize(text.toLowerCase());
        stopOut = true;
    } else if(!_.isArray(text)) {
        return text;
        stopOut = false;
    }

    return text.reduce(function(document, term) {
        // next line solves https://github.com/NaturalNode/natural/issues/119
        if(typeof document[term] === 'function') document[term] = 0;
        if(!stopOut || stopwords.indexOf(term) < 0)
            document[term] = (document[term] ? document[term] + 1 : 1);
        return document;
    }, {__key: key});
}

function tf(term, document) {
    return document[term] ? document[term]: 0;
}

function documentHasTerm(term, document) {
    return document[term] && document[term] > 0;
}

function TfIdf(deserialized) {
    if(deserialized)
        this.documents = deserialized.documents;
    else
        this.documents = [];

    this._idfCache = {};
}

module.exports = TfIdf;
TfIdf.tf = tf;

TfIdf.prototype.idf = function(term, force) {

    // Lookup the term in the New term-IDF caching,
    // this will cut search times down exponentially on large document sets.
    if(this._idfCache[term] && this._idfCache.hasOwnProperty(term) && force !== true)
        return this._idfCache[term];

    var docsWithTerm = this.documents.reduce(function(count, document) {
        return count + (documentHasTerm(term, document) ? 1 : 0);
    }, 0);

    var idf = Math.log((this.documents.length) / (docsWithTerm));

    // Add the idf to the term cache and return it
    this._idfCache[term] = idf;
    return idf;
};

// If restoreCache is set to true, all terms idf scores currently cached will be recomputed.
// Otherwise, the cache will just be wiped clean
TfIdf.prototype.addDocument = function(document, key, restoreCache) {
    this.documents.push(buildDocument(document, key));

    // make sure the cache is invalidated when new documents arrive
    if(restoreCache === true) {
        for(var term in this._idfCache) {
            // invoking idf with the force option set will
            // force a recomputation of the idf, and it will
            // automatically refresh the cache value.
            this.idf(term, true);
        }
    }
    else {
        this._idfCache = {};
    }
};

// If restoreCache is set to true, all terms idf scores currently cached will be recomputed.
// Otherwise, the cache will just be wiped clean
TfIdf.prototype.addFileSync = function(path, encoding, key, restoreCache) {
    if(!encoding)
        encoding = 'UTF-8';

    var document = fs.readFileSync(path, 'UTF-8');
    this.documents.push(buildDocument(document, key));

    // make sure the cache is invalidated when new documents arrive
    if(restoreCache === true) {
        for(var term in this._idfCache) {
            // invoking idf with the force option set will
            // force a recomputation of the idf, and it will
            // automatically refresh the cache value.
            this.idf(term, true);
        }
    }
    else {
        this._idfCache = {};
    }
};

TfIdf.prototype.tfidf = function(terms, d) {
    var _this = this;

    if(!_.isArray(terms))
        terms = tokenizer.tokenize(terms.toString().toLowerCase());

    return terms.reduce(function(value, term) {
        return value + (tf(term, _this.documents[d]) * _this.idf(term));
    }, 0.0);
};

TfIdf.prototype.listTerms = function(d) {
    var terms = [];

    for(var term in this.documents[d]) {
        if(term != '__key')
    	   terms.push({term: term, tfidf: this.tfidf(term, d)})
    }

    return terms.sort(function(x, y) { return y.tfidf - x.tfidf });
}

TfIdf.prototype.tfidfs = function(terms, callback) {
    var tfidfs = new Array(this.documents.length);

    for(var i = 0; i < this.documents.length; i++) {
        tfidfs[i] = this.tfidf(terms, i);

        if(callback)
            callback(i, tfidfs[i], this.documents[i].__key);
    }

    return tfidfs;
};
<commit_msg>No more NaNs<commit_after>/*
Copyright (c) 2011, Rob Ellis, Chris Umbel

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

var _ = require("underscore")._,
    Tokenizer = require('../tokenizers/regexp_tokenizer').WordTokenizer,
    tokenizer = new Tokenizer(),
    stopwords = require('../util/stopwords').words,
    fs = require('fs');

function buildDocument(text, key) {
    var stopOut;

    if(typeof text === 'string') {
        text = tokenizer.tokenize(text.toLowerCase());
        stopOut = true;
    } else if(!_.isArray(text)) {
        return text;
        stopOut = false;
    }

    return text.reduce(function(document, term) {
        // next line solves https://github.com/NaturalNode/natural/issues/119
        if(typeof document[term] === 'function') document[term] = 0;
        if(!stopOut || stopwords.indexOf(term) < 0)
            document[term] = (document[term] ? document[term] + 1 : 1);
        return document;
    }, {__key: key});
}

function tf(term, document) {
    return document[term] ? document[term]: 0;
}

function documentHasTerm(term, document) {
    return document[term] && document[term] > 0;
}

function TfIdf(deserialized) {
    if(deserialized)
        this.documents = deserialized.documents;
    else
        this.documents = [];

    this._idfCache = {};
}

module.exports = TfIdf;
TfIdf.tf = tf;

TfIdf.prototype.idf = function(term, force) {

    // Lookup the term in the New term-IDF caching,
    // this will cut search times down exponentially on large document sets.
    if(this._idfCache[term] && this._idfCache.hasOwnProperty(term) && force !== true)
        return this._idfCache[term];

    var docsWithTerm = this.documents.reduce(function(count, document) {
        return count + (documentHasTerm(term, document) ? 1 : 0);
    }, 0);

    var idf = Math.log((this.documents.length) / (docsWithTerm));

    // Add the idf to the term cache and return it
    this._idfCache[term] = idf;
    return idf;
};

// If restoreCache is set to true, all terms idf scores currently cached will be recomputed.
// Otherwise, the cache will just be wiped clean
TfIdf.prototype.addDocument = function(document, key, restoreCache) {
    this.documents.push(buildDocument(document, key));

    // make sure the cache is invalidated when new documents arrive
    if(restoreCache === true) {
        for(var term in this._idfCache) {
            // invoking idf with the force option set will
            // force a recomputation of the idf, and it will
            // automatically refresh the cache value.
            this.idf(term, true);
        }
    }
    else {
        this._idfCache = {};
    }
};

// If restoreCache is set to true, all terms idf scores currently cached will be recomputed.
// Otherwise, the cache will just be wiped clean
TfIdf.prototype.addFileSync = function(path, encoding, key, restoreCache) {
    if(!encoding)
        encoding = 'UTF-8';

    var document = fs.readFileSync(path, 'UTF-8');
    this.documents.push(buildDocument(document, key));

    // make sure the cache is invalidated when new documents arrive
    if(restoreCache === true) {
        for(var term in this._idfCache) {
            // invoking idf with the force option set will
            // force a recomputation of the idf, and it will
            // automatically refresh the cache value.
            this.idf(term, true);
        }
    }
    else {
        this._idfCache = {};
    }
};

TfIdf.prototype.tfidf = function(terms, d) {
    var _this = this;

    if(!_.isArray(terms))
        terms = tokenizer.tokenize(terms.toString().toLowerCase());

    return terms.reduce(function(value, term) {
        var idf = _this.idf(term);
        idf = idf === Infinity ? 0 : idf;
        return value + (tf(term, _this.documents[d]) * idf);
    }, 0.0);
};

TfIdf.prototype.listTerms = function(d) {
    var terms = [];

    for(var term in this.documents[d]) {
        if(term != '__key')
    	   terms.push({term: term, tfidf: this.tfidf(term, d)})
    }

    return terms.sort(function(x, y) { return y.tfidf - x.tfidf });
}

TfIdf.prototype.tfidfs = function(terms, callback) {
    var tfidfs = new Array(this.documents.length);

    for(var i = 0; i < this.documents.length; i++) {
        tfidfs[i] = this.tfidf(terms, i);

        if(callback)
            callback(i, tfidfs[i], this.documents[i].__key);
    }

    return tfidfs;
};
<|endoftext|>


<commit_before>/*
 * Parsley.js - django admin helper
*/

!function ($) {
  'use strict';

  $( window ).on( 'load', function () {
    $( 'form' ).each( function () {
      $( this ).parsley({
      });
    } );
  } );
}(window.jQuery || window.Zepto);
<commit_msg>Don't parsleyfy Django admin search boxes<commit_after>/*
 * Parsley.js - django admin helper
 */
! function($) {
    'use strict';

    $(window).on('load', function() {
        // Don't parsleyfy Django search boxes. It breaks layout
        $('form:not(#changelist-search, #changelist-form)').each(function() {
            $(this).parsley({});
        });
    });
}(window.jQuery || window.Zepto);
<|endoftext|>


<commit_before>/**
 * @author Sam Thompson
 *
 * Provides basic UI functionality of a panel
 */
$( function()
{
	"use strict";
	$.widget( 'jqueryDash.panel', $.jqueryDash.localStorageObject, {

		_mode: 'init',
		_modeEdit: 'edit',
		_modeView: 'view',

		options: {
			id: 0,
			mode: 'view',
			minWidth: 196,
			minHeight: 196,
			position: {
				w: 200,
				h: 200,
				x: 8,
				y: 9
			},
			ordering: null
		},

		_create: function()
		{
			var
				initialPos,
				initialWidth,
				initialHeight;

			this.element.data( 'panelType', this.widgetName );

			// Load the saved panel position
			initialPos = ( this.isSetting( 'posX' ) && this.isSetting( 'posY' ) ) ?
						 { 'x': this.setting( 'posX' ), 'y': this.setting( 'posY' ) } :
						 { 'x': this.options.position.x, 'y': this.options.position.y };

			// Load the saved panel size
			initialWidth = ( this.isSetting( 'width' ) ) ? this.setting( 'width' ) : this.options.position.w;
			initialHeight = ( this.isSetting( 'height' ) ) ? this.setting( 'height' ) : this.options.position.h;

			this.element
				.width( initialWidth )
				.height( initialHeight )
				.css( {
					'position': 'absolute',
					'top': initialPos.y,
					'left': initialPos.x
				} );

			// Set the default mode
			this.mode( this.options.mode );

			// Set the ordering if one is specified
			if( this.options.ordering !== null )
			{
				this.setOrdering( this.options.ordering );
			}
			else
			{
				// Load the ordering setting
				if( this.isSetting( 'ordering' ) )
				{
					this.element.zIndex( this.setting( 'ordering' ) );
				}
			}
		},

		_getStorageNamespace: function()
		{
			return this.options.id;
		},

		/**
		 * Gets or sets the mode of this panel
		 *
		 * @param {string} mode Optional - Acts as setter if provided
		 * @returns {string} Current mode
		 */
		mode: function( mode )
		{
			// Set the mode if provided
			if( mode !== undefined && mode !== this._mode )
			{

				if( mode === this._modeEdit )
				{
					// destroy view mode if required
					if( this._mode === this._modeView )
					{
						this._destroyViewPanel();
					}
					this._drawEditPanel();
					this._mode = this._modeEdit;
				}
				else
				{
					// destroy edit mode if required
					if( this._mode === this._modeEdit )
					{
						this._destroyEditPanel();
					}
					// open view
					this._drawViewPanel();
					this._mode = this._modeView;
				}
			}

			// Return the mode - allows this method to be used as a getter if no mode is passed
			return this._mode;
		},

		/**
		 * Completely removes this widget
		 * @private
		 */
		_destroy: function()
		{
			// Remove settings for this object from this, and the controller's local storage
			this.removeSettings();
			this.element.parent().trigger( 'deletePanel', this.options.id );

			// destroy anything specific to whatever mode we are in
			switch( this._mode )
			{
				case this._modeEdit:
					this._destroyEditPanel();
					break;
				case this._modeView:
					this._destroyViewPanel();
					break;
			}

			// remove the element from the DOM
			this.element.remove();

			// Destroy this widget
			this._super();
		},

		/**
		 * Creates the editor interface for this panel
		 *
		 * @private
		 */
		_drawEditPanel: function()
		{
			var self = this;
			this.element
				// Set the panel to be movable
				.draggable( {
					containment: 'parent',
					grid: [50, 50],
					'handle': '.move-panel',
					start: function()
					{
						self._bringToFront();
					},
					stop: function()
					{
						var position = $( this ).position();
						self.setting( 'posX', position.left );
						self.setting( 'posY', position.top );
					}
				} )
				// Set the panel to be resizable
				.resizable( {
					minWidth: this.options.minWidth,
					minHeight: this.options.minHeight,
					handles: 'n,s,e,w,se,sw,nw',
					grid: 50,
					containment: 'parent',
					start: function()
					{
						self._bringToFront();
					},
					stop: function()
					{
						self.setting( 'width', $( this ).width() );
						self.setting( 'height', $( this ).height() );
					}
				} )
				.append(
					$( '<a>', {'class': 'button delete-panel', 'text': 'x', 'title': 'Delete Panel'} ).click( function()
					{
						if( confirm( 'Are you sure you want to delete this panel?' ) )
						{
							self._destroy();
						}
					} ),
					$( '<a>', {'class': 'move-panel', 'html': '≡', 'title': 'Move Panel'} )
				)
				.click( function()
				{
					self._bringToFront();
				} );

			$( 'body' ).disableSelection();
		},

		/**
		 * Destroys the editor interface for this panel
		 *
		 * @private
		 */
		_destroyEditPanel: function()
		{
			var parent = this.element.parent();
			this.element
				.detach()
				.draggable( 'destroy' )
				.resizable( 'destroy' )
				.html( '' )
				.appendTo( parent );
			$( 'body' ).enableSelection();
		},

		/**
		 * Creates the view interface for this panel
		 *
		 * @private
		 */
		_drawViewPanel: function()
		{
			this.element.append( $( '<div>', { 'class': 'content', 'text': 'content' } ) );
		},

		/**
		 * Destroys the view interface for this panel
		 *
		 * @private
		 */
		_destroyViewPanel: function()
		{
			this.element.html( '' );
		},

		/**
		 * Called by the _create method or when panels are reorder by the Panels controller
		 *
		 * @param order New z-index for this panel
		 */
		setOrdering: function( order )
		{
			this.element.zIndex( order );
			this.setting( 'ordering', order );
		},

		/**
		 * Brings this panel to the front
		 *
		 * @private
		 */
		_bringToFront: function()
		{
			this.element.parent().panels( 'setFrontPanel', this );
		}

	} );
} );<commit_msg>added the widget name onto each panel<commit_after>/**
 * @author Sam Thompson
 *
 * Provides basic UI functionality of a panel
 */
$( function()
{
	"use strict";
	$.widget( 'jqueryDash.panel', $.jqueryDash.localStorageObject, {

		_mode: 'init',
		_modeEdit: 'edit',
		_modeView: 'view',

		options: {
			id: 0,
			mode: 'view',
			minWidth: 196,
			minHeight: 196,
			position: {
				w: 200,
				h: 200,
				x: 8,
				y: 9
			},
			ordering: null
		},

		_create: function()
		{
			var
				initialPos,
				initialWidth,
				initialHeight;

			this.element.data( 'panelType', this.widgetName );

			// Load the saved panel position
			initialPos = ( this.isSetting( 'posX' ) && this.isSetting( 'posY' ) ) ?
						 { 'x': this.setting( 'posX' ), 'y': this.setting( 'posY' ) } :
						 { 'x': this.options.position.x, 'y': this.options.position.y };

			// Load the saved panel size
			initialWidth = ( this.isSetting( 'width' ) ) ? this.setting( 'width' ) : this.options.position.w;
			initialHeight = ( this.isSetting( 'height' ) ) ? this.setting( 'height' ) : this.options.position.h;

			this.element
				.width( initialWidth )
				.height( initialHeight )
				.css( {
					'position': 'absolute',
					'top': initialPos.y,
					'left': initialPos.x
				} )
				.addClass( this.widgetName );

			// Set the default mode
			this.mode( this.options.mode );

			// Set the ordering if one is specified
			if( this.options.ordering !== null )
			{
				this.setOrdering( this.options.ordering );
			}
			else
			{
				// Load the ordering setting
				if( this.isSetting( 'ordering' ) )
				{
					this.element.zIndex( this.setting( 'ordering' ) );
				}
			}
		},

		_getStorageNamespace: function()
		{
			return this.options.id;
		},

		/**
		 * Gets or sets the mode of this panel
		 *
		 * @param {string} mode Optional - Acts as setter if provided
		 * @returns {string} Current mode
		 */
		mode: function( mode )
		{
			// Set the mode if provided
			if( mode !== undefined && mode !== this._mode )
			{

				if( mode === this._modeEdit )
				{
					// destroy view mode if required
					if( this._mode === this._modeView )
					{
						this._destroyViewPanel();
					}
					this._drawEditPanel();
					this._mode = this._modeEdit;
				}
				else
				{
					// destroy edit mode if required
					if( this._mode === this._modeEdit )
					{
						this._destroyEditPanel();
					}
					// open view
					this._drawViewPanel();
					this._mode = this._modeView;
				}
			}

			// Return the mode - allows this method to be used as a getter if no mode is passed
			return this._mode;
		},

		/**
		 * Completely removes this widget
		 * @private
		 */
		_destroy: function()
		{
			// Remove settings for this object from this, and the controller's local storage
			this.removeSettings();
			this.element.parent().trigger( 'deletePanel', this.options.id );

			// destroy anything specific to whatever mode we are in
			switch( this._mode )
			{
				case this._modeEdit:
					this._destroyEditPanel();
					break;
				case this._modeView:
					this._destroyViewPanel();
					break;
			}

			// remove the element from the DOM
			this.element.remove();

			// Destroy this widget
			this._super();
		},

		/**
		 * Creates the editor interface for this panel
		 *
		 * @private
		 */
		_drawEditPanel: function()
		{
			var self = this;
			this.element
				// Set the panel to be movable
				.draggable( {
					containment: 'parent',
					grid: [50, 50],
					'handle': '.move-panel',
					start: function()
					{
						self._bringToFront();
					},
					stop: function()
					{
						var position = $( this ).position();
						self.setting( 'posX', position.left );
						self.setting( 'posY', position.top );
					}
				} )
				// Set the panel to be resizable
				.resizable( {
					minWidth: this.options.minWidth,
					minHeight: this.options.minHeight,
					handles: 'n,s,e,w,se,sw,nw',
					grid: 50,
					containment: 'parent',
					start: function()
					{
						self._bringToFront();
					},
					stop: function()
					{
						self.setting( 'width', $( this ).width() );
						self.setting( 'height', $( this ).height() );
					}
				} )
				.append(
					$( '<a>', {'class': 'button delete-panel', 'text': 'x', 'title': 'Delete Panel'} ).click( function()
					{
						if( confirm( 'Are you sure you want to delete this panel?' ) )
						{
							self._destroy();
						}
					} ),
					$( '<a>', {'class': 'move-panel', 'html': '≡', 'title': 'Move Panel'} )
				)
				.click( function()
				{
					self._bringToFront();
				} );

			$( 'body' ).disableSelection();
		},

		/**
		 * Destroys the editor interface for this panel
		 *
		 * @private
		 */
		_destroyEditPanel: function()
		{
			var parent = this.element.parent();
			this.element
				.detach()
				.draggable( 'destroy' )
				.resizable( 'destroy' )
				.html( '' )
				.appendTo( parent );
			$( 'body' ).enableSelection();
		},

		/**
		 * Creates the view interface for this panel
		 *
		 * @private
		 */
		_drawViewPanel: function()
		{
			this.element.append( $( '<div>', { 'class': 'content', 'text': 'content' } ) );
		},

		/**
		 * Destroys the view interface for this panel
		 *
		 * @private
		 */
		_destroyViewPanel: function()
		{
			this.element.html( '' );
		},

		/**
		 * Called by the _create method or when panels are reorder by the Panels controller
		 *
		 * @param order New z-index for this panel
		 */
		setOrdering: function( order )
		{
			this.element.zIndex( order );
			this.setting( 'ordering', order );
		},

		/**
		 * Brings this panel to the front
		 *
		 * @private
		 */
		_bringToFront: function()
		{
			this.element.parent().panels( 'setFrontPanel', this );
		}

	} );
} );<|endoftext|>


<commit_before>isUser = function(userId) {
  return userId;
};

mayAdmin = function(userId) {
  var user = getUser(userId);
  return Roles.userIsInRole(user, 'admin');
};

isAdmin = function(userId) {
  var user = getUser(userId);
  return mayAdmin(user) && user.profile.adminEnabled;
};

isOwner = function(userId, doc) {
  if (!doc) return false;
  var user = getUser(userId);

  return (
    isAdmin(user) ||
    user._id === doc.ownerId ||
    _.intersection(user.groups, doc.ownerGroups || []).length > 0
  );
};

hasAccess = function(userId, doc) {
  if (!doc) return false;
  var user = getUser(userId);

  return (
    Roles.userIsInRole(user, 'fullAccess') ||
    isOwner(userId, doc) ||
    _.intersection(user.groups, doc.accessGroups || []).length > 0
  );
};

filterByOwnership = function(userId) {
  var user = getUser(userId);

  return isAdmin(user) ? {} : {
    $or: [
      { ownerId: user._id },
      { ownerGroups: { $elemMatch: { $in: user.groups || [] } } }
    ]
  };
};

filterByAccess = function(userId) {
  var user = getUser(userId);
  var filter = Roles.userIsInRole(user, 'fullAccess') ? {} : filterByOwnership(userId);

  if (filter.hasOwnProperty('$or')) {
    filter['$or'].push({
      accessGroups: { $elemMatch: { $in: user.groups || [] } }
    });
  }

  return filter;
};

requireUser = function(userId) {
  if (!isUser(userId)) {
    throw new Meteor.Error('access-denied', "You must be logged in for that action.");
  }
};

requireOwnership = function(userId, doc) {
  if (!isOwner(userId, doc)) {
    throw new Meteor.Error('access-denied', `You don't have ownership for this entity (${doc._id}).`);
  }
};

requireAccess = function(userId, doc) {
  if (!hasAccess(userId, doc)) {
    throw new Meteor.Error('access-denied', `You don't have access permissions for this entity (${doc._id}).`);
  }
};

requireAdmin = function(userId) {
  if (!isAdmin(userId)) {
    throw new Meteor.Error('access-denied', "You must have admin privileges for that action.");
  }
}<commit_msg>minor<commit_after>isUser = function(userId) {
  return userId;
};

mayAdmin = function(userId) {
  var user = getUser(userId);
  return Roles.userIsInRole(user, 'admin');
};

isAdmin = function(userId) {
  var user = getUser(userId);
  return mayAdmin(user) && user.profile.adminEnabled;
};

isOwner = function(userId, doc) {
  if (!doc) return false;
  var user = getUser(userId);

  return (
    isAdmin(user) ||
    user._id === doc.ownerId ||
    _.intersection(user.groups, doc.ownerGroups || []).length > 0
  );
};

hasAccess = function(userId, doc) {
  if (!doc) return false;
  var user = getUser(userId);

  return (
    Roles.userIsInRole(user, 'fullAccess') ||
    isOwner(userId, doc) ||
    _.intersection(user.groups, doc.accessGroups || []).length > 0
  );
};

filterByOwnership = function(userId) {
  var user = getUser(userId);

  return isAdmin(user) ? {} : {
    $or: [
      { ownerId: user._id },
      { ownerGroups: { $elemMatch: { $in: user.groups || [] } } }
    ]
  };
};

filterByAccess = function(userId) {
  var user = getUser(userId);
  var filter = Roles.userIsInRole(user, 'fullAccess') ? {} : filterByOwnership(userId);

  if (filter.hasOwnProperty('$or')) {
    filter['$or'].push({
      accessGroups: { $elemMatch: { $in: user.groups || [] } }
    });
  }

  return filter;
};

requireUser = function(userId) {
  if (!isUser(userId)) {
    throw new Meteor.Error('access-denied', "You must be logged in for that action.");
  }
};

requireOwnership = function(userId, doc) {
  if (!isOwner(userId, doc)) {
    throw new Meteor.Error('access-denied', `You don't have ownership for this entity.`);
  }
};

requireAccess = function(userId, doc) {
  if (!hasAccess(userId, doc)) {
    throw new Meteor.Error('access-denied', `You don't have access permissions for this entity.`);
  }
};

requireAdmin = function(userId) {
  if (!isAdmin(userId)) {
    throw new Meteor.Error('access-denied', "You must have admin privileges for that action.");
  }
}<|endoftext|>


<commit_before>// @flow

import { AsyncStorage, NativeModules, PermissionsAndroid } from 'react-native'

type Status = 'authorized' | 'denied' | 'restricted' | 'undetermined'
type Rationale = { title: string, message: string }
type Options = string | { type: string, rationale?: Rationale }

const permissionTypes = {
  location: PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
  camera: PermissionsAndroid.PERMISSIONS.CAMERA,
  microphone: PermissionsAndroid.PERMISSIONS.RECORD_AUDIO,
  contacts: PermissionsAndroid.PERMISSIONS.READ_CONTACTS,
  event: PermissionsAndroid.PERMISSIONS.READ_CALENDAR,
  storage: PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE,
  photo: PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE,
  callPhone: PermissionsAndroid.PERMISSIONS.CALL_PHONE,
  readSms: PermissionsAndroid.PERMISSIONS.READ_SMS,
  receiveSms: PermissionsAndroid.PERMISSIONS.RECEIVE_SMS,
}

const RESULTS = {
  [PermissionsAndroid.RESULTS.GRANTED]: 'authorized',
  [PermissionsAndroid.RESULTS.DENIED]: 'denied',
  [PermissionsAndroid.RESULTS.NEVER_ASK_AGAIN]: 'restricted',
}

const STORAGE_KEY = '@RNPermissions:didAskPermission:'

const setDidAskOnce = (permission: string) =>
  AsyncStorage.setItem(STORAGE_KEY + permission, 'true')

const getDidAskOnce = (permission: string) =>
  AsyncStorage.getItem(STORAGE_KEY + permission).then(item => !!item)

class ReactNativePermissions {
  canOpenSettings: () => Promise<boolean> = () => Promise.resolve(false)

  openSettings: () => Promise<*> = () =>
    Promise.reject(new Error("'openSettings' is deprecated on android"))

  getTypes: () => Array<string> = () => Object.keys(permissionTypes)

  check = (permission: string, type?: string): Promise<Status> => {
    if (!permissionTypes[permission]) {
      const error = new Error(
        `ReactNativePermissions: ${
          permission
        } is not a valid permission type on Android`,
      )

      return Promise.reject(error)
    }

    return PermissionsAndroid.check(permissionTypes[permission]).then(
      isAuthorized => {
        if (isAuthorized) {
          return 'authorized'
        }

        return getDidAskOnce(permission).then(didAsk => {
          if (didAsk) {
            return NativeModules.PermissionsAndroid.shouldShowRequestPermissionRationale(
              permissionTypes[permission],
            ).then(shouldShow => (shouldShow ? 'denied' : 'restricted'))
          }

          return 'undetermined'
        })
      },
    )
  }

  request = (permission: string, options?: Options): Promise<Status> => {
    if (!permissionTypes[permission]) {
      const error = new Error(
        `ReactNativePermissions: ${
          permission
        } is not a valid permission type on Android`,
      )

      return Promise.reject(error)
    }

    let rationale

    if (options && options.rationale) {
      rationale = options.rationale
    }

    return PermissionsAndroid.request(
      permissionTypes[permission],
      rationale,
    ).then(result => {
      // PermissionsAndroid.request() to native module resolves to boolean
      // rather than string if running on OS version prior to Android M
      if (typeof result === 'boolean') {
        return result ? 'authorized' : 'denied'
      }

      return setDidAskOnce(permission).then(() => RESULTS[result])
    })
  }

  checkMultiple = (permissions: Array<string>): Promise<{ [string]: string }> =>
    Promise.all(permissions.map(permission => this.check(permission))).then(
      result =>
        result.reduce((acc, value, index) => {
          const name = permissions[index]
          acc[name] = value
          return acc
        }, {}),
    )
}

module.exports = new ReactNativePermissions()
<commit_msg>Fixed bug with Android < 23<commit_after>// @flow

import { AsyncStorage, NativeModules, PermissionsAndroid } from 'react-native'

type Status = 'authorized' | 'denied' | 'restricted' | 'undetermined'
type Rationale = { title: string, message: string }
type Options = string | { type: string, rationale?: Rationale }

const permissionTypes = {
  location: PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
  camera: PermissionsAndroid.PERMISSIONS.CAMERA,
  microphone: PermissionsAndroid.PERMISSIONS.RECORD_AUDIO,
  contacts: PermissionsAndroid.PERMISSIONS.READ_CONTACTS,
  event: PermissionsAndroid.PERMISSIONS.READ_CALENDAR,
  storage: PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
  photo: PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
  callPhone: PermissionsAndroid.PERMISSIONS.CALL_PHONE,
  readSms: PermissionsAndroid.PERMISSIONS.READ_SMS,
  receiveSms: PermissionsAndroid.PERMISSIONS.RECEIVE_SMS,
}

const RESULTS = {
  [PermissionsAndroid.RESULTS.GRANTED]: 'authorized',
  [PermissionsAndroid.RESULTS.DENIED]: 'denied',
  [PermissionsAndroid.RESULTS.NEVER_ASK_AGAIN]: 'restricted',
}

const STORAGE_KEY = '@RNPermissions:didAskPermission:'

const setDidAskOnce = (permission: string) =>
  AsyncStorage.setItem(STORAGE_KEY + permission, 'true')

const getDidAskOnce = (permission: string) =>
  AsyncStorage.getItem(STORAGE_KEY + permission).then(item => !!item)

class ReactNativePermissions {
  canOpenSettings: () => Promise<boolean> = () => Promise.resolve(false)

  openSettings: () => Promise<*> = () =>
    Promise.reject(new Error("'openSettings' is deprecated on android"))

  getTypes: () => Array<string> = () => Object.keys(permissionTypes)

  check = (permission: string, type?: string): Promise<Status> => {
    if (!permissionTypes[permission]) {
      const error = new Error(
        `ReactNativePermissions: ${
          permission
        } is not a valid permission type on Android`,
      )

      return Promise.reject(error)
    }

    return PermissionsAndroid.check(permissionTypes[permission]).then(
      isAuthorized => {
        if (isAuthorized) {
          return 'authorized'
        }

        return getDidAskOnce(permission).then(didAsk => {
          if (didAsk) {
            return NativeModules.PermissionsAndroid.shouldShowRequestPermissionRationale(
              permissionTypes[permission],
            ).then(shouldShow => (shouldShow ? 'denied' : 'restricted'))
          }

          return 'undetermined'
        })
      },
    )
  }

  request = (permission: string, options?: Options): Promise<Status> => {
    if (!permissionTypes[permission]) {
      const error = new Error(
        `ReactNativePermissions: ${
          permission
        } is not a valid permission type on Android`,
      )

      return Promise.reject(error)
    }

    let rationale

    if (options && options.rationale) {
      rationale = options.rationale
    }

    return PermissionsAndroid.request(
      permissionTypes[permission],
      rationale,
    ).then(result => {
      // PermissionsAndroid.request() to native module resolves to boolean
      // rather than string if running on OS version prior to Android M
      if (typeof result === 'boolean') {
        return result ? 'authorized' : 'denied'
      }

      return setDidAskOnce(permission).then(() => RESULTS[result])
    })
  }

  checkMultiple = (permissions: Array<string>): Promise<{ [string]: string }> =>
    Promise.all(permissions.map(permission => this.check(permission))).then(
      result =>
        result.reduce((acc, value, index) => {
          const name = permissions[index]
          acc[name] = value
          return acc
        }, {}),
    )
}

module.exports = new ReactNativePermissions()
<|endoftext|>


<commit_before>define([
    'dojo/text!app/templates/ResultsGrid.html',

    'dojo/_base/declare',
    'dojo/_base/array',
    'dojo/_base/lang',

    'dojo/store/Memory',
    'dojo/topic',

    'dojo/dom-class',

    'dijit/_WidgetBase',
    'dijit/_TemplatedMixin',

    'dgrid/OnDemandGrid',
    'dgrid/Selection',

    'esri/tasks/query',

    'app/config'
], function(
    template,

    declare,
    array,
    lang,

    Memory,
    topic,

    domClass,

    _WidgetBase,
    _TemplatedMixin,

    Grid,
    Selection,

    Query,

    config
) {
    return declare([_WidgetBase, _TemplatedMixin], {
        // description:
        //      Sorts and displays the search results.

        templateString: template,
        baseClass: 'results-grid',

        // grid: Grid
        //      the main grid
        grid: null,

        // Properties to be sent into constructor

        postCreate: function() {
            // summary:
            //    Overrides method of same name in dijit._Widget.
            // tags:
            //    private
            console.log('app.ResultsGrid::postCreate', arguments);

            this.setupConnections();
        },
        setupConnections: function() {
            // summary:
            //      wire events, and such
            console.log('app.ResultsGrid::setupConnections', arguments);

            this.own(
                topic.subscribe(config.topics.events.search, lang.hitch(this, 'search')),
                topic.subscribe(config.topics.events.updateEnd, lang.hitch(this, 'showSearchResultsInGrid'))
            );
        },
        startup: function() {
            // summary:
            //      creates the dgrid
            console.log('app.ResultsGrid::startup', arguments);
            this.store = new Memory({
                data: []
            });

            this.query = new Query();

            this.grid = new(declare([Grid, Selection]))({
                bufferRows: Infinity,
                store: this.store,
                noDataMessage: 'No results found.',
                loadingMessage: 'Querying boundaries...',
                columns: {
                    id: 'id',
                    name: 'Boundary Name',
                    service: 'Type of Service',
                    level: 'Level of Service',
                    geometry: 'shape'
                },
                selectionMode: 'single'
            }, this.domNode);

            this.grid.on('dgrid-select', function(events) {

                var row = events.rows[0];
                if (!row) {
                    return;
                }

                topic.publish(config.topics.map.highlight, row.data.geometry);
                topic.publish(config.topics.map.zoom, row.data.geometry);
                topic.publish(config.topics.events.setTitle, row.data.name);
            });

            this.grid.styleColumn('geometry', 'display: none;');
            this.grid.styleColumn('id', 'display: none;');
        },
        showSearchResultsInGrid: function (result) {
            // summary:
            //      description
            // param or return
            console.log('app.ResultsGrid:showSearchResultsInGrid', arguments);

            this.store.data = null;
            this.grid.refresh();

            var data = result.target.graphics.map(function(feature) {
                return {
                    // property names used here match those used when creating the dgrid
                    'id': feature.attributes.OBJECTID,
                    'name': feature.attributes.NAME,
                    'service': feature.attributes.SERVICE_TYPE,
                    'level': feature.attributes.SERVICE_LEVEL,
                    'geometry': feature.geometry
                };
            });

            this.store.data = data;
            this.grid.refresh();

            domClass.remove(this.domNode, 'hide');
            this.grid.startup();
        },
        search: function(args) {
            // summary:
            //      queries the data and displays features in a grid
            // args: { point - the map point click geometry, layer - the layer being queried }
            console.log('app.ResultsGrid::search', arguments);

            if (this.grid) {
                this.grid.store.data = null;
                this.grid.refresh();
            }

            var self = this;
            this.query.geometry = args.point;
            if (args.layer.layerDefinitions) {
                this.query.where = args.layer.layerDefinitions[0];
            }

            args.layer.queryFeatures(this.query, function(results) {
                var data = array.map(results.features, function(feature) {
                    return {
                        // property names used here match those used when creating the dgrid
                        'id': feature.attributes.OBJECTID,
                        'name': feature.attributes.NAME,
                        'service': feature.attributes.SERVICE_TYPE,
                        'level': feature.attributes.SERVICE_LEVEL,
                        'geometry': feature.geometry
                    };
                });

                self.store.data = data;
                self.grid.refresh();

                domClass.remove(self.domNode, 'hide');
                self.grid.startup();
            });
        }
    });
});
<commit_msg>fix click after filter is reset<commit_after>define([
    'dojo/text!app/templates/ResultsGrid.html',

    'dojo/_base/declare',
    'dojo/_base/array',
    'dojo/_base/lang',

    'dojo/store/Memory',
    'dojo/topic',

    'dojo/dom-class',

    'dijit/_WidgetBase',
    'dijit/_TemplatedMixin',

    'dgrid/OnDemandGrid',
    'dgrid/Selection',

    'esri/tasks/query',

    'app/config'
], function (
    template,

    declare,
    array,
    lang,

    Memory,
    topic,

    domClass,

    _WidgetBase,
    _TemplatedMixin,

    Grid,
    Selection,

    Query,

    config
) {
    return declare([_WidgetBase, _TemplatedMixin], {
        // description:
        //      Sorts and displays the search results.

        templateString: template,
        baseClass: 'results-grid',

        // grid: Grid
        //      the main grid
        grid: null,

        // Properties to be sent into constructor

        postCreate: function () {
            // summary:
            //    Overrides method of same name in dijit._Widget.
            // tags:
            //    private
            console.log('app.ResultsGrid::postCreate', arguments);

            this.setupConnections();
        },
        setupConnections: function () {
            // summary:
            //      wire events, and such
            console.log('app.ResultsGrid::setupConnections', arguments);

            this.own(
                topic.subscribe(config.topics.events.search, lang.hitch(this, 'search')),
                topic.subscribe(config.topics.events.updateEnd, lang.hitch(this, 'showSearchResultsInGrid'))
            );
        },
        startup: function () {
            // summary:
            //      creates the dgrid
            console.log('app.ResultsGrid::startup', arguments);
            this.store = new Memory({
                data: []
            });

            this.query = new Query();

            this.grid = new(declare([Grid, Selection]))({
                bufferRows: Infinity,
                store: this.store,
                noDataMessage: 'No results found.',
                loadingMessage: 'Querying boundaries...',
                columns: {
                    id: 'id',
                    name: 'Boundary Name',
                    service: 'Type of Service',
                    level: 'Level of Service',
                    geometry: 'shape'
                },
                selectionMode: 'single'
            }, this.domNode);

            this.grid.on('dgrid-select', function (events) {

                var row = events.rows[0];
                if (!row) {
                    return;
                }

                topic.publish(config.topics.map.highlight, row.data.geometry);
                topic.publish(config.topics.map.zoom, row.data.geometry);
                topic.publish(config.topics.events.setTitle, row.data.name);
            });

            this.grid.styleColumn('geometry', 'display: none;');
            this.grid.styleColumn('id', 'display: none;');
        },
        showSearchResultsInGrid: function (result) {
            // summary:
            //      description
            // param or return
            console.log('app.ResultsGrid:showSearchResultsInGrid', arguments);

            this.store.data = null;
            this.grid.refresh();

            var data = result.target.graphics.map(function (feature) {
                return {
                    // property names used here match those used when creating the dgrid
                    'id': feature.attributes.OBJECTID,
                    'name': feature.attributes.NAME,
                    'service': feature.attributes.SERVICE_TYPE,
                    'level': feature.attributes.SERVICE_LEVEL,
                    'geometry': feature.geometry
                };
            });

            this.store.data = data;
            this.grid.refresh();

            domClass.remove(this.domNode, 'hide');
            this.grid.startup();
        },
        search: function (args) {
            // summary:
            //      queries the data and displays features in a grid
            // args: { point - the map point click geometry, layer - the layer being queried }
            console.log('app.ResultsGrid::search', arguments);

            var self = this;
            this.query.geometry = args.point;
            if (args.layer.layerDefinitions) {
                this.query.where = args.layer.layerDefinitions[0];
            }

            var priorQuery = args.layer.getDefinitionExpression();
            if (priorQuery === '1=2') {
                args.layer.setVisibility(false);
                args.layer.setDefinitionExpression();
            }

            args.layer.queryFeatures(this.query, function (results) {
                args.layer.setDefinitionExpression(priorQuery);
                args.layer.setVisibility(true);

                var data = array.map(results.features, function (feature) {
                    return {
                        // property names used here match those used when creating the dgrid
                        'id': feature.attributes.OBJECTID,
                        'name': feature.attributes.NAME,
                        'service': feature.attributes.SERVICE_TYPE,
                        'level': feature.attributes.SERVICE_LEVEL,
                        'geometry': feature.geometry
                    };
                });

                self.store.data = data;
                self.grid.refresh();

                domClass.remove(self.domNode, 'hide');
                self.grid.startup();
            }, function () {
                args.layer.setDefinitionExpression(priorQuery);
                args.layer.setVisibility(true);

                if (self.grid) {
                    self.grid.store.data = null;
                    self.grid.refresh();
                }
            });
        }
    });
});
<|endoftext|>


<commit_before>'use strict'
/*
 * See the NOTICE.txt file distributed with this work for additional information
 * regarding copyright ownership.
 * Sematext licenses logagent-js to you under
 * the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
var path = require('path')
var fs = require('fs')
var os = require('os')
var Tail = require('tail-forever')
var glob = require('glob')
var logger = require('../../util/logger.js')

function InputFile (options, eventEmitter) {
  this.eventEmitter = eventEmitter
  this.options = options
  this.filesToWatch = []
  this.fileNamesToWatch = []
  this.scanCounter = 0
  this.stats = {}
  this.sigTermHandled = false
  this.laStats = require('../../core/printStats')
  this.laStats.fileManger = this
  this.activated = false
}

function getFilesizeInBytes (filename) {
  try {
    var stats = fs.statSync(filename)
    return stats.size
  } catch (fsErr) {
    return -1
  }
}

InputFile.prototype.stop = function (cb) {
  this.terminate()
  cb()
}
InputFile.prototype.start = function () {
  var globPattern = this.options.glob || process.env.GLOB_PATTERN
  if (this.options.args && this.options.args.length > 0) {
    this.filePointers = this.readFilePointers()
    // tail files
    this.tailFiles(this.options.args)
    this.activated = true
  }
  if (globPattern) {
    this.activated = true
    if (!this.filePointers) {
      this.filePointers = this.readFilePointers()
    }
    // remove quotes from shell script
    globPattern = globPattern.replace(/"/g, '').replace(/'/g, '').replace(/\s/g, '')
    logger.log('using glob pattern: ' + globPattern)
    this.tailFilesFromGlob(globPattern, 60000)
  }
}

InputFile.prototype.tailFiles = function (fileList) {
  fileList.forEach(this.tailFile.bind(this))
}
InputFile.prototype.getTempDir = function () {
  return this.options.diskBufferDir || process.env.LOGSENE_TMP_DIR || os.tmpDir()
}

InputFile.prototype.getTailPosition = function (file) {
  var storedPos = this.filePointers[file]
  if (!storedPos) {
    logger.debug('no position stored for ' + file)
    // tail from end of file
    return {start: this.options.tailStartPosition || getFilesizeInBytes(file)}
  } else {
    var fd = fs.openSync(file, 'r')
    var stat = fs.fstatSync(fd)
    if (stat.ino === storedPos.inode) {
      return {start: storedPos.pos, inode: storedPos.inode}
    } else {
      logger.debug('Watching file ' + file + ' inode changed, set tail position = 0')
      return {start: 0}
    }
  }
}

InputFile.prototype.tailFilesFromGlob = function (globPattern, scanTime) {
  if (globPattern) {
    glob(globPattern, {
      strict: false,
      silent: false
    }, function globCb (err, files) {
      if (!err) {
        this.tailFiles(files)
      } else {
        logger.error('Error in glob file patttern ' + globPattern + ': ' + err.message)
      }
    }.bind(this))
    if (!this.globPattern && scanTime > 0) {
      this.globPattern = globPattern
      setInterval(function scanFilesTimer () {
        this.scanCounter = 1
        this.tailFilesFromGlob(this.globPattern, scanTime)
      }.bind(this), scanTime)
    }
  }
}

InputFile.prototype.tailFile = function (file) {
  var tail = null
  var pos = {start: 0}
  if (this.fileNamesToWatch.indexOf(file) > -1) {
    // check if we watch this file already
    return null
  } else {
  }
  try {
    pos = this.getTailPosition(file)
  } catch (error) {
    // file might not exists, we ignore it and start watching
    pos = {start: 0}
  }
  if (this.scanCounter > 0) {
    // a new file matched the glob pattern
    // reading from begin of file
    logger.log('New file detected: ' + file)
    pos = {start: 0}
  }
  try {
    if (pos.start == -1) {
      // there was no postion stored, let's start from the beginning
      // throw new Error('File ' + file + ' does not exist.')
      pos.start = 0
    }
    tail = new Tail(file, pos)
    this.filesToWatch.push(tail)
    this.fileNamesToWatch.push(file)
    var context = {sourceName: file, startPos: pos}
    tail.on('line', function (line) {
      this.stats[file] = (this.stats[file] || 0) + 1
      this.eventEmitter.emit('data.raw', line, context)
    }.bind(this))
    tail.once('error', function (error) {
      var errMessage = 'ERROR tailing file ' + file + ': ' + error
      logger.error(errMessage)
      this.eventEmitter.emit('error.plugin.input.file', errMessage, {file: file, error: error})
    }.bind(this))
    logger.log('Watching file:' + file + ' from position: ' + pos.start)
    return tail
  } catch (error) {
    // log('ERROR tailing file ' + file + ': ' + error)
    return null
  }
}

InputFile.prototype.terminate = function () {
  if (!this.sigTermHandled && this.activated) {
    this.sigTermHandled = true
    this.savePositions()
  }
}

InputFile.prototype.savePositions = function () {
  var filePositions = this.filesToWatch.map(function filesToWatchMap (tailObj) {
    try {
      var position = tailObj.unwatch()
      position.fileName = tailObj.filename
      logger.log('Stop watching ' + tailObj.filename + ' inode: ' + position.inode + ' pos:' + position.pos)
      return position
    } catch (fileExistsError) {
      // file got removed
      return null
    }
  })
  try {
    var fileName = path.join(this.getTempDir(), 'logagentTailPointers.json')
    fs.writeFileSync(fileName, JSON.stringify(filePositions))
    logger.log('File positions stored in: ' + fileName)
  } catch (err) {
    logger.log('error writing file pointers:' + err)
  }
}

InputFile.prototype.readFilePointers = function () {
  var filePointers = {}
  try {
    var fileName = path.join(this.getTempDir(), 'logagentTailPointers.json')
    var fp = fs.readFileSync(fileName)
    var filePointerArr = JSON.parse(fp)
    filePointerArr.forEach(function storeFp (f) {
      filePointers[f.fileName] = {pos: f.pos, inode: f.inode}
    })
    if (Object.keys(filePointers).length > 0) {
      logger.debug(JSON.stringify(filePointers, null, '\t'))
    }
    fs.unlinkSync(fileName)
  } catch (err) {
    logger.log('No stored file postions (file not found):' + fileName)
  }
  return filePointers
}

module.exports = InputFile
<commit_msg>reset tail-forever every N minutes<commit_after>'use strict'
/*
 * See the NOTICE.txt file distributed with this work for additional information
 * regarding copyright ownership.
 * Sematext licenses logagent-js to you under
 * the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
var path = require('path')
var fs = require('fs')
var os = require('os')
var Tail = require('tail-forever')
var glob = require('glob')
var logger = require('../../util/logger.js')

function InputFile (options, eventEmitter) {
  this.eventEmitter = eventEmitter
  this.options = options
  this.filesToWatch = []
  this.fileNamesToWatch = []
  this.scanCounter = 0
  this.stats = {}
  this.sigTermHandled = false
  this.laStats = require('../../core/printStats')
  this.laStats.fileManger = this
  this.activated = false
  this.timers = []
  var self = this
  // stop all tail-forever instances every 10 minutes and restart watching
  // this should release open file descriptors in tail-forver
  setInterval(self.resetFilePointers.bind(this), 10 * 60 * 1000)
}

function getFilesizeInBytes (filename) {
  try {
    var stats = fs.statSync(filename)
    return stats.size
  } catch (fsErr) {
    return -1
  }
}

InputFile.prototype.stop = function (cb) {
  this.terminate()
  cb()
}
InputFile.prototype.start = function () {
  this.timers.forEach(function stopTimer (t) {
    clearInterval(t)
  })
  var globPattern = this.options.glob || process.env.GLOB_PATTERN
  if (this.options.args && this.options.args.length > 0) {
    this.filePointers = this.readFilePointers()
    // tail files
    this.tailFiles(this.options.args)
    this.activated = true
  }
  if (globPattern) {
    this.activated = true
    if (!this.filePointers) {
      this.filePointers = this.readFilePointers()
    }
    // remove quotes from shell script
    globPattern = globPattern.replace(/"/g, '').replace(/'/g, '').replace(/\s/g, '')
    logger.log('using glob pattern: ' + globPattern)
    this.tailFilesFromGlob(globPattern, 60000)
  }
}

InputFile.prototype.tailFiles = function (fileList) {
  fileList.forEach(this.tailFile.bind(this))
}
InputFile.prototype.getTempDir = function () {
  return this.options.diskBufferDir || process.env.LOGSENE_TMP_DIR || os.tmpdir()
}

InputFile.prototype.getTailPosition = function (file) {
  var storedPos = this.filePointers[file]
  if (!storedPos) {
    logger.debug('no position stored for ' + file)
    // tail from end of file
    return {start: this.options.tailStartPosition || getFilesizeInBytes(file)}
  } else {
    var fd = fs.openSync(file, 'r')
    var stat = fs.fstatSync(fd)
    if (stat.ino === storedPos.inode) {
      return {start: storedPos.pos, inode: storedPos.inode}
    } else {
      logger.debug('Watching file ' + file + ' inode changed, set tail position = 0')
      return {start: 0}
    }
  }
}

InputFile.prototype.tailFilesFromGlob = function (globPattern, scanTime) {
  if (globPattern) {
    glob(globPattern, {
      strict: false,
      silent: false
    }, function globCb (err, files) {
      if (!err) {
        this.tailFiles(files)
      } else {
        logger.error('Error in glob file patttern ' + globPattern + ': ' + err.message)
      }
    }.bind(this))
    if (!this.globPattern && scanTime > 0) {
      this.globPattern = globPattern
      var tid = setInterval(function scanFilesTimer () {
        this.scanCounter = 1
        this.tailFilesFromGlob(this.globPattern, scanTime)
      }.bind(this), scanTime)
      this.timers.push(tid)
    }
  }
}

InputFile.prototype.tailFile = function (file) {
  var tail = null
  var pos = {start: 0}
  if (this.fileNamesToWatch.indexOf(file) > -1) {
    // check if we watch this file already
    return null
  } else {
  }
  try {
    pos = this.getTailPosition(file)
  } catch (error) {
    // file might not exists, we ignore it and start watching
    pos = {start: 0}
  }
  if (this.scanCounter > 0) {
    // a new file matched the glob pattern
    // reading from begin of file
    logger.log('New file detected: ' + file)
    pos = {start: 0}
  }
  try {
    if (pos.start === -1) {
      // there was no postion stored, let's start from the beginning
      // throw new Error('File ' + file + ' does not exist.')
      pos.start = 0
    }
    tail = new Tail(file, pos)
    this.filesToWatch.push(tail)
    this.fileNamesToWatch.push(file)
    var context = {sourceName: file, startPos: pos}
    tail.on('line', function (line) {
      this.stats[file] = (this.stats[file] || 0) + 1
      this.eventEmitter.emit('data.raw', line, context)
    }.bind(this))
    tail.once('error', function (error) {
      var errMessage = 'ERROR tailing file ' + file + ': ' + error
      logger.error(errMessage)
      this.eventEmitter.emit('error.plugin.input.file', errMessage, {file: file, error: error})
    }.bind(this))
    logger.log('Watching file:' + file + ' from position: ' + pos.start)
    return tail
  } catch (error) {
    // log('ERROR tailing file ' + file + ': ' + error)
    return null
  }
}

InputFile.prototype.terminate = function () {
  if (!this.sigTermHandled && this.activated) {
    this.sigTermHandled = true
    this.savePositions()
  }
}

InputFile.prototype.resetFilePointers = function () {
  logger.log('reset file pointers')
  var self = this
  self.savePositions()
  self.filePointers = self.readFilePointers()
  self.scanCounter = 0
  // var ftw = self.filesToWatch
  self.filesToWatch = []
  self.fileNamesToWatch = []
  self.start()
/*
ftw.forEach(function startTailFile (tailObj) {
  try {
    self.tailFile(tailObj.filename)
  } catch (error) {
    logger.log(error)
  }
})
*/
}

InputFile.prototype.savePositions = function () {
  var filePositions = this.filesToWatch.map(function filesToWatchMap (tailObj) {
    try {
      var position = tailObj.unwatch()
      position.fileName = tailObj.filename
      logger.log('Stop watching ' + tailObj.filename + ' inode: ' + position.inode + ' pos:' + position.pos)
      return position
    } catch (fileExistsError) {
      // file got removed
      return null
    }
  })
  try {
    var fileName = path.join(this.getTempDir(), 'logagentTailPointers.json')
    fs.writeFileSync(fileName, JSON.stringify(filePositions))
    logger.log('File positions stored in: ' + fileName)
  } catch (err) {
    logger.log('error writing file pointers:' + err)
  }
}

InputFile.prototype.readFilePointers = function () {
  var filePointers = {}
  try {
    var fileName = path.join(this.getTempDir(), 'logagentTailPointers.json')
    var fp = fs.readFileSync(fileName)
    var filePointerArr = JSON.parse(fp)
    filePointerArr.forEach(function storeFp (f) {
      filePointers[f.fileName] = {pos: f.pos, inode: f.inode}
    })
    if (Object.keys(filePointers).length > 0) {
      logger.debug(JSON.stringify(filePointers, null, '\t'))
    }
    fs.unlinkSync(fileName)
    logger.log(filePointers)
  } catch (err) {
    logger.log('No stored file postions (file not found):' + fileName)
  }
  return filePointers
}

module.exports = InputFile
<|endoftext|>


<commit_before>'use strict'
/*
 * See the NOTICE.txt file distributed with this work for additional information
 * regarding copyright ownership.
 * Sematext licenses logagent-js to you under
 * the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
var path = require('path')
var fs = require('fs')
var os = require('os')
var Tail = require('tail-forever')
var glob = require('glob')
var logger = require('../../util/logger.js')

function InputFile (options, eventEmitter) {
  this.eventEmitter = eventEmitter
  this.options = options
  this.filesToWatch = []
  this.fileNamesToWatch = []
  this.scanCounter = 0
  this.stats = {}
  this.sigTermHandled = false
  this.laStats = require('../../core/printStats')
  this.laStats.fileManger = this
  this.activated = false
}

function getFilesizeInBytes (filename) {
  try {
    var stats = fs.statSync(filename)
    return stats.size
  } catch (fsErr) {
    return -1
  }
}

InputFile.prototype.stop = function (cb) {
  this.terminate()
  cb()
}
InputFile.prototype.start = function () {
  var globPattern = this.options.glob || process.env.GLOB_PATTERN
  if (this.options.args && this.options.args.length > 0) {
    this.filePointers = this.readFilePointers()
    // tail files
    this.tailFiles(this.options.args)
    this.activated = true
  }
  if (globPattern) {
    this.activated = true
    if (!this.filePointers) {
      this.filePointers = this.readFilePointers()
    }
    // remove quotes from shell script
    globPattern = globPattern.replace(/"/g, '').replace(/'/g, '').replace(/\s/g, '')
    logger.log('using glob pattern: ' + globPattern)
    this.tailFilesFromGlob(globPattern, 60000)
  }
}

InputFile.prototype.tailFiles = function (fileList) {
  fileList.forEach(this.tailFile.bind(this))
}
InputFile.prototype.getTempDir = function () {
  return this.options.diskBufferDir || process.env.LOGSENE_TMP_DIR || os.tmpdir()
}

InputFile.prototype.getTailPosition = function (file) {
  var storedPos = this.filePointers[file]
  if (!storedPos) {
    logger.debug('no position stored for ' + file)
    // tail from end of file
    return {start: this.options.tailStartPosition || getFilesizeInBytes(file)}
  } else {
    var fd = fs.openSync(file, 'r')
    var stat = fs.fstatSync(fd)
    if (stat.ino === storedPos.inode) {
      return {start: storedPos.pos, inode: storedPos.inode}
    } else {
      logger.debug('Watching file ' + file + ' inode changed, set tail position = 0')
      return {start: 0}
    }
  }
}

InputFile.prototype.tailFilesFromGlob = function (globPattern, scanTime) {
  if (globPattern) {
    glob(globPattern, {
      strict: false,
      silent: false
    }, function globCb (err, files) {
      if (!err) {
        this.tailFiles(files)
      } else {
        logger.error('Error in glob file patttern ' + globPattern + ': ' + err.message)
      }
    }.bind(this))
    if (!this.globPattern && scanTime > 0) {
      this.globPattern = globPattern
      setInterval(function scanFilesTimer () {
        this.scanCounter = 1
        this.tailFilesFromGlob(this.globPattern, scanTime)
      }.bind(this), scanTime)
    }
  }
}

InputFile.prototype.tailFile = function (file) {
  var tail = null
  var pos = {start: 0}
  if (this.fileNamesToWatch.indexOf(file) > -1) {
    // check if we watch this file already
    return null
  }
  try {
    pos = this.getTailPosition(file)
  } catch (error) {
    // file might not exists, we ignore it and start watching
    pos = {start: 0}
  }
  if (this.scanCounter > 0) {
    // a new file matched the glob pattern
    // reading from begin of file
    logger.log('New file detected: ' + file)
    pos = {start: 0}
  }
  try {
    if (pos.start === -1) {
      // there was no postion stored, let's start from the beginning
      // throw new Error('File ' + file + ' does not exist.')
      pos.start = 0
    }
    tail = new Tail(file, pos)
    this.filesToWatch.push(tail)
    this.fileNamesToWatch.push(file)
    var context = {sourceName: file, startPos: pos}
    tail.on('line', function (line) {
      this.stats[file] = (this.stats[file] || 0) + 1
      this.eventEmitter.emit('data.raw', line, context)
    }.bind(this))
    tail.once('error', function (error) {
      var errMessage = 'ERROR tailing file ' + file + ': ' + error
      logger.error(errMessage)
      this.eventEmitter.emit('error.plugin.input.file', errMessage, {file: file, error: error})
    }.bind(this))
    logger.log('Watching file:' + file + ' from position: ' + pos.start)
    return tail
  } catch (error) {
    // log('ERROR tailing file ' + file + ': ' + error)
    return null
  }
}

InputFile.prototype.terminate = function () {
  if (!this.sigTermHandled && this.activated) {
    this.sigTermHandled = true
    this.savePositions()
  }
}

InputFile.prototype.savePositions = function () {
  var filePositions = this.filesToWatch.map(function filesToWatchMap (tailObj) {
    try {
      var position = tailObj.unwatch()
      position.fileName = tailObj.filename
      logger.log('Stop watching ' + tailObj.filename + ' inode: ' + position.inode + ' pos:' + position.pos)
      return position
    } catch (fileExistsError) {
      // file got removed
      return null
    }
  })
  try {
    var fileName = path.join(this.getTempDir(), 'logagentTailPointers.json')
    fs.writeFileSync(fileName, JSON.stringify(filePositions))
    logger.log('File positions stored in: ' + fileName)
  } catch (err) {
    logger.log('error writing file pointers:' + err)
  }
}

InputFile.prototype.readFilePointers = function () {
  var filePointers = {}
  try {
    var fileName = path.join(this.getTempDir(), 'logagentTailPointers.json')
    var fp = fs.readFileSync(fileName)
    var filePointerArr = JSON.parse(fp)
    filePointerArr.forEach(function storeFp (f) {
      filePointers[f.fileName] = {pos: f.pos, inode: f.inode}
    })
    if (Object.keys(filePointers).length > 0) {
      logger.debug(JSON.stringify(filePointers, null, '\t'))
    }
    fs.unlinkSync(fileName)
  } catch (err) {
    logger.log('No stored file postions (file not found):' + fileName)
  }
  return filePointers
}

module.exports = InputFile
<commit_msg>use platform specific EOL<commit_after>'use strict'
/*
 * See the NOTICE.txt file distributed with this work for additional information
 * regarding copyright ownership.
 * Sematext licenses logagent-js to you under
 * the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
var path = require('path')
var fs = require('fs')
var os = require('os')
var Tail = require('tail-forever')
var glob = require('glob')
var logger = require('../../util/logger.js')

function InputFile (options, eventEmitter) {
  this.eventEmitter = eventEmitter
  this.options = options
  this.filesToWatch = []
  this.fileNamesToWatch = []
  this.scanCounter = 0
  this.stats = {}
  this.sigTermHandled = false
  this.laStats = require('../../core/printStats')
  this.laStats.fileManger = this
  this.activated = false
}

function getFilesizeInBytes (filename) {
  try {
    var stats = fs.statSync(filename)
    return stats.size
  } catch (fsErr) {
    return -1
  }
}

InputFile.prototype.stop = function (cb) {
  this.terminate()
  cb()
}
InputFile.prototype.start = function () {
  var globPattern = this.options.glob || process.env.GLOB_PATTERN
  if (this.options.args && this.options.args.length > 0) {
    this.filePointers = this.readFilePointers()
    // tail files
    this.tailFiles(this.options.args)
    this.activated = true
  }
  if (globPattern) {
    this.activated = true
    if (!this.filePointers) {
      this.filePointers = this.readFilePointers()
    }
    // remove quotes from shell script
    globPattern = globPattern.replace(/"/g, '').replace(/'/g, '').replace(/\s/g, '')
    logger.log('using glob pattern: ' + globPattern)
    this.tailFilesFromGlob(globPattern, 60000)
  }
}

InputFile.prototype.tailFiles = function (fileList) {
  fileList.forEach(this.tailFile.bind(this))
}
InputFile.prototype.getTempDir = function () {
  return this.options.diskBufferDir || process.env.LOGSENE_TMP_DIR || os.tmpdir()
}

InputFile.prototype.getTailPosition = function (file) {
  var storedPos = this.filePointers[file]
  if (!storedPos) {
    logger.debug('no position stored for ' + file)
    // tail from end of file
    return {start: this.options.tailStartPosition || getFilesizeInBytes(file)}
  } else {
    var fd = fs.openSync(file, 'r')
    var stat = fs.fstatSync(fd)
    if (stat.ino === storedPos.inode) {
      return {start: storedPos.pos, inode: storedPos.inode}
    } else {
      logger.debug('Watching file ' + file + ' inode changed, set tail position = 0')
      return {start: 0}
    }
  }
}

InputFile.prototype.tailFilesFromGlob = function (globPattern, scanTime) {
  if (globPattern) {
    glob(globPattern, {
      strict: false,
      silent: false
    }, function globCb (err, files) {
      if (!err) {
        this.tailFiles(files)
      } else {
        logger.error('Error in glob file patttern ' + globPattern + ': ' + err.message)
      }
    }.bind(this))
    if (!this.globPattern && scanTime > 0) {
      this.globPattern = globPattern
      setInterval(function scanFilesTimer () {
        this.scanCounter = 1
        this.tailFilesFromGlob(this.globPattern, scanTime)
      }.bind(this), scanTime)
    }
  }
}

InputFile.prototype.tailFile = function (file) {
  var tail = null
  var pos = {start: 0}
  if (this.fileNamesToWatch.indexOf(file) > -1) {
    // check if we watch this file already
    return null
  }
  try {
    pos = this.getTailPosition(file)
  } catch (error) {
    // file might not exists, we ignore it and start watching
    pos = {start: 0}
  }
  if (this.scanCounter > 0) {
    // a new file matched the glob pattern
    // reading from begin of file
    logger.log('New file detected: ' + file)
    pos = {start: 0}
  }
  try {
    if (pos.start === -1) {
      // there was no postion stored, let's start from the beginning
      // throw new Error('File ' + file + ' does not exist.')
      pos.start = 0
    }
    // pass platform specific EOL
    pos.separator = os.EOL
    tail = new Tail(file, pos)
    this.filesToWatch.push(tail)
    this.fileNamesToWatch.push(file)
    var context = {sourceName: file, startPos: pos}
    tail.on('line', function (line) {
      this.stats[file] = (this.stats[file] || 0) + 1
      this.eventEmitter.emit('data.raw', line, context)
    }.bind(this))
    tail.once('error', function (error) {
      var errMessage = 'ERROR tailing file ' + file + ': ' + error
      logger.error(errMessage)
      this.eventEmitter.emit('error.plugin.input.file', errMessage, {file: file, error: error})
    }.bind(this))
    logger.log('Watching file:' + file + ' from position: ' + pos.start)
    return tail
  } catch (error) {
    // log('ERROR tailing file ' + file + ': ' + error)
    return null
  }
}

InputFile.prototype.terminate = function () {
  if (!this.sigTermHandled && this.activated) {
    this.sigTermHandled = true
    this.savePositions()
  }
}

InputFile.prototype.savePositions = function () {
  var filePositions = this.filesToWatch.map(function filesToWatchMap (tailObj) {
    try {
      var position = tailObj.unwatch()
      position.fileName = tailObj.filename
      logger.log('Stop watching ' + tailObj.filename + ' inode: ' + position.inode + ' pos:' + position.pos)
      return position
    } catch (fileExistsError) {
      // file got removed
      return null
    }
  })
  try {
    var fileName = path.join(this.getTempDir(), 'logagentTailPointers.json')
    fs.writeFileSync(fileName, JSON.stringify(filePositions))
    logger.log('File positions stored in: ' + fileName)
  } catch (err) {
    logger.log('error writing file pointers:' + err)
  }
}

InputFile.prototype.readFilePointers = function () {
  var filePointers = {}
  try {
    var fileName = path.join(this.getTempDir(), 'logagentTailPointers.json')
    var fp = fs.readFileSync(fileName)
    var filePointerArr = JSON.parse(fp)
    filePointerArr.forEach(function storeFp (f) {
      filePointers[f.fileName] = {pos: f.pos, inode: f.inode}
    })
    if (Object.keys(filePointers).length > 0) {
      logger.debug(JSON.stringify(filePointers, null, '\t'))
    }
    fs.unlinkSync(fileName)
  } catch (err) {
    logger.log('No stored file postions (file not found):' + fileName)
  }
  return filePointers
}

module.exports = InputFile
<|endoftext|>


<commit_before>var cache_manager = require('cache-manager');
var s3 = new (require('aws-sdk')).S3({params:{Bucket: process.env.S3_BUCKET_NAME}});

module.exports = {
    init: function() {
        this.cache = cache_manager.caching({
            store: s3_cache
        });
    },

    beforePhantomRequest: function(req, res, next) {
        if(req.method !== 'GET') {
            return next();
        }

        this.cache.get(req.prerender.url, function (err, result) {
            if(err) console.error(err);

            if (!err && result) {
                console.log('cache hit');
                return res.send(200, result.Body);
            }

            next();
        });
    },

    afterPhantomRequest: function(req, res, next) {
        this.cache.set(req.prerender.url, req.prerender.documentHTML, function(err, result) {
            if (err) console.error(err);
        });
        next();
    }
};

var s3_cache = {
    get: function(key, callback) {
        if (process.env.S3_PREFIX_KEY) {
            key = process.env.S3_PREFIX_KEY + '/' + key;
        }

        s3.getObject({
            Key: key
        }, callback);
    },
    set: function(key, value, callback) {
        if (process.env.S3_PREFIX_KEY) {
            key = process.env.S3_PREFIX_KEY + '/' + key;
        }

        var request = s3.putObject({
            Key: key,
            ContentType: 'text/html;charset=UTF-8',
            StorageClass: 'REDUCED_REDUNDANCY',
            Body: value
        }, callback);

        if (!callback) {
            request.send();
        }
    }
};
<commit_msg>s3 plugin: cache only "200 OK" pages<commit_after>var cache_manager = require('cache-manager');
var s3 = new (require('aws-sdk')).S3({params:{Bucket: process.env.S3_BUCKET_NAME}});

module.exports = {
    init: function() {
        this.cache = cache_manager.caching({
            store: s3_cache
        });
    },

    beforePhantomRequest: function(req, res, next) {
        if(req.method !== 'GET') {
            return next();
        }

        this.cache.get(req.prerender.url, function (err, result) {
            if(err) console.error(err);

            if (!err && result) {
                console.log('cache hit');
                return res.send(200, result.Body);
            }

            next();
        });
    },

    afterPhantomRequest: function(req, res, next) {
        if(req.prerender.statusCode === 200) {
            this.cache.set(req.prerender.url, req.prerender.documentHTML, function(err, result) {
                if (err) console.error(err);
            });
        }
        next();
    }
};

var s3_cache = {
    get: function(key, callback) {
        if (process.env.S3_PREFIX_KEY) {
            key = process.env.S3_PREFIX_KEY + '/' + key;
        }

        s3.getObject({
            Key: key
        }, callback);
    },
    set: function(key, value, callback) {
        if (process.env.S3_PREFIX_KEY) {
            key = process.env.S3_PREFIX_KEY + '/' + key;
        }

        var request = s3.putObject({
            Key: key,
            ContentType: 'text/html;charset=UTF-8',
            StorageClass: 'REDUCED_REDUNDANCY',
            Body: value
        }, callback);

        if (!callback) {
            request.send();
        }
    }
};
<|endoftext|>


<commit_before>var PassThrough = require('stream').PassThrough;
var net = require('net');
var rules = require('../rules');
var config = require('../../util').config;
var CRLF = '\r\n';
var CRLF_BUF = new Buffer(CRLF);
var MAX_BYTES = 1024 * 256;
var TIMEOUT = config.timeout || 36000;

function parsePairs(pairs, buffer, start) {
	for (var i = start || 0, len = buffer.length; i < len; i++) {
		var pair = getPair(buffer[i]);
		if (pair) {
			var value = pairs[pair.key];
			if (value) {
				if (!Array.isArray(value)) {
					value = [value];
				}
				value.push(pair.value);
			}
			pairs[pair.key] = value || pair.value;
		}
	}

	return pairs;
}

function getPair(line) {
	if (!(line = line && line.trim())) {
		return;
	}

	var index = line.indexOf(':');
	return index != -1 ? {
		key: line.substring(0, index).trim().toLowerCase(),
		value: line.substring(index + 1).trim()
	} : null;
}

function endIndexOf(buffer, start, end) {
	start = start || 0;
	end = end || buffer.length;
	for (; start < end; start++) {
		if (buffer[start] == CRLF_BUF[0] && buffer[start + 1] == CRLF_BUF[1]
		&& buffer[start + 2] == CRLF_BUF[0] && buffer[start + 3] == CRLF_BUF[1]) {
			return start;
		}
	}

	return -1;
}

module.exports = function parseHeaders(socket, callback) {
	var proxySocket, buffer, timeoutId, res;

	socket.on('error', callback).on('data', parseData);

	function parseData(data) {
		clearTimeout(timeoutId);
		buffer = buffer ? Buffer.concat([buffer, data]) : data;
		var endIndex = endIndexOf(buffer);
		if (endIndex == -1) {
			if (buffer.length > MAX_BYTES) {
				emitError(new Error('parse error'));
			} else {
				timeoutId = setTimeout(emitError, TIMEOUT);
			}
			return;
		}

		socket.pause();
		socket.removeListener('data', parseData);
		buffer = buffer.slice(0, endIndex).toString().trim().split(/\r\n/g);
		res = new PassThrough();
		res.push(buffer);
		socket.pipe(res);
		parsePairs(res.headers = {}, buffer, 1);
		var options = res.headers[config.httpsProxyHost];
		options = options && url.parse('http://' + options);
		if (!options || !net.isIP(options.hostname)) {
			return emitError(new Error('unsupport the request'));
		}
		res.options = options;
		callback(null, res);
	}

	function emitError(err) {
		socket.destroy();
		err = err || new Error('timeout');
		res && res.emit('error', err);
		callback(err);
	}
};<commit_msg>https-proxy<commit_after>var PassThrough = require('stream').PassThrough;
var net = require('net');
var rules = require('../rules');
var config = require('../../util').config;
var CRLF = '\r\n';
var CRLF_BUF = new Buffer(CRLF);
var MAX_BYTES = 1024 * 256;
var TIMEOUT = config.timeout || 36000;

function parsePairs(pairs, buffer, start) {
	for (var i = start || 0, len = buffer.length; i < len; i++) {
		var pair = getPair(buffer[i]);
		if (pair) {
			var value = pairs[pair.key];
			if (value) {
				if (!Array.isArray(value)) {
					value = [value];
				}
				value.push(pair.value);
			}
			pairs[pair.key] = value || pair.value;
		}
	}

	return pairs;
}

function getPair(line) {
	if (!(line = line && line.trim())) {
		return;
	}

	var index = line.indexOf(':');
	return index != -1 ? {
		key: line.substring(0, index).trim().toLowerCase(),
		value: line.substring(index + 1).trim()
	} : null;
}

function endIndexOf(buffer, start, end) {
	start = start || 0;
	end = end || buffer.length;
	for (; start < end; start++) {
		if (buffer[start] == CRLF_BUF[0] && buffer[start + 1] == CRLF_BUF[1]
		&& buffer[start + 2] == CRLF_BUF[0] && buffer[start + 3] == CRLF_BUF[1]) {
			return start;
		}
	}

	return -1;
}

module.exports = function parseHeaders(socket, callback) {
	var proxySocket, buffer, timeoutId, res;

	socket.on('error', callback).on('data', parseData);

	function parseData(data) {
		clearTimeout(timeoutId);
		buffer = buffer ? Buffer.concat([buffer, data]) : data;
		var endIndex = endIndexOf(buffer);
		if (endIndex == -1) {
			if (buffer.length > MAX_BYTES) {
				emitError(new Error('parse error'));
			} else {
				timeoutId = setTimeout(emitError, TIMEOUT);
			}
			return;
		}

		socket.pause();
		socket.removeListener('data', parseData);
		buffer = buffer.slice(0, endIndex).toString().trim().split(/\r\n/g);
		var res = new PassThrough();
		res.push(buffer);
		socket.pipe(res);
		parsePairs(res.headers = {}, buffer, 1);
		var options = res.headers[config.httpsProxyHost];
		options = options && url.parse('http://' + options);
		if (!options || !net.isIP(options.hostname)) {
			return emitError(new Error('unsupport the request'));
		}
		res.options = options;
		callback(null, res);
	}

	function emitError(err) {
		socket.destroy();
		err = err || new Error('timeout');
		res && res.emit('error', err);
		callback(err);
	}
};<|endoftext|>


<commit_before>/* globals db */
/* jshint strict: false */
db.vocablists.find({}).forEach(function(vocablist) {
  var idArray = [];
  if (vocablist.vocab && vocablist.vocab.length > 0) {
    db.vocabs.insert(vocablist.vocab, {ordered: false});
  }
  vocablist.vocab.forEach(function(vocab) {
    idArray.push(db.vocabs.findOne({'english.translation': vocab.english.translation})._id);
  });
  db.vocablists.update({_id: vocablist._id}, {$set: {vocab: idArray}});
});
<commit_msg>Fixes seeding<commit_after>/* globals db */
/* jshint strict: false */
db.vocablists.find({}).forEach(function(vocablist) {
  var idArray = [];
  if (vocablist.vocab && vocablist.vocab.length > 0) {
    vocablist.vocab.forEach(function(vocab) {
      if (vocab.english && vocab.english.lastTested.length === 0) {
        delete vocab.english.lastTested;
      }
      if (vocab.korean && vocab.korean.lastTested.length === 0) {
        delete vocab.korean.lastTested;
      }
      if (vocab.japanese && vocab.japanese.lastTested.length === 0) {
        delete vocab.japanese.lastTested;
      }
    });
    db.vocabs.insert(vocablist.vocab, {ordered: false});
  }
  vocablist.vocab.forEach(function(vocab) {
    idArray.push(db.vocabs.findOne({'english.translation': vocab.english.translation})._id);
  });
  db.vocablists.update({_id: vocablist._id}, {$set: {vocab: idArray}});
});
<|endoftext|>


<commit_before>describe('model', function () {
    var model;

    beforeEach(function () {
        // given
        model = new Model();
    });

    afterEach(function () {
        $.mockjaxClear();
    });

    it("getProduct", function (done) {
        // given
        $.mockjax({
            // mockjax input
            url: '/product',
            data: { productId: 4711},
            // mockjax output
            responseText: { error: false, product: { name: 'banana'}},
            responseTime: 1
        });

        // when
        model.getProduct(4711, function (error, product) {

            // then
            expect(error).toBe(null);
            expect(product.name).toBe('banana');
            done(); // important for async test, must be called in final callback
        });
    });

    it("getProduct when server returns an error", function (done) {
        // given
        $.mockjax({
            url: '/product',
            data: { productId: 17},
            responseText: { error: { message: "product with id 17 not found"}},
            responseTime: 1
        });

        // when
        model.getProduct(17, function (error, product) {

            // then
            expect(error.message).toBe("product with id 17 not found");
            done();
        });
    });

    it("getProduct when server unresponsive", function (done) {
        // when
        model.getProduct(17, function (error, product) {

            // then
            expect(error.message).toBe("server connection failed");
            done();
        });
    });
});<commit_msg>Altered AJAX sample to use a nested describe<commit_after>describe("model", function () {
    var model;

    beforeEach(function () {
        model = new Model();
    });

    afterEach(function () {
        $.mockjaxClear();
    });

    describe("getProduct", function() {
        it("retrieves product info", function (done) {
            // given
            $.mockjax({
                // mockjax input
                url: '/product',
                data: { productId: 4711},
                // mockjax output
                responseText: { error: false, product: { name: 'banana'}},
                responseTime: 1
            });

            // when
            model.getProduct(4711, function (error, product) {

                // then
                expect(error).toBe(null);
                expect(product.name).toBe('banana');
                done(); // important for async test, must be called in final callback
            });
        });

        it("reports product-not-found server error", function (done) {
            // given
            $.mockjax({
                url: '/product',
                data: { productId: 17},
                responseText: { error: { message: "product with id 17 not found"}},
                responseTime: 1
            });

            // when
            model.getProduct(17, function (error, product) {

                // then
                expect(error.message).toBe("product with id 17 not found");
                done();
            });
        });

        it("handles unresponsive server", function (done) {
            // when
            model.getProduct(17, function (error, product) {

                // then
                expect(error.message).toBe("server connection failed");
                done();
            });
        });
    });

});<|endoftext|>


<commit_before>'use strict';

if( document.getElementById( 'inventory_link_753' ) )
{
	GetOption( {
		'link-inventory': true,
		'link-inventory-gift-subid': true,
		'enhancement-inventory-sidebar': true,
		'enhancement-inventory-update-urls': true,
		'enhancement-inventory-quick-sell': true,
		'enhancement-inventory-quick-sell-auto': false,
		'enhancement-inventory-no-sell-reload': true
	}, function( items )
	{
		if( items[ 'enhancement-inventory-sidebar' ] )
		{
			var style = document.createElement( 'link' );
			style.id = 'steamdb_inventory_sidebar';
			style.type = 'text/css';
			style.rel = 'stylesheet';
			style.href = GetLocalResource( 'styles/inventory-sidebar.css' );

			document.head.appendChild( style );
		}

		if( items[ 'link-inventory' ] )
		{
			document.body.dataset.steamdbLinks = 'true';
		}

		if( items[ 'link-inventory-gift-subid' ] )
		{
			document.body.dataset.steamdbGiftSubid = 'true';
		}

		if( items[ 'enhancement-inventory-quick-sell' ] )
		{
			document.body.dataset.steamdbQuickSell = 'true';
		}

		if( items[ 'enhancement-inventory-quick-sell-auto' ] )
		{
			document.body.dataset.steamdbQuickSellAuto = 'true';
		}

		if( items[ 'enhancement-inventory-no-sell-reload' ] )
		{
			document.body.dataset.steamdbNoSellReload = 'true';
		}

		var element = document.createElement( 'script' );
		element.id = 'steamdb_inventory_hook';
		element.type = 'text/javascript';
		element.src = GetLocalResource( 'scripts/community/inventory.js' );
		element.dataset.homepage = GetHomepage();

		document.head.appendChild( element );
	} );
}
<commit_msg>Remove left over param<commit_after>'use strict';

if( document.getElementById( 'inventory_link_753' ) )
{
	GetOption( {
		'link-inventory': true,
		'link-inventory-gift-subid': true,
		'enhancement-inventory-sidebar': true,
		'enhancement-inventory-quick-sell': true,
		'enhancement-inventory-quick-sell-auto': false,
		'enhancement-inventory-no-sell-reload': true
	}, function( items )
	{
		if( items[ 'enhancement-inventory-sidebar' ] )
		{
			var style = document.createElement( 'link' );
			style.id = 'steamdb_inventory_sidebar';
			style.type = 'text/css';
			style.rel = 'stylesheet';
			style.href = GetLocalResource( 'styles/inventory-sidebar.css' );

			document.head.appendChild( style );
		}

		if( items[ 'link-inventory' ] )
		{
			document.body.dataset.steamdbLinks = 'true';
		}

		if( items[ 'link-inventory-gift-subid' ] )
		{
			document.body.dataset.steamdbGiftSubid = 'true';
		}

		if( items[ 'enhancement-inventory-quick-sell' ] )
		{
			document.body.dataset.steamdbQuickSell = 'true';
		}

		if( items[ 'enhancement-inventory-quick-sell-auto' ] )
		{
			document.body.dataset.steamdbQuickSellAuto = 'true';
		}

		if( items[ 'enhancement-inventory-no-sell-reload' ] )
		{
			document.body.dataset.steamdbNoSellReload = 'true';
		}

		var element = document.createElement( 'script' );
		element.id = 'steamdb_inventory_hook';
		element.type = 'text/javascript';
		element.src = GetLocalResource( 'scripts/community/inventory.js' );
		element.dataset.homepage = GetHomepage();

		document.head.appendChild( element );
	} );
}
<|endoftext|>