<commit_before>/**
 * Create a notification
 * @constructor
 */
function Notification (payload) {
	this.encoding = 'utf8';

	this.payload = payload || {};
	this.expiry = 0;
	this.identifier = 0;
	this.priority = 10;

	this.retryLimit = -1;

	/** @deprecated since v1.3.0 used connection#pushNotification instead which accepts device token separately **/
	this.device = undefined;

	this.alert = undefined;
	this.badge = undefined;
	this.sound = undefined;
	/** @since v1.2.0 */
	this.newsstandAvailable = undefined;

	this.contentAvailable = undefined;

	this.mdm = undefined;

	this.compiled = false;

	this.truncateAtWordEnd = false;
}

/**
 * Clone a notification to send to multiple devices
 * @param {Device} [device] Device the notification will be sent to
 * @returns {Notification} A notification containing the same properties as the receiver
 * @since v1.2.0
 * @deprecated Since v1.3.0, notifications are not tied to a device so do not need cloning.
 */
Notification.prototype.clone = function (device) {
	var notification = new Notification();

	notification.encoding = this.encoding;
	notification.payload = this.payload;
	notification.expiry = this.expiry;
	notification.identifier = this.identifier;
	notification.priority = this.priority;
	notification.device = device;

	notification.alert = this.alert;
	notification.badge = this.badge;
	notification.sound = this.sound;
	notification.newsstandAvailable = this.newsstandAvailable;
	notification.contentAvailable = this.contentAvailable;
	notification.mdm = this.mdm;
	notification.truncateAtWordEnd = this.truncateAtWordEnd;

	return notification;
};

/**
 * Set the expiry value on the payload
 * @param {Number} [expiry] Timestamp when the notification should expire.
 * @since v1.3.5
 */
Notification.prototype.setExpiry = function (expiry) {
	this.expiry = expiry;
	return this;
};

/**
 * Set the priority
 * @param {Number} [priority=10] Priority value for the notification.
 * @since v1.3.9
 */
 Notification.prototype.setPriority = function (priority) {
 	this.priority = priority;
 	return this;
 }

/**
 * Set the "badge" value on the alert object
 * @param {Number} [badge] Badge Value
 * @since v1.3.5
 */
Notification.prototype.setBadge = function (badge) {
	this.badge = badge;
	return this;
};

/**
 * Set the "sound" value on the alert object
 * @param {String} [sound] Sound file name
 * @since v1.3.5
 */
Notification.prototype.setSound = function (sound) {
	this.sound = sound;
	return this;
};

/**
 * Set the alert text for the notification
 * @param {String} alertText The text of the alert message.
 * @see The Payload Documentation
 * @since v1.2.0
 */
Notification.prototype.setAlertText = function (text) {
	if(typeof this.alert != "object") {
		this.alert = text;
	}
	else {
		this.prepareAlert();
		this.alert['body'] = text;
	}
};

/**
 * Set the action-loc-key property on the alert object
 * @param {String} [key] If a string is specified, displays an alert with two buttons, whose behavior is described in Table 3-1. However, iOS uses the string as a key to get a localized string in the current localization to use for the right button’s title instead of “View”. If the value is null, the system displays an alert with a single OK button that simply dismisses the alert when tapped.
 * @see The Payload Documentation
 * @since v1.2.0
 */
Notification.prototype.setActionLocKey = function (key) {
	this.prepareAlert();
	this.alert['action-loc-key'] = key;
	return this;
};

/**
 * Set the loc-key parameter on the alert object
 * @param {String} [key] A key to an alert-message string in a Localizable.strings file for the current localization (which is set by the user’s language preference).
 * @see The Payload Documentation
 * @since v1.2.0
 */
Notification.prototype.setLocKey = function (key) {
	this.prepareAlert();
	if(!key) {
		delete this.alert["loc-key"];
		return;
	}
	this.alert['loc-key'] = key;
	return this;
};

/**
 * Set the loc-args parameter on the alert object
 * @param {String[]} [args] Variable string values to appear in place of the format specifiers in loc-key.
 * @see The Payload Documentation
 * @since v1.2.0
 */
Notification.prototype.setLocArgs = function (args) {
	this.prepareAlert();
	if(!args) {
		delete this.alert["loc-args"];
		return;
	}
	this.alert['loc-args'] = args;
	return this;
};

/**
 * Set the launch-image parameter on the alert object
 * @param {String} [image] The filename of an image file in the application bundle; it may include the extension or omit it.
 * @see The Payload Documentation
 * @since v1.2.0
 */
Notification.prototype.setLaunchImage = function (image) {
	this.prepareAlert();
	if(!image) {
		delete this.alert["launch-image"];
		return;
	}
	this.alert["launch-image"] = image;
	return this;
};

/**
 * Set the 'content-available' flag on the payload
 * @param {Boolean} [contentAvailable] Whether the content-available flag should be set or not.
 * @since v1.3.5
 */
Notification.prototype.setContentAvailable = function (contentAvailable) {
	this.contentAvailable = contentAvailable;
	return this;
};

/**
 * Set the 'content-available' flag on the payload
 * @param {Boolean} [newsstandAvailable] Whether the content-available flag should be set or not.
 * @since v1.3.5
 */
Notification.prototype.setNewsstandAvailable = function (newsstandAvailable) {
	this.newsstandAvailable = newsstandAvailable;
	return this;
};

/**
 * Set the 'mdm' flag on the payload
 * @param {Object} [mdm] The mdm property for the payload.
 * @since v1.3.5
 */
Notification.prototype.setMDM = function (mdm) {
	this.mdm = mdm;
	return this;
};

/**
 * Set the 'truncateAtWordEnd' flag for truncation logic
 * @param {Boolean} [truncateAtWordEnd] Whether the truncateAtWordEnd flag should be set or not.
 */

Notification.prototype.setTruncateAtWordEnd = function (truncateAtWordEnd) {
    this.truncateAtWordEnd = truncateAtWordEnd;
    return this;
};

/**
 * If an alert object doesn't already exist create it and transfer any existing message into the .body property
 * @private
 * @since v1.2.0
 */
Notification.prototype.prepareAlert = function () {
	var existingValue = this.alert;
	if(typeof existingValue != "object") {
		this.alert = {};
		if(typeof existingValue == "string") {
			this.alert.body = existingValue;
		}
	}
};

/**
 * @returns {Number} Byte length of the notification payload
 * @since v1.2.0
 */
Notification.prototype.length = function () {
	return Buffer.byteLength(JSON.stringify(this), this.encoding || 'utf8');
};

/**
 * If the notification payload is too long to send this method will attempt to trim the alert body text.
 * @returns {Number} The number of characters removed from the body text. If a negative value is returned, the text is too short to be trimmed enough.
 * @since v1.2.0
 */
Notification.prototype.trim = function() {
	var tooLong = this.length() - 256;
	if(tooLong <= 0) {
		return 0;
	}
	var length;
	var encoding = this.encoding || 'utf8';
	if(typeof this.alert == "string") {
		length = Buffer.byteLength(this.alert, encoding);
		if (length < tooLong) {
			return length - tooLong;
		}
		this.alert = this.truncateStringToLength(this.alert, length - tooLong);
		return tooLong;
	}
	else if(typeof this.alert == "object" && typeof this.alert.body == "string") {
		length = Buffer.byteLength(this.alert.body, encoding);
		if (length < tooLong) {
			return length - tooLong;
		}
		this.alert.body = this.truncateStringToLength(this.alert.body, length - tooLong);
		return tooLong;
	}
	return -tooLong;
};

/**
 * Compile a notification down to its JSON format. Compilation is final, changes made to the notification after this method is called will not be reflected in further calls.
 * @returns {String} JSON payload for the notification.
 * @since v1.3.0
 */
Notification.prototype.compile = function () {
	if(this.compiled) {
		return this.compiledPayload;
	}
	this.compiledPayload = JSON.stringify(this);
	this.compiled = true;
	return this.compiledPayload;
};

/**
 * @param {String} [string] Unicode string to be truncated
 * @param {Number} [length] The maximum number of bytes permitted in the Unicode string
 * @returns {String} Truncated String
 * @private
 */
Notification.prototype.truncateStringToLength = function (string, length) {
	// Convert to a buffer and back to a string with the correct encoding to truncate the unicode series correctly.
	var result = new Buffer(string, this.encoding || 'utf8').toString(this.encoding || 'utf8', 0, length);
	if (this.truncateAtWordEnd === true) {
		var lastSpaceIndexInResult = result.lastIndexOf(' ');

		// Only truncate the string further if the remainder isn't a whole word
		// which we can tell by checking the *next* character in the original string
		if(lastSpaceIndexInResult != -1 && string.charAt(result.length + 1) != ' '){
			result=result.substr(0,lastSpaceIndexInResult);
		}
	}

	// since we might have chopped off the end of a multi-byte sequence, remove any
	// invalid characters (represented as U+FFFD "REPLACEMENT CHARACTER") for UTF-8
	// or orphaned lead surrogates for UTF-16 (UCS-2) - where only the tail surrogate
	// has been removed.
	var done = false;
	var encoding = this.encoding || 'utf8';

	if (encoding != 'utf8' && encoding != 'utf16le' && encoding != 'ucs2') {
		return result;
	}
	while (! done) {
		var lastIndex = result.length - 1;
		var code = result.charCodeAt(lastIndex);
		if (code != 0xFFFD && encoding == 'utf8') {
			done = true;
		}
		else if ((code < 0xD800 || code > 0xDBFF) && (encoding == 'utf16le' || encoding == 'ucs2')) {
			done = true;
		}
		else {
			result = result.substr(0, lastIndex);
		}
	}

	return result;
};

/**
 * @private
 */
Notification.prototype.toJSON = function () {
	if (this.payload === undefined) {
		this.payload = {};
	}
	if (typeof this.mdm == 'string') {
		this.payload.mdm = this.mdm;
		return this.payload;
	}
	if (this.payload.aps === undefined) {
		this.payload.aps = {};
	}
	if (typeof this.badge == 'number') {
		this.payload.aps.badge = this.badge;
	}
	if (typeof this.sound == 'string') {
		this.payload.aps.sound = this.sound;
	}
	if (typeof this.alert == 'string' || typeof this.alert == 'object') {
		this.payload.aps.alert = this.alert;
	}
	if (this.newsstandAvailable || this.contentAvailable) {
		this.payload.aps['content-available'] = 1;
	}
	return this.payload;
};

module.exports = Notification;
<commit_msg>'url-args' is required for safari website notifications<commit_after>/**
 * Create a notification
 * @constructor
 */
function Notification (payload) {
	this.encoding = 'utf8';

	this.payload = payload || {};
	this.expiry = 0;
	this.identifier = 0;
	this.priority = 10;

	this.retryLimit = -1;

	/** @deprecated since v1.3.0 used connection#pushNotification instead which accepts device token separately **/
	this.device = undefined;

	this.alert = undefined;
	this.badge = undefined;
	this.sound = undefined;
	/** @since v1.2.0 */
	this.newsstandAvailable = undefined;

	this.contentAvailable = undefined;

	this.mdm = undefined;

	this.compiled = false;

	this.truncateAtWordEnd = false;

	this.urlArgs = undefined;
}

/**
 * Clone a notification to send to multiple devices
 * @param {Device} [device] Device the notification will be sent to
 * @returns {Notification} A notification containing the same properties as the receiver
 * @since v1.2.0
 * @deprecated Since v1.3.0, notifications are not tied to a device so do not need cloning.
 */
Notification.prototype.clone = function (device) {
	var notification = new Notification();

	notification.encoding = this.encoding;
	notification.payload = this.payload;
	notification.expiry = this.expiry;
	notification.identifier = this.identifier;
	notification.priority = this.priority;
	notification.device = device;

	notification.alert = this.alert;
	notification.badge = this.badge;
	notification.sound = this.sound;
	notification.newsstandAvailable = this.newsstandAvailable;
	notification.contentAvailable = this.contentAvailable;
	notification.mdm = this.mdm;
	notification.truncateAtWordEnd = this.truncateAtWordEnd;
	notification.urlArgs = this.urlArgs;

	return notification;
};

/**
 * Set the expiry value on the payload
 * @param {Number} [expiry] Timestamp when the notification should expire.
 * @since v1.3.5
 */
Notification.prototype.setExpiry = function (expiry) {
	this.expiry = expiry;
	return this;
};

/**
 * Set the priority
 * @param {Number} [priority=10] Priority value for the notification.
 * @since v1.3.9
 */
 Notification.prototype.setPriority = function (priority) {
 	this.priority = priority;
 	return this;
 }

/**
 * Set the "badge" value on the alert object
 * @param {Number} [badge] Badge Value
 * @since v1.3.5
 */
Notification.prototype.setBadge = function (badge) {
	this.badge = badge;
	return this;
};

/**
 * Set the "sound" value on the alert object
 * @param {String} [sound] Sound file name
 * @since v1.3.5
 */
Notification.prototype.setSound = function (sound) {
	this.sound = sound;
	return this;
};

/**
 * Set the alert text for the notification
 * @param {String} alertText The text of the alert message.
 * @see The Payload Documentation
 * @since v1.2.0
 */
Notification.prototype.setAlertText = function (text) {
	if(typeof this.alert != "object") {
		this.alert = text;
	}
	else {
		this.prepareAlert();
		this.alert['body'] = text;
	}
};

/**
 * Set the action-loc-key property on the alert object
 * @param {String} [key] If a string is specified, displays an alert with two buttons, whose behavior is described in Table 3-1. However, iOS uses the string as a key to get a localized string in the current localization to use for the right button’s title instead of “View”. If the value is null, the system displays an alert with a single OK button that simply dismisses the alert when tapped.
 * @see The Payload Documentation
 * @since v1.2.0
 */
Notification.prototype.setActionLocKey = function (key) {
	this.prepareAlert();
	this.alert['action-loc-key'] = key;
	return this;
};

/**
 * Set the loc-key parameter on the alert object
 * @param {String} [key] A key to an alert-message string in a Localizable.strings file for the current localization (which is set by the user’s language preference).
 * @see The Payload Documentation
 * @since v1.2.0
 */
Notification.prototype.setLocKey = function (key) {
	this.prepareAlert();
	if(!key) {
		delete this.alert["loc-key"];
		return;
	}
	this.alert['loc-key'] = key;
	return this;
};

/**
 * Set the loc-args parameter on the alert object
 * @param {String[]} [args] Variable string values to appear in place of the format specifiers in loc-key.
 * @see The Payload Documentation
 * @since v1.2.0
 */
Notification.prototype.setLocArgs = function (args) {
	this.prepareAlert();
	if(!args) {
		delete this.alert["loc-args"];
		return;
	}
	this.alert['loc-args'] = args;
	return this;
};

/**
 * Set the launch-image parameter on the alert object
 * @param {String} [image] The filename of an image file in the application bundle; it may include the extension or omit it.
 * @see The Payload Documentation
 * @since v1.2.0
 */
Notification.prototype.setLaunchImage = function (image) {
	this.prepareAlert();
	if(!image) {
		delete this.alert["launch-image"];
		return;
	}
	this.alert["launch-image"] = image;
	return this;
};

/**
 * Set the 'content-available' flag on the payload
 * @param {Boolean} [contentAvailable] Whether the content-available flag should be set or not.
 * @since v1.3.5
 */
Notification.prototype.setContentAvailable = function (contentAvailable) {
	this.contentAvailable = contentAvailable;
	return this;
};

/**
 * Set the 'content-available' flag on the payload
 * @param {Boolean} [newsstandAvailable] Whether the content-available flag should be set or not.
 * @since v1.3.5
 */
Notification.prototype.setNewsstandAvailable = function (newsstandAvailable) {
	this.newsstandAvailable = newsstandAvailable;
	return this;
};

/**
 * Set the 'mdm' flag on the payload
 * @param {Object} [mdm] The mdm property for the payload.
 * @since v1.3.5
 */
Notification.prototype.setMDM = function (mdm) {
	this.mdm = mdm;
	return this;
};

/**
 * Set the 'truncateAtWordEnd' flag for truncation logic
 * @param {Boolean} [truncateAtWordEnd] Whether the truncateAtWordEnd flag should be set or not.
 */
Notification.prototype.setTruncateAtWordEnd = function (truncateAtWordEnd) {
	this.truncateAtWordEnd = truncateAtWordEnd;
	return this;
};

/**
 * Set the urlArgs for the notification
 * @param {Array} [urlArgs] The url args for the endpoint
 * @see The Web Payload Documentation
 * @since v1.4.1
 */
Notification.prototype.setUrlArgs = function (urlArgs) {
	this.urlArgs = urlArgs;
	return this;
};

/**
 * If an alert object doesn't already exist create it and transfer any existing message into the .body property
 * @private
 * @since v1.2.0
 */
Notification.prototype.prepareAlert = function () {
	var existingValue = this.alert;
	if(typeof existingValue != "object") {
		this.alert = {};
		if(typeof existingValue == "string") {
			this.alert.body = existingValue;
		}
	}
};

/**
 * @returns {Number} Byte length of the notification payload
 * @since v1.2.0
 */
Notification.prototype.length = function () {
	return Buffer.byteLength(JSON.stringify(this), this.encoding || 'utf8');
};

/**
 * If the notification payload is too long to send this method will attempt to trim the alert body text.
 * @returns {Number} The number of characters removed from the body text. If a negative value is returned, the text is too short to be trimmed enough.
 * @since v1.2.0
 */
Notification.prototype.trim = function() {
	var tooLong = this.length() - 256;
	if(tooLong <= 0) {
		return 0;
	}
	var length;
	var encoding = this.encoding || 'utf8';
	if(typeof this.alert == "string") {
		length = Buffer.byteLength(this.alert, encoding);
		if (length < tooLong) {
			return length - tooLong;
		}
		this.alert = this.truncateStringToLength(this.alert, length - tooLong);
		return tooLong;
	}
	else if(typeof this.alert == "object" && typeof this.alert.body == "string") {
		length = Buffer.byteLength(this.alert.body, encoding);
		if (length < tooLong) {
			return length - tooLong;
		}
		this.alert.body = this.truncateStringToLength(this.alert.body, length - tooLong);
		return tooLong;
	}
	return -tooLong;
};

/**
 * Compile a notification down to its JSON format. Compilation is final, changes made to the notification after this method is called will not be reflected in further calls.
 * @returns {String} JSON payload for the notification.
 * @since v1.3.0
 */
Notification.prototype.compile = function () {
	if(this.compiled) {
		return this.compiledPayload;
	}
	this.compiledPayload = JSON.stringify(this);
	this.compiled = true;
	return this.compiledPayload;
};

/**
 * @param {String} [string] Unicode string to be truncated
 * @param {Number} [length] The maximum number of bytes permitted in the Unicode string
 * @returns {String} Truncated String
 * @private
 */
Notification.prototype.truncateStringToLength = function (string, length) {
	// Convert to a buffer and back to a string with the correct encoding to truncate the unicode series correctly.
	var result = new Buffer(string, this.encoding || 'utf8').toString(this.encoding || 'utf8', 0, length);
	if (this.truncateAtWordEnd === true) {
		var lastSpaceIndexInResult = result.lastIndexOf(' ');

		// Only truncate the string further if the remainder isn't a whole word
		// which we can tell by checking the *next* character in the original string
		if(lastSpaceIndexInResult != -1 && string.charAt(result.length + 1) != ' '){
			result=result.substr(0,lastSpaceIndexInResult);
		}
	}

	// since we might have chopped off the end of a multi-byte sequence, remove any
	// invalid characters (represented as U+FFFD "REPLACEMENT CHARACTER") for UTF-8
	// or orphaned lead surrogates for UTF-16 (UCS-2) - where only the tail surrogate
	// has been removed.
	var done = false;
	var encoding = this.encoding || 'utf8';

	if (encoding != 'utf8' && encoding != 'utf16le' && encoding != 'ucs2') {
		return result;
	}
	while (! done) {
		var lastIndex = result.length - 1;
		var code = result.charCodeAt(lastIndex);
		if (code != 0xFFFD && encoding == 'utf8') {
			done = true;
		}
		else if ((code < 0xD800 || code > 0xDBFF) && (encoding == 'utf16le' || encoding == 'ucs2')) {
			done = true;
		}
		else {
			result = result.substr(0, lastIndex);
		}
	}

	return result;
};

/**
 * @private
 */
Notification.prototype.toJSON = function () {
	if (this.payload === undefined) {
		this.payload = {};
	}
	if (typeof this.mdm == 'string') {
		this.payload.mdm = this.mdm;
		return this.payload;
	}
	if (this.payload.aps === undefined) {
		this.payload.aps = {};
	}
	if (typeof this.badge == 'number') {
		this.payload.aps.badge = this.badge;
	}
	if (typeof this.sound == 'string') {
		this.payload.aps.sound = this.sound;
	}
	if (typeof this.alert == 'string' || typeof this.alert == 'object') {
		this.payload.aps.alert = this.alert;
	}
	if (this.newsstandAvailable || this.contentAvailable) {
		this.payload.aps['content-available'] = 1;
	}
	if (Array.isArray(this.urlArgs)) {
		this.payload.aps['url-args'] = this.urlArgs;
	}

	return this.payload;
};

module.exports = Notification;
<|endoftext|>


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

var error = require('./error'),
  AuthCodeGrant = require('./authCodeGrant'),
  Authorise = require('./authorise'),
  Grant = require('./grant');

module.exports = OAuth2Server;

/**
 * Constructor
 *
 * @param {Object} config Configuration object
 */
function OAuth2Server (config) {

  if (!(this instanceof OAuth2Server)) return new OAuth2Server(config);

  config = config || {};

  if (!config.model) throw new Error('No model supplied to OAuth2Server');
  this.model = config.model;

  this.grants = config.grants || [];
  this.debug = config.debug || false;
  this.passthroughErrors = config.passthroughErrors;
  this.continueAfterResponse = config.continueAfterResponse;

  this.accessTokenLifetime = config.accessTokenLifetime !== undefined ?
    config.accessTokenLifetime : 3600;
  this.refreshTokenLifetime = config.refreshTokenLifetime !== undefined ?
    config.refreshTokenLifetime : 1209600;
  this.authCodeLifetime = config.authCodeLifetime || 30;

  this.regex = {
    clientId: config.clientIdRegex || /^[a-z0-9-_]{3,40}$/i,
    grantType: new RegExp('^(' + this.grants.join('|') + ')$', 'i')
  };
}

/**
 * Authorisation Middleware
 *
 * Returns middleware that will authorise the request using oauth,
 * if successful it will allow the request to proceed to the next handler
 *
 * @return {Function} middleware
 */
OAuth2Server.prototype.authorise = function () {
  var self = this;

  return function (req, res, next) {
    new Authorise(self, req, next);
  };
};

/**
 * Grant Middleware
 *
 * Returns middleware that will grant tokens to valid requests.
 * This would normally be mounted at '/oauth/token' e.g.
 *
 * `app.all('/oauth/token', oauth.grant());`
 *
 * @return {Function} middleware
 */
OAuth2Server.prototype.grant = function () {
  var self = this;

  return function (req, res, next) {
    new Grant(self, req, res, next);
  };
};

/**
 * Code Auth Grant Middleware
 *
 * @param  {Function} check Function will be called with req to check if the
 *                          user has authorised the request.
 * @return {Function}       middleware
 */
OAuth2Server.prototype.authCodeGrant = function (check) {
  var self = this;

  return function (req, res, next) {
    new AuthCodeGrant(self, req, res, next, check);
  };
};

/**
 * OAuth Error Middleware
 *
 * Returns middleware that will catch OAuth errors and ensure an OAuth
 * complaint response
 *
 * @return {Function} middleware
 */
OAuth2Server.prototype.errorHandler = function () {
  var self = this;

  return function (err, req, res, next) {
    if (!(err instanceof error) || self.passthroughErrors) return next(err);

    if (self.debug) console.log(err.stack || err);
    delete err.stack;

    if (err.headers) res.set(err.headers);
    delete err.headers;

    res.send(err.code, err);
  };
};

/**
 * Lockdown
 *
 * When using the lockdown patter, this function should be called after
 * all routes have been declared.
 * It will search through each route and if it has not been explitly bypassed
 * (by passing oauth.bypass) then authorise will be inserted.
 * If oauth.grant has been passed it will replace it with the proper grant
 * middleware
 * NOTE: When using this method, you must PASS the method not CALL the method,
 * e.g.:
 *
 * `
 * app.all('/oauth/token', app.oauth.grant);
 *
 * app.get('/secrets', function (req, res) {
 *   res.send('secrets');
 * });
 *
 * app.get('/public', app.oauth.bypass, function (req, res) {
 *   res.send('publci');
 * });
 *
 * app.oauth.lockdown(app);
 * `
 *
 * @param  {Object} app Express app
 */
OAuth2Server.prototype.lockdown = function (app) {
  var self = this;

  var lockdown = function (route) {
    // Check if it's a grant route
    var pos = route.callbacks.indexOf(self.grant);
    if (pos !== -1) {
      route.callbacks[pos] = self.grant();
      return;
    }

    // Check it's not been explitly bypassed
    pos = route.callbacks.indexOf(self.bypass);
    if (pos === -1) {
      route.callbacks.unshift(self.authorise());
    } else {
      route.callbacks.splice(pos, 1);
    }
  };

  for (var method in app.routes) {
    app.routes[method].forEach(lockdown);
  }
};

/**
 * Bypass
 *
 * This is used as placeholder for when using the lockdown pattern
 *
 * @return {Function} noop
 */
OAuth2Server.prototype.bypass = function () {};
<commit_msg>Support custom loggers<commit_after>/**
 * Copyright 2013-present NightWorld.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var error = require('./error'),
  AuthCodeGrant = require('./authCodeGrant'),
  Authorise = require('./authorise'),
  Grant = require('./grant');

module.exports = OAuth2Server;

/**
 * Constructor
 *
 * @param {Object} config Configuration object
 */
function OAuth2Server (config) {

  if (!(this instanceof OAuth2Server)) return new OAuth2Server(config);

  config = config || {};

  if (!config.model) throw new Error('No model supplied to OAuth2Server');
  this.model = config.model;

  this.grants = config.grants || [];
  this.debug = config.debug || function () {};
  if (typeof(this.debug) !== 'function') {
      this.debug = console.log;
  }
  this.passthroughErrors = config.passthroughErrors;
  this.continueAfterResponse = config.continueAfterResponse;

  this.accessTokenLifetime = config.accessTokenLifetime !== undefined ?
    config.accessTokenLifetime : 3600;
  this.refreshTokenLifetime = config.refreshTokenLifetime !== undefined ?
    config.refreshTokenLifetime : 1209600;
  this.authCodeLifetime = config.authCodeLifetime || 30;

  this.regex = {
    clientId: config.clientIdRegex || /^[a-z0-9-_]{3,40}$/i,
    grantType: new RegExp('^(' + this.grants.join('|') + ')$', 'i')
  };
}

/**
 * Authorisation Middleware
 *
 * Returns middleware that will authorise the request using oauth,
 * if successful it will allow the request to proceed to the next handler
 *
 * @return {Function} middleware
 */
OAuth2Server.prototype.authorise = function () {
  var self = this;

  return function (req, res, next) {
    new Authorise(self, req, next);
  };
};

/**
 * Grant Middleware
 *
 * Returns middleware that will grant tokens to valid requests.
 * This would normally be mounted at '/oauth/token' e.g.
 *
 * `app.all('/oauth/token', oauth.grant());`
 *
 * @return {Function} middleware
 */
OAuth2Server.prototype.grant = function () {
  var self = this;

  return function (req, res, next) {
    new Grant(self, req, res, next);
  };
};

/**
 * Code Auth Grant Middleware
 *
 * @param  {Function} check Function will be called with req to check if the
 *                          user has authorised the request.
 * @return {Function}       middleware
 */
OAuth2Server.prototype.authCodeGrant = function (check) {
  var self = this;

  return function (req, res, next) {
    new AuthCodeGrant(self, req, res, next, check);
  };
};

/**
 * OAuth Error Middleware
 *
 * Returns middleware that will catch OAuth errors and ensure an OAuth
 * complaint response
 *
 * @return {Function} middleware
 */
OAuth2Server.prototype.errorHandler = function () {
  var self = this;

  return function (err, req, res, next) {
    if (!(err instanceof error) || self.passthroughErrors) return next(err);

    self.debug(err.stack || err);
    delete err.stack;

    if (err.headers) res.set(err.headers);
    delete err.headers;

    res.send(err.code, err);
  };
};

/**
 * Lockdown
 *
 * When using the lockdown patter, this function should be called after
 * all routes have been declared.
 * It will search through each route and if it has not been explitly bypassed
 * (by passing oauth.bypass) then authorise will be inserted.
 * If oauth.grant has been passed it will replace it with the proper grant
 * middleware
 * NOTE: When using this method, you must PASS the method not CALL the method,
 * e.g.:
 *
 * `
 * app.all('/oauth/token', app.oauth.grant);
 *
 * app.get('/secrets', function (req, res) {
 *   res.send('secrets');
 * });
 *
 * app.get('/public', app.oauth.bypass, function (req, res) {
 *   res.send('publci');
 * });
 *
 * app.oauth.lockdown(app);
 * `
 *
 * @param  {Object} app Express app
 */
OAuth2Server.prototype.lockdown = function (app) {
  var self = this;

  var lockdown = function (route) {
    // Check if it's a grant route
    var pos = route.callbacks.indexOf(self.grant);
    if (pos !== -1) {
      route.callbacks[pos] = self.grant();
      return;
    }

    // Check it's not been explitly bypassed
    pos = route.callbacks.indexOf(self.bypass);
    if (pos === -1) {
      route.callbacks.unshift(self.authorise());
    } else {
      route.callbacks.splice(pos, 1);
    }
  };

  for (var method in app.routes) {
    app.routes[method].forEach(lockdown);
  }
};

/**
 * Bypass
 *
 * This is used as placeholder for when using the lockdown pattern
 *
 * @return {Function} noop
 */
OAuth2Server.prototype.bypass = function () {};
<|endoftext|>


<commit_before>'use strict';

const _ = require('lodash');
const OGMNeoWhere = require('./ogmneo-where');
const OGMObjectParse = require('./ogmneo-parse');

/**
    * @class OGMNeoQuery
 */
class OGMNeoQuery {

    /**
        * Constructs a query object with an label.
        *
        * @constructor
        * @param {string=} label - The query to filter nodes that have to be returned.
    */
    constructor(label) {
        this.label = label;
    }

    /**
        * Convenience method that creates a query object with an label.
        *
        * @static
        * @param {string=} label - The query to filter nodes that have to be returned.
        * @returns {OGMNeoQuery} Created query with label.
    */
    static create(label) {
        return new OGMNeoQuery(label);
    }

    set label(value) {
        if (value && _.isString(value) && !_.isEmpty(value)) {
            this._label = value;
        }
    }
    /**
     * @type {string}
    */
    get label() {
        return this._label;
    }

    /**
     * @type {OGMNeoWhere}
    */
    get whereObject() {
        return  this._where;
    }

    where(value) {
        if (value == null || value instanceof OGMNeoWhere) {
            this._where = value;
        } else {
            throw new Error('where parameter must be an instance of OGMNeoWhere class or null');
        }
        return this;
    }

    /**
        * Add limit constraint to this query object.
        *
        * @param {integer} value - The max number of values that should be returned.
        * @returns {OGMNeoQuery} This instance of query.
    */
    limit(value) {
        if (_.isInteger(value)) {
            this._limit = value;
        }
        return this;
    }

    /**
        * Add DESCENDING order by clause to this query object.
        *
        * @param {string|array} properties - The properties in order to order by for.
        * @returns {OGMNeoQuery} This instance of query.
    */
    descOrderBy(properties) {
        this._orderBy = {
            properties: properties,
            order: 'DESC'
        };
        return this;
    }

    /**
        * Add ASCENDING order by clause to this query object.
        *
        * @param {string|array} properties - The properties in order to order by for.
        * @returns {OGMNeoQuery} This instance of query.
    */
    ascOrderBy(properties) {
        this._orderBy = {
            properties: properties,
            order: 'ASC'
        };
        return this;
    }

    /**
        * Add the properties that must be returned in the objects.
        *
        * @param {string|array} properties - The properties that must to be returned.
        * @returns {OGMNeoQuery} This instance of query.
    */
    return(properties) {
        if (OGMObjectParse.isValidPropertiesArray(properties)) {
            this._return = `RETURN ${OGMObjectParse.parsePropertiesArray(properties)}`;
        }
        return this;
    }

    orderByClause(variable = 'n') {
        if (this._orderBy && OGMObjectParse.isValidPropertiesArray(this._orderBy.properties)) {
            let properties = OGMObjectParse.parsePropertiesArray(this._orderBy.properties, variable);
            return `ORDER BY ${properties} ${this._orderBy.order}`;
        }
        return '';
    }

    limitClause() {
        return (this._limit) ? `LIMIT ${this._limit}` : '';
    }

    returnClause() {
        return (this._return !== undefined) ? this._return : 'RETURN n';
    }
    /**
        * Return cypher query count string matches from this query.
        *
        * @returns {string} Cypher count match builded.
    */
    countCypher() {
        let queryLabel = (this.label) ? `:${this.label}` : '';
        let cypher = `MATCH (n${queryLabel}) ${this._whereStatement()} RETURN COUNT(n) as count`;
        return cypher;
    }

    /**
        * Return cypher nodes match string from this query and return it.
        *
        * @returns {string} Cypher nodes query builded.
    */
    queryCypher() {
        let order = this.orderByClause();
        order = (order !== '')? ` ${order}` : '';
        return `${this.matchCypher()} ${this.returnClause()}${order} ${this.limitClause()}`.trim();
    }

    /**
        * Return ONLY MATCH Statement cypher nodes match a string with this query.
        *
        * @returns {string} Cypher nodes match builded.
    */
    matchCypher() {
        let queryLabel = (this.label) ? `:${this.label}` : '';
        return `MATCH (n${queryLabel}) ${this._whereStatement()}`.trim();
    }

    _whereStatement() {
        return (this.whereObject == null) ? '' : `WHERE ${this.whereObject.clause}`;
    }
}

module.exports = OGMNeoQuery;

<commit_msg>master: Updating docs<commit_after>'use strict';

const _ = require('lodash');
const OGMNeoWhere = require('./ogmneo-where');
const OGMObjectParse = require('./ogmneo-parse');

/**
    * @class OGMNeoQuery
 */
class OGMNeoQuery {

    /**
        * Constructs a query object with an label.
        *
        * @constructor
        * @param {string=} label - The query to filter nodes that have to be returned.
    */
    constructor(label) {
        this.label = label;
    }

    /**
        * Convenience method that creates a query object with an label.
        *
        * @static
        * @param {string=} label - The query to filter nodes that have to be returned.
        * @returns {OGMNeoQuery} Created query with label.
    */
    static create(label) {
        return new OGMNeoQuery(label);
    }

    set label(value) {
        if (value && _.isString(value) && !_.isEmpty(value)) {
            this._label = value;
        }
    }
    /**
     * @type {string}
    */
    get label() {
        return this._label;
    }

    /**
     * @type {OGMNeoWhere}
    */
    get whereObject() {
        return  this._where;
    }

    where(value) {
        if (value == null || value instanceof OGMNeoWhere) {
            this._where = value;
        } else {
            throw new Error('where parameter must be an instance of OGMNeoWhere class or null');
        }
        return this;
    }

    /**
        * Add limit constraint to this query object.
        *
        * @param {integer} value - The max number of values that should be returned.
        * @returns {OGMNeoQuery} This instance of query.
    */
    limit(value) {
        if (_.isInteger(value)) {
            this._limit = value;
        }
        return this;
    }

    /**
        * Add DESCENDING order by clause to this query object.
        *
        * @param {string|array} properties - The properties in order to order by for.
        * @returns {OGMNeoQuery} This instance of query.
    */
    descOrderBy(properties) {
        this._orderBy = {
            properties: properties,
            order: 'DESC'
        };
        return this;
    }

    /**
        * Add ASCENDING order by clause to this query object.
        *
        * @param {string|array} properties - The properties in order to order by for.
        * @returns {OGMNeoQuery} This instance of query.
    */
    ascOrderBy(properties) {
        this._orderBy = {
            properties: properties,
            order: 'ASC'
        };
        return this;
    }

    /**
        * Add the properties that must be returned in the objects.
        *
        * @param {string|array} properties - The properties that must to be returned.
        * @returns {OGMNeoQuery} This instance of query.
    */
    return(properties) {
        if (OGMObjectParse.isValidPropertiesArray(properties)) {
            this._return = `RETURN ${OGMObjectParse.parsePropertiesArray(properties)}`;
        }
        return this;
    }

    orderByClause(variable = 'n') {
        if (this._orderBy && OGMObjectParse.isValidPropertiesArray(this._orderBy.properties)) {
            let properties = OGMObjectParse.parsePropertiesArray(this._orderBy.properties, variable);
            return `ORDER BY ${properties} ${this._orderBy.order}`;
        }
        return '';
    }

    limitClause() {
        return (this._limit) ? `LIMIT ${this._limit}` : '';
    }

    returnClause() {
        return (this._return !== undefined) ? this._return : 'RETURN n';
    }
    /**
        * Return cypher query string for count that represents this query.
        *
        * @returns {string} Cypher count match string.
    */
    countCypher() {
        let queryLabel = (this.label) ? `:${this.label}` : '';
        let cypher = `MATCH (n${queryLabel}) ${this._whereStatement()} RETURN COUNT(n) as count`;
        return cypher;
    }

    /**
        * Return full cypher query string related to this query.
        *
        * @returns {string} Cypher query.
    */
    queryCypher() {
        let order = this.orderByClause();
        order = (order !== '')? ` ${order}` : '';
        return `${this.matchCypher()} ${this.returnClause()}${order} ${this.limitClause()}`.trim();
    }

    /**
        * Return ONLY MATCH cypher statement string that represents this query.
        *
        * @returns {string} Cypher match query.
    */
    matchCypher() {
        let queryLabel = (this.label) ? `:${this.label}` : '';
        return `MATCH (n${queryLabel}) ${this._whereStatement()}`.trim();
    }

    _whereStatement() {
        return (this.whereObject == null) ? '' : `WHERE ${this.whereObject.clause}`;
    }
}

module.exports = OGMNeoQuery;

<|endoftext|>


<commit_before>'use strict';

/* Modules */
// Declare app level module which depends on filters, and services
angular.module('Berserker', ['Berserker.filters', 'Berserker.services', 'Berserker.directives'])
        .config(
        [
            '$routeProvider',
            function($routeProvider) {
                $routeProvider.when('/downloads', {
                    templateUrl: 'partials/downloads.html',
                    controller: DownloadListCtrl
                })
                        .when(
                        '/settings', {
                    templateUrl: 'partials/settings.html',
                    controller: SettingsCtrl
                })
                        .otherwise({
                    redirectTo: '/settings'});
            }]);

/* Controllers */
function DownloadListCtrl($scope, Command) {
    $scope.downloads = Command.get({command: 'aria2.getGlobalOption'});
}
DownloadListCtrl.$inject = ['$scope', 'Command'];

function SettingsCtrl($scope, $http) {
    $http({
        method: 'POST',
        url: 'command/aria2.getGlobalOption',
        headers: {
            Accept: "application/json"
        }
    }).success(function(data, status) {
        $scope.master = [];
        angular.forEach(data.result, function(value, key) {
            $scope.master.push({
                key: key,
                value: value
            });
        });
        $scope.settings = angular.copy($scope.master);
    });

    $scope.filter = {
        query: '',
        modified: false
    };

    $scope.update = function() {
        var changeset = {};
        for (var i = 0; i < $scope.settings.length; ++i) {
            if (!angular.equals($scope.settings[i], $scope.master[i])) {
                changeset[$scope.settings[i].key] = $scope.settings[i].value;
            }
        }
        $http({
            method: 'POST',
            url: 'command/aria2.changeGlobalOption',
            headers: {
                Accept: "application/json"
            },
            data: changeset
        }).success(function(data, status) {
            console.dir(data);
        }).error(function(data, status) {
            console.dir(data);
        });
    };

    $scope.isUnchanged = function() {
        return angular.equals($scope.settings, $scope.master);
    };

    $scope.reset = function() {
        $scope.settings = angular.copy($scope.master);
        $scope.filter.query = '';
        if ($scope.filter.modified) {
            $('#mod').button('toggle');
            $scope.filter.modified = false;
        }
        $('ng-dirty').removeClass('ng-dirty').addClass('ng-pristine');
        $("html, body").animate({scrollTop: 0}, "slow");
    };

    $scope.toggleModified = function() {
        $scope.filter.modified = !$scope.filter.modified;
    };

    $scope.markDirty = function(setting) {
        setting.dirty = true;
    };
}
SettingsCtrl.$inject = ['$scope', '$http'];

/* Directives */
angular.module('Berserker.directives', ['$strap.directives'])
        .directive('appVersion',
        ['version', function(version) {
                return function(scope, elm, attrs) {
                    elm.text(version);
                };
            }]);

/* Filters */
angular.module('Berserker.filters', []).filter('interpolate', ['version', function(version) {
        return function(text) {
            return String(text).replace(/\%VERSION\%/mg, version);
        };
    }]).filter('settingsFilter', function() {
    return function(items, field) {
        var result = [];
        if (typeof items === 'object') {
            for (var i = 0; i < items.length; ++i) {
                if ((items[i].key + items[i].value).indexOf(field.query) !== -1) {
                    if (!field.modified || items[i].dirty) {
                        result.push(items[i]);
                    }
                }
            }
        }
        return result;
    };
});

/* Services */
angular.module('Berserker.services', []).value('version', '0.1');<commit_msg>Extracted  send functionality into helper function.<commit_after>'use strict';

/* Modules */
// Declare app level module which depends on filters, and services
angular.module('Berserker', ['Berserker.filters', 'Berserker.services', 'Berserker.directives'])
        .config(
        [
            '$routeProvider',
            function($routeProvider) {
                $routeProvider.when('/downloads', {
                    templateUrl: 'partials/downloads.html',
                    controller: DownloadListCtrl
                })
                        .when(
                        '/settings', {
                    templateUrl: 'partials/settings.html',
                    controller: SettingsCtrl
                })
                        .otherwise({
                    redirectTo: '/settings'});
            }]);

/* Controllers */
function DownloadListCtrl($scope, Command) {
    $scope.downloads = Command.get({command: 'aria2.getGlobalOption'});
}
DownloadListCtrl.$inject = ['$scope', 'Command'];

function SettingsCtrl($scope, $http) {
    sendCommand($http, 'command/aria2.getGlobalOption').success(function(data, status) {
        $scope.master = [];
        angular.forEach(data.result, function(value, key) {
            $scope.master.push({
                key: key,
                value: value
            });
        });
        $scope.settings = angular.copy($scope.master);
    });

    $scope.filter = {
        query: '',
        modified: false
    };

    $scope.update = function() {
        var changeset = {};
        for (var i = 0; i < $scope.settings.length; ++i) {
            if (!angular.equals($scope.settings[i], $scope.master[i])) {
                changeset[$scope.settings[i].key] = $scope.settings[i].value;
            }
        }
        sendCommand($http, 'command/aria2.changeGlobalOption').success(function(data, status) {
            console.dir(data);
        });
    };

    $scope.isUnchanged = function() {
        return angular.equals($scope.settings, $scope.master);
    };

    $scope.reset = function() {
        $scope.settings = angular.copy($scope.master);
        $scope.filter.query = '';
        if ($scope.filter.modified) {
            $('#mod').button('toggle');
            $scope.filter.modified = false;
        }
        $('ng-dirty').removeClass('ng-dirty').addClass('ng-pristine');
        $("html, body").animate({scrollTop: 0}, "slow");
    };

    $scope.toggleModified = function() {
        $scope.filter.modified = !$scope.filter.modified;
    };

    $scope.markDirty = function(setting) {
        setting.dirty = true;
    };
}
SettingsCtrl.$inject = ['$scope', '$http'];

/* Directives */
angular.module('Berserker.directives', ['$strap.directives'])
        .directive('appVersion',
        ['version', function(version) {
                return function(scope, elm, attrs) {
                    elm.text(version);
                };
            }]);

/* Filters */
angular.module('Berserker.filters', []).filter('interpolate', ['version', function(version) {
        return function(text) {
            return String(text).replace(/\%VERSION\%/mg, version);
        };
    }]).filter('settingsFilter', function() {
    return function(items, field) {
        var result = [];
        if (typeof items === 'object') {
            for (var i = 0; i < items.length; ++i) {
                if ((items[i].key + items[i].value).indexOf(field.query) !== -1) {
                    if (!field.modified || items[i].dirty) {
                        result.push(items[i]);
                    }
                }
            }
        }
        return result;
    };
});

/* Services */
angular.module('Berserker.services', []).value('version', '0.1');

/* Helper Functions */
function sendCommand($http, url) {
    return $http({
        method: 'POST',
        url: url,
        headers: {
            Accept: "application/json"
        }
    }).error(function(data, status) {
        console.error('Error - Status: %s\n Message: %j', status, data);
    });
}<|endoftext|>


<commit_before>!function(global, $) {
	'use strict';
	var i18n = ccmi18n_helpGuides['change-content-edit-mode'];
	var $area = $('div.ccm-area:not(.ccm-global-area)').eq(0);
	var $block = $area.find('.ccm-block-edit').eq(0);
	var steps = [{
		content: '
' + i18n[0].title + '
' + i18n[0].text + '
',
		highlightTarget: false,
		nextButton: true,
		target: $('[data-guide-toolbar-action=check-in]'),
		my: 'top left',
		at: 'bottom center',
		setup: function(tour, options) {
			ConcreteHelpGuideManager.clearGuideToLaunchOnRefresh();
		}
	},{
		content: '
' + i18n[1].title + '
' + i18n[1].text + '
',
		highlightTarget: false,
		nextButton: false,
		target: $block,
		my: 'top left',
		at: 'bottom center',
		setup: function(tour, options) {
			ConcreteEvent.subscribe('ConcreteMenuShow.changeContentEditModeTour', function(e, args) {
				tour.next();
			});
		},
		teardown: function(tour, options) {
			ConcreteEvent.unsubscribe('ConcreteMenuShow.changeContentEditModeTour');
		}
	},{
		content: '
' + i18n[2].title + '
' + i18n[2].text + '
',
		highlightTarget: false,
		nextButton: true,
		setup: function(tour, options) {
			var target = $('div#ccm-popover-menu-container div.ccm-edit-mode-block-menu').eq(0);
			return {target: target}
		},
		teardown: function() {
			ConcreteMenuManager.getActiveMenu().hide();
		},
		my: 'left center',
		at: 'right center'
	},{
		content: '
' + i18n[3].title + '
' + i18n[3].text + '
',
		highlightTarget: true,
		nextButton: true,
		target: $('[data-guide-toolbar-action=check-in]'),
		my: 'top left',
		at: 'bottom center'
	}];

	var tour = new Tourist.Tour({
		steps: steps,
		tipClass: 'Bootstrap',
		tipOptions:{
			showEffect: 'slidein'
		}
	});
	tour.on('start', function() {

	});
	tour.on('stop', function() {
		$('.ccm-dialog-help-wrapper').show();
	});

	ConcreteHelpGuideManager.register('change-content-edit-mode', tour);

}(window, jQuery);<commit_msg>guide bug fix<commit_after>!function(global, $) {
	'use strict';
	var i18n = ccmi18n_helpGuides['change-content-edit-mode'];
	var $area = $('div.ccm-area:not(.ccm-global-area)').eq(0);
	var $block = $area.find('.ccm-block-edit').eq(0);
	var steps = [{
		content: '
' + i18n[0].title + '
' + i18n[0].text + '
',
		highlightTarget: false,
		nextButton: true,
		target: $('[data-guide-toolbar-action=check-in]'),
		my: 'top left',
		at: 'bottom center',
		setup: function(tour, options) {
			ConcreteHelpGuideManager.clearGuideToLaunchOnRefresh();
		}
	},{
		content: '
' + i18n[1].title + '
' + i18n[1].text + '
',
		highlightTarget: false,
		nextButton: false,
		target: $block,
		my: 'top left',
		at: 'bottom center',
		setup: function(tour, options) {
			ConcreteEvent.subscribe('ConcreteMenuShow.changeContentEditModeTour', function(e, args) {
				tour.next();
			});
		},
		teardown: function(tour, options) {
			ConcreteEvent.unsubscribe('ConcreteMenuShow.changeContentEditModeTour');
		}
	},{
		content: '
' + i18n[2].title + '
' + i18n[2].text + '
',
		highlightTarget: false,
		nextButton: true,
		setup: function(tour, options) {
			var target = $('div#ccm-popover-menu-container div.ccm-edit-mode-block-menu').eq(0);
			return {target: target}
		},
		teardown: function() {
			var menu = ConcreteMenuManager.getActiveMenu();
			if (menu) {
				menu.hide();
			}
		},
		my: 'left center',
		at: 'right center'
	},{
		content: '
' + i18n[3].title + '
' + i18n[3].text + '
',
		highlightTarget: true,
		nextButton: true,
		target: $('[data-guide-toolbar-action=check-in]'),
		my: 'top left',
		at: 'bottom center'
	}];

	var tour = new Tourist.Tour({
		steps: steps,
		tipClass: 'Bootstrap',
		tipOptions:{
			showEffect: 'slidein'
		}
	});
	tour.on('start', function() {

	});
	tour.on('stop', function() {
		$('.ccm-dialog-help-wrapper').show();
	});

	ConcreteHelpGuideManager.register('change-content-edit-mode', tour);

}(window, jQuery);<|endoftext|>


<commit_before>var setInterval = require('timers').setInterval;
var clearInterval = require('timers').clearInterval;
var Buffer = require('buffer').Buffer;

/*
The MIT License (MIT)

Copyright (c) 2014 Voxer IP LLC. All rights reserved.

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.
*/
module.exports = PacketQueue;

/// Coalesce metrics packets.
///
/// send(buffer, offset, length)
/// options - (optional)
///   * block - Integer, maximum block size
///   * flush - Integer, millisecond flush interval
///
function PacketQueue(send, options) {
    if (!(this instanceof PacketQueue)) {
        return new PacketQueue(send, options);
    }

    options = options || {};
    this._send = send;
    this._blockSize = options.block || 1440;
    this._queue = null;
    this._writePos = null;
    this._reset();

    // Don't let stuff queue forever.
    var self = this;
    this._interval = setInterval(function() {
        if (self._queue.length) {
            self._sendPacket();
        }
    }, options.flush || 1000);
    this._interval.unref();
}

PacketQueue.prototype.destroy = function() {
    clearInterval(this._interval);
}

PacketQueue.prototype._reset = function() {
    this._queue = [];
    this._writePos = 0;
}

PacketQueue.prototype.write = function(str) {
    if (this._writePos + str.length >= this._blockSize) {
       this._sendPacket();
    }
    this._queue.push(str);
    this._writePos += str.length + 1;
}

PacketQueue.prototype._sendPacket = function() {
    var buf = new Buffer(this._queue.join('\n'));
    this._send(buf, 0, buf.length);
    this._reset();
}
<commit_msg>Add trailing new line.<commit_after>var setInterval = require('timers').setInterval;
var clearInterval = require('timers').clearInterval;
var Buffer = require('buffer').Buffer;

/*
The MIT License (MIT)

Copyright (c) 2014 Voxer IP LLC. All rights reserved.

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.
*/
module.exports = PacketQueue;

/// Coalesce metrics packets.
///
/// send(buffer, offset, length)
/// options - (optional)
///   * block - Integer, maximum block size
///   * flush - Integer, millisecond flush interval
///
function PacketQueue(send, options) {
    if (!(this instanceof PacketQueue)) {
        return new PacketQueue(send, options);
    }

    options = options || {};
    this._send = send;
    this._blockSize = options.block || 1440;
    this._queue = null;
    this._writePos = null;
    this._reset();

    // Don't let stuff queue forever.
    var self = this;
    this._interval = setInterval(function() {
        if (self._queue.length) {
            self._sendPacket();
        }
    }, options.flush || 1000);
    this._interval.unref();
}

PacketQueue.prototype.destroy = function() {
    clearInterval(this._interval);
}

PacketQueue.prototype._reset = function() {
    this._queue = [];
    this._writePos = 0;
}

PacketQueue.prototype.write = function(str) {
    if (this._writePos + str.length >= this._blockSize) {
       this._sendPacket();
    }
    this._queue.push(str);
    this._writePos += str.length + 1;
}

PacketQueue.prototype._sendPacket = function() {
    var buf = new Buffer(this._queue.join('\n') + '\n');
    this._send(buf, 0, buf.length);
    this._reset();
}
<|endoftext|>


<commit_before>var SMB = require( '../smb' )

/**
 * SMB Packet Constructor
 * @return {Packet}
 */
function Packet() {

  if( !(this instanceof Packet) )
    return new Packet()

  this.header = new Packet.Header()

}

/**
 * Packet type lookup table
 * @type {Object}
 */
Packet.type = {}
Packet.type[ SMB.COMMAND.NEGOTIATE ] = 'Negotiate'
Packet.type[ SMB.COMMAND.SESSION_SETUP ] = 'SessionSetup'
Packet.type[ SMB.COMMAND.LOGOFF ] = 'Logoff'
Packet.type[ SMB.COMMAND.TREE_CONNECT ] = 'TreeConnect'
Packet.type[ SMB.COMMAND.TREE_DISCONNECT ] = 'TreeDisconnect'
Packet.type[ SMB.COMMAND.CREATE ] = 'Create'
Packet.type[ SMB.COMMAND.CLOSE ] = 'Close'
Packet.type[ SMB.COMMAND.FLUSH ] = 'Flush'
Packet.type[ SMB.COMMAND.READ ] = 'Read'
Packet.type[ SMB.COMMAND.WRITE ] = 'Write'
Packet.type[ SMB.COMMAND.LOCK ] = 'Lock'
Packet.type[ SMB.COMMAND.IOCTL ] = 'Ioctl'
Packet.type[ SMB.COMMAND.CANCEL ] = 'Cancel'
Packet.type[ SMB.COMMAND.ECHO ] = 'Echo'
Packet.type[ SMB.COMMAND.QUERY_DIRECTORY ] = 'QueryDirectory'
Packet.type[ SMB.COMMAND.CHANGE_NOTIFY ] = 'ChangeNotify'
Packet.type[ SMB.COMMAND.QUERY_INFO ] = 'QueryInfo'
Packet.type[ SMB.COMMAND.SET_INFO ] = 'SetInfo'
Packet.type[ SMB.COMMAND.OPLOCK_BREAK ] = 'OplockBreak'

/**
 * SMB Packet Header
 * @type {Function}
 */
Packet.Header = require( './header' )

/**
 * Identifies message type (req/res) and
 * message format (NOTIFY, ERROR, ...)
 * @param  {Buffer} buffer
 * @return {[type]}
 * @todo
 */
Packet.identify = function( buffer ) {

  var command = buffer.readUInt16LE( 12 )
  var flags = buffer.readUInt32LE( 16 )
  var isResponse = flags & SMB.PACKET.SERVER_TO_REDIR

  var type = Packet.type[ command ]
  if( type == null ) return void 0

  // 'OplockBreak' and 'LeaseBreak' have the same
  // command code, which means we have to distinguish
  // between them here, also they have more types
  // than just Request/Response, which have to distinguished
  // by checking their respective 'structureSize'
  if( type === 'OplockBreak' ) {
    throw new Error( 'Not implemented' )
  }

  var subtype = isResponse ? 'Response' : 'Request'
  var Ctor = SMB.Message[ type ][ subtype ]

  return Ctor

}

/**
 * Parse a message buffer
 * @param  {Buffer}  buffer
 * @return {Packet}
 * @todo
 */
Packet.parse = function( buffer ) {

  // Identify packet / message type
  var Message = Packet.identify( buffer )
  if( typeof Message !== 'function' ) {
    throw new Error( 'Unknown packet type' )
  }

  return new Message().parse( buffer )

}

/**
 * SMB Packet Prototype
 * @type {Object}
 */
Packet.prototype = {

  constructor: Packet,

  get isAsync()     { return !!this.getFlag( SMB.PACKET.ASYNC_COMMAND ) },
  get isResponse()  { return !!this.getFlag( SMB.PACKET.SERVER_TO_REDIR ) },
  get isRequest()   { return  !this.getFlag( SMB.PACKET.SERVER_TO_REDIR ) },
  get isCompound()  { return !!this.getFlag( SMB.PACKET.RELATED_OPERATIONS ) },
  get isSigned()    { return !!this.getFlag( SMB.PACKET.SIGNED ) },
  get isReplay()    { return !!this.getFlag( SMB.PACKET.REPLAY_OPERATION ) },

  getFlag: function( flag ) {
    return this.header.flags & flag
  },

  setFlag: function( flag ) {
    this.header.flags = this.header.flags | flag
  },

  parse: function( buffer ) {
    this.parseHeader( buffer )
    this.parsePayload(
      buffer.slice( this.header.structureSize )
    )
  },

  parseHeader: function( buffer ) {
    this.header.parse( buffer )
    return this
  },

  parsePayload: function( buffer ) {
    throw new Error( 'Not implemented' )
  },

  serialize: function() {
    throw new Error( 'Not implemented' )
  },

  toBuffer: function() {
    return Buffer.concat([
      this.header.toBuffer(),
      this.serialize()
    ])
  },

}

// Exports
module.exports = Packet
<commit_msg>Updated lib/packet: Added debug log msgs<commit_after>var SMB = require( '../smb' )
var log = require( 'debug' )( 'SMB:PACKET' )

/**
 * SMB Packet Constructor
 * @return {Packet}
 */
function Packet() {

  if( !(this instanceof Packet) )
    return new Packet()

  this.header = new Packet.Header()

}

/**
 * Packet type lookup table
 * @type {Object}
 */
Packet.type = {}
Packet.type[ SMB.COMMAND.NEGOTIATE ] = 'Negotiate'
Packet.type[ SMB.COMMAND.SESSION_SETUP ] = 'SessionSetup'
Packet.type[ SMB.COMMAND.LOGOFF ] = 'Logoff'
Packet.type[ SMB.COMMAND.TREE_CONNECT ] = 'TreeConnect'
Packet.type[ SMB.COMMAND.TREE_DISCONNECT ] = 'TreeDisconnect'
Packet.type[ SMB.COMMAND.CREATE ] = 'Create'
Packet.type[ SMB.COMMAND.CLOSE ] = 'Close'
Packet.type[ SMB.COMMAND.FLUSH ] = 'Flush'
Packet.type[ SMB.COMMAND.READ ] = 'Read'
Packet.type[ SMB.COMMAND.WRITE ] = 'Write'
Packet.type[ SMB.COMMAND.LOCK ] = 'Lock'
Packet.type[ SMB.COMMAND.IOCTL ] = 'Ioctl'
Packet.type[ SMB.COMMAND.CANCEL ] = 'Cancel'
Packet.type[ SMB.COMMAND.ECHO ] = 'Echo'
Packet.type[ SMB.COMMAND.QUERY_DIRECTORY ] = 'QueryDirectory'
Packet.type[ SMB.COMMAND.CHANGE_NOTIFY ] = 'ChangeNotify'
Packet.type[ SMB.COMMAND.QUERY_INFO ] = 'QueryInfo'
Packet.type[ SMB.COMMAND.SET_INFO ] = 'SetInfo'
Packet.type[ SMB.COMMAND.OPLOCK_BREAK ] = 'OplockBreak'

/**
 * SMB Packet Header
 * @type {Function}
 */
Packet.Header = require( './header' )

/**
 * Identifies message type (req/res) and
 * message format (NOTIFY, ERROR, ...)
 * @param  {Buffer} buffer
 * @return {[type]}
 * @todo
 */
Packet.identify = function( buffer ) {

  var command = buffer.readUInt16LE( 12 )
  var flags = buffer.readUInt32LE( 16 )
  var isResponse = flags & SMB.PACKET.SERVER_TO_REDIR

  log( 'identifying', command.toString( 16 ), 'with', flags.toString( 2 ) )
  log( 'isResponse', isResponse )

  var type = Packet.type[ command ]
  if( type == null ) return void 0

  // 'OplockBreak' and 'LeaseBreak' have the same
  // command code, which means we have to distinguish
  // between them here, also they have more types
  // than just Request/Response, which have to distinguished
  // by checking their respective 'structureSize'
  if( type === 'OplockBreak' ) {
    throw new Error( 'Not implemented' )
  }

  var subtype = isResponse ? 'Response' : 'Request'
  var Ctor = SMB.Message[ type ][ subtype ]

  return Ctor

}

/**
 * Parse a message buffer
 * @param  {Buffer}  buffer
 * @return {Packet}
 * @todo
 */
Packet.parse = function( buffer ) {

  // Identify packet / message type
  var Message = Packet.identify( buffer )
  if( typeof Message !== 'function' ) {
    throw new Error( 'Unknown packet type' )
  }

  return new Message().parse( buffer )

}

/**
 * SMB Packet Prototype
 * @type {Object}
 */
Packet.prototype = {

  constructor: Packet,

  get isAsync()     { return !!this.getFlag( SMB.PACKET.ASYNC_COMMAND ) },
  get isResponse()  { return !!this.getFlag( SMB.PACKET.SERVER_TO_REDIR ) },
  get isRequest()   { return  !this.getFlag( SMB.PACKET.SERVER_TO_REDIR ) },
  get isCompound()  { return !!this.getFlag( SMB.PACKET.RELATED_OPERATIONS ) },
  get isSigned()    { return !!this.getFlag( SMB.PACKET.SIGNED ) },
  get isReplay()    { return !!this.getFlag( SMB.PACKET.REPLAY_OPERATION ) },

  getFlag: function( flag ) {
    return this.header.flags & flag
  },

  setFlag: function( flag ) {
    this.header.flags = this.header.flags | flag
  },

  parse: function( buffer ) {
    this.parseHeader( buffer )
    this.parsePayload(
      buffer.slice( this.header.structureSize )
    )
  },

  parseHeader: function( buffer ) {
    this.header.parse( buffer )
    return this
  },

  parsePayload: function( buffer ) {
    throw new Error( 'Not implemented' )
  },

  serialize: function() {
    throw new Error( 'Not implemented' )
  },

  toBuffer: function() {
    return Buffer.concat([
      this.header.toBuffer(),
      this.serialize()
    ])
  },

}

// Exports
module.exports = Packet
<|endoftext|>


<commit_before>import $ from 'jquery';
import logger from './helpers/logger';

/*
 * plugin constructor
 */
export default function BindInput( params ) {

    var element = params.element,
        options = params.options || {},
        loggerObj = params.loggerObj || logger();

    if ( typeof element === 'undefined' ) {
        return;
    }

    this.element$ = $(element);
    this.options = options;
    this.loggerObj = loggerObj;

    this.init();
}

/*
 * plugin prototype
 * init
 */
BindInput.prototype.init = function () {
    /*
     * receiver field is mandatory
     */
    if ( ! this.options.receiver ) {
        this.loggerObj.log('You must bind an input to some other receiver in options');
        return false;
    }

    this
        .setReceiver()
        .setListeners();

    return this;
};
/*
 * setting receiver
 */
BindInput.prototype.setReceiver = function() {

    this.receiver$ = this.options.receiver instanceof $ ?
                            this.options.receiver :
                            $(this.options.receiver);

    return this;
};
/*
 * setting field listeners
 */
BindInput.prototype.setListeners = function() {

    $(document).ready( $.proxy(this.matchFields, this) );
    /*
     * and for every change
     */
    this.element$.on( 'change', $.proxy(this.matchFields, this) );
};
/**
 *
 */
BindInput.prototype.matchFields = function() {

    if ( ! this.receiver$ ) {
       return this;
    }
    /*
     * set the same option on receiver
     */
    var value = this.element$.val();
    this.receiver$.val( value );

    if ( this.element$.val() !== this.receiver$.val() ) {
        // fallback to text if option not found
        let receiverOption$ = this.receiver$.find('option').filter(
            function findCurrentOption() {
                return $(this).text() === value;
            }
        );
        receiverOption$.prop('selected', true);
    }

    return this;
};<commit_msg>use destructuring for the constructor params<commit_after>import $ from 'jquery';
import logger from './helpers/logger';

/*
 * plugin constructor
 */
export default function BindInput( params ) {

    var {element, options, loggerObj} = params;

    if ( typeof element === 'undefined' ) {
        return;
    }

    options = options || {};
    loggerObj = loggerObj || logger();

    this.element$ = $(element);
    this.options = options;
    this.loggerObj = loggerObj;

    this.init();
}

/*
 * plugin prototype
 * init
 */
BindInput.prototype.init = function () {
    /*
     * receiver field is mandatory
     */
    if ( ! this.options.receiver ) {
        this.loggerObj.log('You must bind an input to some other receiver in options');
        return false;
    }

    this
        .setReceiver()
        .setListeners();

    return this;
};
/*
 * setting receiver
 */
BindInput.prototype.setReceiver = function() {

    this.receiver$ = this.options.receiver instanceof $ ?
                            this.options.receiver :
                            $(this.options.receiver);

    return this;
};
/*
 * setting field listeners
 */
BindInput.prototype.setListeners = function() {

    $(document).ready( $.proxy(this.matchFields, this) );
    /*
     * and for every change
     */
    this.element$.on( 'change', $.proxy(this.matchFields, this) );
};
/**
 *
 */
BindInput.prototype.matchFields = function() {

    if ( ! this.receiver$ ) {
       return this;
    }
    /*
     * set the same option on receiver
     */
    var value = this.element$.val();
    this.receiver$.val( value );

    if ( this.element$.val() !== this.receiver$.val() ) {
        // fallback to text if option not found
        let receiverOption$ = this.receiver$.find('option').filter(
            function findCurrentOption() {
                return $(this).text() === value;
            }
        );
        receiverOption$.prop('selected', true);
    }

    return this;
};<|endoftext|>


<commit_before>/*jshint strict:false, undef:false, unused:false */

var onCut = function ( event ) {
    var clipboardData = event.clipboardData;
    var range = this.getSelection();
    var node = this.createElement( 'div' );
    var body = this._body;
    var self = this;

    // Save undo checkpoint
    this.saveUndoState( range );

    // Edge only seems to support setting plain text as of 2016-03-11.
    if ( !isEdge && clipboardData ) {
        moveRangeBoundariesUpTree( range, body );
        node.appendChild( deleteContentsOfRange( range, body ) );
        clipboardData.setData( 'text/html', node.innerHTML );
        event.preventDefault();
    } else {
        setTimeout( function () {
            try {
                // If all content removed, ensure div at start of body.
                self._ensureBottomLine();
            } catch ( error ) {
                self.didError( error );
            }
        }, 0 );
    }

    this.setSelection( range );
};

var onCopy = function ( event ) {
    var clipboardData = event.clipboardData;
    var range = this.getSelection();
    var node = this.createElement( 'div' );

    // Edge only seems to support setting plain text as of 2016-03-11.
    if ( !isEdge && clipboardData ) {
        node.appendChild( range.cloneContents() );
        clipboardData.setData( 'text/html', node.innerHTML );
        event.preventDefault();
    }
};

var onPaste = function ( event ) {
    var clipboardData = event.clipboardData,
        items = clipboardData && clipboardData.items,
        fireDrop = false,
        hasImage = false,
        plainItem = null,
        self = this,
        l, item, type, types, data;

    // Current HTML5 Clipboard interface
    // ---------------------------------
    // https://html.spec.whatwg.org/multipage/interaction.html

    // Edge only provides access to plain text as of 2016-03-11.
    if ( !isEdge && items ) {
        event.preventDefault();
        l = items.length;
        while ( l-- ) {
            item = items[l];
            type = item.type;
            if ( type === 'text/html' ) {
                /*jshint loopfunc: true */
                item.getAsString( function ( html ) {
                    self.insertHTML( html, true );
                });
                /*jshint loopfunc: false */
                return;
            }
            if ( type === 'text/plain' ) {
                plainItem = item;
            }
            if ( /^image\/.*/.test( type ) ) {
                hasImage = true;
            }
        }
        // Treat image paste as a drop of an image file.
        if ( hasImage ) {
            this.fireEvent( 'dragover', {
                dataTransfer: clipboardData,
                /*jshint loopfunc: true */
                preventDefault: function () {
                    fireDrop = true;
                }
                /*jshint loopfunc: false */
            });
            if ( fireDrop ) {
                this.fireEvent( 'drop', {
                    dataTransfer: clipboardData
                });
            }
        } else if ( plainItem ) {
            item.getAsString( function ( text ) {
                self.insertPlainText( text, true );
            });
        }
        return;
    }

    // Old interface
    // -------------

    // Safari (and indeed many other OS X apps) copies stuff as text/rtf
    // rather than text/html; even from a webpage in Safari. The only way
    // to get an HTML version is to fallback to letting the browser insert
    // the content. Same for getting image data. *Sigh*.
    //
    // Firefox is even worse: it doesn't even let you know that there might be
    // an RTF version on the clipboard, but it will also convert to HTML if you
    // let the browser insert the content. I've filed
    // https://bugzilla.mozilla.org/show_bug.cgi?id=1254028
    types = clipboardData && clipboardData.types;
    if ( !isEdge && types && (
            indexOf.call( types, 'text/html' ) > -1 || (
                !isGecko &&
                indexOf.call( types, 'text/plain' ) > -1 &&
                indexOf.call( types, 'text/rtf' ) < 0 )
            )) {
        event.preventDefault();
        // Abiword on Linux copies a plain text and html version, but the HTML
        // version is the empty string! So always try to get HTML, but if none,
        // insert plain text instead.
        if (( data = clipboardData.getData( 'text/html' ) )) {
            this.insertHTML( data, true );
        } else if (( data = clipboardData.getData( 'text/plain' ) )) {
            this.insertPlainText( data, true );
        }
        return;
    }

    // No interface. Includes all versions of IE :(
    // --------------------------------------------

    this._awaitingPaste = true;

    var body = this._body,
        range = this.getSelection(),
        startContainer = range.startContainer,
        startOffset = range.startOffset,
        endContainer = range.endContainer,
        endOffset = range.endOffset,
        startBlock = getStartBlockOfRange( range );

    // We need to position the pasteArea in the visible portion of the screen
    // to stop the browser auto-scrolling.
    var pasteArea = this.createElement( 'DIV', {
        style: 'position: absolute; overflow: hidden; top:' +
            ( body.scrollTop +
                ( startBlock ? startBlock.getBoundingClientRect().top : 0 ) ) +
            'px; right: 150%; width: 1px; height: 1px;'
    });
    body.appendChild( pasteArea );
    range.selectNodeContents( pasteArea );
    this.setSelection( range );

    // A setTimeout of 0 means this is added to the back of the
    // single javascript thread, so it will be executed after the
    // paste event.
    setTimeout( function () {
        try {
            // IE sometimes fires the beforepaste event twice; make sure it is
            // not run again before our after paste function is called.
            self._awaitingPaste = false;

            // Get the pasted content and clean
            var html = '',
                next = pasteArea,
                first, range;

            // #88: Chrome can apparently split the paste area if certain
            // content is inserted; gather them all up.
            while ( pasteArea = next ) {
                next = pasteArea.nextSibling;
                detach( pasteArea );
                // Safari and IE like putting extra divs around things.
                first = pasteArea.firstChild;
                if ( first && first === pasteArea.lastChild &&
                        first.nodeName === 'DIV' ) {
                    pasteArea = first;
                }
                html += pasteArea.innerHTML;
            }

            range = self._createRange(
                startContainer, startOffset, endContainer, endOffset );
            self.setSelection( range );

            if ( html ) {
                self.insertHTML( html, true );
            }
        } catch ( error ) {
            self.didError( error );
        }
    }, 0 );
};
<commit_msg>Set a plain text version too on cut/copy<commit_after>/*jshint strict:false, undef:false, unused:false */

var onCut = function ( event ) {
    var clipboardData = event.clipboardData;
    var range = this.getSelection();
    var node = this.createElement( 'div' );
    var body = this._body;
    var self = this;

    // Save undo checkpoint
    this.saveUndoState( range );

    // Edge only seems to support setting plain text as of 2016-03-11.
    if ( !isEdge && clipboardData ) {
        moveRangeBoundariesUpTree( range, body );
        node.appendChild( deleteContentsOfRange( range, body ) );
        clipboardData.setData( 'text/html', node.innerHTML );
        clipboard.setData( 'text/plain', node.innerText || node.textContent );
        event.preventDefault();
    } else {
        setTimeout( function () {
            try {
                // If all content removed, ensure div at start of body.
                self._ensureBottomLine();
            } catch ( error ) {
                self.didError( error );
            }
        }, 0 );
    }

    this.setSelection( range );
};

var onCopy = function ( event ) {
    var clipboardData = event.clipboardData;
    var range = this.getSelection();
    var node = this.createElement( 'div' );

    // Edge only seems to support setting plain text as of 2016-03-11.
    if ( !isEdge && clipboardData ) {
        node.appendChild( range.cloneContents() );
        clipboardData.setData( 'text/html', node.innerHTML );
        clipboard.setData( 'text/plain', node.innerText || node.textContent );
        event.preventDefault();
    }
};

var onPaste = function ( event ) {
    var clipboardData = event.clipboardData,
        items = clipboardData && clipboardData.items,
        fireDrop = false,
        hasImage = false,
        plainItem = null,
        self = this,
        l, item, type, types, data;

    // Current HTML5 Clipboard interface
    // ---------------------------------
    // https://html.spec.whatwg.org/multipage/interaction.html

    // Edge only provides access to plain text as of 2016-03-11.
    if ( !isEdge && items ) {
        event.preventDefault();
        l = items.length;
        while ( l-- ) {
            item = items[l];
            type = item.type;
            if ( type === 'text/html' ) {
                /*jshint loopfunc: true */
                item.getAsString( function ( html ) {
                    self.insertHTML( html, true );
                });
                /*jshint loopfunc: false */
                return;
            }
            if ( type === 'text/plain' ) {
                plainItem = item;
            }
            if ( /^image\/.*/.test( type ) ) {
                hasImage = true;
            }
        }
        // Treat image paste as a drop of an image file.
        if ( hasImage ) {
            this.fireEvent( 'dragover', {
                dataTransfer: clipboardData,
                /*jshint loopfunc: true */
                preventDefault: function () {
                    fireDrop = true;
                }
                /*jshint loopfunc: false */
            });
            if ( fireDrop ) {
                this.fireEvent( 'drop', {
                    dataTransfer: clipboardData
                });
            }
        } else if ( plainItem ) {
            item.getAsString( function ( text ) {
                self.insertPlainText( text, true );
            });
        }
        return;
    }

    // Old interface
    // -------------

    // Safari (and indeed many other OS X apps) copies stuff as text/rtf
    // rather than text/html; even from a webpage in Safari. The only way
    // to get an HTML version is to fallback to letting the browser insert
    // the content. Same for getting image data. *Sigh*.
    //
    // Firefox is even worse: it doesn't even let you know that there might be
    // an RTF version on the clipboard, but it will also convert to HTML if you
    // let the browser insert the content. I've filed
    // https://bugzilla.mozilla.org/show_bug.cgi?id=1254028
    types = clipboardData && clipboardData.types;
    if ( !isEdge && types && (
            indexOf.call( types, 'text/html' ) > -1 || (
                !isGecko &&
                indexOf.call( types, 'text/plain' ) > -1 &&
                indexOf.call( types, 'text/rtf' ) < 0 )
            )) {
        event.preventDefault();
        // Abiword on Linux copies a plain text and html version, but the HTML
        // version is the empty string! So always try to get HTML, but if none,
        // insert plain text instead.
        if (( data = clipboardData.getData( 'text/html' ) )) {
            this.insertHTML( data, true );
        } else if (( data = clipboardData.getData( 'text/plain' ) )) {
            this.insertPlainText( data, true );
        }
        return;
    }

    // No interface. Includes all versions of IE :(
    // --------------------------------------------

    this._awaitingPaste = true;

    var body = this._body,
        range = this.getSelection(),
        startContainer = range.startContainer,
        startOffset = range.startOffset,
        endContainer = range.endContainer,
        endOffset = range.endOffset,
        startBlock = getStartBlockOfRange( range );

    // We need to position the pasteArea in the visible portion of the screen
    // to stop the browser auto-scrolling.
    var pasteArea = this.createElement( 'DIV', {
        style: 'position: absolute; overflow: hidden; top:' +
            ( body.scrollTop +
                ( startBlock ? startBlock.getBoundingClientRect().top : 0 ) ) +
            'px; right: 150%; width: 1px; height: 1px;'
    });
    body.appendChild( pasteArea );
    range.selectNodeContents( pasteArea );
    this.setSelection( range );

    // A setTimeout of 0 means this is added to the back of the
    // single javascript thread, so it will be executed after the
    // paste event.
    setTimeout( function () {
        try {
            // IE sometimes fires the beforepaste event twice; make sure it is
            // not run again before our after paste function is called.
            self._awaitingPaste = false;

            // Get the pasted content and clean
            var html = '',
                next = pasteArea,
                first, range;

            // #88: Chrome can apparently split the paste area if certain
            // content is inserted; gather them all up.
            while ( pasteArea = next ) {
                next = pasteArea.nextSibling;
                detach( pasteArea );
                // Safari and IE like putting extra divs around things.
                first = pasteArea.firstChild;
                if ( first && first === pasteArea.lastChild &&
                        first.nodeName === 'DIV' ) {
                    pasteArea = first;
                }
                html += pasteArea.innerHTML;
            }

            range = self._createRange(
                startContainer, startOffset, endContainer, endOffset );
            self.setSelection( range );

            if ( html ) {
                self.insertHTML( html, true );
            }
        } catch ( error ) {
            self.didError( error );
        }
    }, 0 );
};
<|endoftext|>


<commit_before>/**
 * This class represents the bounding box of a Body.
 */
define(["physics/vector2"], function(Vector2) {
	var Invalid = true;
	var Valid = false;

	var AABB = function(minPt, maxPt) {
		this.Min = minPt || Vector2.Zero.copy();
		this.Max = maxPt || Vector2.Zero.copy();
		this.Validity = typeof minPt === "undefined" ? Invalid : Valid;
	};

	AABB.prototype.clear = function() {
		this.Min.set(Vector2.Zero);
		this.Max.set(Vector2.Zero);
		this.Validity = Invalid;
	};

	AABB.prototype.expandToInclude = function(pt) {
		if (this.Validity == Valid) {
			if (pt.x < this.Min.x) {
				this.Min.x = pt.x;
			} else if (pt.x > this.Max.x) {
				this.Max.x = pt.x;
			}

			if (pt.y < this.Min.y) {
				this.Min.y = pt.y;
			} else if (pt.y > this.Max.y) {
				this.Max.y = pt.y;
			}
		} else {
			this.Min.set(pt);
			this.Max.set(pt);
			this.Validity = Valid;
		};
	};

	AABB.prototype.contains = function(pt) {
		if (this.Validity == Invalid) { return false; };

		return ((pt.x >= this.Min.x) && (pt.x <= this.Max.x) && (pt.y >= this.Min.y) && (pt.y <= this.Max.y));
	};

	AABB.prototype.containsAABB = function(other) {
		if (this.Validity == Invalid) { return false; };
		if (other.Validity == Invalid) { return false; };

		return (other.Min.x >= this.Min.x) &&
			(other.Max.x <= this.Max.x) &&
			(other.Min.y >= this.Min.y) &&
			(other.Max.y <= this.Max.y);
	};

	AABB.prototype.intersects = function(box) {
			var overlapX = ((this.Min.x <= box.Max.x) && (this.Max.x >= box.Min.x));
			var overlapY = ((this.Min.y <= box.Max.y) && (this.Max.y >= box.Min.y));

			return (overlapX && overlapY);
	};

	AABB.prototype.getSize = function() { return this.Max.sub(this.Min); };

	AABB.prototype.getMiddle = function() {
		return this.Min.add(this.Max.sub(this.Min).mulFloat(0.5));
	};
	AABB.prototype.getTopLeft = function() {
		return this.Min;
	};
	AABB.prototype.getTopRight = function() {
		return new Vector2(this.Max.x, this.Min.y);
	};
	AABB.prototype.getBottomLeft = function() {
		return new Vector2(this.Min.x, this.Max.y);
	};
	AABB.prototype.getBottomRight = function() {
		return this.Max;
	};
	AABB.prototype.subdivide = function() {
		var min = this.Min,
			middle = this.getMiddle(),
			max = this.Max;

		var i = new AABB(min, middle);
		return [
		    new AABB(min, middle),
		    new AABB(new Vector2(middle.x, min.y), new Vector2(max.x, middle.y)),
		    new AABB(new Vector2(min.x, middle.y), new Vector2(middle.x, max.y)),
		    new AABB(middle, max)
		];
	};

	AABB.prototype.debugDraw = function(debugDraw) {
		debugDraw.drawPolyline([
				this.Min,
				new Vector2(this.Min.x, this.Max.y),
				this.Max,
				new Vector2(this.Max.x, this.Min.y),
				this.Min
			],
			"red",
			1.0,
			1
		);
	};

	return AABB;
});
<commit_msg>copyright test aabb<commit_after>/**
 * This class represents the bounding box of a Body.
 *
 */
define(["physics/vector2"], function(Vector2) {
	var Invalid = true;
	var Valid = false;

	var AABB = function(minPt, maxPt) {
		this.Min = minPt || Vector2.Zero.copy();
		this.Max = maxPt || Vector2.Zero.copy();
		this.Validity = typeof minPt === "undefined" ? Invalid : Valid;
	};

	AABB.prototype.clear = function() {
		this.Min.set(Vector2.Zero);
		this.Max.set(Vector2.Zero);
		this.Validity = Invalid;
	};

	AABB.prototype.expandToInclude = function(pt) {
		if (this.Validity == Valid) {
			if (pt.x < this.Min.x) {
				this.Min.x = pt.x;
			} else if (pt.x > this.Max.x) {
				this.Max.x = pt.x;
			}

			if (pt.y < this.Min.y) {
				this.Min.y = pt.y;
			} else if (pt.y > this.Max.y) {
				this.Max.y = pt.y;
			}
		} else {
			this.Min.set(pt);
			this.Max.set(pt);
			this.Validity = Valid;
		};
	};

	AABB.prototype.contains = function(pt) {
		if (this.Validity == Invalid) { return false; };

		return ((pt.x >= this.Min.x) && (pt.x <= this.Max.x) && (pt.y >= this.Min.y) && (pt.y <= this.Max.y));
	};

	AABB.prototype.containsAABB = function(other) {
		if (this.Validity == Invalid) { return false; };
		if (other.Validity == Invalid) { return false; };

		return (other.Min.x >= this.Min.x) &&
			(other.Max.x <= this.Max.x) &&
			(other.Min.y >= this.Min.y) &&
			(other.Max.y <= this.Max.y);
	};

	AABB.prototype.intersects = function(box) {
			var overlapX = ((this.Min.x <= box.Max.x) && (this.Max.x >= box.Min.x));
			var overlapY = ((this.Min.y <= box.Max.y) && (this.Max.y >= box.Min.y));

			return (overlapX && overlapY);
	};

	AABB.prototype.getSize = function() { return this.Max.sub(this.Min); };

	AABB.prototype.getMiddle = function() {
		return this.Min.add(this.Max.sub(this.Min).mulFloat(0.5));
	};
	AABB.prototype.getTopLeft = function() {
		return this.Min;
	};
	AABB.prototype.getTopRight = function() {
		return new Vector2(this.Max.x, this.Min.y);
	};
	AABB.prototype.getBottomLeft = function() {
		return new Vector2(this.Min.x, this.Max.y);
	};
	AABB.prototype.getBottomRight = function() {
		return this.Max;
	};
	AABB.prototype.subdivide = function() {
		var min = this.Min,
			middle = this.getMiddle(),
			max = this.Max;

		var i = new AABB(min, middle);
		return [
		    new AABB(min, middle),
		    new AABB(new Vector2(middle.x, min.y), new Vector2(max.x, middle.y)),
		    new AABB(new Vector2(min.x, middle.y), new Vector2(middle.x, max.y)),
		    new AABB(middle, max)
		];
	};

	AABB.prototype.debugDraw = function(debugDraw) {
		debugDraw.drawPolyline([
				this.Min,
				new Vector2(this.Min.x, this.Max.y),
				this.Max,
				new Vector2(this.Max.x, this.Min.y),
				this.Min
			],
			"red",
			1.0,
			1
		);
	};

	return AABB;
});
<|endoftext|>


<commit_before>var mozilla = require('source-map');
var Base64  = require('js-base64').Base64;
var path    = require('path');
var fs      = require('fs');

// Detect previous map
class PreviousMap {
    constructor(root, opts, id) {
        this.file = opts.from || id;

        this.loadAnnotation(root);
        var inlinePrefix = '# sourceMappingURL=data:';
        this.inline = this.startWith(this.annotation, inlinePrefix);

        var text = this.loadMap(opts.map ? opts.map.prev : undefined);
        if ( text ) this.text = text;
    }

    // Return SourceMapConsumer object to read map
    consumer() {
        if ( !this.consumerCache ) {
            this.consumerCache = new mozilla.SourceMapConsumer(this.text);
        }
        return this.consumerCache;
    }

    // Is map has sources content
    withContent() {
        return !!(this.consumer().sourcesContent &&
                  this.consumer().sourcesContent.length > 0);
    }

    // Is `string` is starting with `start`
    startWith(string, start) {
        if ( !string ) return false;
        return string.substr(0, start.length) == start;
    }

    // Load for annotation comment from previous compilation step
    loadAnnotation(root) {
        var last = root.last;
        if ( !last ) return;
        if ( last.type != 'comment' ) return;

        if ( this.startWith(last.text, '# sourceMappingURL=') ) {
            this.annotation = last.text;
        }
    }

    // Encode different type of inline
    decodeInline(text) {
        var uri    = '# sourceMappingURL=data:application/json,';
        var base64 = '# sourceMappingURL=data:application/json;base64,';

        if ( this.startWith(text, uri) ) {
            return decodeURIComponent( text.substr(uri.length) );

        } else if ( this.startWith(text, base64) ) {
            return Base64.decode( text.substr(base64.length) );

        } else {
            var encoding = text.match(/ata:application\/json;([^,]+),/)[1];
            throw new Error('Unsupported source map encoding ' + encoding);
        }
    }

    // Load previous map
    loadMap(prev) {
        if ( prev === false ) return;

        if ( prev ) {
            if ( typeof(prev) == 'string' ) {
                return prev;
            } else if ( prev instanceof mozilla.SourceMapConsumer ) {
                return mozilla.SourceMapGenerator
                    .fromSourceMap(prev).toString();
            } else if ( prev instanceof mozilla.SourceMapGenerator ) {
                return prev.toString();
            } else if ( typeof(prev) == 'object' && prev.mappings ) {
                return JSON.stringify(prev);
            } else {
                throw new Error('Unsupported previous source map format: ' +
                    prev.toString());
            }

        } else if ( this.inline ) {
            return this.decodeInline(this.annotation);

        } else if ( this.annotation ) {
            var map = this.annotation.replace('# sourceMappingURL=', '');
            if ( this.file ) map = path.join(path.dirname(this.file), map);

            this.root = path.dirname(map);
            if ( fs.existsSync && fs.existsSync(map) ) {
                return fs.readFileSync(map, 'utf-8').toString();
            }
        }
    }
}

module.exports = PreviousMap;
<commit_msg>Trim UTF-8 BOM marker<commit_after>var mozilla = require('source-map');
var Base64  = require('js-base64').Base64;
var path    = require('path');
var fs      = require('fs');

// Detect previous map
class PreviousMap {
    constructor(root, opts, id) {
        this.file = opts.from || id;

        this.loadAnnotation(root);
        var inlinePrefix = '# sourceMappingURL=data:';
        this.inline = this.startWith(this.annotation, inlinePrefix);

        var text = this.loadMap(opts.map ? opts.map.prev : undefined);
        if ( text ) this.text = text;
    }

    // Return SourceMapConsumer object to read map
    consumer() {
        if ( !this.consumerCache ) {
            this.consumerCache = new mozilla.SourceMapConsumer(this.text);
        }
        return this.consumerCache;
    }

    // Is map has sources content
    withContent() {
        return !!(this.consumer().sourcesContent &&
                  this.consumer().sourcesContent.length > 0);
    }

    // Is `string` is starting with `start`
    startWith(string, start) {
        if ( !string ) return false;
        return string.substr(0, start.length) == start;
    }

    // Load for annotation comment from previous compilation step
    loadAnnotation(root) {
        var last = root.last;
        if ( !last ) return;
        if ( last.type != 'comment' ) return;

        if ( this.startWith(last.text, '# sourceMappingURL=') ) {
            this.annotation = last.text;
        }
    }

    // Encode different type of inline
    decodeInline(text) {
        var uri    = '# sourceMappingURL=data:application/json,';
        var base64 = '# sourceMappingURL=data:application/json;base64,';

        if ( this.startWith(text, uri) ) {
            return decodeURIComponent( text.substr(uri.length) );

        } else if ( this.startWith(text, base64) ) {
            return Base64.decode( text.substr(base64.length) );

        } else {
            var encoding = text.match(/ata:application\/json;([^,]+),/)[1];
            throw new Error('Unsupported source map encoding ' + encoding);
        }
    }

    // Load previous map
    loadMap(prev) {
        if ( prev === false ) return;

        if ( prev ) {
            if ( typeof(prev) == 'string' ) {
                return prev;
            } else if ( prev instanceof mozilla.SourceMapConsumer ) {
                return mozilla.SourceMapGenerator
                    .fromSourceMap(prev).toString();
            } else if ( prev instanceof mozilla.SourceMapGenerator ) {
                return prev.toString();
            } else if ( typeof(prev) == 'object' && prev.mappings ) {
                return JSON.stringify(prev);
            } else {
                throw new Error('Unsupported previous source map format: ' +
                    prev.toString());
            }

        } else if ( this.inline ) {
            return this.decodeInline(this.annotation);

        } else if ( this.annotation ) {
            var map = this.annotation.replace('# sourceMappingURL=', '');
            if ( this.file ) map = path.join(path.dirname(this.file), map);

            this.root = path.dirname(map);
            if ( fs.existsSync && fs.existsSync(map) ) {
                return fs.readFileSync(map, 'utf-8').toString().trim();
            }
        }
    }
}

module.exports = PreviousMap;
<|endoftext|>


<commit_before>import Ember from 'ember';
var SettingsAboutController = Ember.Controller.extend({
    updateNotificationCount: 0,

    actions: {
       updateNotificationChange: function (count) {
            this.set('updateNotificationCount', count);
        }
    }
});

export default SettingsAboutController;
<commit_msg>Fixing lint error causing build to fail<commit_after>import Ember from 'ember';
var SettingsAboutController = Ember.Controller.extend({
    updateNotificationCount: 0,

    actions: {
        updateNotificationChange: function (count) {
            this.set('updateNotificationCount', count);
        }
    }
});

export default SettingsAboutController;
<|endoftext|>