mirror of
https://github.com/moparisthebest/kaiwa
synced 2025-02-16 15:10:11 -05:00
19812 lines
577 KiB
JavaScript
19812 lines
577 KiB
JavaScript
(function(e){if("function"==typeof bootstrap)bootstrap("xmpp",e);else if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else if("undefined"!=typeof ses){if(!ses.ok())return;ses.makeXMPP=e}else"undefined"!=typeof window?window.XMPP=e():global.XMPP=e()})(function(){var define,ses,bootstrap,module,exports;
|
|
return (function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require=="function"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error("Cannot find module '"+n+"'")}var u=t[n]={exports:{}};e[n][0].call(u.exports,function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require=="function"&&require;for(var s=0;s<n.length;s++)i(n[s]);return i})({1:[function(require,module,exports){
|
|
exports.Message = require('./lib/stanza/message');
|
|
exports.Presence = require('./lib/stanza/presence');
|
|
exports.Iq = require('./lib/stanza/iq');
|
|
|
|
exports.Client = require('./lib/client');
|
|
exports.crypto = require('crypto');
|
|
|
|
exports.createClient = function (opts) {
|
|
var client = new exports.Client(opts);
|
|
|
|
client.use(require('./lib/plugins/disco'));
|
|
client.use(require('./lib/plugins/chatstates'));
|
|
client.use(require('./lib/plugins/delayed'));
|
|
client.use(require('./lib/plugins/forwarding'));
|
|
client.use(require('./lib/plugins/carbons'));
|
|
client.use(require('./lib/plugins/time'));
|
|
client.use(require('./lib/plugins/mam'));
|
|
client.use(require('./lib/plugins/receipts'));
|
|
client.use(require('./lib/plugins/idle'));
|
|
client.use(require('./lib/plugins/correction'));
|
|
client.use(require('./lib/plugins/attention'));
|
|
client.use(require('./lib/plugins/version'));
|
|
client.use(require('./lib/plugins/invisible'));
|
|
client.use(require('./lib/plugins/muc'));
|
|
client.use(require('./lib/plugins/webrtc'));
|
|
client.use(require('./lib/plugins/pubsub'));
|
|
client.use(require('./lib/plugins/avatar'));
|
|
|
|
return client;
|
|
};
|
|
|
|
},{"./lib/client":2,"./lib/plugins/attention":3,"./lib/plugins/avatar":4,"./lib/plugins/carbons":5,"./lib/plugins/chatstates":6,"./lib/plugins/correction":7,"./lib/plugins/delayed":8,"./lib/plugins/disco":9,"./lib/plugins/forwarding":10,"./lib/plugins/idle":11,"./lib/plugins/invisible":12,"./lib/plugins/mam":13,"./lib/plugins/muc":14,"./lib/plugins/pubsub":15,"./lib/plugins/receipts":16,"./lib/plugins/time":17,"./lib/plugins/version":18,"./lib/plugins/webrtc":19,"./lib/stanza/iq":33,"./lib/stanza/message":35,"./lib/stanza/presence":37,"crypto":60}],2:[function(require,module,exports){
|
|
var WildEmitter = require('wildemitter');
|
|
var _ = require('../vendor/lodash');
|
|
var async = require('async');
|
|
var uuid = require('node-uuid');
|
|
var SASL = require('./stanza/sasl');
|
|
var Message = require('./stanza/message');
|
|
var Presence = require('./stanza/presence');
|
|
var Iq = require('./stanza/iq');
|
|
var WSConnection = require('./websocket');
|
|
var getHostMeta = require('hostmeta');
|
|
var SASLFactory = require('saslmechanisms');
|
|
|
|
SASLFactory = new SASLFactory();
|
|
SASLFactory.use(require('sasl-external'));
|
|
SASLFactory.use(require('sasl-scram-sha-1'));
|
|
SASLFactory.use(require('sasl-digest-md5'));
|
|
SASLFactory.use(require('sasl-plain'));
|
|
SASLFactory.use(require('sasl-anonymous'));
|
|
|
|
|
|
// Ensure that all basic stanza relationships are established
|
|
require('./stanza/stream');
|
|
require('./stanza/sm');
|
|
require('./stanza/roster');
|
|
require('./stanza/error');
|
|
require('./stanza/streamError');
|
|
require('./stanza/streamFeatures');
|
|
require('./stanza/bind');
|
|
require('./stanza/session');
|
|
|
|
|
|
function Client(opts) {
|
|
var self = this;
|
|
|
|
WildEmitter.call(this);
|
|
|
|
this.config = opts || {};
|
|
this._idPrefix = uuid.v4();
|
|
this._idCount = 0;
|
|
|
|
this.negotiatedFeatures = {};
|
|
this.featureOrder = [
|
|
'sasl',
|
|
'streamManagement',
|
|
'bind',
|
|
'streamManagement',
|
|
'session'
|
|
];
|
|
this.features = {};
|
|
|
|
this.conn = new WSConnection();
|
|
this.conn.on('*', function (eventName, data) {
|
|
self.emit(eventName, data);
|
|
});
|
|
|
|
this.on('streamFeatures', function (features) {
|
|
var series = [function (cb) { cb(null, features); }];
|
|
var seriesNames = ['setup'];
|
|
|
|
self.featureOrder.forEach(function (name) {
|
|
if (features._extensions[name] && !self.negotiatedFeatures[name]) {
|
|
series.push(function (features, cb) {
|
|
if (!self.negotiatedFeatures[name] && self.features[name]) {
|
|
self.features[name](features, cb);
|
|
} else {
|
|
cb(null, features);
|
|
}
|
|
});
|
|
seriesNames.push(name);
|
|
}
|
|
});
|
|
|
|
async.waterfall(series, function (cmd) {
|
|
if (cmd === 'restart') {
|
|
self.conn.restart();
|
|
} else if (cmd === 'disconnect') {
|
|
self.disconnect();
|
|
}
|
|
});
|
|
});
|
|
|
|
this.features.sasl = function (features, cb) {
|
|
var mech = SASLFactory.create(features.sasl.mechanisms);
|
|
|
|
self.on('sasl:success', 'sasl', function () {
|
|
self.negotiatedFeatures.sasl = true;
|
|
self.releaseGroup('sasl');
|
|
self.emit('auth:success');
|
|
cb('restart');
|
|
});
|
|
self.on('sasl:challenge', 'sasl', function (challenge) {
|
|
mech.challenge(challenge.value);
|
|
self.send(new SASL.Response({
|
|
value: mech.response(self.getCredentials())
|
|
}));
|
|
cb();
|
|
});
|
|
self.on('sasl:failure', 'sasl', function () {
|
|
self.releaseGroup('sasl');
|
|
self.emit('auth:failed');
|
|
cb('disconnect');
|
|
});
|
|
self.on('sasl:abort', 'sasl', function () {
|
|
self.releaseGroup('sasl');
|
|
self.emit('auth:failed');
|
|
cb('disconnect');
|
|
});
|
|
|
|
var auth = {
|
|
mechanism: mech.name
|
|
};
|
|
|
|
if (mech.clientFirst) {
|
|
auth.value = mech.response(self.getCredentials());
|
|
}
|
|
self.send(new SASL.Auth(auth));
|
|
};
|
|
|
|
this.features.bind = function (features, cb) {
|
|
self.sendIq({
|
|
type: 'set',
|
|
bind: {
|
|
resource: self.config.resource
|
|
}
|
|
}, function (err, resp) {
|
|
self.negotiatedFeatures.bind = true;
|
|
self.emit('session:bound', resp.bind.jid);
|
|
self.jid = resp.bind.jid;
|
|
if (!features._extensions.session) {
|
|
self.sessionStarted = true;
|
|
self.emit('session:started', resp.bind.jid);
|
|
}
|
|
cb(null, features);
|
|
});
|
|
};
|
|
|
|
this.features.session = function (features, cb) {
|
|
self.sendIq({
|
|
type: 'set',
|
|
session: {}
|
|
}, function () {
|
|
self.negotiatedFeatures.session = true;
|
|
self.sessionStarted = true;
|
|
self.emit('session:started', self.jid);
|
|
cb(null, features);
|
|
});
|
|
};
|
|
|
|
this.features.streamManagement = function (features, cb) {
|
|
self.on('stream:management:enabled', 'sm', function (enabled) {
|
|
self.conn.sm.enabled(enabled);
|
|
self.negotiatedFeatures.streamManagement = true;
|
|
|
|
self.on('stream:management:ack', 'connection', function (ack) {
|
|
self.conn.sm.process(ack);
|
|
});
|
|
|
|
self.on('stream:management:request', 'connection', function (request) {
|
|
self.conn.sm.ack();
|
|
});
|
|
|
|
self.releaseGroup('sm');
|
|
cb(null, features);
|
|
});
|
|
|
|
self.on('stream:management:resumed', 'sm', function (resumed) {
|
|
self.conn.sm.enabled(resumed);
|
|
self.negotiatedFeatures.streamManagement = true;
|
|
self.negotiatedFeatures.bind = true;
|
|
self.sessionStarted = true;
|
|
|
|
self.on('stream:management:ack', 'connection', function (ack) {
|
|
self.conn.sm.process(ack);
|
|
});
|
|
|
|
self.on('stream:management:request', 'connection', function (request) {
|
|
self.conn.sm.ack();
|
|
});
|
|
|
|
self.releaseGroup('sm');
|
|
cb(null, features);
|
|
});
|
|
|
|
self.on('stream:management:failed', 'sm', function (failed) {
|
|
self.conn.sm.failed();
|
|
self.emit('session:end');
|
|
self.releaseGroup('session');
|
|
self.releaseGroup('sm');
|
|
cb(null, features);
|
|
});
|
|
|
|
|
|
if (!self.conn.sm.id) {
|
|
if (self.negotiatedFeatures.bind) {
|
|
self.conn.sm.enable();
|
|
} else {
|
|
cb(null, features);
|
|
}
|
|
} else if (self.conn.sm.id && self.conn.sm.allowResume) {
|
|
self.conn.sm.resume();
|
|
} else {
|
|
cb(null, features);
|
|
}
|
|
};
|
|
|
|
this.on('disconnected', function () {
|
|
self.sessionStarted = false;
|
|
self.negotiatedFeatures.sasl = false;
|
|
self.negotiatedFeatures.streamManagement = false;
|
|
self.negotiatedFeatures.bind = false;
|
|
self.releaseGroup('connection');
|
|
});
|
|
|
|
this.on('iq:set:roster', function (iq) {
|
|
self.emit('roster:update', iq);
|
|
self.sendIq({
|
|
id: iq.id,
|
|
type: 'result'
|
|
});
|
|
});
|
|
|
|
this.on('iq', function (iq) {
|
|
var iqType = iq.type;
|
|
var exts = Object.keys(iq._extensions);
|
|
var children = iq.xml.childNodes;
|
|
|
|
var childCount = 0;
|
|
_.each(children, function (child) {
|
|
if (child.nodeType === 1) {
|
|
childCount += 1;
|
|
}
|
|
});
|
|
|
|
if (iq.type === 'get' || iq.type === 'set') {
|
|
// Invalid request
|
|
if (childCount != 1) {
|
|
return self.sendIq({
|
|
id: iq.id,
|
|
type: 'error',
|
|
error: {
|
|
type: 'modify',
|
|
condition: 'bad-request'
|
|
}
|
|
});
|
|
}
|
|
|
|
// Valid request, but we don't have support for the
|
|
// payload data.
|
|
if (!exts.length) {
|
|
return self.sendIq({
|
|
id: iq.id,
|
|
type: 'error',
|
|
error: {
|
|
type: 'cancel',
|
|
condition: 'feature-not-implemented'
|
|
}
|
|
});
|
|
}
|
|
|
|
var iqEvent = 'iq:' + iqType + ':' + exts[0];
|
|
if (self.callbacks[iqEvent]) {
|
|
self.emit(iqEvent, iq);
|
|
} else {
|
|
// We support the payload data, but there's
|
|
// nothing registered to handle it.
|
|
self.sendIq({
|
|
id: iq.id,
|
|
type: 'error',
|
|
error: {
|
|
type: 'cancel',
|
|
condition: 'feature-not-implemented'
|
|
}
|
|
});
|
|
}
|
|
}
|
|
});
|
|
|
|
this.on('message', function (msg) {
|
|
if (Object.keys(msg.$body).length) {
|
|
if (msg.type === 'chat' || msg.type === 'normal') {
|
|
self.emit('chat', msg);
|
|
} else if (msg.type === 'groupchat') {
|
|
self.emit('groupchat', msg);
|
|
}
|
|
}
|
|
});
|
|
|
|
this.on('presence', function (pres) {
|
|
var presType = pres.type || 'available';
|
|
self.emit(presType, pres);
|
|
});
|
|
}
|
|
|
|
Client.prototype = Object.create(WildEmitter.prototype, {
|
|
constructor: {
|
|
value: Client
|
|
}
|
|
});
|
|
|
|
Client.prototype.__defineGetter__('stream', function () {
|
|
return this.conn ? this.conn.stream : undefined;
|
|
});
|
|
|
|
Client.prototype.use = function (pluginInit) {
|
|
pluginInit(this);
|
|
};
|
|
|
|
Client.prototype.nextId = function () {
|
|
return this._idPrefix + '-' + (this._idCount++).toString(16);
|
|
};
|
|
|
|
Client.prototype.discoverBindings = function (server, cb) {
|
|
getHostMeta(server, function (err, data) {
|
|
if (err) return cb(err, []);
|
|
|
|
var results = [];
|
|
var links = data.links || [];
|
|
|
|
links.forEach(function (link) {
|
|
if (link.href && link.rel === 'urn:xmpp:altconnect:websocket') {
|
|
results.push(link.href);
|
|
}
|
|
});
|
|
|
|
cb(false, results);
|
|
});
|
|
};
|
|
|
|
Client.prototype.getCredentials = function () {
|
|
var creds = this.config.credentials || {};
|
|
var requestedJID = this.config.jid;
|
|
|
|
var username = creds.username || requestedJID.slice(0, requestedJID.indexOf('@'));
|
|
var server = creds.server || requestedJID.slice(requestedJID.indexOf('@') + 1);
|
|
|
|
var defaultCreds = {
|
|
username: username,
|
|
password: this.config.password,
|
|
server: server,
|
|
host: server,
|
|
realm: server,
|
|
serviceType: 'xmpp',
|
|
serviceName: server
|
|
};
|
|
|
|
return _.extend(defaultCreds, creds);
|
|
};
|
|
|
|
Client.prototype.connect = function (opts) {
|
|
var self = this;
|
|
|
|
_.extend(self.config, opts || {});
|
|
|
|
if (self.config.wsURL) {
|
|
return self.conn.connect(self.config);
|
|
}
|
|
|
|
self.discoverBindings(self.config.server, function (err, endpoints) {
|
|
if (!err && endpoints.length) {
|
|
self.config.wsURL = endpoints[0];
|
|
self.conn.connect(self.config);
|
|
} else {
|
|
self.disconnect();
|
|
}
|
|
});
|
|
};
|
|
|
|
Client.prototype.disconnect = function () {
|
|
if (this.sessionStarted) {
|
|
this.emit('session:end');
|
|
this.releaseGroup('session');
|
|
}
|
|
this.sessionStarted = false;
|
|
this.releaseGroup('connection');
|
|
if (this.conn) {
|
|
this.conn.disconnect();
|
|
}
|
|
};
|
|
|
|
Client.prototype.send = function (data) {
|
|
this.conn.send(data);
|
|
};
|
|
|
|
Client.prototype.sendMessage = function (data) {
|
|
data = data || {};
|
|
if (!data.id) {
|
|
data.id = this.nextId();
|
|
}
|
|
var message = new Message(data);
|
|
|
|
this.emit('message:sent', message);
|
|
this.send(message);
|
|
|
|
return data.id;
|
|
};
|
|
|
|
Client.prototype.sendPresence = function (data) {
|
|
data = data || {};
|
|
if (!data.id) {
|
|
data.id = this.nextId();
|
|
}
|
|
this.send(new Presence(data));
|
|
|
|
return data.id;
|
|
};
|
|
|
|
Client.prototype.sendIq = function (data, cb) {
|
|
data = data || {};
|
|
cb = cb || function () {};
|
|
if (!data.id) {
|
|
data.id = this.nextId();
|
|
}
|
|
if (data.type === 'get' || data.type === 'set') {
|
|
this.once('id:' + data.id, 'session', function (resp) {
|
|
if (resp._extensions.error) {
|
|
cb(resp, null);
|
|
} else {
|
|
cb(null, resp);
|
|
}
|
|
});
|
|
}
|
|
this.send(new Iq(data));
|
|
|
|
return data.id;
|
|
};
|
|
|
|
Client.prototype.getRoster = function (cb) {
|
|
var self = this;
|
|
cb = cb || function () {};
|
|
|
|
this.sendIq({
|
|
type: 'get',
|
|
roster: {
|
|
ver: self.config.rosterVer
|
|
}
|
|
}, function (err, resp) {
|
|
if (err) {
|
|
return cb(err);
|
|
}
|
|
if (resp.type === 'result') {
|
|
if (resp.roster.ver) {
|
|
self.config.rosterVer = resp.roster.ver;
|
|
self.emit('roster:ver', resp.roster.ver);
|
|
}
|
|
}
|
|
cb(null, resp);
|
|
});
|
|
};
|
|
|
|
Client.prototype.updateRosterItem = function (item, cb) {
|
|
this.sendIq({
|
|
type: 'set',
|
|
roster: {
|
|
items: [item]
|
|
}
|
|
}, cb);
|
|
};
|
|
|
|
Client.prototype.removeRosterItem = function (jid, cb) {
|
|
this.updateRosterItem({jid: jid, subscription: 'remove'}, cb);
|
|
};
|
|
|
|
Client.prototype.subscribe = function (jid) {
|
|
this.sendPresence({type: 'subscribe', to: jid});
|
|
};
|
|
|
|
Client.prototype.unsubscribe = function (jid) {
|
|
this.sendPresence({type: 'unsubscribe', to: jid});
|
|
};
|
|
|
|
Client.prototype.acceptSubscription = function (jid) {
|
|
this.sendPresence({type: 'subscribed', to: jid});
|
|
};
|
|
|
|
Client.prototype.denySubscription = function (jid) {
|
|
this.sendPresence({type: 'unsubscribed', to: jid});
|
|
};
|
|
|
|
|
|
module.exports = Client;
|
|
|
|
},{"../vendor/lodash":90,"./stanza/bind":23,"./stanza/error":30,"./stanza/iq":33,"./stanza/message":35,"./stanza/presence":37,"./stanza/roster":41,"./stanza/sasl":43,"./stanza/session":44,"./stanza/sm":45,"./stanza/stream":46,"./stanza/streamError":47,"./stanza/streamFeatures":48,"./websocket":52,"async":53,"hostmeta":67,"node-uuid":76,"sasl-anonymous":78,"sasl-digest-md5":80,"sasl-external":82,"sasl-plain":84,"sasl-scram-sha-1":86,"saslmechanisms":88,"wildemitter":89}],3:[function(require,module,exports){
|
|
require('../stanza/attention');
|
|
|
|
|
|
module.exports = function (client) {
|
|
client.disco.addFeature('urn:xmpp:attention:0');
|
|
|
|
|
|
client.getAttention = function (jid, opts) {
|
|
opts = opts || {};
|
|
opts.to = jid;
|
|
opts.type = 'headline';
|
|
opts.attention = true;
|
|
client.sendMessage(opts);
|
|
};
|
|
|
|
client.on('message', function (msg) {
|
|
if (msg._extensions._attention) {
|
|
client.emit('attention', msg);
|
|
}
|
|
});
|
|
};
|
|
|
|
},{"../stanza/attention":21}],4:[function(require,module,exports){
|
|
var stanzas = require('../stanza/avatar');
|
|
|
|
|
|
module.exports = function (client) {
|
|
client.disco.addFeature('urn:xmpp:avatar:metadata+notify');
|
|
|
|
client.on('pubsubEvent', function (msg) {
|
|
if (!msg.event._extensions.updated) return;
|
|
if (msg.event.updated.node !== 'urn:xmpp:avatar:metadata') return;
|
|
|
|
client.emit('avatar', {
|
|
jid: msg.from,
|
|
avatars: msg.event.updated.published[0].avatars
|
|
});
|
|
});
|
|
|
|
client.publishAvatar = function (id, data, cb) {
|
|
client.publish(null, 'urn:xmpp:avatar:data', {
|
|
id: id,
|
|
avatarData: data
|
|
}, cb);
|
|
};
|
|
|
|
client.useAvatars = function (info, cb) {
|
|
client.publish(null, 'urn:xmpp:avatar:metadata', {
|
|
id: 'current',
|
|
avatars: info
|
|
}, cb);
|
|
};
|
|
|
|
client.getAvatar = function (jid, id, cb) {
|
|
client.getItem(jid, 'urn:xmpp:avatar:data', id, cb);
|
|
};
|
|
};
|
|
|
|
},{"../stanza/avatar":22}],5:[function(require,module,exports){
|
|
var stanzas = require('../stanza/carbons');
|
|
|
|
|
|
module.exports = function (client) {
|
|
client.disco.addFeature('urn:xmpp:carbons:2');
|
|
|
|
client.enableCarbons = function (cb) {
|
|
this.sendIq({
|
|
type: 'set',
|
|
enableCarbons: true
|
|
}, cb);
|
|
};
|
|
|
|
client.disableCarbons = function (cb) {
|
|
this.sendIq({
|
|
type: 'set',
|
|
disableCarbons: true
|
|
}, cb);
|
|
};
|
|
|
|
client.on('message', function (msg) {
|
|
if (msg._extensions.carbonSent) {
|
|
return client.emit('carbon:sent', msg);
|
|
}
|
|
if (msg._extensions.carbonReceived) {
|
|
return client.emit('carbon:received', msg);
|
|
}
|
|
});
|
|
};
|
|
|
|
},{"../stanza/carbons":25}],6:[function(require,module,exports){
|
|
var stanzas = require('../stanza/chatstates');
|
|
|
|
|
|
module.exports = function (client) {
|
|
client.disco.addFeature('http://jabber.org/protocol/chatstates');
|
|
|
|
client.on('message', function (msg) {
|
|
if (msg.chatState) {
|
|
client.emit('chatState', {
|
|
to: msg.to,
|
|
from: msg.from,
|
|
chatState: msg.chatState
|
|
});
|
|
}
|
|
});
|
|
};
|
|
|
|
},{"../stanza/chatstates":26}],7:[function(require,module,exports){
|
|
var stanzas = require('../stanza/replace');
|
|
|
|
|
|
module.exports = function (client) {
|
|
client.disco.addFeature('urn:xmpp:message-correct:0');
|
|
|
|
client.on('message', function (msg) {
|
|
if (msg.replace) {
|
|
client.emit('replace', msg);
|
|
client.emit('replace:' + msg.id, msg);
|
|
}
|
|
});
|
|
};
|
|
|
|
},{"../stanza/replace":40}],8:[function(require,module,exports){
|
|
var stanzas = require('../stanza/delayed');
|
|
|
|
|
|
module.exports = function (client) {
|
|
client.disco.addFeature('urn:xmpp:delay');
|
|
};
|
|
|
|
},{"../stanza/delayed":28}],9:[function(require,module,exports){
|
|
/*global unescape, escape */
|
|
|
|
var _ = require('../../vendor/lodash');
|
|
var crypto = require('crypto');
|
|
|
|
require('../stanza/disco');
|
|
require('../stanza/caps');
|
|
|
|
|
|
var UTF8 = {
|
|
encode: function (s) {
|
|
return unescape(encodeURIComponent(s));
|
|
},
|
|
decode: function (s) {
|
|
return decodeURIComponent(escape(s));
|
|
}
|
|
};
|
|
|
|
|
|
function verifyVerString(info, hash, check) {
|
|
if (hash === 'sha-1') {
|
|
hash = 'sha1';
|
|
}
|
|
var computed = this._generatedVerString(info, hash);
|
|
return computed && computed == check;
|
|
}
|
|
|
|
|
|
function generateVerString(info, hash) {
|
|
var S = '';
|
|
var features = info.features.sort();
|
|
var identities = [];
|
|
var formTypes = {};
|
|
var formOrder = [];
|
|
|
|
|
|
_.forEach(info.identities, function (identity) {
|
|
identities.push([
|
|
identity.category || '',
|
|
identity.type || '',
|
|
identity.lang || '',
|
|
identity.name || ''
|
|
].join('/'));
|
|
});
|
|
|
|
var idLen = identities.length;
|
|
var featureLen = features.length;
|
|
|
|
identities = _.unique(identities, true);
|
|
features = _.unique(features, true);
|
|
|
|
if (featureLen != features.length || idLen != identities.length) {
|
|
return false;
|
|
}
|
|
|
|
|
|
S += identities.join('<') + '<';
|
|
S += features.join('<') + '<';
|
|
|
|
|
|
var illFormed = false;
|
|
_.forEach(info.extensions, function (ext) {
|
|
var fields = ext.fields;
|
|
for (var i = 0, len = fields.length; i < len; i++) {
|
|
if (fields[i].name == 'FORM_TYPE' && fields[i].type == 'hidden') {
|
|
var name = fields[i].value;
|
|
if (formTypes[name]) {
|
|
illFormed = true;
|
|
return;
|
|
}
|
|
formTypes[name] = ext;
|
|
formOrder.push(name);
|
|
return;
|
|
}
|
|
}
|
|
});
|
|
if (illFormed) {
|
|
return false;
|
|
}
|
|
|
|
formOrder.sort();
|
|
|
|
_.forEach(formOrder, function (name) {
|
|
var ext = formTypes[name];
|
|
var fields = {};
|
|
var fieldOrder = [];
|
|
|
|
S += '<' + name;
|
|
|
|
_.forEach(ext.fields, function (field) {
|
|
var fieldName = field.name;
|
|
if (fieldName != 'FORM_TYPE') {
|
|
var values = field.value || '';
|
|
if (typeof values != 'object') {
|
|
values = values.split('\n');
|
|
}
|
|
fields[fieldName] = values.sort();
|
|
fieldOrder.push(fieldName);
|
|
}
|
|
});
|
|
|
|
fieldOrder.sort();
|
|
|
|
_.forEach(fieldOrder, function (fieldName) {
|
|
S += '<' + fieldName;
|
|
_.forEach(fields[fieldName], function (val) {
|
|
S += '<' + val;
|
|
});
|
|
});
|
|
});
|
|
|
|
if (hash === 'sha-1') {
|
|
hash = 'sha1';
|
|
}
|
|
|
|
var ver = crypto.createHash(hash).update(UTF8.encode(S)).digest('base64');
|
|
var padding = 4 - ver.length % 4;
|
|
if (padding === 4) {
|
|
padding = 0;
|
|
}
|
|
|
|
for (var i = 0; i < padding; i++) {
|
|
ver += '=';
|
|
}
|
|
return ver;
|
|
}
|
|
|
|
|
|
function Disco(client) {
|
|
this.features = {};
|
|
this.identities = {};
|
|
this.extensions = {};
|
|
this.items = {};
|
|
this.caps = {};
|
|
}
|
|
|
|
Disco.prototype = {
|
|
constructor: {
|
|
value: Disco
|
|
},
|
|
addFeature: function (feature, node) {
|
|
node = node || '';
|
|
if (!this.features[node]) {
|
|
this.features[node] = [];
|
|
}
|
|
this.features[node].push(feature);
|
|
},
|
|
addIdentity: function (identity, node) {
|
|
node = node || '';
|
|
if (!this.identities[node]) {
|
|
this.identities[node] = [];
|
|
}
|
|
this.identities[node].push(identity);
|
|
},
|
|
addItem: function (item, node) {
|
|
node = node || '';
|
|
if (!this.items[node]) {
|
|
this.items[node] = [];
|
|
}
|
|
this.items[node].push(item);
|
|
},
|
|
addExtension: function (form, node) {
|
|
node = node || '';
|
|
if (!this.extensions[node]) {
|
|
this.extensions[node] = [];
|
|
}
|
|
this.extensions[node].push(form);
|
|
}
|
|
};
|
|
|
|
module.exports = function (client) {
|
|
client.disco = new Disco(client);
|
|
|
|
client.disco.addFeature('http://jabber.org/protocol/disco#info');
|
|
client.disco.addIdentity({
|
|
category: 'client',
|
|
type: 'web'
|
|
});
|
|
|
|
client.getDiscoInfo = function (jid, node, cb) {
|
|
this.sendIq({
|
|
to: jid,
|
|
type: 'get',
|
|
discoInfo: {
|
|
node: node
|
|
}
|
|
}, cb);
|
|
};
|
|
|
|
client.getDiscoItems = function (jid, node, cb) {
|
|
this.sendIq({
|
|
to: jid,
|
|
type: 'get',
|
|
discoItems: {
|
|
node: node
|
|
}
|
|
}, cb);
|
|
};
|
|
|
|
client.updateCaps = function () {
|
|
this.disco.caps = {
|
|
node: this.config.capsNode || 'https://stanza.io',
|
|
hash: 'sha-1',
|
|
ver: generateVerString({
|
|
identities: this.disco.identities[''],
|
|
features: this.disco.features[''],
|
|
extensions: this.disco.extensions['']
|
|
}, 'sha-1')
|
|
};
|
|
};
|
|
|
|
client.on('iq:get:discoInfo', function (iq) {
|
|
var node = iq.discoInfo.node;
|
|
var reportedNode = iq.discoInfo.node;
|
|
|
|
if (node === client.disco.caps.node + '#' + client.disco.caps.ver) {
|
|
reportedNode = node;
|
|
node = '';
|
|
}
|
|
client.sendIq(iq.resultReply({
|
|
discoInfo: {
|
|
node: reportedNode,
|
|
identities: client.disco.identities[node] || [],
|
|
features: client.disco.features[node] || [],
|
|
extensions: client.disco.extensions[node] || []
|
|
}
|
|
}));
|
|
});
|
|
|
|
client.on('iq:get:discoItems', function (iq) {
|
|
var node = iq.discoInfo.node;
|
|
client.sendIq(iq.resultReply({
|
|
discoItems: {
|
|
node: node,
|
|
items: client.disco.items[node] || []
|
|
}
|
|
}));
|
|
});
|
|
};
|
|
|
|
},{"../../vendor/lodash":90,"../stanza/caps":24,"../stanza/disco":29,"crypto":60}],10:[function(require,module,exports){
|
|
var stanzas = require('../stanza/forwarded');
|
|
|
|
|
|
module.exports = function (client) {
|
|
client.disco.addFeature('urn:xmpp:forward:0');
|
|
};
|
|
|
|
},{"../stanza/forwarded":31}],11:[function(require,module,exports){
|
|
var stanzas = require('../stanza/idle');
|
|
|
|
|
|
module.exports = function (client) {
|
|
client.disco.addFeature('urn:xmpp:idle:0');
|
|
};
|
|
|
|
},{"../stanza/idle":32}],12:[function(require,module,exports){
|
|
require('../stanza/visibility');
|
|
|
|
|
|
module.exports = function (client) {
|
|
client.goInvisible = function (cb) {
|
|
this.sendIq({
|
|
type: 'set',
|
|
invisible: true
|
|
});
|
|
};
|
|
|
|
client.goVisible = function (cb) {
|
|
this.sendIq({
|
|
type: 'set',
|
|
visible: true
|
|
});
|
|
};
|
|
};
|
|
|
|
},{"../stanza/visibility":51}],13:[function(require,module,exports){
|
|
var stanzas = require('../stanza/mam');
|
|
|
|
|
|
module.exports = function (client) {
|
|
client.disco.addFeature('urn:xmpp:mam:tmp');
|
|
|
|
client.getHistory = function (opts, cb) {
|
|
var self = this;
|
|
var queryid = this.nextId();
|
|
|
|
opts = opts || {};
|
|
opts.queryid = queryid;
|
|
|
|
var mamResults = [];
|
|
this.on('mam:' + queryid, 'session', function (msg) {
|
|
mamResults.push(msg);
|
|
});
|
|
|
|
cb = cb || function () {};
|
|
|
|
this.sendIq({
|
|
type: 'get',
|
|
id: queryid,
|
|
mamQuery: opts
|
|
}, function (err, resp) {
|
|
if (err) {
|
|
cb(err);
|
|
} else {
|
|
self.off('mam:' + queryid);
|
|
resp.mamQuery.results = mamResults;
|
|
cb(null, resp);
|
|
}
|
|
});
|
|
};
|
|
|
|
client.getHistoryPreferences = function (cb) {
|
|
client.sendIq({
|
|
type: 'get',
|
|
mamPrefs: {}
|
|
}, cb);
|
|
};
|
|
|
|
client.setHistoryPreferences = function (opts, cb) {
|
|
client.sendIq({
|
|
type: 'set',
|
|
mamPrefs: opts
|
|
}, cb);
|
|
};
|
|
|
|
client.on('message', function (msg) {
|
|
if (msg._extensions.mam) {
|
|
client.emit('mam:' + msg.mam.queryid, msg);
|
|
}
|
|
});
|
|
};
|
|
|
|
},{"../stanza/mam":34}],14:[function(require,module,exports){
|
|
require('../stanza/muc');
|
|
|
|
|
|
module.exports = function (client) {
|
|
client.joinRoom = function (room, nick, opts) {
|
|
opts = opts || {};
|
|
opts.to = room + '/' + nick;
|
|
opts.caps = this.disco.caps;
|
|
opts.joinMuc = opts.joinMuc || {};
|
|
|
|
this.sendPresence(opts);
|
|
};
|
|
|
|
client.leaveRoom = function (room, nick, opts) {
|
|
opts = opts || {};
|
|
opts.to = room + '/' + nick;
|
|
opts.type = 'unavailable';
|
|
this.sendPresence(opts);
|
|
};
|
|
};
|
|
|
|
},{"../stanza/muc":36}],15:[function(require,module,exports){
|
|
var stanzas = require('../stanza/pubsub');
|
|
|
|
|
|
module.exports = function (client) {
|
|
|
|
client.on('message', function (msg) {
|
|
if (msg._extensions.event) {
|
|
client.emit('pubsubEvent', msg);
|
|
}
|
|
});
|
|
|
|
client.subscribeToNode = function (jid, opts, cb) {
|
|
client.sendIq({
|
|
type: 'set',
|
|
to: jid,
|
|
pubsub: {
|
|
subscribe: {
|
|
node: opts.node,
|
|
jid: opts.jid || client.jid
|
|
}
|
|
}
|
|
}, cb);
|
|
};
|
|
|
|
client.unsubscribeFromNode = function (jid, opts, cb) {
|
|
client.sendIq({
|
|
type: 'set',
|
|
to: jid,
|
|
pubsub: {
|
|
unsubscribe: {
|
|
node: opts.node,
|
|
jid: opts.jid || client.jid.split('/')[0]
|
|
}
|
|
}
|
|
}, cb);
|
|
};
|
|
|
|
client.publish = function (jid, node, item, cb) {
|
|
client.sendIq({
|
|
type: 'set',
|
|
to: jid,
|
|
pubsub: {
|
|
publish: {
|
|
node: node,
|
|
item: item
|
|
}
|
|
}
|
|
}, cb);
|
|
};
|
|
|
|
client.getItem = function (jid, node, id, cb) {
|
|
client.sendIq({
|
|
type: 'get',
|
|
to: jid,
|
|
pubsub: {
|
|
retrieve: {
|
|
node: node,
|
|
item: id
|
|
}
|
|
}
|
|
}, cb);
|
|
};
|
|
|
|
client.getItems = function (jid, node, opts, cb) {
|
|
opts = opts || {};
|
|
opts.node = node;
|
|
client.sendIq({
|
|
type: 'get',
|
|
to: jid,
|
|
pubsub: {
|
|
retrieve: {
|
|
node: node,
|
|
max: opts.max
|
|
},
|
|
rsm: opts.rsm
|
|
}
|
|
}, cb);
|
|
};
|
|
|
|
client.retract = function (jid, node, id, notify, cb) {
|
|
client.sendIq({
|
|
type: 'set',
|
|
to: jid,
|
|
pubsub: {
|
|
retract: {
|
|
node: node,
|
|
notify: notify,
|
|
id: id
|
|
}
|
|
}
|
|
}, cb);
|
|
};
|
|
|
|
client.purgeNode = function (jid, node, cb) {
|
|
client.sendIq({
|
|
type: 'set',
|
|
to: jid,
|
|
pubsubOwner: {
|
|
purge: node
|
|
}
|
|
}, cb);
|
|
};
|
|
|
|
client.deleteNode = function (jid, node, cb) {
|
|
client.sendIq({
|
|
type: 'set',
|
|
to: jid,
|
|
pubsubOwner: {
|
|
del: node
|
|
}
|
|
}, cb);
|
|
};
|
|
|
|
client.createNode = function (jid, node, config, cb) {
|
|
var cmd = {
|
|
type: 'set',
|
|
to: jid,
|
|
pubsubOwner: {
|
|
create: node
|
|
}
|
|
};
|
|
|
|
if (config) {
|
|
cmd.pubsubOwner.config = {form: config};
|
|
}
|
|
|
|
client.sendIq(cmd, cb);
|
|
};
|
|
};
|
|
|
|
},{"../stanza/pubsub":38}],16:[function(require,module,exports){
|
|
var stanzas = require('../stanza/receipts');
|
|
|
|
|
|
module.exports = function (client) {
|
|
client.disco.addFeature('urn:xmpp:receipts');
|
|
|
|
client.on('message', function (msg) {
|
|
var ackTypes = {
|
|
normal: true,
|
|
chat: true,
|
|
headline: true
|
|
};
|
|
if (ackTypes[msg.type] && msg.requestReceipt && !msg._extensions.receipt) {
|
|
client.sendMessage({
|
|
to: msg.from,
|
|
receipt: {
|
|
id: msg.id
|
|
},
|
|
id: msg.id
|
|
});
|
|
}
|
|
if (msg._extensions.receipt) {
|
|
client.emit('receipt:' + msg.receipt.id);
|
|
}
|
|
});
|
|
};
|
|
|
|
},{"../stanza/receipts":39}],17:[function(require,module,exports){
|
|
var stanzas = require('../stanza/time');
|
|
|
|
|
|
module.exports = function (client) {
|
|
client.disco.addFeature('urn:xmpp:time');
|
|
|
|
client.getTime = function (jid, cb) {
|
|
this.sendIq({
|
|
to: jid,
|
|
type: 'get',
|
|
time: true
|
|
}, cb);
|
|
};
|
|
|
|
client.on('iq:get:time', function (iq) {
|
|
var time = new Date();
|
|
client.sendIq(iq.resultReply({
|
|
time: {
|
|
utc: time,
|
|
tzo: time.getTimezoneOffset()
|
|
}
|
|
}));
|
|
});
|
|
};
|
|
|
|
},{"../stanza/time":49}],18:[function(require,module,exports){
|
|
require('../stanza/version');
|
|
|
|
|
|
module.exports = function (client) {
|
|
client.disco.addFeature('jabber:iq:version');
|
|
|
|
client.on('iq:get:version', function (iq) {
|
|
client.sendIq(iq.resultReply({
|
|
version: client.config.version || {
|
|
name: 'stanza.io'
|
|
}
|
|
}));
|
|
});
|
|
|
|
client.getSoftwareVersion = function (jid, cb) {
|
|
this.sendIq({
|
|
to: jid,
|
|
type: 'get',
|
|
version: {}
|
|
}, cb);
|
|
};
|
|
};
|
|
|
|
},{"../stanza/version":50}],19:[function(require,module,exports){
|
|
var uuid = require('node-uuid');
|
|
|
|
// normalize environment
|
|
var RTCPeerConnection = null;
|
|
var RTCSessionDescription = null;
|
|
var RTCIceCandidate = null;
|
|
var getUserMedia = null;
|
|
var attachMediaStream = null;
|
|
var reattachMediaStream = null;
|
|
var browser = null;
|
|
var webRTCSupport = true;
|
|
|
|
|
|
if (navigator.mozGetUserMedia) {
|
|
browser = "firefox";
|
|
|
|
// The RTCPeerConnection object.
|
|
RTCPeerConnection = window.mozRTCPeerConnection;
|
|
|
|
// The RTCSessionDescription object.
|
|
RTCSessionDescription = window.mozRTCSessionDescription;
|
|
|
|
// The RTCIceCandidate object.
|
|
RTCIceCandidate = window.mozRTCIceCandidate;
|
|
|
|
// Get UserMedia (only difference is the prefix).
|
|
// Code from Adam Barth.
|
|
getUserMedia = navigator.mozGetUserMedia.bind(navigator);
|
|
|
|
// Attach a media stream to an element.
|
|
attachMediaStream = function (element, stream) {
|
|
element.mozSrcObject = stream;
|
|
element.play();
|
|
};
|
|
|
|
reattachMediaStream = function (to, from) {
|
|
to.mozSrcObject = from.mozSrcObject;
|
|
to.play();
|
|
};
|
|
|
|
// Fake get{Video,Audio}Tracks
|
|
MediaStream.prototype.getVideoTracks = function () {
|
|
return [];
|
|
};
|
|
|
|
MediaStream.prototype.getAudioTracks = function () {
|
|
return [];
|
|
};
|
|
} else if (navigator.webkitGetUserMedia) {
|
|
browser = "chrome";
|
|
|
|
// The RTCPeerConnection object.
|
|
RTCPeerConnection = window.webkitRTCPeerConnection;
|
|
|
|
// Get UserMedia (only difference is the prefix).
|
|
// Code from Adam Barth.
|
|
getUserMedia = navigator.webkitGetUserMedia.bind(navigator);
|
|
|
|
// Attach a media stream to an element.
|
|
attachMediaStream = function (element, stream) {
|
|
element.autoplay = true;
|
|
element.src = webkitURL.createObjectURL(stream);
|
|
};
|
|
|
|
reattachMediaStream = function (to, from) {
|
|
to.src = from.src;
|
|
};
|
|
|
|
// The representation of tracks in a stream is changed in M26.
|
|
// Unify them for earlier Chrome versions in the coexisting period.
|
|
if (!webkitMediaStream.prototype.getVideoTracks) {
|
|
webkitMediaStream.prototype.getVideoTracks = function () {
|
|
return this.videoTracks;
|
|
};
|
|
webkitMediaStream.prototype.getAudioTracks = function () {
|
|
return this.audioTracks;
|
|
};
|
|
}
|
|
|
|
// New syntax of getXXXStreams method in M26.
|
|
if (!window.webkitRTCPeerConnection.prototype.getLocalStreams) {
|
|
window.webkitRTCPeerConnection.prototype.getLocalStreams = function () {
|
|
return this.localStreams;
|
|
};
|
|
window.webkitRTCPeerConnection.prototype.getRemoteStreams = function () {
|
|
return this.remoteStreams;
|
|
};
|
|
}
|
|
} else {
|
|
webRTCSupport = false;
|
|
}
|
|
|
|
|
|
function WebRTC(client) {
|
|
var self = this;
|
|
|
|
this.client = client;
|
|
this.peerConnectionConfig = {
|
|
iceServers: browser == 'firefox' ? [{url: 'stun:124.124.124.2'}] : [{url: 'stun:stun.l.google.com:19302'}]
|
|
};
|
|
this.peerConnectionConstraints = {
|
|
optional: [{DtlsSrtpKeyAgreement: true}]
|
|
};
|
|
this.media = {
|
|
audio: true,
|
|
video: {
|
|
mandatory: {},
|
|
optional: []
|
|
}
|
|
};
|
|
this.sessions = {};
|
|
this.peerSessions = {};
|
|
|
|
this.attachMediaStream = attachMediaStream;
|
|
|
|
// check for support
|
|
if (!webRTCSupport) {
|
|
client.emit('webrtc:unsupported');
|
|
return self;
|
|
} else {
|
|
client.emit('webrtc:supported');
|
|
|
|
client.disco.addFeature('http://stanza.io/protocol/sox');
|
|
|
|
client.on('message', function (msg) {
|
|
if (msg.type !== 'error' && msg._extensions.sox) {
|
|
var session;
|
|
var fullId = msg.from + ':' + msg.sox.sid;
|
|
|
|
if (msg.sox.type === 'offer') {
|
|
console.log('got an offer');
|
|
session = new Peer(client, msg.from, msg.sox.sid);
|
|
self.sessions[fullId] = session;
|
|
if (!self.peerSessions[msg.from]) {
|
|
self.peerSessions[msg.from] = [];
|
|
}
|
|
self.peerSessions[msg.from].push(fullId);
|
|
} else if (msg.sox.type === 'answer') {
|
|
console.log('got an answer');
|
|
session = self.sessions[fullId];
|
|
if (session) {
|
|
console.log('Setting remote description');
|
|
session.conn.setRemoteDescription(new RTCSessionDescription({
|
|
type: 'answer',
|
|
sdp: msg.sox.sdp
|
|
}));
|
|
}
|
|
} else if (msg.sox.type === 'candidate') {
|
|
session = self.sessions[fullId];
|
|
if (session) {
|
|
console.log('Adding new ICE candidate');
|
|
session.conn.addIceCandidate(new RTCIceCandidate({
|
|
sdpMLineIndex: msg.sox.label,
|
|
candidate: msg.sox.sdp
|
|
}));
|
|
}
|
|
}
|
|
client.emit('webrtc:' + msg.sox.type, msg);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
WebRTC.prototype = {
|
|
constructor: {
|
|
value: WebRTC
|
|
},
|
|
testReadiness: function () {
|
|
var self = this;
|
|
if (this.localStream && this.client.sessionStarted) {
|
|
// This timeout is a workaround for the strange no-audio bug
|
|
// as described here: https://code.google.com/p/webrtc/issues/detail?id=1525
|
|
// remove timeout when this is fixed.
|
|
setTimeout(function () {
|
|
self.client.emit('webrtc:ready');
|
|
}, 1000);
|
|
}
|
|
},
|
|
startLocalMedia: function (element) {
|
|
var self = this;
|
|
getUserMedia(this.media, function (stream) {
|
|
attachMediaStream(element, stream);
|
|
self.localStream = stream;
|
|
self.testReadiness();
|
|
}, function () {
|
|
throw new Error('Failed to get access to local media.');
|
|
});
|
|
},
|
|
offerSession: function (peer) {
|
|
var self = this;
|
|
var sid = uuid.v4();
|
|
var session = new Peer(this.client, peer, sid);
|
|
|
|
this.sessions[peer + ':' + sid] = session;
|
|
if (!this.peerSessions[peer]) {
|
|
this.peerSessions[peer] = [];
|
|
}
|
|
this.peerSessions[peer].push(peer + ':' + sid);
|
|
|
|
session.conn.createOffer(function (sdp) {
|
|
console.log('Setting local description');
|
|
session.conn.setLocalDescription(sdp);
|
|
console.log('Sending offer');
|
|
self.client.sendMessage({
|
|
to: peer,
|
|
sox: {
|
|
type: 'offer',
|
|
sid: sid,
|
|
sdp: sdp.sdp
|
|
}
|
|
});
|
|
}, null, this.mediaConstraints);
|
|
},
|
|
acceptSession: function (offerMsg) {
|
|
var self = this;
|
|
var session = self.sessions[offerMsg.from + ':' + offerMsg.sox.sid];
|
|
|
|
if (session) {
|
|
console.log('Setting remote description');
|
|
session.conn.setRemoteDescription(new RTCSessionDescription({
|
|
type: 'offer',
|
|
sdp: offerMsg.sox.sdp
|
|
}));
|
|
session.conn.createAnswer(function (sdp) {
|
|
console.log('Setting local description');
|
|
session.conn.setLocalDescription(sdp);
|
|
console.log('Sending answer');
|
|
self.client.sendMessage({
|
|
to: session.jid,
|
|
sox: {
|
|
type: 'answer',
|
|
sid: session.sid,
|
|
sdp: sdp.sdp
|
|
}
|
|
});
|
|
}, null, this.mediaConstraints);
|
|
}
|
|
},
|
|
declineSession: function (offerMsg) {
|
|
this.endSession(offerMsg.from, offerMsg.sox.sid);
|
|
},
|
|
endSession: function (peer, sid) {
|
|
var session = this.sessions[peer + ':' + sid];
|
|
if (session) {
|
|
var fullId = peer + ':' + sid;
|
|
var index = this.peerSessions[peer].indexOf(fullId);
|
|
|
|
if (index != -1) {
|
|
this.peerSessions.splice(index, 1);
|
|
}
|
|
this.sessions[fullId] = undefined;
|
|
|
|
session.conn.close();
|
|
this.client.emit('webrtc:stream:removed', {
|
|
sid: session.sid,
|
|
peer: session.jid
|
|
});
|
|
|
|
this.client.sendMessage({
|
|
to: peer,
|
|
sox: {
|
|
type: 'end',
|
|
sid: sid
|
|
}
|
|
});
|
|
}
|
|
},
|
|
// Audio controls
|
|
mute: function () {
|
|
this._audioEnabled(false);
|
|
this.client.emit('webrtc:audio:off');
|
|
},
|
|
unmute: function () {
|
|
this._audioEnabled(true);
|
|
this.client.emit('webrtc:audio:on');
|
|
},
|
|
// Video controls
|
|
pauseVideo: function () {
|
|
this._videoEnabled(false);
|
|
this.client.emit('webrtc:video:off');
|
|
},
|
|
resumeVideo: function () {
|
|
this._videoEnabled(true);
|
|
this.client.emit('webrtc:video:on');
|
|
},
|
|
// Combined controls
|
|
pause: function () {
|
|
this.mute();
|
|
this.pauseVideo();
|
|
},
|
|
resume: function () {
|
|
this.unmute();
|
|
this.resumeVideo();
|
|
},
|
|
// Internal methods for enabling/disabling audio/video
|
|
_audioEnabled: function (bool) {
|
|
this.localStream.getAudioTracks().forEach(function (track) {
|
|
track.enabled = !!bool;
|
|
});
|
|
},
|
|
_videoEnabled: function (bool) {
|
|
this.localStream.getVideoTracks().forEach(function (track) {
|
|
track.enabled = !!bool;
|
|
});
|
|
}
|
|
};
|
|
|
|
|
|
function Peer(client, jid, sid) {
|
|
var self = this;
|
|
|
|
this.client = client;
|
|
this.jid = jid;
|
|
this.sid = sid;
|
|
this.closed = false;
|
|
|
|
this.conn = new RTCPeerConnection(client.webrtc.peerConnectionConfig, client.webrtc.peerConnectionConstraints);
|
|
this.conn.addStream(client.webrtc.localStream);
|
|
this.conn.onicecandidate = function (event) {
|
|
if (self.closed) return;
|
|
if (event.candidate) {
|
|
console.log('Sending candidate');
|
|
self.client.sendMessage({
|
|
mto: self.jid,
|
|
sox: {
|
|
type: 'candidate',
|
|
sid: self.sid,
|
|
label: event.candidate.sdpMLineIndex,
|
|
id: event.candidate.sdpMid,
|
|
sdp: event.candidate.candidate
|
|
}
|
|
});
|
|
} else {
|
|
console.log('End of ICE candidates');
|
|
}
|
|
};
|
|
this.conn.onaddstream = function (event) {
|
|
self.client.emit('webrtc:stream:added', {
|
|
stream: event.stream,
|
|
sid: self.sid,
|
|
peer: self.jid
|
|
});
|
|
};
|
|
this.conn.onremovestream = function (event) {
|
|
self.client.emit('webrtc:stream:removed', {
|
|
sid: self.sid,
|
|
peer: self.jid
|
|
});
|
|
};
|
|
|
|
this.mediaConstraints = {
|
|
mandatory: {
|
|
OfferToReceiveAudio: true,
|
|
OfferToReceiveVideo: true
|
|
}
|
|
};
|
|
}
|
|
|
|
Peer.prototype = {
|
|
constructor: {
|
|
value: Peer
|
|
}
|
|
};
|
|
|
|
|
|
module.exports = function (client) {
|
|
client.webrtc = new WebRTC(client);
|
|
};
|
|
|
|
},{"node-uuid":76}],20:[function(require,module,exports){
|
|
var SM = require('./stanza/sm');
|
|
var MAX_SEQ = Math.pow(2, 32);
|
|
|
|
|
|
function mod(v, n) {
|
|
return ((v % n) + n) % n;
|
|
}
|
|
|
|
|
|
function StreamManagement(conn) {
|
|
this.conn = conn;
|
|
this.id = false;
|
|
this.allowResume = true;
|
|
this.started = false;
|
|
this.lastAck = 0;
|
|
this.handled = 0;
|
|
this.windowSize = 1;
|
|
this.windowCount = 0;
|
|
this.unacked = [];
|
|
}
|
|
|
|
StreamManagement.prototype = {
|
|
constructor: {
|
|
value: StreamManagement
|
|
},
|
|
enable: function () {
|
|
var enable = new SM.Enable();
|
|
enable.resume = this.allowResume;
|
|
this.conn.send(enable);
|
|
this.handled = 0;
|
|
this.started = true;
|
|
},
|
|
resume: function () {
|
|
var resume = new SM.Resume({
|
|
h: this.handled,
|
|
previd: this.id
|
|
});
|
|
this.conn.send(resume);
|
|
this.started = true;
|
|
},
|
|
enabled: function (resp) {
|
|
this.id = resp.id;
|
|
},
|
|
resumed: function (resp) {
|
|
this.id = resp.id;
|
|
if (resp.h) {
|
|
this.process(resp, true);
|
|
}
|
|
},
|
|
failed: function (resp) {
|
|
this.started = false;
|
|
this.id = false;
|
|
this.lastAck = 0;
|
|
this.handled = 0;
|
|
this.windowCount = 0;
|
|
this.unacked = [];
|
|
},
|
|
ack: function () {
|
|
this.conn.send(new SM.Ack({
|
|
h: this.handled
|
|
}));
|
|
},
|
|
request: function () {
|
|
this.conn.send(new SM.Request());
|
|
},
|
|
process: function (ack, resend) {
|
|
var self = this;
|
|
var numAcked = mod(ack.h - this.lastAck, MAX_SEQ);
|
|
|
|
for (var i = 0; i < numAcked && this.unacked.length > 0; i++) {
|
|
this.conn.emit('stanza:acked', this.unacked.shift());
|
|
}
|
|
if (resend) {
|
|
var resendUnacked = this.unacked;
|
|
this.unacked = [];
|
|
resendUnacked.forEach(function (stanza) {
|
|
self.conn.send(stanza);
|
|
});
|
|
}
|
|
this.lastAck = ack.h;
|
|
},
|
|
track: function (stanza) {
|
|
var name = stanza._name;
|
|
var acceptable = {
|
|
message: true,
|
|
presence: true,
|
|
iq: true
|
|
};
|
|
|
|
if (this.started && acceptable[name]) {
|
|
this.unacked.push(stanza);
|
|
this.windowCount += 1;
|
|
if (this.windowCount == this.windowSize) {
|
|
this.request();
|
|
this.windowCount = 0;
|
|
}
|
|
}
|
|
},
|
|
handle: function (stanza) {
|
|
if (this.started) {
|
|
this.handled = mod(this.handled + 1, MAX_SEQ);
|
|
}
|
|
}
|
|
};
|
|
|
|
module.exports = StreamManagement;
|
|
|
|
},{"./stanza/sm":45}],21:[function(require,module,exports){
|
|
var stanza = require('jxt');
|
|
var Message = require('./message');
|
|
|
|
|
|
function Attention(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
Attention.prototype = {
|
|
constructor: {
|
|
value: Attention
|
|
},
|
|
NS: 'urn:xmpp:attention:0',
|
|
EL: 'attention',
|
|
_name: '_attention',
|
|
toString: stanza.toString,
|
|
toJSON: undefined
|
|
};
|
|
|
|
Message.prototype.__defineGetter__('attention', function () {
|
|
return !!this._extensions._attention;
|
|
});
|
|
Message.prototype.__defineSetter__('attention', function (value) {
|
|
if (value) {
|
|
this._attention = true;
|
|
} else if (this._extensions._attention) {
|
|
this.xml.removeChild(this._extensions._attention.xml);
|
|
delete this._extensions._attention;
|
|
}
|
|
});
|
|
|
|
|
|
stanza.extend(Message, Attention);
|
|
|
|
module.exports = Attention;
|
|
|
|
},{"./message":35,"jxt":74}],22:[function(require,module,exports){
|
|
var _ = require('../../vendor/lodash');
|
|
var stanza = require('jxt');
|
|
var Item = require('./pubsub').Item;
|
|
var EventItem = require('./pubsub').EventItem;
|
|
|
|
|
|
function getAvatarData() {
|
|
return stanza.getSubText(this.xml, 'urn:xmpp:avatar:data', 'data');
|
|
}
|
|
|
|
function setAvatarData(value) {
|
|
stanza.setSubText(this.xml, 'urn:xmpp:avatar:data', 'data', value);
|
|
stanza.setSubAttribute(this.xml, 'urn:xmpp:avatar:data', 'data', 'xmlns', 'urn:xmpp:avatar:data');
|
|
}
|
|
|
|
function getAvatars() {
|
|
var metadata = stanza.find(this.xml, 'urn:xmpp:avatar:metadata', 'metadata');
|
|
var results = [];
|
|
if (metadata.length) {
|
|
var avatars = stanza.find(metadata[0], 'urn:xmpp:avatar:metadata', 'info');
|
|
_.forEach(avatars, function (info) {
|
|
results.push(new Avatar({}, info));
|
|
});
|
|
}
|
|
return results;
|
|
}
|
|
|
|
function setAvatars(value) {
|
|
var metadata = stanza.findOrCreate(this.xml, 'urn:xmpp:avatar:metadata', 'metadata');
|
|
stanza.setAttribute(metadata, 'xmlns', 'urn:xmpp:avatar:metadata');
|
|
_.forEach(value, function (info) {
|
|
var avatar = new Avatar(info);
|
|
metadata.appendChild(avatar.xml);
|
|
});
|
|
}
|
|
|
|
|
|
Item.prototype.__defineGetter__('avatarData', getAvatarData);
|
|
Item.prototype.__defineSetter__('avatarData', setAvatarData);
|
|
EventItem.prototype.__defineGetter__('avatarData', getAvatarData);
|
|
EventItem.prototype.__defineSetter__('avatarData', setAvatarData);
|
|
|
|
Item.prototype.__defineGetter__('avatars', getAvatars);
|
|
Item.prototype.__defineSetter__('avatars', setAvatars);
|
|
EventItem.prototype.__defineGetter__('avatars', getAvatars);
|
|
EventItem.prototype.__defineSetter__('avatars', setAvatars);
|
|
|
|
|
|
|
|
function Avatar(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
Avatar.prototype = {
|
|
constructor: {
|
|
value: Avatar
|
|
},
|
|
_name: 'avatars',
|
|
NS: 'urn:xmpp:avatar:metadata',
|
|
EL: 'info',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON,
|
|
get id() {
|
|
return stanza.getAttribute(this.xml, 'id');
|
|
},
|
|
set id(value) {
|
|
stanza.setAttribute(this.xml, 'id', value);
|
|
},
|
|
get bytes() {
|
|
return stanza.getAttribute(this.xml, 'bytes');
|
|
},
|
|
set bytes(value) {
|
|
stanza.setAttribute(this.xml, 'bytes', value);
|
|
},
|
|
get height() {
|
|
return stanza.getAttribute(this.xml, 'height');
|
|
},
|
|
set height(value) {
|
|
stanza.setAttribute(this.xml, 'height', value);
|
|
},
|
|
get width() {
|
|
return stanza.getAttribute(this.xml, 'width');
|
|
},
|
|
set width(value) {
|
|
stanza.setAttribute(this.xml, 'width', value);
|
|
},
|
|
get type() {
|
|
return stanza.getAttribute(this.xml, 'type', 'image/png');
|
|
},
|
|
set type(value) {
|
|
stanza.setAttribute(this.xml, 'type', value);
|
|
},
|
|
get url() {
|
|
return stanza.getAttribute(this.xml, 'url');
|
|
},
|
|
set url(value) {
|
|
stanza.setAttribute(this.xml, 'url', value);
|
|
}
|
|
};
|
|
|
|
|
|
module.exports = Avatar;
|
|
|
|
},{"../../vendor/lodash":90,"./pubsub":38,"jxt":74}],23:[function(require,module,exports){
|
|
var stanza = require('jxt');
|
|
var Iq = require('./iq');
|
|
var StreamFeatures = require('./streamFeatures');
|
|
|
|
|
|
function Bind(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
Bind.prototype = {
|
|
constructor: {
|
|
value: Bind
|
|
},
|
|
_name: 'bind',
|
|
NS: 'urn:ietf:params:xml:ns:xmpp-bind',
|
|
EL: 'bind',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON,
|
|
get resource() {
|
|
return stanza.getSubText(this.xml, this.NS, 'resource');
|
|
},
|
|
set resource(value) {
|
|
stanza.setSubText(this.xml, this.NS, 'resource');
|
|
},
|
|
get jid() {
|
|
return stanza.getSubText(this.xml, this.NS, 'jid');
|
|
},
|
|
set jid(value) {
|
|
stanza.setSubText(this.xml, this.NS, 'jid');
|
|
}
|
|
};
|
|
|
|
|
|
stanza.extend(Iq, Bind);
|
|
stanza.extend(StreamFeatures, Bind);
|
|
|
|
|
|
module.exports = Bind;
|
|
|
|
},{"./iq":33,"./streamFeatures":48,"jxt":74}],24:[function(require,module,exports){
|
|
var stanza = require('jxt');
|
|
var Presence = require('./presence');
|
|
var StreamFeatures = require('./streamFeatures');
|
|
|
|
|
|
function Caps(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
Caps.prototype = {
|
|
constructor: {
|
|
value: Caps
|
|
},
|
|
NS: 'http://jabber.org/protocol/caps',
|
|
EL: 'c',
|
|
_name: 'caps',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON,
|
|
get ver() {
|
|
return stanza.getAttribute(this.xml, 'ver');
|
|
},
|
|
set ver(value) {
|
|
stanza.setAttribute(this.xml, 'ver', value);
|
|
},
|
|
get node() {
|
|
return stanza.getAttribute(this.xml, 'node');
|
|
},
|
|
set node(value) {
|
|
stanza.setAttribute(this.xml, 'node', value);
|
|
},
|
|
get hash() {
|
|
return stanza.getAttribute(this.xml, 'hash');
|
|
},
|
|
set hash(value) {
|
|
stanza.setAttribute(this.xml, 'hash', value);
|
|
},
|
|
get ext() {
|
|
return stanza.getAttribute(this.xml, 'ext');
|
|
},
|
|
set ext(value) {
|
|
stanza.setAttribute(this.xml, 'ext', value);
|
|
}
|
|
};
|
|
|
|
|
|
stanza.extend(Presence, Caps);
|
|
stanza.extend(StreamFeatures, Caps);
|
|
|
|
|
|
module.exports = Caps;
|
|
|
|
},{"./presence":37,"./streamFeatures":48,"jxt":74}],25:[function(require,module,exports){
|
|
var stanza = require('jxt');
|
|
var Message = require('./message');
|
|
var Iq = require('./iq');
|
|
var Forwarded = require('./forwarded');
|
|
|
|
|
|
function Sent(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
Sent.prototype = {
|
|
constructor: {
|
|
value: Sent
|
|
},
|
|
NS: 'urn:xmpp:carbons:2',
|
|
EL: 'sent',
|
|
_name: 'carbonSent',
|
|
_eventname: 'carbon:sent',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON
|
|
};
|
|
|
|
|
|
function Received(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
Received.prototype = {
|
|
constructor: {
|
|
value: Received
|
|
},
|
|
NS: 'urn:xmpp:carbons:2',
|
|
EL: 'received',
|
|
_name: 'carbonReceived',
|
|
_eventname: 'carbon:received',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON
|
|
};
|
|
|
|
|
|
function Private(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
Private.prototype = {
|
|
constructor: {
|
|
value: Private
|
|
},
|
|
NS: 'urn:xmpp:carbons:2',
|
|
EL: 'private',
|
|
_name: 'carbonPrivate',
|
|
_eventname: 'carbon:private',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON
|
|
};
|
|
|
|
|
|
function Enable(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
Enable.prototype = {
|
|
constructor: {
|
|
value: Enable
|
|
},
|
|
NS: 'urn:xmpp:carbons:2',
|
|
EL: 'enable',
|
|
_name: 'enableCarbons',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON
|
|
};
|
|
|
|
|
|
function Disable(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
Disable.prototype = {
|
|
constructor: {
|
|
value: Disable
|
|
},
|
|
NS: 'urn:xmpp:carbons:2',
|
|
EL: 'disable',
|
|
_name: 'disableCarbons',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON
|
|
};
|
|
|
|
|
|
stanza.extend(Sent, Forwarded);
|
|
stanza.extend(Received, Forwarded);
|
|
stanza.extend(Message, Sent);
|
|
stanza.extend(Message, Received);
|
|
stanza.extend(Message, Private);
|
|
stanza.extend(Iq, Enable);
|
|
stanza.extend(Iq, Disable);
|
|
|
|
|
|
exports.Sent = Sent;
|
|
exports.Received = Received;
|
|
exports.Private = Private;
|
|
exports.Enable = Enable;
|
|
exports.Disable = Disable;
|
|
|
|
},{"./forwarded":31,"./iq":33,"./message":35,"jxt":74}],26:[function(require,module,exports){
|
|
var stanza = require('jxt');
|
|
var Message = require('./message');
|
|
|
|
|
|
function ChatStateActive(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
ChatStateActive.prototype = {
|
|
constructor: {
|
|
value: ChatStateActive
|
|
},
|
|
NS: 'http://jabber.org/protocol/chatstates',
|
|
EL: 'active',
|
|
_name: 'chatStateActive',
|
|
_eventname: 'chat:active',
|
|
toString: stanza.toString,
|
|
toJSON: undefined
|
|
};
|
|
|
|
|
|
function ChatStateComposing(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
ChatStateComposing.prototype = {
|
|
constructor: {
|
|
value: ChatStateComposing
|
|
},
|
|
NS: 'http://jabber.org/protocol/chatstates',
|
|
EL: 'composing',
|
|
_name: 'chatStateComposing',
|
|
_eventname: 'chat:composing',
|
|
toString: stanza.toString,
|
|
toJSON: undefined
|
|
};
|
|
|
|
|
|
function ChatStatePaused(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
ChatStatePaused.prototype = {
|
|
constructor: {
|
|
value: ChatStatePaused
|
|
},
|
|
NS: 'http://jabber.org/protocol/chatstates',
|
|
EL: 'paused',
|
|
_name: 'chatStatePaused',
|
|
_eventname: 'chat:paused',
|
|
toString: stanza.toString,
|
|
toJSON: undefined
|
|
};
|
|
|
|
|
|
function ChatStateInactive(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
ChatStateInactive.prototype = {
|
|
constructor: {
|
|
value: ChatStateInactive
|
|
},
|
|
NS: 'http://jabber.org/protocol/chatstates',
|
|
EL: 'inactive',
|
|
_name: 'chatStateInactive',
|
|
_eventname: 'chat:inactive',
|
|
toString: stanza.toString,
|
|
toJSON: undefined
|
|
};
|
|
|
|
|
|
function ChatStateGone(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
ChatStateGone.prototype = {
|
|
constructor: {
|
|
value: ChatStateGone
|
|
},
|
|
NS: 'http://jabber.org/protocol/chatstates',
|
|
EL: 'gone',
|
|
_name: 'chatStateGone',
|
|
_eventname: 'chat:gone',
|
|
toString: stanza.toString,
|
|
toJSON: undefined
|
|
};
|
|
|
|
|
|
stanza.extend(Message, ChatStateActive);
|
|
stanza.extend(Message, ChatStateComposing);
|
|
stanza.extend(Message, ChatStatePaused);
|
|
stanza.extend(Message, ChatStateInactive);
|
|
stanza.extend(Message, ChatStateGone);
|
|
|
|
|
|
Message.prototype.__defineGetter__('chatState', function () {
|
|
var self = this;
|
|
var states = ['Active', 'Composing', 'Paused', 'Inactive', 'Gone'];
|
|
|
|
for (var i = 0; i < states.length; i++) {
|
|
if (self._extensions['chatState' + states[i]]) {
|
|
return states[i].toLowerCase();
|
|
}
|
|
}
|
|
return '';
|
|
});
|
|
Message.prototype.__defineSetter__('chatState', function (value) {
|
|
var self = this;
|
|
var states = ['Active', 'Composing', 'Paused', 'Inactive', 'Gone'];
|
|
|
|
states.forEach(function (state) {
|
|
if (self._extensions['chatState' + state]) {
|
|
self.xml.removeChild(self._extensions['chatState' + state].xml);
|
|
delete self._extensions['chatState' + state];
|
|
}
|
|
});
|
|
if (value) {
|
|
this['chatState' + value.charAt(0).toUpperCase() + value.slice(1)];
|
|
}
|
|
});
|
|
|
|
},{"./message":35,"jxt":74}],27:[function(require,module,exports){
|
|
var _ = require('../../vendor/lodash');
|
|
var stanza = require('jxt');
|
|
var Message = require('./message');
|
|
|
|
|
|
function DataForm(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
DataForm.prototype = {
|
|
constructor: {
|
|
value: DataForm
|
|
},
|
|
NS: 'jabber:x:data',
|
|
EL: 'x',
|
|
_name: 'form',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON,
|
|
get title() {
|
|
return stanza.getSubText(this.xml, this.NS, 'title');
|
|
},
|
|
set title(value) {
|
|
stanza.setSubText(this.xml, this.NS, 'title', value);
|
|
},
|
|
get instructions() {
|
|
return stanza.getMultiSubText(this.xml, this.NS, 'title').join('\n');
|
|
},
|
|
set instructions(value) {
|
|
stanza.setMultiSubText(this.xml, this.NS, 'title', value.split('\n'));
|
|
},
|
|
get type() {
|
|
return stanza.getAttribute(this.xml, 'type', 'form');
|
|
},
|
|
set type(value) {
|
|
stanza.setAttribute(this.xml, 'type', value);
|
|
},
|
|
get fields() {
|
|
var fields = stanza.find(this.xml, this.NS, 'field');
|
|
var results = [];
|
|
|
|
_.forEach(fields, function (field) {
|
|
results.push(new Field({}, field).toJSON());
|
|
});
|
|
return results;
|
|
},
|
|
set fields(value) {
|
|
var self = this;
|
|
_.forEach(value, function (field) {
|
|
self.addField(field);
|
|
});
|
|
},
|
|
addField: function (opts) {
|
|
var field = new Field(opts);
|
|
this.xml.appendChild(field.xml);
|
|
},
|
|
};
|
|
|
|
|
|
function Field(data, xml) {
|
|
stanza.init(this, xml, data);
|
|
this._type = data.type || this.type;
|
|
return this;
|
|
}
|
|
Field.prototype = {
|
|
constructor: {
|
|
value: Field
|
|
},
|
|
NS: 'jabber:x:data',
|
|
EL: 'field',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON,
|
|
get type() {
|
|
return stanza.getAttribute(this.xml, 'type', 'text-single');
|
|
},
|
|
set type(value) {
|
|
this._type = value;
|
|
stanza.setAttribute(this.xml, 'type', value);
|
|
},
|
|
get name() {
|
|
return stanza.getAttribute(this.xml, 'var');
|
|
},
|
|
set name(value) {
|
|
stanza.setAttribute(this.xml, 'var', value);
|
|
},
|
|
get desc() {
|
|
return stanza.getSubText(this.xml, this.NS, 'desc');
|
|
},
|
|
set desc(value) {
|
|
stanza.setSubText(this.xml, this.NS, 'desc', value);
|
|
},
|
|
get value() {
|
|
var vals = stanza.getMultiSubText(this.xml, this.NS, 'value');
|
|
if (this._type === 'boolean') {
|
|
return vals[0] === '1' || vals[0] === 'true';
|
|
}
|
|
if (vals.length > 1) {
|
|
if (this._type === 'text-multi') {
|
|
return vals.join('\n');
|
|
}
|
|
return vals;
|
|
}
|
|
return vals[0];
|
|
},
|
|
set value(value) {
|
|
if (this._type === 'boolean') {
|
|
stanza.setSubText(this.xml, this.NS, 'value', value ? '1' : '0');
|
|
} else {
|
|
if (this._type === 'text-multi') {
|
|
value = value.split('\n');
|
|
}
|
|
stanza.setMultiSubText(this.xml, this.NS, 'value', value);
|
|
}
|
|
},
|
|
get required() {
|
|
var req = stanza.find(this.xml, this.NS, 'required');
|
|
return req.length > 0;
|
|
},
|
|
set required(value) {
|
|
var reqs = stanza.find(this.xml, this.NS, 'required');
|
|
if (value && reqs.length === 0) {
|
|
var req = document.createElementNS(this.NS, 'required');
|
|
this.xml.appendChild(req);
|
|
} else if (!value && reqs.length > 0) {
|
|
_.forEach(reqs, function (req) {
|
|
this.xml.removeChild(req);
|
|
});
|
|
}
|
|
},
|
|
get label() {
|
|
return stanza.getAttribute(this.xml, 'label');
|
|
},
|
|
set label(value) {
|
|
stanza.setAttribute(this.xml, 'label', value);
|
|
},
|
|
get options() {
|
|
var self = this;
|
|
return stanza.getMultiSubText(this.xml, this.NS, 'option', function (sub) {
|
|
return stanza.getSubText(sub, self.NS, 'value');
|
|
});
|
|
},
|
|
set options(value) {
|
|
var self = this;
|
|
stanza.setMultiSubText(this.xml, this.NS, 'option', value, function (val) {
|
|
var opt = document.createElementNS(self.NS, 'option');
|
|
var value = document.createElementNS(self.NS, 'value');
|
|
|
|
opt.appendChild(value);
|
|
value.textContent = val;
|
|
self.xml.appendChild(opt);
|
|
});
|
|
}
|
|
};
|
|
|
|
|
|
stanza.extend(Message, DataForm);
|
|
|
|
|
|
exports.DataForm = DataForm;
|
|
exports.Field = Field;
|
|
|
|
},{"../../vendor/lodash":90,"./message":35,"jxt":74}],28:[function(require,module,exports){
|
|
var stanza = require('jxt');
|
|
var Message = require('./message');
|
|
var Presence = require('./presence');
|
|
|
|
|
|
function DelayedDelivery(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
DelayedDelivery.prototype = {
|
|
constructor: {
|
|
value: DelayedDelivery
|
|
},
|
|
NS: 'urn:xmpp:delay',
|
|
EL: 'delay',
|
|
_name: 'delay',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON,
|
|
get from() {
|
|
return stanza.getAttribute(this.xml, 'from');
|
|
},
|
|
set from(value) {
|
|
stanza.setAttribute(this.xml, 'from', value);
|
|
},
|
|
get stamp() {
|
|
return new Date(stanza.getAttribute(this.xml, 'stamp') || Date.now());
|
|
},
|
|
set stamp(value) {
|
|
stanza.setAttribute(this.xml, 'stamp', value.toISOString());
|
|
},
|
|
get reason() {
|
|
return this.xml.textContent || '';
|
|
},
|
|
set reason(value) {
|
|
this.xml.textContent = value;
|
|
}
|
|
};
|
|
|
|
|
|
stanza.extend(Message, DelayedDelivery);
|
|
stanza.extend(Presence, DelayedDelivery);
|
|
|
|
|
|
module.exports = DelayedDelivery;
|
|
|
|
},{"./message":35,"./presence":37,"jxt":74}],29:[function(require,module,exports){
|
|
var _ = require('../../vendor/lodash');
|
|
var stanza = require('jxt');
|
|
var Iq = require('./iq');
|
|
var RSM = require('./rsm');
|
|
var DataForm = require('./dataforms').DataForm;
|
|
|
|
|
|
function DiscoInfo(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
DiscoInfo.prototype = {
|
|
constructor: {
|
|
value: DiscoInfo
|
|
},
|
|
_name: 'discoInfo',
|
|
NS: 'http://jabber.org/protocol/disco#info',
|
|
EL: 'query',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON,
|
|
get node() {
|
|
return stanza.getAttribute(this.xml, 'node');
|
|
},
|
|
set node(value) {
|
|
stanza.setAttribute(this.xml, 'node', value);
|
|
},
|
|
get identities() {
|
|
var result = [];
|
|
var identities = stanza.find(this.xml, this.NS, 'identity');
|
|
identities.forEach(function (identity) {
|
|
result.push({
|
|
category: stanza.getAttribute(identity, 'category'),
|
|
type: stanza.getAttribute(identity, 'type'),
|
|
lang: identity.getAttributeNS(stanza.XML_NS, 'lang'),
|
|
name: stanza.getAttribute(identity, 'name')
|
|
});
|
|
});
|
|
return result;
|
|
},
|
|
set identities(values) {
|
|
var self = this;
|
|
|
|
var existing = stanza.find(this.xml, this.NS, 'identity');
|
|
existing.forEach(function (item) {
|
|
self.xml.removeChild(item);
|
|
});
|
|
values.forEach(function (value) {
|
|
var identity = document.createElementNS(self.NS, 'identity');
|
|
stanza.setAttribute(identity, 'category', value.category);
|
|
stanza.setAttribute(identity, 'type', value.type);
|
|
stanza.setAttribute(identity, 'name', value.name);
|
|
if (value.lang) {
|
|
identity.setAttributeNS(stanza.XML_NS, 'lang', value.lang);
|
|
}
|
|
self.xml.appendChild(identity);
|
|
});
|
|
|
|
},
|
|
get features() {
|
|
var result = [];
|
|
var features = stanza.find(this.xml, this.NS, 'feature');
|
|
features.forEach(function (feature) {
|
|
result.push(feature.getAttribute('var'));
|
|
});
|
|
return result;
|
|
},
|
|
set features(values) {
|
|
var self = this;
|
|
|
|
var existing = stanza.find(this.xml, this.NS, 'feature');
|
|
existing.forEach(function (item) {
|
|
self.xml.removeChild(item);
|
|
});
|
|
values.forEach(function (value) {
|
|
var feature = document.createElementNS(self.NS, 'feature');
|
|
feature.setAttribute('var', value);
|
|
self.xml.appendChild(feature);
|
|
});
|
|
},
|
|
get extensions() {
|
|
var self = this;
|
|
var result = [];
|
|
|
|
var forms = stanza.find(this.xml, DataForm.NS, DataForm.EL);
|
|
forms.forEach(function (form) {
|
|
var ext = new DataForm({}, form);
|
|
result.push(ext.toJSON());
|
|
});
|
|
},
|
|
set extensions(value) {
|
|
var self = this;
|
|
|
|
var forms = stanza.find(this.xml, DataForm.NS, DataForm.EL);
|
|
forms.forEach(function (form) {
|
|
self.xml.removeChild(form);
|
|
});
|
|
|
|
value.forEach(function (ext) {
|
|
var form = new DataForm(ext);
|
|
self.xml.appendChild(form.xml);
|
|
});
|
|
}
|
|
};
|
|
|
|
|
|
function DiscoItems(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
DiscoItems.prototype = {
|
|
constructor: {
|
|
value: DiscoInfo
|
|
},
|
|
_name: 'discoItems',
|
|
NS: 'http://jabber.org/protocol/disco#items',
|
|
EL: 'query',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON,
|
|
get node() {
|
|
return stanza.getAttribute(this.xml, 'node');
|
|
},
|
|
set node(value) {
|
|
stanza.setAttribute(this.xml, 'node', value);
|
|
},
|
|
get items() {
|
|
var result = [];
|
|
var items = stanza.find(this.xml, this.NS, 'item');
|
|
items.forEach(function (item) {
|
|
result.push({
|
|
jid: stanza.getAttribute(item, 'jid'),
|
|
node: stanza.getAttribute(item, 'node'),
|
|
name: stanza.getAttribute(item, 'name')
|
|
});
|
|
});
|
|
return result;
|
|
},
|
|
set items(values) {
|
|
var self = this;
|
|
|
|
var existing = stanza.find(this.xml, this.NS, 'item');
|
|
existing.forEach(function (item) {
|
|
self.xml.removeChild(item);
|
|
});
|
|
values.forEach(function (value) {
|
|
var item = document.createElementNS(self.NS, 'item');
|
|
stanza.setAttribute(item, 'jid', value.jid);
|
|
stanza.setAttribute(item, 'node', value.node);
|
|
stanza.setAttribute(item, 'name', value.name);
|
|
self.xml.appendChild(item);
|
|
});
|
|
}
|
|
};
|
|
|
|
|
|
stanza.extend(Iq, DiscoInfo);
|
|
stanza.extend(Iq, DiscoItems);
|
|
stanza.extend(DiscoItems, RSM);
|
|
|
|
exports.DiscoInfo = DiscoInfo;
|
|
exports.DiscoItems = DiscoItems;
|
|
|
|
},{"../../vendor/lodash":90,"./dataforms":27,"./iq":33,"./rsm":42,"jxt":74}],30:[function(require,module,exports){
|
|
var _ = require('../../vendor/lodash');
|
|
var stanza = require('jxt');
|
|
var Message = require('./message');
|
|
var Presence = require('./presence');
|
|
var Iq = require('./iq');
|
|
|
|
|
|
function Error(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
Error.prototype = {
|
|
constructor: {
|
|
value: Error
|
|
},
|
|
_name: 'error',
|
|
NS: 'jabber:client',
|
|
EL: 'error',
|
|
_ERR_NS: 'urn:ietf:params:xml:ns:xmpp-stanzas',
|
|
_CONDITIONS: [
|
|
'bad-request', 'conflict', 'feature-not-implemented',
|
|
'forbidden', 'gone', 'internal-server-error',
|
|
'item-not-found', 'jid-malformed', 'not-acceptable',
|
|
'not-allowed', 'not-authorized', 'payment-required',
|
|
'recipient-unavailable', 'redirect',
|
|
'registration-required', 'remote-server-not-found',
|
|
'remote-server-timeout', 'resource-constraint',
|
|
'service-unavailable', 'subscription-required',
|
|
'undefined-condition', 'unexpected-request'
|
|
],
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON,
|
|
get lang() {
|
|
if (this.parent) {
|
|
return this.parent.lang;
|
|
}
|
|
return '';
|
|
},
|
|
get condition() {
|
|
var self = this;
|
|
var result = [];
|
|
this._CONDITIONS.forEach(function (condition) {
|
|
var exists = stanza.find(self.xml, self._ERR_NS, condition);
|
|
if (exists.length) {
|
|
result.push(exists[0].tagName);
|
|
}
|
|
});
|
|
return result[0] || '';
|
|
},
|
|
set condition(value) {
|
|
var self = this;
|
|
this._CONDITIONS.forEach(function (condition) {
|
|
var exists = stanza.find(self.xml, self._ERR_NS, condition);
|
|
if (exists.length) {
|
|
self.xml.removeChild(exists[0]);
|
|
}
|
|
});
|
|
|
|
if (value) {
|
|
var condition = document.createElementNS(this._ERR_NS, value);
|
|
condition.setAttribute('xmlns', this._ERR_NS);
|
|
this.xml.appendChild(condition);
|
|
}
|
|
},
|
|
get gone() {
|
|
return stanza.getSubText(this.xml, this._ERR_NS, 'gone');
|
|
},
|
|
set gone(value) {
|
|
this.condition = 'gone';
|
|
stanza.setSubText(this.xml, this._ERR_NS, 'gone', value);
|
|
},
|
|
get redirect() {
|
|
return stanza.getSubText(this.xml, this._ERR_NS, 'redirect');
|
|
},
|
|
set redirect(value) {
|
|
this.condition = 'redirect';
|
|
stanza.setSubText(this.xml, this._ERR_NS, 'redirect', value);
|
|
},
|
|
get code() {
|
|
return stanza.getAttribute(this.xml, 'code');
|
|
},
|
|
set code(value) {
|
|
stanza.setAttribute(this.xml, 'code', value);
|
|
},
|
|
get type() {
|
|
return stanza.getAttribute(this.xml, 'type');
|
|
},
|
|
set type(value) {
|
|
stanza.setAttribute(this.xml, 'type', value);
|
|
},
|
|
get by() {
|
|
return stanza.getAttribute(this.xml, 'by');
|
|
},
|
|
set by(value) {
|
|
stanza.setAttribute(this.xml, 'by', value);
|
|
},
|
|
get $text() {
|
|
return stanza.getSubLangText(this.xml, this._ERR_NS, 'text', this.lang);
|
|
},
|
|
set text(value) {
|
|
stanza.setSubLangText(this.xml, this._ERR_NS, 'text', value, this.lang);
|
|
},
|
|
get text() {
|
|
var text = this.$text;
|
|
return text[this.lang] || '';
|
|
},
|
|
};
|
|
|
|
stanza.extend(Message, Error);
|
|
stanza.extend(Presence, Error);
|
|
stanza.extend(Iq, Error);
|
|
|
|
|
|
module.exports = Error;
|
|
|
|
},{"../../vendor/lodash":90,"./iq":33,"./message":35,"./presence":37,"jxt":74}],31:[function(require,module,exports){
|
|
var stanza = require('jxt');
|
|
var Message = require('./message');
|
|
var Presence = require('./presence');
|
|
var Iq = require('./iq');
|
|
var DelayedDelivery = require('./delayed');
|
|
|
|
|
|
function Forwarded(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
Forwarded.prototype = {
|
|
constructor: {
|
|
value: Forwarded
|
|
},
|
|
NS: 'urn:xmpp:forward:0',
|
|
EL: 'forwarded',
|
|
_name: 'forwarded',
|
|
_eventname: 'forward',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON
|
|
};
|
|
|
|
|
|
stanza.extend(Message, Forwarded);
|
|
stanza.extend(Forwarded, Message);
|
|
stanza.extend(Forwarded, Presence);
|
|
stanza.extend(Forwarded, Iq);
|
|
stanza.extend(Forwarded, DelayedDelivery);
|
|
|
|
|
|
module.exports = Forwarded;
|
|
|
|
},{"./delayed":28,"./iq":33,"./message":35,"./presence":37,"jxt":74}],32:[function(require,module,exports){
|
|
var stanza = require('jxt');
|
|
var Presence = require('./presence');
|
|
|
|
|
|
function Idle(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
Idle.prototype = {
|
|
constructor: {
|
|
value: Idle
|
|
},
|
|
NS: 'urn:xmpp:idle:0',
|
|
EL: 'idle',
|
|
_name: 'idle',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON,
|
|
get since() {
|
|
return new Date(stanza.getAttribute(this.xml, 'since') || Date.now());
|
|
},
|
|
set since(value) {
|
|
stanza.setAttribute(this.xml, 'since', value.toISOString());
|
|
}
|
|
};
|
|
|
|
|
|
stanza.extend(Presence, Idle);
|
|
|
|
|
|
module.exports = Idle;
|
|
|
|
},{"./presence":37,"jxt":74}],33:[function(require,module,exports){
|
|
var stanza = require('jxt');
|
|
|
|
|
|
function Iq(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
Iq.prototype = {
|
|
constructor: {
|
|
value: Iq
|
|
},
|
|
_name: 'iq',
|
|
NS: 'jabber:client',
|
|
EL: 'iq',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON,
|
|
resultReply: function (data) {
|
|
data.to = this.from;
|
|
data.id = this.id;
|
|
data.type = 'result';
|
|
return new Iq(data);
|
|
},
|
|
errorReply: function (data) {
|
|
data.to = this.from;
|
|
data.id = this.id;
|
|
data.type = 'error';
|
|
return new Iq(data);
|
|
},
|
|
get lang() {
|
|
return this.xml.getAttributeNS(stanza.XML_NS, 'lang') || '';
|
|
},
|
|
set lang(value) {
|
|
this.xml.setAttributeNS(stanza.XML_NS, 'lang', value);
|
|
},
|
|
get id() {
|
|
return stanza.getAttribute(this.xml, 'id');
|
|
},
|
|
set id(value) {
|
|
stanza.setAttribute(this.xml, 'id', value);
|
|
},
|
|
get to() {
|
|
return stanza.getAttribute(this.xml, 'to');
|
|
},
|
|
set to(value) {
|
|
stanza.setAttribute(this.xml, 'to', value);
|
|
},
|
|
get from() {
|
|
return stanza.getAttribute(this.xml, 'from');
|
|
},
|
|
set from(value) {
|
|
stanza.setAttribute(this.xml, 'from', value);
|
|
},
|
|
get type() {
|
|
return stanza.getAttribute(this.xml, 'type');
|
|
},
|
|
set type(value) {
|
|
stanza.setAttribute(this.xml, 'type', value);
|
|
}
|
|
};
|
|
|
|
stanza.topLevel(Iq);
|
|
|
|
|
|
module.exports = Iq;
|
|
|
|
},{"jxt":74}],34:[function(require,module,exports){
|
|
var stanza = require('jxt');
|
|
var Message = require('./message');
|
|
var Iq = require('./iq');
|
|
var Forwarded = require('./forwarded');
|
|
var RSM = require('./rsm');
|
|
|
|
|
|
function MAMQuery(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
MAMQuery.prototype = {
|
|
constructor: {
|
|
value: MAMQuery
|
|
},
|
|
NS: 'urn:xmpp:mam:tmp',
|
|
EL: 'query',
|
|
_name: 'mamQuery',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON,
|
|
get queryid() {
|
|
return stanza.getAttribute(this.xml, 'queryid');
|
|
},
|
|
set queryid(value) {
|
|
stanza.setAttribute(this.xml, 'queryid', value);
|
|
},
|
|
get start() {
|
|
return new Date(stanza.getSubText(this.xml, this.NS, 'start') || Date.now());
|
|
},
|
|
set start(value) {
|
|
stanza.setSubText(this.xml, this.NS, 'start', value.toISOString());
|
|
},
|
|
get end() {
|
|
return new Date(stanza.getSubText(this.xml, this.NS, 'end') || Date.now());
|
|
},
|
|
set end(value) {
|
|
stanza.setSubText(this.xml, this.NS, 'end', value.toISOString());
|
|
}
|
|
};
|
|
MAMQuery.prototype.__defineGetter__('with', function () {
|
|
return stanza.getSubText(this.xml, this.NS, 'with');
|
|
});
|
|
MAMQuery.prototype.__defineSetter__('with', function (value) {
|
|
stanza.setSubText(this.xml, this.NS, 'with', value);
|
|
});
|
|
|
|
|
|
function Result(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
Result.prototype = {
|
|
constructor: {
|
|
value: Result
|
|
},
|
|
NS: 'urn:xmpp:mam:tmp',
|
|
EL: 'result',
|
|
_name: 'mam',
|
|
_eventname: 'mam:result',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON,
|
|
get queryid() {
|
|
return stanza.getAttribute(this.xml, 'queryid');
|
|
},
|
|
set queryid(value) {
|
|
stanza.setAttribute(this.xml, 'queryid', value);
|
|
},
|
|
get id() {
|
|
return stanza.getAttribute(this.xml, 'id');
|
|
},
|
|
set id(value) {
|
|
stanza.setAttribute(this.xml, 'id', value);
|
|
}
|
|
};
|
|
|
|
|
|
function Prefs(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
Prefs.prototype = {
|
|
constructor: {
|
|
value: Prefs
|
|
},
|
|
NS: 'urn:xmpp:mam:tmp',
|
|
EL: 'prefs',
|
|
_name: 'mamPrefs',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON,
|
|
get defaultCondition() {
|
|
return stanza.getAttribute(this.xml, 'default');
|
|
},
|
|
set defaultCondition(value) {
|
|
stanza.setAttribute(this.xml, 'default', value);
|
|
},
|
|
get always() {
|
|
var results = [];
|
|
var container = stanza.find(this.xml, this.NS, 'always');
|
|
if (container.length === 0) {
|
|
return results;
|
|
}
|
|
container = container[0];
|
|
var jids = stanza.getMultiSubText(container, this.NS, 'jid');
|
|
jids.forEach(function (jid) {
|
|
results.push(jid.textContent);
|
|
});
|
|
return results;
|
|
},
|
|
set always(value) {
|
|
if (value.length > 0) {
|
|
var container = stanza.find(this.xml, this.NS, 'always');
|
|
stanza.setMultiSubText(container, this.NS, 'jid', value);
|
|
}
|
|
},
|
|
get never() {
|
|
var results = [];
|
|
var container = stanza.find(this.xml, this.NS, 'always');
|
|
if (container.length === 0) {
|
|
return results;
|
|
}
|
|
container = container[0];
|
|
var jids = stanza.getMultiSubText(container, this.NS, 'jid');
|
|
jids.forEach(function (jid) {
|
|
results.push(jid.textContent);
|
|
});
|
|
return results;
|
|
|
|
},
|
|
set never(value) {
|
|
if (value.length > 0) {
|
|
var container = stanza.find(this.xml, this.NS, 'never');
|
|
stanza.setMultiSubText(container, this.NS, 'jid', value);
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
|
|
|
|
stanza.extend(Iq, MAMQuery);
|
|
stanza.extend(Iq, Prefs);
|
|
stanza.extend(Message, Result);
|
|
stanza.extend(Result, Forwarded);
|
|
stanza.extend(MAMQuery, RSM);
|
|
|
|
|
|
Message.prototype.__defineGetter__('archived', function () {
|
|
var self = this;
|
|
|
|
var archives = stanza.find(this.xml, 'urn:xmpp:mam:tmp', 'archived');
|
|
|
|
var results = [];
|
|
archives.forEach(function (archive) {
|
|
results.push({
|
|
by: stanza.getAttribute(archive, 'by'),
|
|
id: stanza.getAttribute(archive, 'id')
|
|
});
|
|
});
|
|
|
|
return results;
|
|
});
|
|
Message.prototype.__defineSetter__('archived', function (value) {
|
|
var self = this;
|
|
|
|
value.forEach(function (val) {
|
|
var archive = document.createElementNS('urn:xmpp:mam:tmp', 'archived');
|
|
stanza.setAttribute(archive, 'by', val.by);
|
|
stanza.setAttribute(archive, 'id', val.id);
|
|
self.xml.appendChild(archive);
|
|
});
|
|
});
|
|
|
|
|
|
exports.MAMQuery = MAMQuery;
|
|
exports.Result = Result;
|
|
|
|
},{"./forwarded":31,"./iq":33,"./message":35,"./rsm":42,"jxt":74}],35:[function(require,module,exports){
|
|
var _ = require('../../vendor/lodash');
|
|
var stanza = require('jxt');
|
|
|
|
|
|
function Message(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
Message.prototype = {
|
|
constructor: {
|
|
value: Message
|
|
},
|
|
_name: 'message',
|
|
NS: 'jabber:client',
|
|
EL: 'message',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON,
|
|
get lang() {
|
|
return this.xml.getAttributeNS(stanza.XML_NS, 'lang') || '';
|
|
},
|
|
set lang(value) {
|
|
this.xml.setAttributeNS(stanza.XML_NS, 'lang', value);
|
|
},
|
|
get id() {
|
|
return stanza.getAttribute(this.xml, 'id');
|
|
},
|
|
set id(value) {
|
|
stanza.setAttribute(this.xml, 'id', value);
|
|
},
|
|
get to() {
|
|
return stanza.getAttribute(this.xml, 'to');
|
|
},
|
|
set to(value) {
|
|
stanza.setAttribute(this.xml, 'to', value);
|
|
},
|
|
get from() {
|
|
return stanza.getAttribute(this.xml, 'from');
|
|
},
|
|
set from(value) {
|
|
stanza.setAttribute(this.xml, 'from', value);
|
|
},
|
|
get type() {
|
|
return stanza.getAttribute(this.xml, 'type', 'normal');
|
|
},
|
|
set type(value) {
|
|
stanza.setAttribute(this.xml, 'type', value);
|
|
},
|
|
get body() {
|
|
var bodies = this.$body;
|
|
return bodies[this.lang] || '';
|
|
},
|
|
get $body() {
|
|
return stanza.getSubLangText(this.xml, this.NS, 'body', this.lang);
|
|
},
|
|
set body(value) {
|
|
stanza.setSubLangText(this.xml, this.NS, 'body', value, this.lang);
|
|
},
|
|
get thread() {
|
|
return stanza.getSubText(this.xml, this.NS, 'thread');
|
|
},
|
|
set thread(value) {
|
|
stanza.setSubText(this.xml, this.NS, 'thread', value);
|
|
},
|
|
get parentThread() {
|
|
return stanza.getSubAttribute(this.xml, this.NS, 'thread', 'parent');
|
|
},
|
|
set parentThread(value) {
|
|
stanza.setSubAttribute(this.xml, this.NS, 'thread', 'parent', value);
|
|
}
|
|
};
|
|
|
|
stanza.topLevel(Message);
|
|
|
|
|
|
module.exports = Message;
|
|
|
|
},{"../../vendor/lodash":90,"jxt":74}],36:[function(require,module,exports){
|
|
var stanza = require('jxt');
|
|
var Message = require('./message');
|
|
var Presence = require('./presence');
|
|
var Iq = require('./iq');
|
|
|
|
|
|
function MUCJoin(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
MUCJoin.prototype = {
|
|
constructor: {
|
|
value: MUCJoin
|
|
},
|
|
NS: 'http://jabber.org/protocol/muc',
|
|
EL: 'x',
|
|
_name: 'joinMuc',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON,
|
|
get password() {
|
|
return stanza.getSubText(this.xml, this.NS, 'password');
|
|
},
|
|
set password(value) {
|
|
stanza.setSubText(this.xml, this.NS, 'password', value);
|
|
},
|
|
get history() {
|
|
var result = {};
|
|
var hist = stanza.find(this.xml, this.NS, 'history');
|
|
|
|
if (!hist.length) {
|
|
return {};
|
|
}
|
|
hist = hist[0];
|
|
|
|
var maxchars = hist.getAttribute('maxchars') || '';
|
|
var maxstanzas = hist.getAttribute('maxstanas') || '';
|
|
var seconds = hist.getAttribute('seconds') || '';
|
|
var since = hist.getAttribute('since') || '';
|
|
|
|
|
|
if (maxchars) {
|
|
result.maxchars = parseInt(maxchars, 10);
|
|
}
|
|
if (maxstanzas) {
|
|
result.maxstanzas = parseInt(maxstanzas, 10);
|
|
}
|
|
if (seconds) {
|
|
result.seconds = parseInt(seconds, 10);
|
|
}
|
|
if (since) {
|
|
result.since = new Date(since);
|
|
}
|
|
},
|
|
set history(opts) {
|
|
var existing = stanza.find(this.xml, this.NS, 'history');
|
|
if (existing.length) {
|
|
for (var i = 0; i < existing.length; i++) {
|
|
this.xml.removeChild(existing[i]);
|
|
}
|
|
}
|
|
|
|
var hist = document.createElementNS(this.NS, 'history');
|
|
this.xml.appendChild(hist);
|
|
|
|
if (opts.maxchars) {
|
|
hist.setAttribute('' + opts.maxchars);
|
|
}
|
|
if (opts.maxstanzas) {
|
|
hist.setAttribute('' + opts.maxstanzas);
|
|
}
|
|
if (opts.seconds) {
|
|
hist.setAttribute('' + opts.seconds);
|
|
}
|
|
if (opts.since) {
|
|
hist.setAttribute(opts.since.toISOString());
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
stanza.extend(Presence, MUCJoin);
|
|
|
|
exports.MUCJoin = MUCJoin;
|
|
|
|
},{"./iq":33,"./message":35,"./presence":37,"jxt":74}],37:[function(require,module,exports){
|
|
var _ = require('../../vendor/lodash');
|
|
var stanza = require('jxt');
|
|
|
|
|
|
function Presence(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
Presence.prototype = {
|
|
constructor: {
|
|
value: Presence
|
|
},
|
|
_name: 'presence',
|
|
NS: 'jabber:client',
|
|
EL: 'presence',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON,
|
|
get lang() {
|
|
return this.xml.getAttributeNS(stanza.XML_NS, 'lang') || '';
|
|
},
|
|
set lang(value) {
|
|
this.xml.setAttributeNS(stanza.XML_NS, 'lang', value);
|
|
},
|
|
get id() {
|
|
return stanza.getAttribute(this.xml, 'id');
|
|
},
|
|
set id(value) {
|
|
stanza.setAttribute(this.xml, 'id', value);
|
|
},
|
|
get to() {
|
|
return stanza.getAttribute(this.xml, 'to');
|
|
},
|
|
set to(value) {
|
|
stanza.setAttribute(this.xml, 'to', value);
|
|
},
|
|
get from() {
|
|
return stanza.getAttribute(this.xml, 'from');
|
|
},
|
|
set from(value) {
|
|
stanza.setAttribute(this.xml, 'from', value);
|
|
},
|
|
get type() {
|
|
return stanza.getAttribute(this.xml, 'type', 'available');
|
|
},
|
|
set type(value) {
|
|
if (value === 'available') {
|
|
value = false;
|
|
}
|
|
stanza.setAttribute(this.xml, 'type', value);
|
|
},
|
|
get status() {
|
|
var statuses = this.$status;
|
|
return statuses[this.lang] || '';
|
|
},
|
|
get $status() {
|
|
return stanza.getSubLangText(this.xml, this.NS, 'status', this.lang);
|
|
},
|
|
set status(value) {
|
|
stanza.setSubLangText(this.xml, this.NS, 'status', value, this.lang);
|
|
},
|
|
get priority() {
|
|
return stanza.getSubText(this.xml, this.NS, 'priority');
|
|
},
|
|
set priority(value) {
|
|
stanza.setSubText(this.xml, this.NS, 'priority', value);
|
|
},
|
|
get show() {
|
|
return stanza.getSubText(this.xml, this.NS, 'show');
|
|
},
|
|
set show(value) {
|
|
stanza.setSubText(this.xml, this.NS, 'show', value);
|
|
}
|
|
};
|
|
|
|
stanza.topLevel(Presence);
|
|
|
|
|
|
module.exports = Presence;
|
|
|
|
},{"../../vendor/lodash":90,"jxt":74}],38:[function(require,module,exports){
|
|
var _ = require('../../vendor/lodash');
|
|
var stanza = require('jxt');
|
|
var Iq = require('./iq');
|
|
var Message = require('./message');
|
|
var Form = require('./dataforms').DataForm;
|
|
var RSM = require('./rsm');
|
|
|
|
|
|
function Pubsub(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
Pubsub.prototype = {
|
|
constructor: {
|
|
value: Pubsub
|
|
},
|
|
_name: 'pubsub',
|
|
NS: 'http://jabber.org/protocol/pubsub',
|
|
EL: 'pubsub',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON,
|
|
get publishOptions() {
|
|
var conf = stanza.find(this.xml, this.NS, 'publish-options');
|
|
if (conf.length && conf[0].childNodes.length) {
|
|
return new Form({}, conf[0].childNodes[0]);
|
|
}
|
|
},
|
|
set publishOptions(value) {
|
|
var conf = stanza.findOrCreate(this.xml, this.NS, 'publish-options');
|
|
if (value) {
|
|
var form = new Form(value);
|
|
conf.appendChild(form.xml);
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
function PubsubOwner(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
PubsubOwner.prototype = {
|
|
constructor: {
|
|
value: PubsubOwner
|
|
},
|
|
_name: 'pubsubOwner',
|
|
NS: 'http://jabber.org/protocol/pubsub#owner',
|
|
EL: 'pubsub',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON,
|
|
get create() {
|
|
return stanza.getSubAttribute(this.xml, this.NS, 'create', 'node');
|
|
},
|
|
set create(value) {
|
|
stanza.setSubAttribute(this.xml, this.NS, 'create', 'node', value);
|
|
},
|
|
get purge() {
|
|
return stanza.getSubAttribute(this.xml, this.NS, 'purge', 'node');
|
|
},
|
|
set purge(value) {
|
|
stanza.setSubAttribute(this.xml, this.NS, 'purge', 'node', value);
|
|
},
|
|
get del() {
|
|
return stanza.getSubAttribute(this.xml, this.NS, 'delete', 'node');
|
|
},
|
|
set del(value) {
|
|
stanza.setSubAttribute(this.xml, this.NS, 'delete', 'node', value);
|
|
},
|
|
get redirect() {
|
|
var del = stanza.find(this.xml, this.NS, 'delete');
|
|
if (del.length) {
|
|
return stanza.getSubAttribute(del, this.NS, 'redirect', 'uri');
|
|
}
|
|
return '';
|
|
},
|
|
set redirect(value) {
|
|
var del = stanza.findOrCreate(this.xml, this.NS, 'delete');
|
|
stanza.setSubAttribute(del, this.NS, 'redirect', 'uri', value);
|
|
}
|
|
};
|
|
|
|
|
|
function Configure(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
Configure.prototype = {
|
|
constructor: {
|
|
value: Configure
|
|
},
|
|
_name: 'config',
|
|
NS: 'http://jabber.org/protocol/pubsub#owner',
|
|
EL: 'configure',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON,
|
|
get node() {
|
|
return stanza.getAttribute(this.xml, 'node');
|
|
},
|
|
set node(value) {
|
|
stanza.setAttribute(this.xml, 'node', value);
|
|
}
|
|
};
|
|
|
|
|
|
function Event(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
Event.prototype = {
|
|
constructor: {
|
|
value: Event
|
|
},
|
|
_name: 'event',
|
|
NS: 'http://jabber.org/protocol/pubsub#event',
|
|
EL: 'event',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON
|
|
};
|
|
|
|
|
|
function Subscribe(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
Subscribe.prototype = {
|
|
constructor: {
|
|
value: Subscribe
|
|
},
|
|
_name: 'subscribe',
|
|
NS: 'http://jabber.org/protocol/pubsub',
|
|
EL: 'subscribe',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON,
|
|
get node() {
|
|
return stanza.getAttribute(this.xml, 'node');
|
|
},
|
|
set node(value) {
|
|
stanza.setAttribute(this.xml, 'node', value);
|
|
},
|
|
get jid() {
|
|
return stanza.getAttribute(this.xml, 'jid');
|
|
},
|
|
set jid(value) {
|
|
stanza.setAttribute(this.xml, 'jid', value);
|
|
}
|
|
};
|
|
|
|
|
|
function Subscription(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
Subscription.prototype = {
|
|
constructor: {
|
|
value: Subscription
|
|
},
|
|
_name: 'subscription',
|
|
NS: 'http://jabber.org/protocol/pubsub',
|
|
EL: 'subscription',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON,
|
|
get node() {
|
|
return stanza.getAttribute(this.xml, 'node');
|
|
},
|
|
set node(value) {
|
|
stanza.setAttribute(this.xml, 'node', value);
|
|
},
|
|
get jid() {
|
|
return stanza.getAttribute(this.xml, 'jid');
|
|
},
|
|
set jid(value) {
|
|
stanza.setAttribute(this.xml, 'jid', value);
|
|
},
|
|
get subid() {
|
|
return stanza.getAttribute(this.xml, 'subid');
|
|
},
|
|
set subid(value) {
|
|
stanza.setAttribute(this.xml, 'subid', value);
|
|
},
|
|
get type() {
|
|
return stanza.getAttribute(this.xml, 'subscription');
|
|
},
|
|
set type(value) {
|
|
stanza.setAttribute(this.xml, 'subscription', value);
|
|
}
|
|
};
|
|
|
|
|
|
function Unsubscribe(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
Unsubscribe.prototype = {
|
|
constructor: {
|
|
value: Unsubscribe
|
|
},
|
|
_name: 'unsubscribe',
|
|
NS: 'http://jabber.org/protocol/pubsub',
|
|
EL: 'unsubscribe',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON,
|
|
get node() {
|
|
return stanza.getAttribute(this.xml, 'node');
|
|
},
|
|
set node(value) {
|
|
stanza.setAttribute(this.xml, 'node', value);
|
|
},
|
|
get jid() {
|
|
return stanza.getAttribute(this.xml, 'jid');
|
|
},
|
|
set jid(value) {
|
|
stanza.setAttribute(this.xml, 'jid', value);
|
|
}
|
|
};
|
|
|
|
|
|
function Publish(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
Publish.prototype = {
|
|
constructor: {
|
|
value: Publish
|
|
},
|
|
_name: 'publish',
|
|
NS: 'http://jabber.org/protocol/pubsub',
|
|
EL: 'publish',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON,
|
|
get node() {
|
|
return stanza.getAttribute(this.xml, 'node');
|
|
},
|
|
set node(value) {
|
|
stanza.setAttribute(this.xml, 'node', value);
|
|
},
|
|
get item() {
|
|
var items = this.items;
|
|
if (items.length) {
|
|
return items[0];
|
|
}
|
|
},
|
|
set item(value) {
|
|
this.items = [value];
|
|
}
|
|
};
|
|
|
|
|
|
function Retract(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
Retract.prototype = {
|
|
constructor: {
|
|
value: Retract
|
|
},
|
|
_name: 'retract',
|
|
NS: 'http://jabber.org/protocol/pubsub',
|
|
EL: 'retract',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON,
|
|
get node() {
|
|
return stanza.getAttribute(this.xml, 'node');
|
|
},
|
|
set node(value) {
|
|
stanza.setAttribute(this.xml, 'node', value);
|
|
},
|
|
get notify() {
|
|
var notify = stanza.getAttribute(this.xml, 'notify');
|
|
return notify === 'true' || notify === '1';
|
|
},
|
|
set notify(value) {
|
|
if (value) {
|
|
value = '1';
|
|
}
|
|
stanza.setAttribute(this.xml, 'notify', value);
|
|
},
|
|
get id() {
|
|
return stanza.getSubAttribute(this.xml, this.NS, 'item', 'id');
|
|
},
|
|
set id(value) {
|
|
stanza.setSubAttribute(this.xml, this.NS, 'item', 'id', value);
|
|
}
|
|
};
|
|
|
|
|
|
function Retrieve(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
Retrieve.prototype = {
|
|
constructor: {
|
|
value: Retrieve
|
|
},
|
|
_name: 'retrieve',
|
|
NS: 'http://jabber.org/protocol/pubsub',
|
|
EL: 'items',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON,
|
|
get node() {
|
|
return stanza.getAttribute(this.xml, 'node');
|
|
},
|
|
set node(value) {
|
|
stanza.setAttribute(this.xml, 'node', value);
|
|
},
|
|
get max() {
|
|
return stanza.getAttribute(this.xml, 'max_items');
|
|
},
|
|
set max(value) {
|
|
stanza.setAttribute(this.xml, 'max_items', value);
|
|
}
|
|
};
|
|
|
|
|
|
function Item(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
Item.prototype = {
|
|
constructor: {
|
|
value: Item
|
|
},
|
|
_name: 'item',
|
|
NS: 'http://jabber.org/protocol/pubsub',
|
|
EL: 'item',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON,
|
|
get id() {
|
|
return stanza.getAttribute(this.xml, 'id');
|
|
},
|
|
set id(value) {
|
|
stanza.setAttribute(this.xml, 'id', value);
|
|
}
|
|
};
|
|
|
|
|
|
function EventItems(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
EventItems.prototype = {
|
|
constructor: {
|
|
value: EventItems
|
|
},
|
|
_name: 'updated',
|
|
NS: 'http://jabber.org/protocol/pubsub#event',
|
|
EL: 'items',
|
|
toString: stanza.toString,
|
|
toJSON: function () {
|
|
var json = stanza.toJSON.apply(this);
|
|
var items = [];
|
|
_.forEach(json.published, function (item) {
|
|
items.push(item.toJSON());
|
|
});
|
|
json.published = items;
|
|
return json;
|
|
},
|
|
get node() {
|
|
return stanza.getAttribute(this.xml, 'node');
|
|
},
|
|
set node(value) {
|
|
stanza.setAttribute(this.xml, 'node', value);
|
|
},
|
|
get published() {
|
|
var results = [];
|
|
var items = stanza.find(this.xml, this.NS, 'item');
|
|
|
|
_.forEach(items, function (xml) {
|
|
results.push(new EventItem({}, xml));
|
|
});
|
|
return results;
|
|
},
|
|
set published(value) {
|
|
var self = this;
|
|
_.forEach(value, function (data) {
|
|
var item = new EventItem(data);
|
|
this.xml.appendChild(item.xml);
|
|
});
|
|
},
|
|
get retracted() {
|
|
var results = [];
|
|
var retracted = stanza.find(this.xml, this.NS, 'retract');
|
|
|
|
_.forEach(retracted, function (xml) {
|
|
results.push(xml.getAttribute('id'));
|
|
});
|
|
return results;
|
|
},
|
|
set retracted(value) {
|
|
var self = this;
|
|
_.forEach(value, function (id) {
|
|
var retracted = document.createElementNS(self.NS, 'retract');
|
|
retracted.setAttribute('id', id);
|
|
this.xml.appendChild(retracted);
|
|
});
|
|
}
|
|
};
|
|
|
|
|
|
function EventItem(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
EventItem.prototype = {
|
|
constructor: {
|
|
value: EventItem
|
|
},
|
|
_name: 'eventItem',
|
|
NS: 'http://jabber.org/protocol/pubsub#event',
|
|
EL: 'item',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON,
|
|
get id() {
|
|
return stanza.getAttribute(this.xml, 'id');
|
|
},
|
|
set id(value) {
|
|
stanza.setAttribute(this.xml, 'id', value);
|
|
},
|
|
get node() {
|
|
return stanza.getAttribute(this.xml, 'node');
|
|
},
|
|
set node(value) {
|
|
stanza.setAttribute(this.xml, 'node', value);
|
|
},
|
|
get publisher() {
|
|
return stanza.getAttribute(this.xml, 'publisher');
|
|
},
|
|
set publisher(value) {
|
|
stanza.setAttribute(this.xml, 'publisher', value);
|
|
}
|
|
};
|
|
|
|
|
|
stanza.extend(Pubsub, Subscribe);
|
|
stanza.extend(Pubsub, Unsubscribe);
|
|
stanza.extend(Pubsub, Publish);
|
|
stanza.extend(Pubsub, Retrieve);
|
|
stanza.extend(Pubsub, Subscription);
|
|
stanza.extend(PubsubOwner, Configure);
|
|
stanza.extend(Publish, Item);
|
|
stanza.extend(Configure, Form);
|
|
stanza.extend(Pubsub, RSM);
|
|
stanza.extend(Event, EventItems);
|
|
stanza.extend(Message, Event);
|
|
stanza.extend(Iq, Pubsub);
|
|
stanza.extend(Iq, PubsubOwner);
|
|
|
|
exports.Pubsub = Pubsub;
|
|
exports.Item = Item;
|
|
exports.EventItem = EventItem;
|
|
|
|
},{"../../vendor/lodash":90,"./dataforms":27,"./iq":33,"./message":35,"./rsm":42,"jxt":74}],39:[function(require,module,exports){
|
|
var stanza = require('jxt');
|
|
var Message = require('./message');
|
|
|
|
|
|
function Request(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
Request.prototype = {
|
|
constructor: {
|
|
value: Request
|
|
},
|
|
NS: 'urn:xmpp:receipts',
|
|
EL: 'request',
|
|
_name: '_requestReceipt',
|
|
toString: stanza.toString,
|
|
toJSON: undefined
|
|
};
|
|
|
|
|
|
function Received(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
Received.prototype = {
|
|
constructor: {
|
|
value: Received
|
|
},
|
|
NS: 'urn:xmpp:receipts',
|
|
EL: 'received',
|
|
_name: 'receipt',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON,
|
|
get id() {
|
|
return stanza.getAttribute(this.xml, 'id');
|
|
},
|
|
set id(value) {
|
|
stanza.setAttribute(this.xml, 'id', value);
|
|
}
|
|
};
|
|
|
|
|
|
Message.prototype.__defineGetter__('requestReceipt', function () {
|
|
return !!this._extensions._requestReceipt;
|
|
});
|
|
Message.prototype.__defineSetter__('requestReceipt', function (value) {
|
|
if (value) {
|
|
this._requestReceipt = true;
|
|
} else if (this._extensions._requestReceipt) {
|
|
this.xml.removeChild(this._extensions._requestReceipt.xml);
|
|
delete this._extensions._requestReceipt;
|
|
}
|
|
});
|
|
|
|
|
|
stanza.extend(Message, Received);
|
|
stanza.extend(Message, Request);
|
|
|
|
exports.Request = Request;
|
|
exports.Received = Received;
|
|
|
|
},{"./message":35,"jxt":74}],40:[function(require,module,exports){
|
|
var stanza = require('jxt');
|
|
var Message = require('./message');
|
|
|
|
|
|
function Replace(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
Replace.prototype = {
|
|
constructor: {
|
|
value: Replace
|
|
},
|
|
NS: 'urn:xmpp:message-correct:0',
|
|
EL: 'replace',
|
|
_name: '_replace',
|
|
toString: stanza.toString,
|
|
toJSON: undefined,
|
|
get id() {
|
|
return stanza.getAttribute(this.xml, 'id');
|
|
},
|
|
set id(value) {
|
|
stanza.setAttribute(this.xml, 'id', value);
|
|
}
|
|
};
|
|
|
|
|
|
stanza.extend(Message, Replace);
|
|
|
|
Message.prototype.__defineGetter__('replace', function () {
|
|
if (this._extensions._replace) {
|
|
return this._replace.id;
|
|
}
|
|
return '';
|
|
});
|
|
Message.prototype.__defineSetter__('replace', function (value) {
|
|
if (value) {
|
|
this._replace.id = value;
|
|
} else if (this._extensions._replace) {
|
|
this.xml.removeChild(this._extensions._replace.xml);
|
|
delete this._extensions._replace;
|
|
}
|
|
});
|
|
|
|
|
|
module.exports = Replace;
|
|
|
|
},{"./message":35,"jxt":74}],41:[function(require,module,exports){
|
|
var _ = require('../../vendor/lodash');
|
|
var stanza = require('jxt');
|
|
var Iq = require('./iq');
|
|
|
|
|
|
function Roster(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
Roster.prototype = {
|
|
constructor: {
|
|
value: Roster
|
|
},
|
|
_name: 'roster',
|
|
NS: 'jabber:iq:roster',
|
|
EL: 'query',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON,
|
|
get ver() {
|
|
return stanza.getAttribute(this.xml, 'ver');
|
|
},
|
|
set ver(value) {
|
|
var force = (value === '');
|
|
stanza.setAttribute(this.xml, 'ver', value, force);
|
|
},
|
|
get items() {
|
|
var self = this;
|
|
|
|
var items = stanza.find(this.xml, this.NS, 'item');
|
|
if (!items.length) {
|
|
return [];
|
|
}
|
|
var results = [];
|
|
items.forEach(function (item) {
|
|
var data = {
|
|
jid: stanza.getAttribute(item, 'jid', undefined),
|
|
name: stanza.getAttribute(item, 'name', undefined),
|
|
subscription: stanza.getAttribute(item, 'subscription', 'none'),
|
|
ask: stanza.getAttribute(item, 'ask', undefined),
|
|
groups: []
|
|
};
|
|
var groups = stanza.find(item, self.NS, 'group');
|
|
groups.forEach(function (group) {
|
|
data.groups.push(group.textContent);
|
|
});
|
|
results.push(data);
|
|
});
|
|
return results;
|
|
},
|
|
set items(values) {
|
|
var self = this;
|
|
values.forEach(function (value) {
|
|
var item = document.createElementNS(self.NS, 'item');
|
|
stanza.setAttribute(item, 'jid', value.jid);
|
|
stanza.setAttribute(item, 'name', value.name);
|
|
stanza.setAttribute(item, 'subscription', value.subscription);
|
|
stanza.setAttribute(item, 'ask', value.ask);
|
|
(value.groups || []).forEach(function (name) {
|
|
var group = document.createElementNS(self.NS, 'group');
|
|
group.textContent = name;
|
|
item.appendChild(group);
|
|
});
|
|
self.xml.appendChild(item);
|
|
});
|
|
}
|
|
};
|
|
|
|
|
|
stanza.extend(Iq, Roster);
|
|
|
|
|
|
module.exports = Roster;
|
|
|
|
},{"../../vendor/lodash":90,"./iq":33,"jxt":74}],42:[function(require,module,exports){
|
|
var stanza = require('jxt');
|
|
|
|
|
|
function RSM(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
RSM.prototype = {
|
|
constructor: {
|
|
value: RSM
|
|
},
|
|
NS: 'http://jabber.org/protocol/rsm',
|
|
EL: 'set',
|
|
_name: 'rsm',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON,
|
|
get after() {
|
|
return stanza.getSubText(this.xml, this.NS, 'after');
|
|
},
|
|
set after(value) {
|
|
stanza.setSubText(this.xml, this.NS, 'after', value);
|
|
},
|
|
get before() {
|
|
return stanza.getSubText(this.xml, this.NS, 'before');
|
|
},
|
|
set before(value) {
|
|
if (value === true) {
|
|
stanza.findOrCreate(this.xml, this.NS, 'before');
|
|
} else {
|
|
stanza.setSubText(this.xml, this.NS, 'before', value);
|
|
}
|
|
},
|
|
get count() {
|
|
return parseInt(stanza.getSubText(this.xml, this.NS, 'count') || '0', 10);
|
|
},
|
|
set count(value) {
|
|
stanza.setSubText(this.xml, this.NS, 'count', value.toString());
|
|
},
|
|
get first() {
|
|
return stanza.getSubText(this.xml, this.NS, 'first');
|
|
},
|
|
set first(value) {
|
|
stanza.setSubText(this.xml, this.NS, 'first', value);
|
|
},
|
|
get firstIndex() {
|
|
return stanza.getSubAttribute(this.xml, this.NS, 'first', 'index');
|
|
},
|
|
set firstIndex(value) {
|
|
stanza.setSubAttribute(this.xml, this.NS, 'first', 'index', value);
|
|
},
|
|
get index() {
|
|
return stanza.getSubText(this.xml, this.NS, 'index');
|
|
},
|
|
set index(value) {
|
|
stanza.setSubText(this.xml, this.NS, 'index', value);
|
|
},
|
|
get last() {
|
|
return stanza.getSubText(this.xml, this.NS, 'last');
|
|
},
|
|
set last(value) {
|
|
stanza.setSubText(this.xml, this.NS, 'last', value);
|
|
},
|
|
get max() {
|
|
return stanza.getSubText(this.xml, this.NS, 'max');
|
|
},
|
|
set max(value) {
|
|
stanza.setSubText(this.xml, this.NS, 'max', value.toString());
|
|
}
|
|
};
|
|
|
|
|
|
module.exports = RSM;
|
|
|
|
},{"jxt":74}],43:[function(require,module,exports){
|
|
var stanza = require('jxt');
|
|
var _ = require('../../vendor/lodash');
|
|
var StreamFeatures = require('./streamFeatures');
|
|
|
|
|
|
function Mechanisms(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
Mechanisms.prototype = {
|
|
constructor: {
|
|
value: Mechanisms
|
|
},
|
|
_name: 'sasl',
|
|
NS: 'urn:ietf:params:xml:ns:xmpp-sasl',
|
|
EL: 'mechanisms',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON,
|
|
required: true,
|
|
get mechanisms() {
|
|
var result = [];
|
|
var mechs = stanza.find(this.xml, this.NS, 'mechanism');
|
|
mechs.forEach(function (mech) {
|
|
result.push(mech.textContent);
|
|
});
|
|
return result;
|
|
},
|
|
set mechanisms(value) {
|
|
var self = this;
|
|
var mechs = stanza.find(this.xml, this.NS, 'mechanism');
|
|
mechs.forEach(function (mech) {
|
|
self.xml.remove(mech);
|
|
});
|
|
value.forEach(function (name) {
|
|
var mech = document.createElementNS(self.NS, 'mechanism');
|
|
mech.textContent = name;
|
|
self.xml.appendChild(mech);
|
|
});
|
|
}
|
|
};
|
|
|
|
|
|
function Auth(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
Auth.prototype = {
|
|
constructor: {
|
|
value: Auth
|
|
},
|
|
_name: 'saslAuth',
|
|
_eventname: 'sasl:auth',
|
|
NS: 'urn:ietf:params:xml:ns:xmpp-sasl',
|
|
EL: 'auth',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON,
|
|
get value() {
|
|
if (this.xml.textContent && this.xml.textContent != '=') {
|
|
return atob(this.xml.textContent);
|
|
}
|
|
return '';
|
|
},
|
|
set value(value) {
|
|
this.xml.textContent = btoa(value) || '=';
|
|
},
|
|
get mechanism() {
|
|
return stanza.getAttribute(this.xml, 'mechanism');
|
|
},
|
|
set mechanism(value) {
|
|
stanza.setAttribute(this.xml, 'mechanism', value);
|
|
}
|
|
};
|
|
|
|
|
|
function Challenge(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
Challenge.prototype = {
|
|
constructor: {
|
|
value: Challenge
|
|
},
|
|
_name: 'saslChallenge',
|
|
_eventname: 'sasl:challenge',
|
|
NS: 'urn:ietf:params:xml:ns:xmpp-sasl',
|
|
EL: 'challenge',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON,
|
|
get value() {
|
|
if (this.xml.textContent && this.xml.textContent != '=') {
|
|
return atob(this.xml.textContent);
|
|
}
|
|
return '';
|
|
},
|
|
set value(value) {
|
|
this.xml.textContent = btoa(value) || '=';
|
|
}
|
|
};
|
|
|
|
|
|
function Response(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
Response.prototype = {
|
|
constructor: {
|
|
value: Response
|
|
},
|
|
_name: 'saslResponse',
|
|
_eventname: 'sasl:response',
|
|
NS: 'urn:ietf:params:xml:ns:xmpp-sasl',
|
|
EL: 'response',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON,
|
|
get value() {
|
|
if (this.xml.textContent && this.xml.textContent != '=') {
|
|
return atob(this.xml.textContent);
|
|
}
|
|
return '';
|
|
},
|
|
set value(value) {
|
|
this.xml.textContent = btoa(value) || '=';
|
|
}
|
|
};
|
|
|
|
|
|
function Success(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
Success.prototype = {
|
|
constructor: {
|
|
value: Success
|
|
},
|
|
_name: 'saslSuccess',
|
|
_eventname: 'sasl:success',
|
|
NS: 'urn:ietf:params:xml:ns:xmpp-sasl',
|
|
EL: 'success',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON,
|
|
get value() {
|
|
if (this.xml.textContent && this.xml.textContent != '=') {
|
|
return atob(this.xml.textContent);
|
|
}
|
|
return '';
|
|
},
|
|
set value(value) {
|
|
this.xml.textContent = btoa(value) || '=';
|
|
}
|
|
};
|
|
|
|
|
|
function Failure(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
Failure.prototype = {
|
|
constructor: {
|
|
value: Success
|
|
},
|
|
_CONDITIONS: [
|
|
'aborted', 'account-disabled', 'credentials-expired',
|
|
'encryption-required', 'incorrect-encoding', 'invalid-authzid',
|
|
'invalid-mechanism', 'malformed-request', 'mechanism-too-weak',
|
|
'not-authorized', 'temporary-auth-failure',
|
|
],
|
|
_name: 'saslFailure',
|
|
_eventname: 'sasl:failure',
|
|
NS: 'urn:ietf:params:xml:ns:xmpp-sasl',
|
|
EL: 'failure',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON,
|
|
get lang() {
|
|
return this._lang || '';
|
|
},
|
|
set lang(value) {
|
|
this._lang = value;
|
|
},
|
|
get condition() {
|
|
var self = this;
|
|
var result = [];
|
|
this._CONDITIONS.forEach(function (condition) {
|
|
var exists = stanza.find(self.xml, this.NS, condition);
|
|
if (exists.length) {
|
|
result.push(exists[0].tagName);
|
|
}
|
|
});
|
|
return result[0] || '';
|
|
},
|
|
set condition(value) {
|
|
var self = this;
|
|
this._CONDITIONS.forEach(function (condition) {
|
|
var exists = stanza.find(self.xml, self.NS, condition);
|
|
if (exists.length) {
|
|
self.xml.removeChild(exists[0]);
|
|
}
|
|
});
|
|
|
|
if (value) {
|
|
var condition = document.createElementNS(this.NS, value);
|
|
condition.setAttribute('xmlns', this.NS);
|
|
this.xml.appendChild(condition);
|
|
}
|
|
},
|
|
get text() {
|
|
var text = this.$text;
|
|
return text[this.lang] || '';
|
|
},
|
|
get $text() {
|
|
return stanza.getSubLangText(this.xml, this.NS, 'text', this.lang);
|
|
},
|
|
set text(value) {
|
|
stanza.setSubLangText(this.xml, this.NS, 'text', value, this.lang);
|
|
}
|
|
};
|
|
|
|
|
|
function Abort(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
Abort.prototype = {
|
|
constructor: {
|
|
value: Abort
|
|
},
|
|
_name: 'saslAbort',
|
|
_eventname: 'sasl:abort',
|
|
NS: 'urn:ietf:params:xml:ns:xmpp-sasl',
|
|
EL: 'abort',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON
|
|
};
|
|
|
|
|
|
stanza.extend(StreamFeatures, Mechanisms, 'sasl');
|
|
stanza.topLevel(Auth);
|
|
stanza.topLevel(Challenge);
|
|
stanza.topLevel(Response);
|
|
stanza.topLevel(Success);
|
|
stanza.topLevel(Failure);
|
|
stanza.topLevel(Abort);
|
|
|
|
|
|
exports.Mechanisms = Mechanisms;
|
|
exports.Auth = Auth;
|
|
exports.Challenge = Challenge;
|
|
exports.Response = Response;
|
|
exports.Success = Success;
|
|
exports.Failure = Failure;
|
|
exports.Abort = Abort;
|
|
|
|
},{"../../vendor/lodash":90,"./streamFeatures":48,"jxt":74}],44:[function(require,module,exports){
|
|
var stanza = require('jxt');
|
|
var Iq = require('./iq');
|
|
var StreamFeatures = require('./streamFeatures');
|
|
|
|
|
|
function Session(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
Session.prototype = {
|
|
constructor: {
|
|
value: Session
|
|
},
|
|
_name: 'session',
|
|
NS: 'urn:ietf:params:xml:ns:xmpp-session',
|
|
EL: 'session',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON
|
|
};
|
|
|
|
|
|
stanza.extend(StreamFeatures, Session);
|
|
stanza.extend(Iq, Session);
|
|
|
|
|
|
module.exports = Session;
|
|
|
|
},{"./iq":33,"./streamFeatures":48,"jxt":74}],45:[function(require,module,exports){
|
|
var stanza = require('jxt');
|
|
var StreamFeatures = require('./streamFeatures');
|
|
|
|
|
|
function SMFeature(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
SMFeature.prototype = {
|
|
constructor: {
|
|
value: SMFeature
|
|
},
|
|
_name: 'streamManagement',
|
|
NS: 'urn:xmpp:sm:3',
|
|
EL: 'sm',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON
|
|
};
|
|
|
|
|
|
function Enable(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
Enable.prototype = {
|
|
constructor: {
|
|
value: Enable
|
|
},
|
|
_name: 'smEnable',
|
|
_eventname: 'stream:management:enable',
|
|
NS: 'urn:xmpp:sm:3',
|
|
EL: 'enable',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON,
|
|
get resume() {
|
|
return stanza.getBoolAttribute(this.xml, 'resume');
|
|
},
|
|
set resume(val) {
|
|
stanza.setBoolAttribute(this.xml, 'resume', val);
|
|
}
|
|
};
|
|
|
|
|
|
function Enabled(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
Enabled.prototype = {
|
|
constructor: {
|
|
value: Enabled
|
|
},
|
|
_name: 'smEnabled',
|
|
_eventname: 'stream:management:enabled',
|
|
NS: 'urn:xmpp:sm:3',
|
|
EL: 'enabled',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON,
|
|
get id() {
|
|
return stanza.getAttribute(this.xml, 'id');
|
|
},
|
|
set id(value) {
|
|
stanza.setAttribute(this.xml, 'id', value);
|
|
},
|
|
get resume() {
|
|
return stanza.getBoolAttribute(this.xml, 'resume');
|
|
},
|
|
set resume(val) {
|
|
stanza.setBoolAttribute(this.xml, 'resume', val);
|
|
}
|
|
};
|
|
|
|
|
|
function Resume(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
Resume.prototype = {
|
|
constructor: {
|
|
value: Resume
|
|
},
|
|
_name: 'smResume',
|
|
_eventname: 'stream:management:resume',
|
|
NS: 'urn:xmpp:sm:3',
|
|
EL: 'resume',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON,
|
|
get h() {
|
|
return parseInt(stanza.getAttribute(this.xml, 'h', '0'), 10);
|
|
},
|
|
set h(value) {
|
|
stanza.setAttribute(this.xml, 'h', '' + value);
|
|
},
|
|
get previd() {
|
|
return stanza.getAttribute(this.xml, 'previd');
|
|
},
|
|
set previd(value) {
|
|
stanza.setAttribute(this.xml, 'previd', value);
|
|
}
|
|
};
|
|
|
|
|
|
function Resumed(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
Resumed.prototype = {
|
|
constructor: {
|
|
value: Resumed
|
|
},
|
|
_name: 'smResumed',
|
|
_eventname: 'stream:management:resumed',
|
|
NS: 'urn:xmpp:sm:3',
|
|
EL: 'resumed',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON,
|
|
get h() {
|
|
return parseInt(stanza.getAttribute(this.xml, 'h', '0'), 10);
|
|
},
|
|
set h(value) {
|
|
stanza.setAttribute(this.xml, 'h', '' + value);
|
|
},
|
|
get previd() {
|
|
return stanza.getAttribute(this.xml, 'previd');
|
|
},
|
|
set previd(value) {
|
|
stanza.setAttribute(this.xml, 'previd', value);
|
|
}
|
|
};
|
|
|
|
|
|
function Failed(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
Failed.prototype = {
|
|
constructor: {
|
|
value: Failed
|
|
},
|
|
_name: 'smFailed',
|
|
_eventname: 'stream:management:failed',
|
|
NS: 'urn:xmpp:sm:3',
|
|
EL: 'failed',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON
|
|
};
|
|
|
|
|
|
function Ack(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
Ack.prototype = {
|
|
constructor: {
|
|
value: Ack
|
|
},
|
|
_name: 'smAck',
|
|
_eventname: 'stream:management:ack',
|
|
NS: 'urn:xmpp:sm:3',
|
|
EL: 'a',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON,
|
|
get h() {
|
|
return parseInt(stanza.getAttribute(this.xml, 'h', '0'), 10);
|
|
},
|
|
set h(value) {
|
|
stanza.setAttribute(this.xml, 'h', '' + value);
|
|
}
|
|
};
|
|
|
|
|
|
function Request(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
Request.prototype = {
|
|
constructor: {
|
|
value: Request
|
|
},
|
|
_name: 'smRequest',
|
|
_eventname: 'stream:management:request',
|
|
NS: 'urn:xmpp:sm:3',
|
|
EL: 'r',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON
|
|
};
|
|
|
|
|
|
stanza.extend(StreamFeatures, SMFeature);
|
|
stanza.topLevel(Ack);
|
|
stanza.topLevel(Request);
|
|
stanza.topLevel(Enable);
|
|
stanza.topLevel(Enabled);
|
|
stanza.topLevel(Resume);
|
|
stanza.topLevel(Resumed);
|
|
stanza.topLevel(Failed);
|
|
|
|
|
|
exports.SMFeature = SMFeature;
|
|
exports.Enable = Enable;
|
|
exports.Enabled = Enabled;
|
|
exports.Resume = Resume;
|
|
exports.Resumed = Resumed;
|
|
exports.Failed = Failed;
|
|
exports.Ack = Ack;
|
|
exports.Request = Request;
|
|
|
|
},{"./streamFeatures":48,"jxt":74}],46:[function(require,module,exports){
|
|
var stanza = require('jxt');
|
|
|
|
|
|
function Stream(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
Stream.prototype = {
|
|
constructor: {
|
|
value: Stream
|
|
},
|
|
_name: 'stream',
|
|
NS: 'http://etherx.jabber.org/streams',
|
|
EL: 'stream',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON,
|
|
get lang() {
|
|
return this.xml.getAttributeNS(stanza.XML_NS, 'lang') || '';
|
|
},
|
|
set lang(value) {
|
|
this.xml.setAttributeNS(stanza.XML_NS, 'lang', value);
|
|
},
|
|
get id() {
|
|
return stanza.getAttribute(this.xml, 'id');
|
|
},
|
|
set id(value) {
|
|
stanza.setAttribute(this.xml, 'id', value);
|
|
},
|
|
get version() {
|
|
return stanza.getAttribute(this.xml, 'version', '1.0');
|
|
},
|
|
set version(value) {
|
|
stanza.setAttribute(this.xml, 'version', value);
|
|
},
|
|
get to() {
|
|
return stanza.getAttribute(this.xml, 'to');
|
|
},
|
|
set to(value) {
|
|
stanza.setAttribute(this.xml, 'to', value);
|
|
},
|
|
get from() {
|
|
return stanza.getAttribute(this.xml, 'from');
|
|
},
|
|
set from(value) {
|
|
stanza.setAttribute(this.xml, 'from', value);
|
|
}
|
|
};
|
|
|
|
module.exports = Stream;
|
|
|
|
},{"jxt":74}],47:[function(require,module,exports){
|
|
var _ = require('../../vendor/lodash');
|
|
var stanza = require('jxt');
|
|
|
|
|
|
function StreamError(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
StreamError.prototype = {
|
|
constructor: {
|
|
value: StreamError
|
|
},
|
|
_name: 'streamError',
|
|
NS: 'http://etherx.jabber.org/streams',
|
|
EL: 'error',
|
|
_ERR_NS: 'urn:ietf:params:xml:ns:xmpp-streams',
|
|
_CONDITIONS: [
|
|
'bad-format', 'bad-namespace-prefix', 'conflict',
|
|
'connection-timeout', 'host-gone', 'host-unknown',
|
|
'improper-addressing', 'internal-server-error', 'invalid-from',
|
|
'invalid-namespace', 'invalid-xml', 'not-authorized',
|
|
'not-well-formed', 'policy-violation', 'remote-connection-failed',
|
|
'reset', 'resource-constraint', 'restricted-xml', 'see-other-host',
|
|
'system-shutdown', 'undefined-condition', 'unsupported-encoding',
|
|
'unsupported-feature', 'unsupported-stanza-type',
|
|
'unsupported-version'
|
|
],
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON,
|
|
get lang() {
|
|
return this._lang || '';
|
|
},
|
|
set lang(value) {
|
|
this._lang = value;
|
|
},
|
|
get condition() {
|
|
var self = this;
|
|
var result = [];
|
|
this._CONDITIONS.forEach(function (condition) {
|
|
var exists = stanza.find(self.xml, self._ERR_NS, condition);
|
|
if (exists.length) {
|
|
result.push(exists[0].tagName);
|
|
}
|
|
});
|
|
return result[0] || '';
|
|
},
|
|
set condition(value) {
|
|
var self = this;
|
|
this._CONDITIONS.forEach(function (condition) {
|
|
var exists = stanza.find(self.xml, self._ERR_NS, condition);
|
|
if (exists.length) {
|
|
self.xml.removeChild(exists[0]);
|
|
}
|
|
});
|
|
|
|
if (value) {
|
|
var condition = document.createElementNS(this._ERR_NS, value);
|
|
condition.setAttribute('xmlns', this._ERR_NS);
|
|
this.xml.appendChild(condition);
|
|
}
|
|
},
|
|
get seeOtherHost() {
|
|
return stanza.getSubText(this.xml, this._ERR_NS, 'see-other-host');
|
|
},
|
|
set seeOtherHost(value) {
|
|
this.condition = 'see-other-host';
|
|
stanza.setSubText(this.xml, this._ERR_NS, 'see-other-host', value);
|
|
},
|
|
get text() {
|
|
var text = this.$text;
|
|
return text[this.lang] || '';
|
|
},
|
|
get $text() {
|
|
return stanza.getSubLangText(this.xml, this._ERR_NS, 'text', this.lang);
|
|
},
|
|
set text(value) {
|
|
stanza.setSubLangText(this.xml, this._ERR_NS, 'text', value, this.lang);
|
|
}
|
|
};
|
|
|
|
stanza.topLevel(StreamError);
|
|
|
|
|
|
module.exports = StreamError;
|
|
|
|
},{"../../vendor/lodash":90,"jxt":74}],48:[function(require,module,exports){
|
|
var stanza = require('jxt');
|
|
|
|
|
|
function StreamFeatures(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
StreamFeatures.prototype = {
|
|
constructor: {
|
|
value: StreamFeatures
|
|
},
|
|
_name: 'streamFeatures',
|
|
NS: 'http://etherx.jabber.org/streams',
|
|
EL: 'features',
|
|
_FEATURES: [],
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON,
|
|
get features() {
|
|
return this._extensions;
|
|
}
|
|
};
|
|
|
|
stanza.topLevel(StreamFeatures);
|
|
|
|
|
|
module.exports = StreamFeatures;
|
|
|
|
},{"jxt":74}],49:[function(require,module,exports){
|
|
var stanza = require('jxt');
|
|
var Iq = require('./iq');
|
|
|
|
|
|
function EntityTime(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
EntityTime.prototype = {
|
|
constructor: {
|
|
value: EntityTime
|
|
},
|
|
NS: 'urn:xmpp:time',
|
|
EL: 'time',
|
|
_name: 'time',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON,
|
|
get tzo() {
|
|
var split, hrs, min;
|
|
var sign = -1;
|
|
var formatted = stanza.getSubText(this.xml, this.NS, 'tzo');
|
|
|
|
if (!formatted) {
|
|
return 0;
|
|
}
|
|
if (formatted.charAt(0) === '-') {
|
|
sign = 1;
|
|
formatted.slice(1);
|
|
}
|
|
split = formatted.split(':');
|
|
hrs = parseInt(split[0], 10);
|
|
min = parseInt(split[1], 10);
|
|
return (hrs * 60 + min) * sign;
|
|
},
|
|
set tzo(value) {
|
|
var hrs, min;
|
|
var formatted = '-';
|
|
if (typeof value === 'number') {
|
|
if (value < 0) {
|
|
value = -value;
|
|
formatted = '+';
|
|
}
|
|
hrs = value / 60;
|
|
min = value % 60;
|
|
formatted += (hrs < 10 ? '0' : '') + hrs + ':' + (min < 10 ? '0' : '') + min;
|
|
} else {
|
|
formatted = value;
|
|
}
|
|
stanza.setSubText(this.xml, this.NS, 'tzo', formatted);
|
|
},
|
|
get utc() {
|
|
var stamp = stanza.getSubText(this.xml, this.NS, 'utc');
|
|
if (stamp) {
|
|
return new Date(stamp || Date.now());
|
|
}
|
|
return '';
|
|
},
|
|
set utc(value) {
|
|
stanza.setSubText(this.xml, this.NS, 'utc', value.toISOString());
|
|
}
|
|
};
|
|
|
|
|
|
stanza.extend(Iq, EntityTime);
|
|
|
|
module.exports = EntityTime;
|
|
|
|
},{"./iq":33,"jxt":74}],50:[function(require,module,exports){
|
|
var stanza = require('jxt');
|
|
var Iq = require('./iq');
|
|
|
|
|
|
function Version(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
Version.prototype = {
|
|
constructor: {
|
|
value: Version
|
|
},
|
|
NS: 'jabber:iq:version',
|
|
EL: 'query',
|
|
_name: 'version',
|
|
toString: stanza.toString,
|
|
toJSON: stanza.toJSON,
|
|
get name() {
|
|
return stanza.getSubText(this.xml, this.NS, 'name');
|
|
},
|
|
set name(value) {
|
|
stanza.setSubText(this.xml, this.NS, 'name', value);
|
|
},
|
|
get version() {
|
|
return stanza.getSubText(this.xml, this.NS, 'version');
|
|
},
|
|
set version(value) {
|
|
stanza.setSubText(this.xml, this.NS, 'version', value);
|
|
},
|
|
get os() {
|
|
return stanza.getSubText(this.xml, this.NS, 'os');
|
|
},
|
|
set os(value) {
|
|
stanza.setSubText(this.xml, this.NS, 'os', value);
|
|
}
|
|
};
|
|
|
|
|
|
stanza.extend(Iq, Version);
|
|
|
|
|
|
module.exports = Version;
|
|
|
|
},{"./iq":33,"jxt":74}],51:[function(require,module,exports){
|
|
var stanza = require('jxt');
|
|
var Iq = require('./iq');
|
|
|
|
|
|
function Visible(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
Visible.prototype = {
|
|
constructor: {
|
|
value: Visible
|
|
},
|
|
NS: 'urn:xmpp:invisible:0',
|
|
EL: 'visible',
|
|
_name: '_visible',
|
|
toString: stanza.toString,
|
|
toJSON: undefined
|
|
};
|
|
|
|
|
|
function Invisible(data, xml) {
|
|
return stanza.init(this, xml, data);
|
|
}
|
|
Invisible.prototype = {
|
|
constructor: {
|
|
value: Invisible
|
|
},
|
|
NS: 'urn:xmpp:invisible:0',
|
|
EL: 'invisible',
|
|
_name: '_invisible',
|
|
toString: stanza.toString,
|
|
toJSON: undefined
|
|
};
|
|
|
|
|
|
|
|
Iq.prototype.__defineGetter__('visible', function () {
|
|
return !!this._extensions._visible;
|
|
});
|
|
Iq.prototype.__defineSetter__('visible', function (value) {
|
|
if (value) {
|
|
this._visible = true;
|
|
} else if (this._extensions._visible) {
|
|
this.xml.removeChild(this._extensions._visible.xml);
|
|
delete this._extensions._visible;
|
|
}
|
|
});
|
|
|
|
|
|
Iq.prototype.__defineGetter__('invisible', function () {
|
|
return !!this._extensions._invisible;
|
|
});
|
|
Iq.prototype.__defineSetter__('invisible', function (value) {
|
|
if (value) {
|
|
this._invisible = true;
|
|
} else if (this._extensions._invisible) {
|
|
this.xml.removeChild(this._extensions._invisible.xml);
|
|
delete this._extensions._invisible;
|
|
}
|
|
});
|
|
|
|
|
|
stanza.extend(Iq, Visible);
|
|
stanza.extend(Iq, Invisible);
|
|
|
|
exports.Visible = Visible;
|
|
exports.Invisible = Invisible;
|
|
|
|
},{"./iq":33,"jxt":74}],52:[function(require,module,exports){
|
|
var WildEmitter = require('wildemitter');
|
|
var _ = require('../vendor/lodash');
|
|
var async = require('async');
|
|
var Stream = require('./stanza/stream');
|
|
var Message = require('./stanza/message');
|
|
var Presence = require('./stanza/presence');
|
|
var Iq = require('./stanza/iq');
|
|
var StreamManagement = require('./sm');
|
|
var uuid = require('node-uuid');
|
|
|
|
|
|
function WSConnection() {
|
|
var self = this;
|
|
|
|
WildEmitter.call(this);
|
|
|
|
self.sm = new StreamManagement(self);
|
|
|
|
self.sendQueue = async.queue(function (data, cb) {
|
|
if (self.conn) {
|
|
self.emit('raw:outgoing', data);
|
|
|
|
self.sm.track(data);
|
|
|
|
if (typeof data !== 'string') {
|
|
data = data.toString();
|
|
}
|
|
|
|
self.conn.send(data);
|
|
}
|
|
cb();
|
|
}, 1);
|
|
|
|
function wrap(data) {
|
|
var result = [self.streamStart, data, self.streamEnd].join('');
|
|
return result;
|
|
}
|
|
|
|
function parse(data) {
|
|
var nodes = (self.parser.parseFromString(data, 'application/xml')).childNodes;
|
|
for (var i = 0; i < nodes.length; i++) {
|
|
if (nodes[i].nodeType === 1) {
|
|
return nodes[i];
|
|
}
|
|
}
|
|
}
|
|
|
|
self.on('connected', function () {
|
|
self.send([
|
|
'<stream:stream',
|
|
'xmlns:stream="http://etherx.jabber.org/streams"',
|
|
'xmlns="jabber:client"',
|
|
'version="' + (self.config.version || '1.0') + '"',
|
|
'xml:lang="' + (self.config.lang || 'en') + '"',
|
|
'to="' + self.config.server + '">'
|
|
].join(' '));
|
|
});
|
|
|
|
self.on('raw:incoming', function (data) {
|
|
var streamData, ended;
|
|
|
|
data = data.trim();
|
|
data = data.replace(/^(\s*<\?.*\?>\s*)*/, '');
|
|
if (data === '') {
|
|
return;
|
|
}
|
|
|
|
if (data.match(self.streamEnd)) {
|
|
return self.disconnect();
|
|
} else if (self.hasStream) {
|
|
try {
|
|
streamData = new Stream({}, parse(wrap(data)));
|
|
} catch (e) {
|
|
return self.disconnect();
|
|
}
|
|
} else {
|
|
// Inspect start of stream element to get NS prefix name
|
|
var parts = data.match(/^<(\S+:)?(\S+) /);
|
|
self.streamStart = data;
|
|
self.streamEnd = '</' + (parts[1] || '') + parts[2] + '>';
|
|
|
|
ended = false;
|
|
try {
|
|
streamData = new Stream({}, parse(data + self.streamEnd));
|
|
} catch (e) {
|
|
try {
|
|
streamData = new Stream({}, parse(data));
|
|
ended = true;
|
|
} catch (e2) {
|
|
return self.disconnect();
|
|
}
|
|
}
|
|
|
|
self.hasStream = true;
|
|
self.stream = streamData;
|
|
self.emit('stream:start', streamData);
|
|
}
|
|
|
|
_.each(streamData._extensions, function (stanzaObj) {
|
|
if (!stanzaObj.lang) {
|
|
stanzaObj.lang = self.stream.lang;
|
|
}
|
|
|
|
if (stanzaObj._name === 'message' || stanzaObj._name === 'presence' || stanzaObj._name === 'iq') {
|
|
self.sm.handle(stanzaObj);
|
|
self.emit('stanza', stanzaObj);
|
|
}
|
|
self.emit(stanzaObj._eventname || stanzaObj._name, stanzaObj);
|
|
self.emit('stream:data', stanzaObj);
|
|
|
|
if (stanzaObj.id) {
|
|
self.emit('id:' + stanzaObj.id, stanzaObj);
|
|
}
|
|
});
|
|
|
|
if (ended) {
|
|
self.emit('stream:end');
|
|
}
|
|
});
|
|
}
|
|
|
|
WSConnection.prototype = Object.create(WildEmitter.prototype, {
|
|
constructor: {
|
|
value: WSConnection
|
|
}
|
|
});
|
|
|
|
WSConnection.prototype.connect = function (opts) {
|
|
var self = this;
|
|
|
|
self.config = opts;
|
|
|
|
self.hasStream = false;
|
|
self.streamStart = '<stream:stream xmlns:stream="http://etherx.jabber.org/streams">';
|
|
self.streamEnd = '</stream:stream>';
|
|
self.parser = new DOMParser();
|
|
self.serializer = new XMLSerializer();
|
|
|
|
self.conn = new WebSocket(opts.wsURL, 'xmpp');
|
|
|
|
self.conn.onopen = function () {
|
|
self.emit('connected', self);
|
|
};
|
|
|
|
self.conn.onclose = function () {
|
|
self.emit('disconnected', self);
|
|
};
|
|
|
|
self.conn.onmessage = function (wsMsg) {
|
|
self.emit('raw:incoming', wsMsg.data);
|
|
};
|
|
};
|
|
|
|
WSConnection.prototype.disconnect = function () {
|
|
if (this.conn) {
|
|
if (this.hasStream) {
|
|
this.conn.send('</stream:stream>');
|
|
this.emit('raw:outgoing', '</stream:stream>');
|
|
this.emit('stream:end');
|
|
}
|
|
this.hasStream = false;
|
|
this.conn.close();
|
|
this.stream = undefined;
|
|
this.conn = undefined;
|
|
}
|
|
};
|
|
|
|
WSConnection.prototype.restart = function () {
|
|
var self = this;
|
|
self.hasStream = false;
|
|
self.send([
|
|
'<stream:stream',
|
|
'xmlns:stream="http://etherx.jabber.org/streams"',
|
|
'xmlns="jabber:client"',
|
|
'version="' + (self.config.version || '1.0') + '"',
|
|
'xml:lang="' + (self.config.lang || 'en') + '"',
|
|
'to="' + self.config.server + '">'
|
|
].join(' '));
|
|
};
|
|
|
|
WSConnection.prototype.send = function (data) {
|
|
this.sendQueue.push(data);
|
|
};
|
|
|
|
|
|
module.exports = WSConnection;
|
|
|
|
},{"../vendor/lodash":90,"./sm":20,"./stanza/iq":33,"./stanza/message":35,"./stanza/presence":37,"./stanza/stream":46,"async":53,"node-uuid":76,"wildemitter":89}],53:[function(require,module,exports){
|
|
var process=require("__browserify_process");/*global setImmediate: false, setTimeout: false, console: false */
|
|
(function () {
|
|
|
|
var async = {};
|
|
|
|
// global on the server, window in the browser
|
|
var root, previous_async;
|
|
|
|
root = this;
|
|
if (root != null) {
|
|
previous_async = root.async;
|
|
}
|
|
|
|
async.noConflict = function () {
|
|
root.async = previous_async;
|
|
return async;
|
|
};
|
|
|
|
function only_once(fn) {
|
|
var called = false;
|
|
return function() {
|
|
if (called) throw new Error("Callback was already called.");
|
|
called = true;
|
|
fn.apply(root, arguments);
|
|
}
|
|
}
|
|
|
|
//// cross-browser compatiblity functions ////
|
|
|
|
var _each = function (arr, iterator) {
|
|
if (arr.forEach) {
|
|
return arr.forEach(iterator);
|
|
}
|
|
for (var i = 0; i < arr.length; i += 1) {
|
|
iterator(arr[i], i, arr);
|
|
}
|
|
};
|
|
|
|
var _map = function (arr, iterator) {
|
|
if (arr.map) {
|
|
return arr.map(iterator);
|
|
}
|
|
var results = [];
|
|
_each(arr, function (x, i, a) {
|
|
results.push(iterator(x, i, a));
|
|
});
|
|
return results;
|
|
};
|
|
|
|
var _reduce = function (arr, iterator, memo) {
|
|
if (arr.reduce) {
|
|
return arr.reduce(iterator, memo);
|
|
}
|
|
_each(arr, function (x, i, a) {
|
|
memo = iterator(memo, x, i, a);
|
|
});
|
|
return memo;
|
|
};
|
|
|
|
var _keys = function (obj) {
|
|
if (Object.keys) {
|
|
return Object.keys(obj);
|
|
}
|
|
var keys = [];
|
|
for (var k in obj) {
|
|
if (obj.hasOwnProperty(k)) {
|
|
keys.push(k);
|
|
}
|
|
}
|
|
return keys;
|
|
};
|
|
|
|
//// exported async module functions ////
|
|
|
|
//// nextTick implementation with browser-compatible fallback ////
|
|
if (typeof process === 'undefined' || !(process.nextTick)) {
|
|
if (typeof setImmediate === 'function') {
|
|
async.nextTick = function (fn) {
|
|
// not a direct alias for IE10 compatibility
|
|
setImmediate(fn);
|
|
};
|
|
async.setImmediate = async.nextTick;
|
|
}
|
|
else {
|
|
async.nextTick = function (fn) {
|
|
setTimeout(fn, 0);
|
|
};
|
|
async.setImmediate = async.nextTick;
|
|
}
|
|
}
|
|
else {
|
|
async.nextTick = process.nextTick;
|
|
if (typeof setImmediate !== 'undefined') {
|
|
async.setImmediate = setImmediate;
|
|
}
|
|
else {
|
|
async.setImmediate = async.nextTick;
|
|
}
|
|
}
|
|
|
|
async.each = function (arr, iterator, callback) {
|
|
callback = callback || function () {};
|
|
if (!arr.length) {
|
|
return callback();
|
|
}
|
|
var completed = 0;
|
|
_each(arr, function (x) {
|
|
iterator(x, only_once(function (err) {
|
|
if (err) {
|
|
callback(err);
|
|
callback = function () {};
|
|
}
|
|
else {
|
|
completed += 1;
|
|
if (completed >= arr.length) {
|
|
callback(null);
|
|
}
|
|
}
|
|
}));
|
|
});
|
|
};
|
|
async.forEach = async.each;
|
|
|
|
async.eachSeries = function (arr, iterator, callback) {
|
|
callback = callback || function () {};
|
|
if (!arr.length) {
|
|
return callback();
|
|
}
|
|
var completed = 0;
|
|
var iterate = function () {
|
|
iterator(arr[completed], function (err) {
|
|
if (err) {
|
|
callback(err);
|
|
callback = function () {};
|
|
}
|
|
else {
|
|
completed += 1;
|
|
if (completed >= arr.length) {
|
|
callback(null);
|
|
}
|
|
else {
|
|
iterate();
|
|
}
|
|
}
|
|
});
|
|
};
|
|
iterate();
|
|
};
|
|
async.forEachSeries = async.eachSeries;
|
|
|
|
async.eachLimit = function (arr, limit, iterator, callback) {
|
|
var fn = _eachLimit(limit);
|
|
fn.apply(null, [arr, iterator, callback]);
|
|
};
|
|
async.forEachLimit = async.eachLimit;
|
|
|
|
var _eachLimit = function (limit) {
|
|
|
|
return function (arr, iterator, callback) {
|
|
callback = callback || function () {};
|
|
if (!arr.length || limit <= 0) {
|
|
return callback();
|
|
}
|
|
var completed = 0;
|
|
var started = 0;
|
|
var running = 0;
|
|
|
|
(function replenish () {
|
|
if (completed >= arr.length) {
|
|
return callback();
|
|
}
|
|
|
|
while (running < limit && started < arr.length) {
|
|
started += 1;
|
|
running += 1;
|
|
iterator(arr[started - 1], function (err) {
|
|
if (err) {
|
|
callback(err);
|
|
callback = function () {};
|
|
}
|
|
else {
|
|
completed += 1;
|
|
running -= 1;
|
|
if (completed >= arr.length) {
|
|
callback();
|
|
}
|
|
else {
|
|
replenish();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
})();
|
|
};
|
|
};
|
|
|
|
|
|
var doParallel = function (fn) {
|
|
return function () {
|
|
var args = Array.prototype.slice.call(arguments);
|
|
return fn.apply(null, [async.each].concat(args));
|
|
};
|
|
};
|
|
var doParallelLimit = function(limit, fn) {
|
|
return function () {
|
|
var args = Array.prototype.slice.call(arguments);
|
|
return fn.apply(null, [_eachLimit(limit)].concat(args));
|
|
};
|
|
};
|
|
var doSeries = function (fn) {
|
|
return function () {
|
|
var args = Array.prototype.slice.call(arguments);
|
|
return fn.apply(null, [async.eachSeries].concat(args));
|
|
};
|
|
};
|
|
|
|
|
|
var _asyncMap = function (eachfn, arr, iterator, callback) {
|
|
var results = [];
|
|
arr = _map(arr, function (x, i) {
|
|
return {index: i, value: x};
|
|
});
|
|
eachfn(arr, function (x, callback) {
|
|
iterator(x.value, function (err, v) {
|
|
results[x.index] = v;
|
|
callback(err);
|
|
});
|
|
}, function (err) {
|
|
callback(err, results);
|
|
});
|
|
};
|
|
async.map = doParallel(_asyncMap);
|
|
async.mapSeries = doSeries(_asyncMap);
|
|
async.mapLimit = function (arr, limit, iterator, callback) {
|
|
return _mapLimit(limit)(arr, iterator, callback);
|
|
};
|
|
|
|
var _mapLimit = function(limit) {
|
|
return doParallelLimit(limit, _asyncMap);
|
|
};
|
|
|
|
// reduce only has a series version, as doing reduce in parallel won't
|
|
// work in many situations.
|
|
async.reduce = function (arr, memo, iterator, callback) {
|
|
async.eachSeries(arr, function (x, callback) {
|
|
iterator(memo, x, function (err, v) {
|
|
memo = v;
|
|
callback(err);
|
|
});
|
|
}, function (err) {
|
|
callback(err, memo);
|
|
});
|
|
};
|
|
// inject alias
|
|
async.inject = async.reduce;
|
|
// foldl alias
|
|
async.foldl = async.reduce;
|
|
|
|
async.reduceRight = function (arr, memo, iterator, callback) {
|
|
var reversed = _map(arr, function (x) {
|
|
return x;
|
|
}).reverse();
|
|
async.reduce(reversed, memo, iterator, callback);
|
|
};
|
|
// foldr alias
|
|
async.foldr = async.reduceRight;
|
|
|
|
var _filter = function (eachfn, arr, iterator, callback) {
|
|
var results = [];
|
|
arr = _map(arr, function (x, i) {
|
|
return {index: i, value: x};
|
|
});
|
|
eachfn(arr, function (x, callback) {
|
|
iterator(x.value, function (v) {
|
|
if (v) {
|
|
results.push(x);
|
|
}
|
|
callback();
|
|
});
|
|
}, function (err) {
|
|
callback(_map(results.sort(function (a, b) {
|
|
return a.index - b.index;
|
|
}), function (x) {
|
|
return x.value;
|
|
}));
|
|
});
|
|
};
|
|
async.filter = doParallel(_filter);
|
|
async.filterSeries = doSeries(_filter);
|
|
// select alias
|
|
async.select = async.filter;
|
|
async.selectSeries = async.filterSeries;
|
|
|
|
var _reject = function (eachfn, arr, iterator, callback) {
|
|
var results = [];
|
|
arr = _map(arr, function (x, i) {
|
|
return {index: i, value: x};
|
|
});
|
|
eachfn(arr, function (x, callback) {
|
|
iterator(x.value, function (v) {
|
|
if (!v) {
|
|
results.push(x);
|
|
}
|
|
callback();
|
|
});
|
|
}, function (err) {
|
|
callback(_map(results.sort(function (a, b) {
|
|
return a.index - b.index;
|
|
}), function (x) {
|
|
return x.value;
|
|
}));
|
|
});
|
|
};
|
|
async.reject = doParallel(_reject);
|
|
async.rejectSeries = doSeries(_reject);
|
|
|
|
var _detect = function (eachfn, arr, iterator, main_callback) {
|
|
eachfn(arr, function (x, callback) {
|
|
iterator(x, function (result) {
|
|
if (result) {
|
|
main_callback(x);
|
|
main_callback = function () {};
|
|
}
|
|
else {
|
|
callback();
|
|
}
|
|
});
|
|
}, function (err) {
|
|
main_callback();
|
|
});
|
|
};
|
|
async.detect = doParallel(_detect);
|
|
async.detectSeries = doSeries(_detect);
|
|
|
|
async.some = function (arr, iterator, main_callback) {
|
|
async.each(arr, function (x, callback) {
|
|
iterator(x, function (v) {
|
|
if (v) {
|
|
main_callback(true);
|
|
main_callback = function () {};
|
|
}
|
|
callback();
|
|
});
|
|
}, function (err) {
|
|
main_callback(false);
|
|
});
|
|
};
|
|
// any alias
|
|
async.any = async.some;
|
|
|
|
async.every = function (arr, iterator, main_callback) {
|
|
async.each(arr, function (x, callback) {
|
|
iterator(x, function (v) {
|
|
if (!v) {
|
|
main_callback(false);
|
|
main_callback = function () {};
|
|
}
|
|
callback();
|
|
});
|
|
}, function (err) {
|
|
main_callback(true);
|
|
});
|
|
};
|
|
// all alias
|
|
async.all = async.every;
|
|
|
|
async.sortBy = function (arr, iterator, callback) {
|
|
async.map(arr, function (x, callback) {
|
|
iterator(x, function (err, criteria) {
|
|
if (err) {
|
|
callback(err);
|
|
}
|
|
else {
|
|
callback(null, {value: x, criteria: criteria});
|
|
}
|
|
});
|
|
}, function (err, results) {
|
|
if (err) {
|
|
return callback(err);
|
|
}
|
|
else {
|
|
var fn = function (left, right) {
|
|
var a = left.criteria, b = right.criteria;
|
|
return a < b ? -1 : a > b ? 1 : 0;
|
|
};
|
|
callback(null, _map(results.sort(fn), function (x) {
|
|
return x.value;
|
|
}));
|
|
}
|
|
});
|
|
};
|
|
|
|
async.auto = function (tasks, callback) {
|
|
callback = callback || function () {};
|
|
var keys = _keys(tasks);
|
|
if (!keys.length) {
|
|
return callback(null);
|
|
}
|
|
|
|
var results = {};
|
|
|
|
var listeners = [];
|
|
var addListener = function (fn) {
|
|
listeners.unshift(fn);
|
|
};
|
|
var removeListener = function (fn) {
|
|
for (var i = 0; i < listeners.length; i += 1) {
|
|
if (listeners[i] === fn) {
|
|
listeners.splice(i, 1);
|
|
return;
|
|
}
|
|
}
|
|
};
|
|
var taskComplete = function () {
|
|
_each(listeners.slice(0), function (fn) {
|
|
fn();
|
|
});
|
|
};
|
|
|
|
addListener(function () {
|
|
if (_keys(results).length === keys.length) {
|
|
callback(null, results);
|
|
callback = function () {};
|
|
}
|
|
});
|
|
|
|
_each(keys, function (k) {
|
|
var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k];
|
|
var taskCallback = function (err) {
|
|
var args = Array.prototype.slice.call(arguments, 1);
|
|
if (args.length <= 1) {
|
|
args = args[0];
|
|
}
|
|
if (err) {
|
|
var safeResults = {};
|
|
_each(_keys(results), function(rkey) {
|
|
safeResults[rkey] = results[rkey];
|
|
});
|
|
safeResults[k] = args;
|
|
callback(err, safeResults);
|
|
// stop subsequent errors hitting callback multiple times
|
|
callback = function () {};
|
|
}
|
|
else {
|
|
results[k] = args;
|
|
async.setImmediate(taskComplete);
|
|
}
|
|
};
|
|
var requires = task.slice(0, Math.abs(task.length - 1)) || [];
|
|
var ready = function () {
|
|
return _reduce(requires, function (a, x) {
|
|
return (a && results.hasOwnProperty(x));
|
|
}, true) && !results.hasOwnProperty(k);
|
|
};
|
|
if (ready()) {
|
|
task[task.length - 1](taskCallback, results);
|
|
}
|
|
else {
|
|
var listener = function () {
|
|
if (ready()) {
|
|
removeListener(listener);
|
|
task[task.length - 1](taskCallback, results);
|
|
}
|
|
};
|
|
addListener(listener);
|
|
}
|
|
});
|
|
};
|
|
|
|
async.waterfall = function (tasks, callback) {
|
|
callback = callback || function () {};
|
|
if (tasks.constructor !== Array) {
|
|
var err = new Error('First argument to waterfall must be an array of functions');
|
|
return callback(err);
|
|
}
|
|
if (!tasks.length) {
|
|
return callback();
|
|
}
|
|
var wrapIterator = function (iterator) {
|
|
return function (err) {
|
|
if (err) {
|
|
callback.apply(null, arguments);
|
|
callback = function () {};
|
|
}
|
|
else {
|
|
var args = Array.prototype.slice.call(arguments, 1);
|
|
var next = iterator.next();
|
|
if (next) {
|
|
args.push(wrapIterator(next));
|
|
}
|
|
else {
|
|
args.push(callback);
|
|
}
|
|
async.setImmediate(function () {
|
|
iterator.apply(null, args);
|
|
});
|
|
}
|
|
};
|
|
};
|
|
wrapIterator(async.iterator(tasks))();
|
|
};
|
|
|
|
var _parallel = function(eachfn, tasks, callback) {
|
|
callback = callback || function () {};
|
|
if (tasks.constructor === Array) {
|
|
eachfn.map(tasks, function (fn, callback) {
|
|
if (fn) {
|
|
fn(function (err) {
|
|
var args = Array.prototype.slice.call(arguments, 1);
|
|
if (args.length <= 1) {
|
|
args = args[0];
|
|
}
|
|
callback.call(null, err, args);
|
|
});
|
|
}
|
|
}, callback);
|
|
}
|
|
else {
|
|
var results = {};
|
|
eachfn.each(_keys(tasks), function (k, callback) {
|
|
tasks[k](function (err) {
|
|
var args = Array.prototype.slice.call(arguments, 1);
|
|
if (args.length <= 1) {
|
|
args = args[0];
|
|
}
|
|
results[k] = args;
|
|
callback(err);
|
|
});
|
|
}, function (err) {
|
|
callback(err, results);
|
|
});
|
|
}
|
|
};
|
|
|
|
async.parallel = function (tasks, callback) {
|
|
_parallel({ map: async.map, each: async.each }, tasks, callback);
|
|
};
|
|
|
|
async.parallelLimit = function(tasks, limit, callback) {
|
|
_parallel({ map: _mapLimit(limit), each: _eachLimit(limit) }, tasks, callback);
|
|
};
|
|
|
|
async.series = function (tasks, callback) {
|
|
callback = callback || function () {};
|
|
if (tasks.constructor === Array) {
|
|
async.mapSeries(tasks, function (fn, callback) {
|
|
if (fn) {
|
|
fn(function (err) {
|
|
var args = Array.prototype.slice.call(arguments, 1);
|
|
if (args.length <= 1) {
|
|
args = args[0];
|
|
}
|
|
callback.call(null, err, args);
|
|
});
|
|
}
|
|
}, callback);
|
|
}
|
|
else {
|
|
var results = {};
|
|
async.eachSeries(_keys(tasks), function (k, callback) {
|
|
tasks[k](function (err) {
|
|
var args = Array.prototype.slice.call(arguments, 1);
|
|
if (args.length <= 1) {
|
|
args = args[0];
|
|
}
|
|
results[k] = args;
|
|
callback(err);
|
|
});
|
|
}, function (err) {
|
|
callback(err, results);
|
|
});
|
|
}
|
|
};
|
|
|
|
async.iterator = function (tasks) {
|
|
var makeCallback = function (index) {
|
|
var fn = function () {
|
|
if (tasks.length) {
|
|
tasks[index].apply(null, arguments);
|
|
}
|
|
return fn.next();
|
|
};
|
|
fn.next = function () {
|
|
return (index < tasks.length - 1) ? makeCallback(index + 1): null;
|
|
};
|
|
return fn;
|
|
};
|
|
return makeCallback(0);
|
|
};
|
|
|
|
async.apply = function (fn) {
|
|
var args = Array.prototype.slice.call(arguments, 1);
|
|
return function () {
|
|
return fn.apply(
|
|
null, args.concat(Array.prototype.slice.call(arguments))
|
|
);
|
|
};
|
|
};
|
|
|
|
var _concat = function (eachfn, arr, fn, callback) {
|
|
var r = [];
|
|
eachfn(arr, function (x, cb) {
|
|
fn(x, function (err, y) {
|
|
r = r.concat(y || []);
|
|
cb(err);
|
|
});
|
|
}, function (err) {
|
|
callback(err, r);
|
|
});
|
|
};
|
|
async.concat = doParallel(_concat);
|
|
async.concatSeries = doSeries(_concat);
|
|
|
|
async.whilst = function (test, iterator, callback) {
|
|
if (test()) {
|
|
iterator(function (err) {
|
|
if (err) {
|
|
return callback(err);
|
|
}
|
|
async.whilst(test, iterator, callback);
|
|
});
|
|
}
|
|
else {
|
|
callback();
|
|
}
|
|
};
|
|
|
|
async.doWhilst = function (iterator, test, callback) {
|
|
iterator(function (err) {
|
|
if (err) {
|
|
return callback(err);
|
|
}
|
|
if (test()) {
|
|
async.doWhilst(iterator, test, callback);
|
|
}
|
|
else {
|
|
callback();
|
|
}
|
|
});
|
|
};
|
|
|
|
async.until = function (test, iterator, callback) {
|
|
if (!test()) {
|
|
iterator(function (err) {
|
|
if (err) {
|
|
return callback(err);
|
|
}
|
|
async.until(test, iterator, callback);
|
|
});
|
|
}
|
|
else {
|
|
callback();
|
|
}
|
|
};
|
|
|
|
async.doUntil = function (iterator, test, callback) {
|
|
iterator(function (err) {
|
|
if (err) {
|
|
return callback(err);
|
|
}
|
|
if (!test()) {
|
|
async.doUntil(iterator, test, callback);
|
|
}
|
|
else {
|
|
callback();
|
|
}
|
|
});
|
|
};
|
|
|
|
async.queue = function (worker, concurrency) {
|
|
if (concurrency === undefined) {
|
|
concurrency = 1;
|
|
}
|
|
function _insert(q, data, pos, callback) {
|
|
if(data.constructor !== Array) {
|
|
data = [data];
|
|
}
|
|
_each(data, function(task) {
|
|
var item = {
|
|
data: task,
|
|
callback: typeof callback === 'function' ? callback : null
|
|
};
|
|
|
|
if (pos) {
|
|
q.tasks.unshift(item);
|
|
} else {
|
|
q.tasks.push(item);
|
|
}
|
|
|
|
if (q.saturated && q.tasks.length === concurrency) {
|
|
q.saturated();
|
|
}
|
|
async.setImmediate(q.process);
|
|
});
|
|
}
|
|
|
|
var workers = 0;
|
|
var q = {
|
|
tasks: [],
|
|
concurrency: concurrency,
|
|
saturated: null,
|
|
empty: null,
|
|
drain: null,
|
|
push: function (data, callback) {
|
|
_insert(q, data, false, callback);
|
|
},
|
|
unshift: function (data, callback) {
|
|
_insert(q, data, true, callback);
|
|
},
|
|
process: function () {
|
|
if (workers < q.concurrency && q.tasks.length) {
|
|
var task = q.tasks.shift();
|
|
if (q.empty && q.tasks.length === 0) {
|
|
q.empty();
|
|
}
|
|
workers += 1;
|
|
var next = function () {
|
|
workers -= 1;
|
|
if (task.callback) {
|
|
task.callback.apply(task, arguments);
|
|
}
|
|
if (q.drain && q.tasks.length + workers === 0) {
|
|
q.drain();
|
|
}
|
|
q.process();
|
|
};
|
|
var cb = only_once(next);
|
|
worker(task.data, cb);
|
|
}
|
|
},
|
|
length: function () {
|
|
return q.tasks.length;
|
|
},
|
|
running: function () {
|
|
return workers;
|
|
}
|
|
};
|
|
return q;
|
|
};
|
|
|
|
async.cargo = function (worker, payload) {
|
|
var working = false,
|
|
tasks = [];
|
|
|
|
var cargo = {
|
|
tasks: tasks,
|
|
payload: payload,
|
|
saturated: null,
|
|
empty: null,
|
|
drain: null,
|
|
push: function (data, callback) {
|
|
if(data.constructor !== Array) {
|
|
data = [data];
|
|
}
|
|
_each(data, function(task) {
|
|
tasks.push({
|
|
data: task,
|
|
callback: typeof callback === 'function' ? callback : null
|
|
});
|
|
if (cargo.saturated && tasks.length === payload) {
|
|
cargo.saturated();
|
|
}
|
|
});
|
|
async.setImmediate(cargo.process);
|
|
},
|
|
process: function process() {
|
|
if (working) return;
|
|
if (tasks.length === 0) {
|
|
if(cargo.drain) cargo.drain();
|
|
return;
|
|
}
|
|
|
|
var ts = typeof payload === 'number'
|
|
? tasks.splice(0, payload)
|
|
: tasks.splice(0);
|
|
|
|
var ds = _map(ts, function (task) {
|
|
return task.data;
|
|
});
|
|
|
|
if(cargo.empty) cargo.empty();
|
|
working = true;
|
|
worker(ds, function () {
|
|
working = false;
|
|
|
|
var args = arguments;
|
|
_each(ts, function (data) {
|
|
if (data.callback) {
|
|
data.callback.apply(null, args);
|
|
}
|
|
});
|
|
|
|
process();
|
|
});
|
|
},
|
|
length: function () {
|
|
return tasks.length;
|
|
},
|
|
running: function () {
|
|
return working;
|
|
}
|
|
};
|
|
return cargo;
|
|
};
|
|
|
|
var _console_fn = function (name) {
|
|
return function (fn) {
|
|
var args = Array.prototype.slice.call(arguments, 1);
|
|
fn.apply(null, args.concat([function (err) {
|
|
var args = Array.prototype.slice.call(arguments, 1);
|
|
if (typeof console !== 'undefined') {
|
|
if (err) {
|
|
if (console.error) {
|
|
console.error(err);
|
|
}
|
|
}
|
|
else if (console[name]) {
|
|
_each(args, function (x) {
|
|
console[name](x);
|
|
});
|
|
}
|
|
}
|
|
}]));
|
|
};
|
|
};
|
|
async.log = _console_fn('log');
|
|
async.dir = _console_fn('dir');
|
|
/*async.info = _console_fn('info');
|
|
async.warn = _console_fn('warn');
|
|
async.error = _console_fn('error');*/
|
|
|
|
async.memoize = function (fn, hasher) {
|
|
var memo = {};
|
|
var queues = {};
|
|
hasher = hasher || function (x) {
|
|
return x;
|
|
};
|
|
var memoized = function () {
|
|
var args = Array.prototype.slice.call(arguments);
|
|
var callback = args.pop();
|
|
var key = hasher.apply(null, args);
|
|
if (key in memo) {
|
|
callback.apply(null, memo[key]);
|
|
}
|
|
else if (key in queues) {
|
|
queues[key].push(callback);
|
|
}
|
|
else {
|
|
queues[key] = [callback];
|
|
fn.apply(null, args.concat([function () {
|
|
memo[key] = arguments;
|
|
var q = queues[key];
|
|
delete queues[key];
|
|
for (var i = 0, l = q.length; i < l; i++) {
|
|
q[i].apply(null, arguments);
|
|
}
|
|
}]));
|
|
}
|
|
};
|
|
memoized.memo = memo;
|
|
memoized.unmemoized = fn;
|
|
return memoized;
|
|
};
|
|
|
|
async.unmemoize = function (fn) {
|
|
return function () {
|
|
return (fn.unmemoized || fn).apply(null, arguments);
|
|
};
|
|
};
|
|
|
|
async.times = function (count, iterator, callback) {
|
|
var counter = [];
|
|
for (var i = 0; i < count; i++) {
|
|
counter.push(i);
|
|
}
|
|
return async.map(counter, iterator, callback);
|
|
};
|
|
|
|
async.timesSeries = function (count, iterator, callback) {
|
|
var counter = [];
|
|
for (var i = 0; i < count; i++) {
|
|
counter.push(i);
|
|
}
|
|
return async.mapSeries(counter, iterator, callback);
|
|
};
|
|
|
|
async.compose = function (/* functions... */) {
|
|
var fns = Array.prototype.reverse.call(arguments);
|
|
return function () {
|
|
var that = this;
|
|
var args = Array.prototype.slice.call(arguments);
|
|
var callback = args.pop();
|
|
async.reduce(fns, args, function (newargs, fn, cb) {
|
|
fn.apply(that, newargs.concat([function () {
|
|
var err = arguments[0];
|
|
var nextargs = Array.prototype.slice.call(arguments, 1);
|
|
cb(err, nextargs);
|
|
}]))
|
|
},
|
|
function (err, results) {
|
|
callback.apply(that, [err].concat(results));
|
|
});
|
|
};
|
|
};
|
|
|
|
var _applyEach = function (eachfn, fns /*args...*/) {
|
|
var go = function () {
|
|
var that = this;
|
|
var args = Array.prototype.slice.call(arguments);
|
|
var callback = args.pop();
|
|
return eachfn(fns, function (fn, cb) {
|
|
fn.apply(that, args.concat([cb]));
|
|
},
|
|
callback);
|
|
};
|
|
if (arguments.length > 2) {
|
|
var args = Array.prototype.slice.call(arguments, 2);
|
|
return go.apply(this, args);
|
|
}
|
|
else {
|
|
return go;
|
|
}
|
|
};
|
|
async.applyEach = doParallel(_applyEach);
|
|
async.applyEachSeries = doSeries(_applyEach);
|
|
|
|
async.forever = function (fn, callback) {
|
|
function next(err) {
|
|
if (err) {
|
|
if (callback) {
|
|
return callback(err);
|
|
}
|
|
throw err;
|
|
}
|
|
fn(next);
|
|
}
|
|
next();
|
|
};
|
|
|
|
// AMD / RequireJS
|
|
if (typeof define !== 'undefined' && define.amd) {
|
|
define([], function () {
|
|
return async;
|
|
});
|
|
}
|
|
// Node.js
|
|
else if (typeof module !== 'undefined' && module.exports) {
|
|
module.exports = async;
|
|
}
|
|
// included directly via <script> tag
|
|
else {
|
|
root.async = async;
|
|
}
|
|
|
|
}());
|
|
|
|
},{"__browserify_process":66}],54:[function(require,module,exports){
|
|
// UTILITY
|
|
var util = require('util');
|
|
var Buffer = require("buffer").Buffer;
|
|
var pSlice = Array.prototype.slice;
|
|
|
|
function objectKeys(object) {
|
|
if (Object.keys) return Object.keys(object);
|
|
var result = [];
|
|
for (var name in object) {
|
|
if (Object.prototype.hasOwnProperty.call(object, name)) {
|
|
result.push(name);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
// 1. The assert module provides functions that throw
|
|
// AssertionError's when particular conditions are not met. The
|
|
// assert module must conform to the following interface.
|
|
|
|
var assert = module.exports = ok;
|
|
|
|
// 2. The AssertionError is defined in assert.
|
|
// new assert.AssertionError({ message: message,
|
|
// actual: actual,
|
|
// expected: expected })
|
|
|
|
assert.AssertionError = function AssertionError(options) {
|
|
this.name = 'AssertionError';
|
|
this.message = options.message;
|
|
this.actual = options.actual;
|
|
this.expected = options.expected;
|
|
this.operator = options.operator;
|
|
var stackStartFunction = options.stackStartFunction || fail;
|
|
|
|
if (Error.captureStackTrace) {
|
|
Error.captureStackTrace(this, stackStartFunction);
|
|
}
|
|
};
|
|
|
|
// assert.AssertionError instanceof Error
|
|
util.inherits(assert.AssertionError, Error);
|
|
|
|
function replacer(key, value) {
|
|
if (value === undefined) {
|
|
return '' + value;
|
|
}
|
|
if (typeof value === 'number' && (isNaN(value) || !isFinite(value))) {
|
|
return value.toString();
|
|
}
|
|
if (typeof value === 'function' || value instanceof RegExp) {
|
|
return value.toString();
|
|
}
|
|
return value;
|
|
}
|
|
|
|
function truncate(s, n) {
|
|
if (typeof s == 'string') {
|
|
return s.length < n ? s : s.slice(0, n);
|
|
} else {
|
|
return s;
|
|
}
|
|
}
|
|
|
|
assert.AssertionError.prototype.toString = function() {
|
|
if (this.message) {
|
|
return [this.name + ':', this.message].join(' ');
|
|
} else {
|
|
return [
|
|
this.name + ':',
|
|
truncate(JSON.stringify(this.actual, replacer), 128),
|
|
this.operator,
|
|
truncate(JSON.stringify(this.expected, replacer), 128)
|
|
].join(' ');
|
|
}
|
|
};
|
|
|
|
// At present only the three keys mentioned above are used and
|
|
// understood by the spec. Implementations or sub modules can pass
|
|
// other keys to the AssertionError's constructor - they will be
|
|
// ignored.
|
|
|
|
// 3. All of the following functions must throw an AssertionError
|
|
// when a corresponding condition is not met, with a message that
|
|
// may be undefined if not provided. All assertion methods provide
|
|
// both the actual and expected values to the assertion error for
|
|
// display purposes.
|
|
|
|
function fail(actual, expected, message, operator, stackStartFunction) {
|
|
throw new assert.AssertionError({
|
|
message: message,
|
|
actual: actual,
|
|
expected: expected,
|
|
operator: operator,
|
|
stackStartFunction: stackStartFunction
|
|
});
|
|
}
|
|
|
|
// EXTENSION! allows for well behaved errors defined elsewhere.
|
|
assert.fail = fail;
|
|
|
|
// 4. Pure assertion tests whether a value is truthy, as determined
|
|
// by !!guard.
|
|
// assert.ok(guard, message_opt);
|
|
// This statement is equivalent to assert.equal(true, guard,
|
|
// message_opt);. To test strictly for the value true, use
|
|
// assert.strictEqual(true, guard, message_opt);.
|
|
|
|
function ok(value, message) {
|
|
if (!!!value) fail(value, true, message, '==', assert.ok);
|
|
}
|
|
assert.ok = ok;
|
|
|
|
// 5. The equality assertion tests shallow, coercive equality with
|
|
// ==.
|
|
// assert.equal(actual, expected, message_opt);
|
|
|
|
assert.equal = function equal(actual, expected, message) {
|
|
if (actual != expected) fail(actual, expected, message, '==', assert.equal);
|
|
};
|
|
|
|
// 6. The non-equality assertion tests for whether two objects are not equal
|
|
// with != assert.notEqual(actual, expected, message_opt);
|
|
|
|
assert.notEqual = function notEqual(actual, expected, message) {
|
|
if (actual == expected) {
|
|
fail(actual, expected, message, '!=', assert.notEqual);
|
|
}
|
|
};
|
|
|
|
// 7. The equivalence assertion tests a deep equality relation.
|
|
// assert.deepEqual(actual, expected, message_opt);
|
|
|
|
assert.deepEqual = function deepEqual(actual, expected, message) {
|
|
if (!_deepEqual(actual, expected)) {
|
|
fail(actual, expected, message, 'deepEqual', assert.deepEqual);
|
|
}
|
|
};
|
|
|
|
function _deepEqual(actual, expected) {
|
|
// 7.1. All identical values are equivalent, as determined by ===.
|
|
if (actual === expected) {
|
|
return true;
|
|
|
|
} else if (Buffer.isBuffer(actual) && Buffer.isBuffer(expected)) {
|
|
if (actual.length != expected.length) return false;
|
|
|
|
for (var i = 0; i < actual.length; i++) {
|
|
if (actual[i] !== expected[i]) return false;
|
|
}
|
|
|
|
return true;
|
|
|
|
// 7.2. If the expected value is a Date object, the actual value is
|
|
// equivalent if it is also a Date object that refers to the same time.
|
|
} else if (actual instanceof Date && expected instanceof Date) {
|
|
return actual.getTime() === expected.getTime();
|
|
|
|
// 7.3. Other pairs that do not both pass typeof value == 'object',
|
|
// equivalence is determined by ==.
|
|
} else if (typeof actual != 'object' && typeof expected != 'object') {
|
|
return actual == expected;
|
|
|
|
// 7.4. For all other Object pairs, including Array objects, equivalence is
|
|
// determined by having the same number of owned properties (as verified
|
|
// with Object.prototype.hasOwnProperty.call), the same set of keys
|
|
// (although not necessarily the same order), equivalent values for every
|
|
// corresponding key, and an identical 'prototype' property. Note: this
|
|
// accounts for both named and indexed properties on Arrays.
|
|
} else {
|
|
return objEquiv(actual, expected);
|
|
}
|
|
}
|
|
|
|
function isUndefinedOrNull(value) {
|
|
return value === null || value === undefined;
|
|
}
|
|
|
|
function isArguments(object) {
|
|
return Object.prototype.toString.call(object) == '[object Arguments]';
|
|
}
|
|
|
|
function objEquiv(a, b) {
|
|
if (isUndefinedOrNull(a) || isUndefinedOrNull(b))
|
|
return false;
|
|
// an identical 'prototype' property.
|
|
if (a.prototype !== b.prototype) return false;
|
|
//~~~I've managed to break Object.keys through screwy arguments passing.
|
|
// Converting to array solves the problem.
|
|
if (isArguments(a)) {
|
|
if (!isArguments(b)) {
|
|
return false;
|
|
}
|
|
a = pSlice.call(a);
|
|
b = pSlice.call(b);
|
|
return _deepEqual(a, b);
|
|
}
|
|
try {
|
|
var ka = objectKeys(a),
|
|
kb = objectKeys(b),
|
|
key, i;
|
|
} catch (e) {//happens when one is a string literal and the other isn't
|
|
return false;
|
|
}
|
|
// having the same number of owned properties (keys incorporates
|
|
// hasOwnProperty)
|
|
if (ka.length != kb.length)
|
|
return false;
|
|
//the same set of keys (although not necessarily the same order),
|
|
ka.sort();
|
|
kb.sort();
|
|
//~~~cheap key test
|
|
for (i = ka.length - 1; i >= 0; i--) {
|
|
if (ka[i] != kb[i])
|
|
return false;
|
|
}
|
|
//equivalent values for every corresponding key, and
|
|
//~~~possibly expensive deep test
|
|
for (i = ka.length - 1; i >= 0; i--) {
|
|
key = ka[i];
|
|
if (!_deepEqual(a[key], b[key])) return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// 8. The non-equivalence assertion tests for any deep inequality.
|
|
// assert.notDeepEqual(actual, expected, message_opt);
|
|
|
|
assert.notDeepEqual = function notDeepEqual(actual, expected, message) {
|
|
if (_deepEqual(actual, expected)) {
|
|
fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual);
|
|
}
|
|
};
|
|
|
|
// 9. The strict equality assertion tests strict equality, as determined by ===.
|
|
// assert.strictEqual(actual, expected, message_opt);
|
|
|
|
assert.strictEqual = function strictEqual(actual, expected, message) {
|
|
if (actual !== expected) {
|
|
fail(actual, expected, message, '===', assert.strictEqual);
|
|
}
|
|
};
|
|
|
|
// 10. The strict non-equality assertion tests for strict inequality, as
|
|
// determined by !==. assert.notStrictEqual(actual, expected, message_opt);
|
|
|
|
assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
|
|
if (actual === expected) {
|
|
fail(actual, expected, message, '!==', assert.notStrictEqual);
|
|
}
|
|
};
|
|
|
|
function expectedException(actual, expected) {
|
|
if (!actual || !expected) {
|
|
return false;
|
|
}
|
|
|
|
if (expected instanceof RegExp) {
|
|
return expected.test(actual);
|
|
} else if (actual instanceof expected) {
|
|
return true;
|
|
} else if (expected.call({}, actual) === true) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
function _throws(shouldThrow, block, expected, message) {
|
|
var actual;
|
|
|
|
if (typeof expected === 'string') {
|
|
message = expected;
|
|
expected = null;
|
|
}
|
|
|
|
try {
|
|
block();
|
|
} catch (e) {
|
|
actual = e;
|
|
}
|
|
|
|
message = (expected && expected.name ? ' (' + expected.name + ').' : '.') +
|
|
(message ? ' ' + message : '.');
|
|
|
|
if (shouldThrow && !actual) {
|
|
fail('Missing expected exception' + message);
|
|
}
|
|
|
|
if (!shouldThrow && expectedException(actual, expected)) {
|
|
fail('Got unwanted exception' + message);
|
|
}
|
|
|
|
if ((shouldThrow && actual && expected &&
|
|
!expectedException(actual, expected)) || (!shouldThrow && actual)) {
|
|
throw actual;
|
|
}
|
|
}
|
|
|
|
// 11. Expected to throw an error:
|
|
// assert.throws(block, Error_opt, message_opt);
|
|
|
|
assert.throws = function(block, /*optional*/error, /*optional*/message) {
|
|
_throws.apply(this, [true].concat(pSlice.call(arguments)));
|
|
};
|
|
|
|
// EXTENSION! This is annoying to write outside this module.
|
|
assert.doesNotThrow = function(block, /*optional*/error, /*optional*/message) {
|
|
_throws.apply(this, [false].concat(pSlice.call(arguments)));
|
|
};
|
|
|
|
assert.ifError = function(err) { if (err) {throw err;}};
|
|
|
|
},{"buffer":58,"util":56}],55:[function(require,module,exports){
|
|
var process=require("__browserify_process");if (!process.EventEmitter) process.EventEmitter = function () {};
|
|
|
|
var EventEmitter = exports.EventEmitter = process.EventEmitter;
|
|
var isArray = typeof Array.isArray === 'function'
|
|
? Array.isArray
|
|
: function (xs) {
|
|
return Object.prototype.toString.call(xs) === '[object Array]'
|
|
}
|
|
;
|
|
function indexOf (xs, x) {
|
|
if (xs.indexOf) return xs.indexOf(x);
|
|
for (var i = 0; i < xs.length; i++) {
|
|
if (x === xs[i]) return i;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
// By default EventEmitters will print a warning if more than
|
|
// 10 listeners are added to it. This is a useful default which
|
|
// helps finding memory leaks.
|
|
//
|
|
// Obviously not all Emitters should be limited to 10. This function allows
|
|
// that to be increased. Set to zero for unlimited.
|
|
var defaultMaxListeners = 10;
|
|
EventEmitter.prototype.setMaxListeners = function(n) {
|
|
if (!this._events) this._events = {};
|
|
this._events.maxListeners = n;
|
|
};
|
|
|
|
|
|
EventEmitter.prototype.emit = function(type) {
|
|
// If there is no 'error' event listener then throw.
|
|
if (type === 'error') {
|
|
if (!this._events || !this._events.error ||
|
|
(isArray(this._events.error) && !this._events.error.length))
|
|
{
|
|
if (arguments[1] instanceof Error) {
|
|
throw arguments[1]; // Unhandled 'error' event
|
|
} else {
|
|
throw new Error("Uncaught, unspecified 'error' event.");
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (!this._events) return false;
|
|
var handler = this._events[type];
|
|
if (!handler) return false;
|
|
|
|
if (typeof handler == 'function') {
|
|
switch (arguments.length) {
|
|
// fast cases
|
|
case 1:
|
|
handler.call(this);
|
|
break;
|
|
case 2:
|
|
handler.call(this, arguments[1]);
|
|
break;
|
|
case 3:
|
|
handler.call(this, arguments[1], arguments[2]);
|
|
break;
|
|
// slower
|
|
default:
|
|
var args = Array.prototype.slice.call(arguments, 1);
|
|
handler.apply(this, args);
|
|
}
|
|
return true;
|
|
|
|
} else if (isArray(handler)) {
|
|
var args = Array.prototype.slice.call(arguments, 1);
|
|
|
|
var listeners = handler.slice();
|
|
for (var i = 0, l = listeners.length; i < l; i++) {
|
|
listeners[i].apply(this, args);
|
|
}
|
|
return true;
|
|
|
|
} else {
|
|
return false;
|
|
}
|
|
};
|
|
|
|
// EventEmitter is defined in src/node_events.cc
|
|
// EventEmitter.prototype.emit() is also defined there.
|
|
EventEmitter.prototype.addListener = function(type, listener) {
|
|
if ('function' !== typeof listener) {
|
|
throw new Error('addListener only takes instances of Function');
|
|
}
|
|
|
|
if (!this._events) this._events = {};
|
|
|
|
// To avoid recursion in the case that type == "newListeners"! Before
|
|
// adding it to the listeners, first emit "newListeners".
|
|
this.emit('newListener', type, listener);
|
|
|
|
if (!this._events[type]) {
|
|
// Optimize the case of one listener. Don't need the extra array object.
|
|
this._events[type] = listener;
|
|
} else if (isArray(this._events[type])) {
|
|
|
|
// Check for listener leak
|
|
if (!this._events[type].warned) {
|
|
var m;
|
|
if (this._events.maxListeners !== undefined) {
|
|
m = this._events.maxListeners;
|
|
} else {
|
|
m = defaultMaxListeners;
|
|
}
|
|
|
|
if (m && m > 0 && this._events[type].length > m) {
|
|
this._events[type].warned = true;
|
|
console.error('(node) warning: possible EventEmitter memory ' +
|
|
'leak detected. %d listeners added. ' +
|
|
'Use emitter.setMaxListeners() to increase limit.',
|
|
this._events[type].length);
|
|
console.trace();
|
|
}
|
|
}
|
|
|
|
// If we've already got an array, just append.
|
|
this._events[type].push(listener);
|
|
} else {
|
|
// Adding the second element, need to change to array.
|
|
this._events[type] = [this._events[type], listener];
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
EventEmitter.prototype.on = EventEmitter.prototype.addListener;
|
|
|
|
EventEmitter.prototype.once = function(type, listener) {
|
|
var self = this;
|
|
self.on(type, function g() {
|
|
self.removeListener(type, g);
|
|
listener.apply(this, arguments);
|
|
});
|
|
|
|
return this;
|
|
};
|
|
|
|
EventEmitter.prototype.removeListener = function(type, listener) {
|
|
if ('function' !== typeof listener) {
|
|
throw new Error('removeListener only takes instances of Function');
|
|
}
|
|
|
|
// does not use listeners(), so no side effect of creating _events[type]
|
|
if (!this._events || !this._events[type]) return this;
|
|
|
|
var list = this._events[type];
|
|
|
|
if (isArray(list)) {
|
|
var i = indexOf(list, listener);
|
|
if (i < 0) return this;
|
|
list.splice(i, 1);
|
|
if (list.length == 0)
|
|
delete this._events[type];
|
|
} else if (this._events[type] === listener) {
|
|
delete this._events[type];
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
EventEmitter.prototype.removeAllListeners = function(type) {
|
|
if (arguments.length === 0) {
|
|
this._events = {};
|
|
return this;
|
|
}
|
|
|
|
// does not use listeners(), so no side effect of creating _events[type]
|
|
if (type && this._events && this._events[type]) this._events[type] = null;
|
|
return this;
|
|
};
|
|
|
|
EventEmitter.prototype.listeners = function(type) {
|
|
if (!this._events) this._events = {};
|
|
if (!this._events[type]) this._events[type] = [];
|
|
if (!isArray(this._events[type])) {
|
|
this._events[type] = [this._events[type]];
|
|
}
|
|
return this._events[type];
|
|
};
|
|
|
|
EventEmitter.listenerCount = function(emitter, type) {
|
|
var ret;
|
|
if (!emitter._events || !emitter._events[type])
|
|
ret = 0;
|
|
else if (typeof emitter._events[type] === 'function')
|
|
ret = 1;
|
|
else
|
|
ret = emitter._events[type].length;
|
|
return ret;
|
|
};
|
|
|
|
},{"__browserify_process":66}],56:[function(require,module,exports){
|
|
var events = require('events');
|
|
|
|
exports.isArray = isArray;
|
|
exports.isDate = function(obj){return Object.prototype.toString.call(obj) === '[object Date]'};
|
|
exports.isRegExp = function(obj){return Object.prototype.toString.call(obj) === '[object RegExp]'};
|
|
|
|
|
|
exports.print = function () {};
|
|
exports.puts = function () {};
|
|
exports.debug = function() {};
|
|
|
|
exports.inspect = function(obj, showHidden, depth, colors) {
|
|
var seen = [];
|
|
|
|
var stylize = function(str, styleType) {
|
|
// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
|
|
var styles =
|
|
{ 'bold' : [1, 22],
|
|
'italic' : [3, 23],
|
|
'underline' : [4, 24],
|
|
'inverse' : [7, 27],
|
|
'white' : [37, 39],
|
|
'grey' : [90, 39],
|
|
'black' : [30, 39],
|
|
'blue' : [34, 39],
|
|
'cyan' : [36, 39],
|
|
'green' : [32, 39],
|
|
'magenta' : [35, 39],
|
|
'red' : [31, 39],
|
|
'yellow' : [33, 39] };
|
|
|
|
var style =
|
|
{ 'special': 'cyan',
|
|
'number': 'blue',
|
|
'boolean': 'yellow',
|
|
'undefined': 'grey',
|
|
'null': 'bold',
|
|
'string': 'green',
|
|
'date': 'magenta',
|
|
// "name": intentionally not styling
|
|
'regexp': 'red' }[styleType];
|
|
|
|
if (style) {
|
|
return '\u001b[' + styles[style][0] + 'm' + str +
|
|
'\u001b[' + styles[style][1] + 'm';
|
|
} else {
|
|
return str;
|
|
}
|
|
};
|
|
if (! colors) {
|
|
stylize = function(str, styleType) { return str; };
|
|
}
|
|
|
|
function format(value, recurseTimes) {
|
|
// Provide a hook for user-specified inspect functions.
|
|
// Check that value is an object with an inspect function on it
|
|
if (value && typeof value.inspect === 'function' &&
|
|
// Filter out the util module, it's inspect function is special
|
|
value !== exports &&
|
|
// Also filter out any prototype objects using the circular check.
|
|
!(value.constructor && value.constructor.prototype === value)) {
|
|
return value.inspect(recurseTimes);
|
|
}
|
|
|
|
// Primitive types cannot have properties
|
|
switch (typeof value) {
|
|
case 'undefined':
|
|
return stylize('undefined', 'undefined');
|
|
|
|
case 'string':
|
|
var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
|
|
.replace(/'/g, "\\'")
|
|
.replace(/\\"/g, '"') + '\'';
|
|
return stylize(simple, 'string');
|
|
|
|
case 'number':
|
|
return stylize('' + value, 'number');
|
|
|
|
case 'boolean':
|
|
return stylize('' + value, 'boolean');
|
|
}
|
|
// For some reason typeof null is "object", so special case here.
|
|
if (value === null) {
|
|
return stylize('null', 'null');
|
|
}
|
|
|
|
// Look up the keys of the object.
|
|
var visible_keys = Object_keys(value);
|
|
var keys = showHidden ? Object_getOwnPropertyNames(value) : visible_keys;
|
|
|
|
// Functions without properties can be shortcutted.
|
|
if (typeof value === 'function' && keys.length === 0) {
|
|
if (isRegExp(value)) {
|
|
return stylize('' + value, 'regexp');
|
|
} else {
|
|
var name = value.name ? ': ' + value.name : '';
|
|
return stylize('[Function' + name + ']', 'special');
|
|
}
|
|
}
|
|
|
|
// Dates without properties can be shortcutted
|
|
if (isDate(value) && keys.length === 0) {
|
|
return stylize(value.toUTCString(), 'date');
|
|
}
|
|
|
|
var base, type, braces;
|
|
// Determine the object type
|
|
if (isArray(value)) {
|
|
type = 'Array';
|
|
braces = ['[', ']'];
|
|
} else {
|
|
type = 'Object';
|
|
braces = ['{', '}'];
|
|
}
|
|
|
|
// Make functions say that they are functions
|
|
if (typeof value === 'function') {
|
|
var n = value.name ? ': ' + value.name : '';
|
|
base = (isRegExp(value)) ? ' ' + value : ' [Function' + n + ']';
|
|
} else {
|
|
base = '';
|
|
}
|
|
|
|
// Make dates with properties first say the date
|
|
if (isDate(value)) {
|
|
base = ' ' + value.toUTCString();
|
|
}
|
|
|
|
if (keys.length === 0) {
|
|
return braces[0] + base + braces[1];
|
|
}
|
|
|
|
if (recurseTimes < 0) {
|
|
if (isRegExp(value)) {
|
|
return stylize('' + value, 'regexp');
|
|
} else {
|
|
return stylize('[Object]', 'special');
|
|
}
|
|
}
|
|
|
|
seen.push(value);
|
|
|
|
var output = keys.map(function(key) {
|
|
var name, str;
|
|
if (value.__lookupGetter__) {
|
|
if (value.__lookupGetter__(key)) {
|
|
if (value.__lookupSetter__(key)) {
|
|
str = stylize('[Getter/Setter]', 'special');
|
|
} else {
|
|
str = stylize('[Getter]', 'special');
|
|
}
|
|
} else {
|
|
if (value.__lookupSetter__(key)) {
|
|
str = stylize('[Setter]', 'special');
|
|
}
|
|
}
|
|
}
|
|
if (visible_keys.indexOf(key) < 0) {
|
|
name = '[' + key + ']';
|
|
}
|
|
if (!str) {
|
|
if (seen.indexOf(value[key]) < 0) {
|
|
if (recurseTimes === null) {
|
|
str = format(value[key]);
|
|
} else {
|
|
str = format(value[key], recurseTimes - 1);
|
|
}
|
|
if (str.indexOf('\n') > -1) {
|
|
if (isArray(value)) {
|
|
str = str.split('\n').map(function(line) {
|
|
return ' ' + line;
|
|
}).join('\n').substr(2);
|
|
} else {
|
|
str = '\n' + str.split('\n').map(function(line) {
|
|
return ' ' + line;
|
|
}).join('\n');
|
|
}
|
|
}
|
|
} else {
|
|
str = stylize('[Circular]', 'special');
|
|
}
|
|
}
|
|
if (typeof name === 'undefined') {
|
|
if (type === 'Array' && key.match(/^\d+$/)) {
|
|
return str;
|
|
}
|
|
name = JSON.stringify('' + key);
|
|
if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
|
|
name = name.substr(1, name.length - 2);
|
|
name = stylize(name, 'name');
|
|
} else {
|
|
name = name.replace(/'/g, "\\'")
|
|
.replace(/\\"/g, '"')
|
|
.replace(/(^"|"$)/g, "'");
|
|
name = stylize(name, 'string');
|
|
}
|
|
}
|
|
|
|
return name + ': ' + str;
|
|
});
|
|
|
|
seen.pop();
|
|
|
|
var numLinesEst = 0;
|
|
var length = output.reduce(function(prev, cur) {
|
|
numLinesEst++;
|
|
if (cur.indexOf('\n') >= 0) numLinesEst++;
|
|
return prev + cur.length + 1;
|
|
}, 0);
|
|
|
|
if (length > 50) {
|
|
output = braces[0] +
|
|
(base === '' ? '' : base + '\n ') +
|
|
' ' +
|
|
output.join(',\n ') +
|
|
' ' +
|
|
braces[1];
|
|
|
|
} else {
|
|
output = braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
|
|
}
|
|
|
|
return output;
|
|
}
|
|
return format(obj, (typeof depth === 'undefined' ? 2 : depth));
|
|
};
|
|
|
|
|
|
function isArray(ar) {
|
|
return Array.isArray(ar) ||
|
|
(typeof ar === 'object' && Object.prototype.toString.call(ar) === '[object Array]');
|
|
}
|
|
|
|
|
|
function isRegExp(re) {
|
|
typeof re === 'object' && Object.prototype.toString.call(re) === '[object RegExp]';
|
|
}
|
|
|
|
|
|
function isDate(d) {
|
|
return typeof d === 'object' && Object.prototype.toString.call(d) === '[object Date]';
|
|
}
|
|
|
|
function pad(n) {
|
|
return n < 10 ? '0' + n.toString(10) : n.toString(10);
|
|
}
|
|
|
|
var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
|
|
'Oct', 'Nov', 'Dec'];
|
|
|
|
// 26 Feb 16:19:34
|
|
function timestamp() {
|
|
var d = new Date();
|
|
var time = [pad(d.getHours()),
|
|
pad(d.getMinutes()),
|
|
pad(d.getSeconds())].join(':');
|
|
return [d.getDate(), months[d.getMonth()], time].join(' ');
|
|
}
|
|
|
|
exports.log = function (msg) {};
|
|
|
|
exports.pump = null;
|
|
|
|
var Object_keys = Object.keys || function (obj) {
|
|
var res = [];
|
|
for (var key in obj) res.push(key);
|
|
return res;
|
|
};
|
|
|
|
var Object_getOwnPropertyNames = Object.getOwnPropertyNames || function (obj) {
|
|
var res = [];
|
|
for (var key in obj) {
|
|
if (Object.hasOwnProperty.call(obj, key)) res.push(key);
|
|
}
|
|
return res;
|
|
};
|
|
|
|
var Object_create = Object.create || function (prototype, properties) {
|
|
// from es5-shim
|
|
var object;
|
|
if (prototype === null) {
|
|
object = { '__proto__' : null };
|
|
}
|
|
else {
|
|
if (typeof prototype !== 'object') {
|
|
throw new TypeError(
|
|
'typeof prototype[' + (typeof prototype) + '] != \'object\''
|
|
);
|
|
}
|
|
var Type = function () {};
|
|
Type.prototype = prototype;
|
|
object = new Type();
|
|
object.__proto__ = prototype;
|
|
}
|
|
if (typeof properties !== 'undefined' && Object.defineProperties) {
|
|
Object.defineProperties(object, properties);
|
|
}
|
|
return object;
|
|
};
|
|
|
|
exports.inherits = function(ctor, superCtor) {
|
|
ctor.super_ = superCtor;
|
|
ctor.prototype = Object_create(superCtor.prototype, {
|
|
constructor: {
|
|
value: ctor,
|
|
enumerable: false,
|
|
writable: true,
|
|
configurable: true
|
|
}
|
|
});
|
|
};
|
|
|
|
var formatRegExp = /%[sdj%]/g;
|
|
exports.format = function(f) {
|
|
if (typeof f !== 'string') {
|
|
var objects = [];
|
|
for (var i = 0; i < arguments.length; i++) {
|
|
objects.push(exports.inspect(arguments[i]));
|
|
}
|
|
return objects.join(' ');
|
|
}
|
|
|
|
var i = 1;
|
|
var args = arguments;
|
|
var len = args.length;
|
|
var str = String(f).replace(formatRegExp, function(x) {
|
|
if (x === '%%') return '%';
|
|
if (i >= len) return x;
|
|
switch (x) {
|
|
case '%s': return String(args[i++]);
|
|
case '%d': return Number(args[i++]);
|
|
case '%j': return JSON.stringify(args[i++]);
|
|
default:
|
|
return x;
|
|
}
|
|
});
|
|
for(var x = args[i]; i < len; x = args[++i]){
|
|
if (x === null || typeof x !== 'object') {
|
|
str += ' ' + x;
|
|
} else {
|
|
str += ' ' + exports.inspect(x);
|
|
}
|
|
}
|
|
return str;
|
|
};
|
|
|
|
},{"events":55}],57:[function(require,module,exports){
|
|
exports.readIEEE754 = function(buffer, offset, isBE, mLen, nBytes) {
|
|
var e, m,
|
|
eLen = nBytes * 8 - mLen - 1,
|
|
eMax = (1 << eLen) - 1,
|
|
eBias = eMax >> 1,
|
|
nBits = -7,
|
|
i = isBE ? 0 : (nBytes - 1),
|
|
d = isBE ? 1 : -1,
|
|
s = buffer[offset + i];
|
|
|
|
i += d;
|
|
|
|
e = s & ((1 << (-nBits)) - 1);
|
|
s >>= (-nBits);
|
|
nBits += eLen;
|
|
for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8);
|
|
|
|
m = e & ((1 << (-nBits)) - 1);
|
|
e >>= (-nBits);
|
|
nBits += mLen;
|
|
for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8);
|
|
|
|
if (e === 0) {
|
|
e = 1 - eBias;
|
|
} else if (e === eMax) {
|
|
return m ? NaN : ((s ? -1 : 1) * Infinity);
|
|
} else {
|
|
m = m + Math.pow(2, mLen);
|
|
e = e - eBias;
|
|
}
|
|
return (s ? -1 : 1) * m * Math.pow(2, e - mLen);
|
|
};
|
|
|
|
exports.writeIEEE754 = function(buffer, value, offset, isBE, mLen, nBytes) {
|
|
var e, m, c,
|
|
eLen = nBytes * 8 - mLen - 1,
|
|
eMax = (1 << eLen) - 1,
|
|
eBias = eMax >> 1,
|
|
rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0),
|
|
i = isBE ? (nBytes - 1) : 0,
|
|
d = isBE ? -1 : 1,
|
|
s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0;
|
|
|
|
value = Math.abs(value);
|
|
|
|
if (isNaN(value) || value === Infinity) {
|
|
m = isNaN(value) ? 1 : 0;
|
|
e = eMax;
|
|
} else {
|
|
e = Math.floor(Math.log(value) / Math.LN2);
|
|
if (value * (c = Math.pow(2, -e)) < 1) {
|
|
e--;
|
|
c *= 2;
|
|
}
|
|
if (e + eBias >= 1) {
|
|
value += rt / c;
|
|
} else {
|
|
value += rt * Math.pow(2, 1 - eBias);
|
|
}
|
|
if (value * c >= 2) {
|
|
e++;
|
|
c /= 2;
|
|
}
|
|
|
|
if (e + eBias >= eMax) {
|
|
m = 0;
|
|
e = eMax;
|
|
} else if (e + eBias >= 1) {
|
|
m = (value * c - 1) * Math.pow(2, mLen);
|
|
e = e + eBias;
|
|
} else {
|
|
m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen);
|
|
e = 0;
|
|
}
|
|
}
|
|
|
|
for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8);
|
|
|
|
e = (e << mLen) | m;
|
|
eLen += mLen;
|
|
for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8);
|
|
|
|
buffer[offset + i - d] |= s * 128;
|
|
};
|
|
|
|
},{}],58:[function(require,module,exports){
|
|
var assert = require('assert');
|
|
exports.Buffer = Buffer;
|
|
exports.SlowBuffer = Buffer;
|
|
Buffer.poolSize = 8192;
|
|
exports.INSPECT_MAX_BYTES = 50;
|
|
|
|
function Buffer(subject, encoding, offset) {
|
|
if (!(this instanceof Buffer)) {
|
|
return new Buffer(subject, encoding, offset);
|
|
}
|
|
this.parent = this;
|
|
this.offset = 0;
|
|
|
|
var type;
|
|
|
|
// Are we slicing?
|
|
if (typeof offset === 'number') {
|
|
this.length = coerce(encoding);
|
|
this.offset = offset;
|
|
} else {
|
|
// Find the length
|
|
switch (type = typeof subject) {
|
|
case 'number':
|
|
this.length = coerce(subject);
|
|
break;
|
|
|
|
case 'string':
|
|
this.length = Buffer.byteLength(subject, encoding);
|
|
break;
|
|
|
|
case 'object': // Assume object is an array
|
|
this.length = coerce(subject.length);
|
|
break;
|
|
|
|
default:
|
|
throw new Error('First argument needs to be a number, ' +
|
|
'array or string.');
|
|
}
|
|
|
|
// Treat array-ish objects as a byte array.
|
|
if (isArrayIsh(subject)) {
|
|
for (var i = 0; i < this.length; i++) {
|
|
if (subject instanceof Buffer) {
|
|
this[i] = subject.readUInt8(i);
|
|
}
|
|
else {
|
|
this[i] = subject[i];
|
|
}
|
|
}
|
|
} else if (type == 'string') {
|
|
// We are a string
|
|
this.length = this.write(subject, 0, encoding);
|
|
} else if (type === 'number') {
|
|
for (var i = 0; i < this.length; i++) {
|
|
this[i] = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Buffer.prototype.get = function get(i) {
|
|
if (i < 0 || i >= this.length) throw new Error('oob');
|
|
return this[i];
|
|
};
|
|
|
|
Buffer.prototype.set = function set(i, v) {
|
|
if (i < 0 || i >= this.length) throw new Error('oob');
|
|
return this[i] = v;
|
|
};
|
|
|
|
Buffer.byteLength = function (str, encoding) {
|
|
switch (encoding || "utf8") {
|
|
case 'hex':
|
|
return str.length / 2;
|
|
|
|
case 'utf8':
|
|
case 'utf-8':
|
|
return utf8ToBytes(str).length;
|
|
|
|
case 'ascii':
|
|
case 'binary':
|
|
return str.length;
|
|
|
|
case 'base64':
|
|
return base64ToBytes(str).length;
|
|
|
|
default:
|
|
throw new Error('Unknown encoding');
|
|
}
|
|
};
|
|
|
|
Buffer.prototype.utf8Write = function (string, offset, length) {
|
|
var bytes, pos;
|
|
return Buffer._charsWritten = blitBuffer(utf8ToBytes(string), this, offset, length);
|
|
};
|
|
|
|
Buffer.prototype.asciiWrite = function (string, offset, length) {
|
|
var bytes, pos;
|
|
return Buffer._charsWritten = blitBuffer(asciiToBytes(string), this, offset, length);
|
|
};
|
|
|
|
Buffer.prototype.binaryWrite = Buffer.prototype.asciiWrite;
|
|
|
|
Buffer.prototype.base64Write = function (string, offset, length) {
|
|
var bytes, pos;
|
|
return Buffer._charsWritten = blitBuffer(base64ToBytes(string), this, offset, length);
|
|
};
|
|
|
|
Buffer.prototype.base64Slice = function (start, end) {
|
|
var bytes = Array.prototype.slice.apply(this, arguments)
|
|
return require("base64-js").fromByteArray(bytes);
|
|
};
|
|
|
|
Buffer.prototype.utf8Slice = function () {
|
|
var bytes = Array.prototype.slice.apply(this, arguments);
|
|
var res = "";
|
|
var tmp = "";
|
|
var i = 0;
|
|
while (i < bytes.length) {
|
|
if (bytes[i] <= 0x7F) {
|
|
res += decodeUtf8Char(tmp) + String.fromCharCode(bytes[i]);
|
|
tmp = "";
|
|
} else
|
|
tmp += "%" + bytes[i].toString(16);
|
|
|
|
i++;
|
|
}
|
|
|
|
return res + decodeUtf8Char(tmp);
|
|
}
|
|
|
|
Buffer.prototype.asciiSlice = function () {
|
|
var bytes = Array.prototype.slice.apply(this, arguments);
|
|
var ret = "";
|
|
for (var i = 0; i < bytes.length; i++)
|
|
ret += String.fromCharCode(bytes[i]);
|
|
return ret;
|
|
}
|
|
|
|
Buffer.prototype.binarySlice = Buffer.prototype.asciiSlice;
|
|
|
|
Buffer.prototype.inspect = function() {
|
|
var out = [],
|
|
len = this.length;
|
|
for (var i = 0; i < len; i++) {
|
|
out[i] = toHex(this[i]);
|
|
if (i == exports.INSPECT_MAX_BYTES) {
|
|
out[i + 1] = '...';
|
|
break;
|
|
}
|
|
}
|
|
return '<Buffer ' + out.join(' ') + '>';
|
|
};
|
|
|
|
|
|
Buffer.prototype.hexSlice = function(start, end) {
|
|
var len = this.length;
|
|
|
|
if (!start || start < 0) start = 0;
|
|
if (!end || end < 0 || end > len) end = len;
|
|
|
|
var out = '';
|
|
for (var i = start; i < end; i++) {
|
|
out += toHex(this[i]);
|
|
}
|
|
return out;
|
|
};
|
|
|
|
|
|
Buffer.prototype.toString = function(encoding, start, end) {
|
|
encoding = String(encoding || 'utf8').toLowerCase();
|
|
start = +start || 0;
|
|
if (typeof end == 'undefined') end = this.length;
|
|
|
|
// Fastpath empty strings
|
|
if (+end == start) {
|
|
return '';
|
|
}
|
|
|
|
switch (encoding) {
|
|
case 'hex':
|
|
return this.hexSlice(start, end);
|
|
|
|
case 'utf8':
|
|
case 'utf-8':
|
|
return this.utf8Slice(start, end);
|
|
|
|
case 'ascii':
|
|
return this.asciiSlice(start, end);
|
|
|
|
case 'binary':
|
|
return this.binarySlice(start, end);
|
|
|
|
case 'base64':
|
|
return this.base64Slice(start, end);
|
|
|
|
case 'ucs2':
|
|
case 'ucs-2':
|
|
return this.ucs2Slice(start, end);
|
|
|
|
default:
|
|
throw new Error('Unknown encoding');
|
|
}
|
|
};
|
|
|
|
|
|
Buffer.prototype.hexWrite = function(string, offset, length) {
|
|
offset = +offset || 0;
|
|
var remaining = this.length - offset;
|
|
if (!length) {
|
|
length = remaining;
|
|
} else {
|
|
length = +length;
|
|
if (length > remaining) {
|
|
length = remaining;
|
|
}
|
|
}
|
|
|
|
// must be an even number of digits
|
|
var strLen = string.length;
|
|
if (strLen % 2) {
|
|
throw new Error('Invalid hex string');
|
|
}
|
|
if (length > strLen / 2) {
|
|
length = strLen / 2;
|
|
}
|
|
for (var i = 0; i < length; i++) {
|
|
var byte = parseInt(string.substr(i * 2, 2), 16);
|
|
if (isNaN(byte)) throw new Error('Invalid hex string');
|
|
this[offset + i] = byte;
|
|
}
|
|
Buffer._charsWritten = i * 2;
|
|
return i;
|
|
};
|
|
|
|
|
|
Buffer.prototype.write = function(string, offset, length, encoding) {
|
|
// Support both (string, offset, length, encoding)
|
|
// and the legacy (string, encoding, offset, length)
|
|
if (isFinite(offset)) {
|
|
if (!isFinite(length)) {
|
|
encoding = length;
|
|
length = undefined;
|
|
}
|
|
} else { // legacy
|
|
var swap = encoding;
|
|
encoding = offset;
|
|
offset = length;
|
|
length = swap;
|
|
}
|
|
|
|
offset = +offset || 0;
|
|
var remaining = this.length - offset;
|
|
if (!length) {
|
|
length = remaining;
|
|
} else {
|
|
length = +length;
|
|
if (length > remaining) {
|
|
length = remaining;
|
|
}
|
|
}
|
|
encoding = String(encoding || 'utf8').toLowerCase();
|
|
|
|
switch (encoding) {
|
|
case 'hex':
|
|
return this.hexWrite(string, offset, length);
|
|
|
|
case 'utf8':
|
|
case 'utf-8':
|
|
return this.utf8Write(string, offset, length);
|
|
|
|
case 'ascii':
|
|
return this.asciiWrite(string, offset, length);
|
|
|
|
case 'binary':
|
|
return this.binaryWrite(string, offset, length);
|
|
|
|
case 'base64':
|
|
return this.base64Write(string, offset, length);
|
|
|
|
case 'ucs2':
|
|
case 'ucs-2':
|
|
return this.ucs2Write(string, offset, length);
|
|
|
|
default:
|
|
throw new Error('Unknown encoding');
|
|
}
|
|
};
|
|
|
|
|
|
// slice(start, end)
|
|
Buffer.prototype.slice = function(start, end) {
|
|
if (end === undefined) end = this.length;
|
|
|
|
if (end > this.length) {
|
|
throw new Error('oob');
|
|
}
|
|
if (start > end) {
|
|
throw new Error('oob');
|
|
}
|
|
|
|
return new Buffer(this, end - start, +start);
|
|
};
|
|
|
|
// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
|
|
Buffer.prototype.copy = function(target, target_start, start, end) {
|
|
var source = this;
|
|
start || (start = 0);
|
|
if (end === undefined || isNaN(end)) {
|
|
end = this.length;
|
|
}
|
|
target_start || (target_start = 0);
|
|
|
|
if (end < start) throw new Error('sourceEnd < sourceStart');
|
|
|
|
// Copy 0 bytes; we're done
|
|
if (end === start) return 0;
|
|
if (target.length == 0 || source.length == 0) return 0;
|
|
|
|
if (target_start < 0 || target_start >= target.length) {
|
|
throw new Error('targetStart out of bounds');
|
|
}
|
|
|
|
if (start < 0 || start >= source.length) {
|
|
throw new Error('sourceStart out of bounds');
|
|
}
|
|
|
|
if (end < 0 || end > source.length) {
|
|
throw new Error('sourceEnd out of bounds');
|
|
}
|
|
|
|
// Are we oob?
|
|
if (end > this.length) {
|
|
end = this.length;
|
|
}
|
|
|
|
if (target.length - target_start < end - start) {
|
|
end = target.length - target_start + start;
|
|
}
|
|
|
|
var temp = [];
|
|
for (var i=start; i<end; i++) {
|
|
assert.ok(typeof this[i] !== 'undefined', "copying undefined buffer bytes!");
|
|
temp.push(this[i]);
|
|
}
|
|
|
|
for (var i=target_start; i<target_start+temp.length; i++) {
|
|
target[i] = temp[i-target_start];
|
|
}
|
|
};
|
|
|
|
// fill(value, start=0, end=buffer.length)
|
|
Buffer.prototype.fill = function fill(value, start, end) {
|
|
value || (value = 0);
|
|
start || (start = 0);
|
|
end || (end = this.length);
|
|
|
|
if (typeof value === 'string') {
|
|
value = value.charCodeAt(0);
|
|
}
|
|
if (!(typeof value === 'number') || isNaN(value)) {
|
|
throw new Error('value is not a number');
|
|
}
|
|
|
|
if (end < start) throw new Error('end < start');
|
|
|
|
// Fill 0 bytes; we're done
|
|
if (end === start) return 0;
|
|
if (this.length == 0) return 0;
|
|
|
|
if (start < 0 || start >= this.length) {
|
|
throw new Error('start out of bounds');
|
|
}
|
|
|
|
if (end < 0 || end > this.length) {
|
|
throw new Error('end out of bounds');
|
|
}
|
|
|
|
for (var i = start; i < end; i++) {
|
|
this[i] = value;
|
|
}
|
|
}
|
|
|
|
// Static methods
|
|
Buffer.isBuffer = function isBuffer(b) {
|
|
return b instanceof Buffer || b instanceof Buffer;
|
|
};
|
|
|
|
Buffer.concat = function (list, totalLength) {
|
|
if (!isArray(list)) {
|
|
throw new Error("Usage: Buffer.concat(list, [totalLength])\n \
|
|
list should be an Array.");
|
|
}
|
|
|
|
if (list.length === 0) {
|
|
return new Buffer(0);
|
|
} else if (list.length === 1) {
|
|
return list[0];
|
|
}
|
|
|
|
if (typeof totalLength !== 'number') {
|
|
totalLength = 0;
|
|
for (var i = 0; i < list.length; i++) {
|
|
var buf = list[i];
|
|
totalLength += buf.length;
|
|
}
|
|
}
|
|
|
|
var buffer = new Buffer(totalLength);
|
|
var pos = 0;
|
|
for (var i = 0; i < list.length; i++) {
|
|
var buf = list[i];
|
|
buf.copy(buffer, pos);
|
|
pos += buf.length;
|
|
}
|
|
return buffer;
|
|
};
|
|
|
|
// helpers
|
|
|
|
function coerce(length) {
|
|
// Coerce length to a number (possibly NaN), round up
|
|
// in case it's fractional (e.g. 123.456) then do a
|
|
// double negate to coerce a NaN to 0. Easy, right?
|
|
length = ~~Math.ceil(+length);
|
|
return length < 0 ? 0 : length;
|
|
}
|
|
|
|
function isArray(subject) {
|
|
return (Array.isArray ||
|
|
function(subject){
|
|
return {}.toString.apply(subject) == '[object Array]'
|
|
})
|
|
(subject)
|
|
}
|
|
|
|
function isArrayIsh(subject) {
|
|
return isArray(subject) || Buffer.isBuffer(subject) ||
|
|
subject && typeof subject === 'object' &&
|
|
typeof subject.length === 'number';
|
|
}
|
|
|
|
function toHex(n) {
|
|
if (n < 16) return '0' + n.toString(16);
|
|
return n.toString(16);
|
|
}
|
|
|
|
function utf8ToBytes(str) {
|
|
var byteArray = [];
|
|
for (var i = 0; i < str.length; i++)
|
|
if (str.charCodeAt(i) <= 0x7F)
|
|
byteArray.push(str.charCodeAt(i));
|
|
else {
|
|
var h = encodeURIComponent(str.charAt(i)).substr(1).split('%');
|
|
for (var j = 0; j < h.length; j++)
|
|
byteArray.push(parseInt(h[j], 16));
|
|
}
|
|
|
|
return byteArray;
|
|
}
|
|
|
|
function asciiToBytes(str) {
|
|
var byteArray = []
|
|
for (var i = 0; i < str.length; i++ )
|
|
// Node's code seems to be doing this and not & 0x7F..
|
|
byteArray.push( str.charCodeAt(i) & 0xFF );
|
|
|
|
return byteArray;
|
|
}
|
|
|
|
function base64ToBytes(str) {
|
|
return require("base64-js").toByteArray(str);
|
|
}
|
|
|
|
function blitBuffer(src, dst, offset, length) {
|
|
var pos, i = 0;
|
|
while (i < length) {
|
|
if ((i+offset >= dst.length) || (i >= src.length))
|
|
break;
|
|
|
|
dst[i + offset] = src[i];
|
|
i++;
|
|
}
|
|
return i;
|
|
}
|
|
|
|
function decodeUtf8Char(str) {
|
|
try {
|
|
return decodeURIComponent(str);
|
|
} catch (err) {
|
|
return String.fromCharCode(0xFFFD); // UTF 8 invalid char
|
|
}
|
|
}
|
|
|
|
// read/write bit-twiddling
|
|
|
|
Buffer.prototype.readUInt8 = function(offset, noAssert) {
|
|
var buffer = this;
|
|
|
|
if (!noAssert) {
|
|
assert.ok(offset !== undefined && offset !== null,
|
|
'missing offset');
|
|
|
|
assert.ok(offset < buffer.length,
|
|
'Trying to read beyond buffer length');
|
|
}
|
|
|
|
if (offset >= buffer.length) return;
|
|
|
|
return buffer[offset];
|
|
};
|
|
|
|
function readUInt16(buffer, offset, isBigEndian, noAssert) {
|
|
var val = 0;
|
|
|
|
|
|
if (!noAssert) {
|
|
assert.ok(typeof (isBigEndian) === 'boolean',
|
|
'missing or invalid endian');
|
|
|
|
assert.ok(offset !== undefined && offset !== null,
|
|
'missing offset');
|
|
|
|
assert.ok(offset + 1 < buffer.length,
|
|
'Trying to read beyond buffer length');
|
|
}
|
|
|
|
if (offset >= buffer.length) return 0;
|
|
|
|
if (isBigEndian) {
|
|
val = buffer[offset] << 8;
|
|
if (offset + 1 < buffer.length) {
|
|
val |= buffer[offset + 1];
|
|
}
|
|
} else {
|
|
val = buffer[offset];
|
|
if (offset + 1 < buffer.length) {
|
|
val |= buffer[offset + 1] << 8;
|
|
}
|
|
}
|
|
|
|
return val;
|
|
}
|
|
|
|
Buffer.prototype.readUInt16LE = function(offset, noAssert) {
|
|
return readUInt16(this, offset, false, noAssert);
|
|
};
|
|
|
|
Buffer.prototype.readUInt16BE = function(offset, noAssert) {
|
|
return readUInt16(this, offset, true, noAssert);
|
|
};
|
|
|
|
function readUInt32(buffer, offset, isBigEndian, noAssert) {
|
|
var val = 0;
|
|
|
|
if (!noAssert) {
|
|
assert.ok(typeof (isBigEndian) === 'boolean',
|
|
'missing or invalid endian');
|
|
|
|
assert.ok(offset !== undefined && offset !== null,
|
|
'missing offset');
|
|
|
|
assert.ok(offset + 3 < buffer.length,
|
|
'Trying to read beyond buffer length');
|
|
}
|
|
|
|
if (offset >= buffer.length) return 0;
|
|
|
|
if (isBigEndian) {
|
|
if (offset + 1 < buffer.length)
|
|
val = buffer[offset + 1] << 16;
|
|
if (offset + 2 < buffer.length)
|
|
val |= buffer[offset + 2] << 8;
|
|
if (offset + 3 < buffer.length)
|
|
val |= buffer[offset + 3];
|
|
val = val + (buffer[offset] << 24 >>> 0);
|
|
} else {
|
|
if (offset + 2 < buffer.length)
|
|
val = buffer[offset + 2] << 16;
|
|
if (offset + 1 < buffer.length)
|
|
val |= buffer[offset + 1] << 8;
|
|
val |= buffer[offset];
|
|
if (offset + 3 < buffer.length)
|
|
val = val + (buffer[offset + 3] << 24 >>> 0);
|
|
}
|
|
|
|
return val;
|
|
}
|
|
|
|
Buffer.prototype.readUInt32LE = function(offset, noAssert) {
|
|
return readUInt32(this, offset, false, noAssert);
|
|
};
|
|
|
|
Buffer.prototype.readUInt32BE = function(offset, noAssert) {
|
|
return readUInt32(this, offset, true, noAssert);
|
|
};
|
|
|
|
|
|
/*
|
|
* Signed integer types, yay team! A reminder on how two's complement actually
|
|
* works. The first bit is the signed bit, i.e. tells us whether or not the
|
|
* number should be positive or negative. If the two's complement value is
|
|
* positive, then we're done, as it's equivalent to the unsigned representation.
|
|
*
|
|
* Now if the number is positive, you're pretty much done, you can just leverage
|
|
* the unsigned translations and return those. Unfortunately, negative numbers
|
|
* aren't quite that straightforward.
|
|
*
|
|
* At first glance, one might be inclined to use the traditional formula to
|
|
* translate binary numbers between the positive and negative values in two's
|
|
* complement. (Though it doesn't quite work for the most negative value)
|
|
* Mainly:
|
|
* - invert all the bits
|
|
* - add one to the result
|
|
*
|
|
* Of course, this doesn't quite work in Javascript. Take for example the value
|
|
* of -128. This could be represented in 16 bits (big-endian) as 0xff80. But of
|
|
* course, Javascript will do the following:
|
|
*
|
|
* > ~0xff80
|
|
* -65409
|
|
*
|
|
* Whoh there, Javascript, that's not quite right. But wait, according to
|
|
* Javascript that's perfectly correct. When Javascript ends up seeing the
|
|
* constant 0xff80, it has no notion that it is actually a signed number. It
|
|
* assumes that we've input the unsigned value 0xff80. Thus, when it does the
|
|
* binary negation, it casts it into a signed value, (positive 0xff80). Then
|
|
* when you perform binary negation on that, it turns it into a negative number.
|
|
*
|
|
* Instead, we're going to have to use the following general formula, that works
|
|
* in a rather Javascript friendly way. I'm glad we don't support this kind of
|
|
* weird numbering scheme in the kernel.
|
|
*
|
|
* (BIT-MAX - (unsigned)val + 1) * -1
|
|
*
|
|
* The astute observer, may think that this doesn't make sense for 8-bit numbers
|
|
* (really it isn't necessary for them). However, when you get 16-bit numbers,
|
|
* you do. Let's go back to our prior example and see how this will look:
|
|
*
|
|
* (0xffff - 0xff80 + 1) * -1
|
|
* (0x007f + 1) * -1
|
|
* (0x0080) * -1
|
|
*/
|
|
Buffer.prototype.readInt8 = function(offset, noAssert) {
|
|
var buffer = this;
|
|
var neg;
|
|
|
|
if (!noAssert) {
|
|
assert.ok(offset !== undefined && offset !== null,
|
|
'missing offset');
|
|
|
|
assert.ok(offset < buffer.length,
|
|
'Trying to read beyond buffer length');
|
|
}
|
|
|
|
if (offset >= buffer.length) return;
|
|
|
|
neg = buffer[offset] & 0x80;
|
|
if (!neg) {
|
|
return (buffer[offset]);
|
|
}
|
|
|
|
return ((0xff - buffer[offset] + 1) * -1);
|
|
};
|
|
|
|
function readInt16(buffer, offset, isBigEndian, noAssert) {
|
|
var neg, val;
|
|
|
|
if (!noAssert) {
|
|
assert.ok(typeof (isBigEndian) === 'boolean',
|
|
'missing or invalid endian');
|
|
|
|
assert.ok(offset !== undefined && offset !== null,
|
|
'missing offset');
|
|
|
|
assert.ok(offset + 1 < buffer.length,
|
|
'Trying to read beyond buffer length');
|
|
}
|
|
|
|
val = readUInt16(buffer, offset, isBigEndian, noAssert);
|
|
neg = val & 0x8000;
|
|
if (!neg) {
|
|
return val;
|
|
}
|
|
|
|
return (0xffff - val + 1) * -1;
|
|
}
|
|
|
|
Buffer.prototype.readInt16LE = function(offset, noAssert) {
|
|
return readInt16(this, offset, false, noAssert);
|
|
};
|
|
|
|
Buffer.prototype.readInt16BE = function(offset, noAssert) {
|
|
return readInt16(this, offset, true, noAssert);
|
|
};
|
|
|
|
function readInt32(buffer, offset, isBigEndian, noAssert) {
|
|
var neg, val;
|
|
|
|
if (!noAssert) {
|
|
assert.ok(typeof (isBigEndian) === 'boolean',
|
|
'missing or invalid endian');
|
|
|
|
assert.ok(offset !== undefined && offset !== null,
|
|
'missing offset');
|
|
|
|
assert.ok(offset + 3 < buffer.length,
|
|
'Trying to read beyond buffer length');
|
|
}
|
|
|
|
val = readUInt32(buffer, offset, isBigEndian, noAssert);
|
|
neg = val & 0x80000000;
|
|
if (!neg) {
|
|
return (val);
|
|
}
|
|
|
|
return (0xffffffff - val + 1) * -1;
|
|
}
|
|
|
|
Buffer.prototype.readInt32LE = function(offset, noAssert) {
|
|
return readInt32(this, offset, false, noAssert);
|
|
};
|
|
|
|
Buffer.prototype.readInt32BE = function(offset, noAssert) {
|
|
return readInt32(this, offset, true, noAssert);
|
|
};
|
|
|
|
function readFloat(buffer, offset, isBigEndian, noAssert) {
|
|
if (!noAssert) {
|
|
assert.ok(typeof (isBigEndian) === 'boolean',
|
|
'missing or invalid endian');
|
|
|
|
assert.ok(offset + 3 < buffer.length,
|
|
'Trying to read beyond buffer length');
|
|
}
|
|
|
|
return require('./buffer_ieee754').readIEEE754(buffer, offset, isBigEndian,
|
|
23, 4);
|
|
}
|
|
|
|
Buffer.prototype.readFloatLE = function(offset, noAssert) {
|
|
return readFloat(this, offset, false, noAssert);
|
|
};
|
|
|
|
Buffer.prototype.readFloatBE = function(offset, noAssert) {
|
|
return readFloat(this, offset, true, noAssert);
|
|
};
|
|
|
|
function readDouble(buffer, offset, isBigEndian, noAssert) {
|
|
if (!noAssert) {
|
|
assert.ok(typeof (isBigEndian) === 'boolean',
|
|
'missing or invalid endian');
|
|
|
|
assert.ok(offset + 7 < buffer.length,
|
|
'Trying to read beyond buffer length');
|
|
}
|
|
|
|
return require('./buffer_ieee754').readIEEE754(buffer, offset, isBigEndian,
|
|
52, 8);
|
|
}
|
|
|
|
Buffer.prototype.readDoubleLE = function(offset, noAssert) {
|
|
return readDouble(this, offset, false, noAssert);
|
|
};
|
|
|
|
Buffer.prototype.readDoubleBE = function(offset, noAssert) {
|
|
return readDouble(this, offset, true, noAssert);
|
|
};
|
|
|
|
|
|
/*
|
|
* We have to make sure that the value is a valid integer. This means that it is
|
|
* non-negative. It has no fractional component and that it does not exceed the
|
|
* maximum allowed value.
|
|
*
|
|
* value The number to check for validity
|
|
*
|
|
* max The maximum value
|
|
*/
|
|
function verifuint(value, max) {
|
|
assert.ok(typeof (value) == 'number',
|
|
'cannot write a non-number as a number');
|
|
|
|
assert.ok(value >= 0,
|
|
'specified a negative value for writing an unsigned value');
|
|
|
|
assert.ok(value <= max, 'value is larger than maximum value for type');
|
|
|
|
assert.ok(Math.floor(value) === value, 'value has a fractional component');
|
|
}
|
|
|
|
Buffer.prototype.writeUInt8 = function(value, offset, noAssert) {
|
|
var buffer = this;
|
|
|
|
if (!noAssert) {
|
|
assert.ok(value !== undefined && value !== null,
|
|
'missing value');
|
|
|
|
assert.ok(offset !== undefined && offset !== null,
|
|
'missing offset');
|
|
|
|
assert.ok(offset < buffer.length,
|
|
'trying to write beyond buffer length');
|
|
|
|
verifuint(value, 0xff);
|
|
}
|
|
|
|
if (offset < buffer.length) {
|
|
buffer[offset] = value;
|
|
}
|
|
};
|
|
|
|
function writeUInt16(buffer, value, offset, isBigEndian, noAssert) {
|
|
if (!noAssert) {
|
|
assert.ok(value !== undefined && value !== null,
|
|
'missing value');
|
|
|
|
assert.ok(typeof (isBigEndian) === 'boolean',
|
|
'missing or invalid endian');
|
|
|
|
assert.ok(offset !== undefined && offset !== null,
|
|
'missing offset');
|
|
|
|
assert.ok(offset + 1 < buffer.length,
|
|
'trying to write beyond buffer length');
|
|
|
|
verifuint(value, 0xffff);
|
|
}
|
|
|
|
for (var i = 0; i < Math.min(buffer.length - offset, 2); i++) {
|
|
buffer[offset + i] =
|
|
(value & (0xff << (8 * (isBigEndian ? 1 - i : i)))) >>>
|
|
(isBigEndian ? 1 - i : i) * 8;
|
|
}
|
|
|
|
}
|
|
|
|
Buffer.prototype.writeUInt16LE = function(value, offset, noAssert) {
|
|
writeUInt16(this, value, offset, false, noAssert);
|
|
};
|
|
|
|
Buffer.prototype.writeUInt16BE = function(value, offset, noAssert) {
|
|
writeUInt16(this, value, offset, true, noAssert);
|
|
};
|
|
|
|
function writeUInt32(buffer, value, offset, isBigEndian, noAssert) {
|
|
if (!noAssert) {
|
|
assert.ok(value !== undefined && value !== null,
|
|
'missing value');
|
|
|
|
assert.ok(typeof (isBigEndian) === 'boolean',
|
|
'missing or invalid endian');
|
|
|
|
assert.ok(offset !== undefined && offset !== null,
|
|
'missing offset');
|
|
|
|
assert.ok(offset + 3 < buffer.length,
|
|
'trying to write beyond buffer length');
|
|
|
|
verifuint(value, 0xffffffff);
|
|
}
|
|
|
|
for (var i = 0; i < Math.min(buffer.length - offset, 4); i++) {
|
|
buffer[offset + i] =
|
|
(value >>> (isBigEndian ? 3 - i : i) * 8) & 0xff;
|
|
}
|
|
}
|
|
|
|
Buffer.prototype.writeUInt32LE = function(value, offset, noAssert) {
|
|
writeUInt32(this, value, offset, false, noAssert);
|
|
};
|
|
|
|
Buffer.prototype.writeUInt32BE = function(value, offset, noAssert) {
|
|
writeUInt32(this, value, offset, true, noAssert);
|
|
};
|
|
|
|
|
|
/*
|
|
* We now move onto our friends in the signed number category. Unlike unsigned
|
|
* numbers, we're going to have to worry a bit more about how we put values into
|
|
* arrays. Since we are only worrying about signed 32-bit values, we're in
|
|
* slightly better shape. Unfortunately, we really can't do our favorite binary
|
|
* & in this system. It really seems to do the wrong thing. For example:
|
|
*
|
|
* > -32 & 0xff
|
|
* 224
|
|
*
|
|
* What's happening above is really: 0xe0 & 0xff = 0xe0. However, the results of
|
|
* this aren't treated as a signed number. Ultimately a bad thing.
|
|
*
|
|
* What we're going to want to do is basically create the unsigned equivalent of
|
|
* our representation and pass that off to the wuint* functions. To do that
|
|
* we're going to do the following:
|
|
*
|
|
* - if the value is positive
|
|
* we can pass it directly off to the equivalent wuint
|
|
* - if the value is negative
|
|
* we do the following computation:
|
|
* mb + val + 1, where
|
|
* mb is the maximum unsigned value in that byte size
|
|
* val is the Javascript negative integer
|
|
*
|
|
*
|
|
* As a concrete value, take -128. In signed 16 bits this would be 0xff80. If
|
|
* you do out the computations:
|
|
*
|
|
* 0xffff - 128 + 1
|
|
* 0xffff - 127
|
|
* 0xff80
|
|
*
|
|
* You can then encode this value as the signed version. This is really rather
|
|
* hacky, but it should work and get the job done which is our goal here.
|
|
*/
|
|
|
|
/*
|
|
* A series of checks to make sure we actually have a signed 32-bit number
|
|
*/
|
|
function verifsint(value, max, min) {
|
|
assert.ok(typeof (value) == 'number',
|
|
'cannot write a non-number as a number');
|
|
|
|
assert.ok(value <= max, 'value larger than maximum allowed value');
|
|
|
|
assert.ok(value >= min, 'value smaller than minimum allowed value');
|
|
|
|
assert.ok(Math.floor(value) === value, 'value has a fractional component');
|
|
}
|
|
|
|
function verifIEEE754(value, max, min) {
|
|
assert.ok(typeof (value) == 'number',
|
|
'cannot write a non-number as a number');
|
|
|
|
assert.ok(value <= max, 'value larger than maximum allowed value');
|
|
|
|
assert.ok(value >= min, 'value smaller than minimum allowed value');
|
|
}
|
|
|
|
Buffer.prototype.writeInt8 = function(value, offset, noAssert) {
|
|
var buffer = this;
|
|
|
|
if (!noAssert) {
|
|
assert.ok(value !== undefined && value !== null,
|
|
'missing value');
|
|
|
|
assert.ok(offset !== undefined && offset !== null,
|
|
'missing offset');
|
|
|
|
assert.ok(offset < buffer.length,
|
|
'Trying to write beyond buffer length');
|
|
|
|
verifsint(value, 0x7f, -0x80);
|
|
}
|
|
|
|
if (value >= 0) {
|
|
buffer.writeUInt8(value, offset, noAssert);
|
|
} else {
|
|
buffer.writeUInt8(0xff + value + 1, offset, noAssert);
|
|
}
|
|
};
|
|
|
|
function writeInt16(buffer, value, offset, isBigEndian, noAssert) {
|
|
if (!noAssert) {
|
|
assert.ok(value !== undefined && value !== null,
|
|
'missing value');
|
|
|
|
assert.ok(typeof (isBigEndian) === 'boolean',
|
|
'missing or invalid endian');
|
|
|
|
assert.ok(offset !== undefined && offset !== null,
|
|
'missing offset');
|
|
|
|
assert.ok(offset + 1 < buffer.length,
|
|
'Trying to write beyond buffer length');
|
|
|
|
verifsint(value, 0x7fff, -0x8000);
|
|
}
|
|
|
|
if (value >= 0) {
|
|
writeUInt16(buffer, value, offset, isBigEndian, noAssert);
|
|
} else {
|
|
writeUInt16(buffer, 0xffff + value + 1, offset, isBigEndian, noAssert);
|
|
}
|
|
}
|
|
|
|
Buffer.prototype.writeInt16LE = function(value, offset, noAssert) {
|
|
writeInt16(this, value, offset, false, noAssert);
|
|
};
|
|
|
|
Buffer.prototype.writeInt16BE = function(value, offset, noAssert) {
|
|
writeInt16(this, value, offset, true, noAssert);
|
|
};
|
|
|
|
function writeInt32(buffer, value, offset, isBigEndian, noAssert) {
|
|
if (!noAssert) {
|
|
assert.ok(value !== undefined && value !== null,
|
|
'missing value');
|
|
|
|
assert.ok(typeof (isBigEndian) === 'boolean',
|
|
'missing or invalid endian');
|
|
|
|
assert.ok(offset !== undefined && offset !== null,
|
|
'missing offset');
|
|
|
|
assert.ok(offset + 3 < buffer.length,
|
|
'Trying to write beyond buffer length');
|
|
|
|
verifsint(value, 0x7fffffff, -0x80000000);
|
|
}
|
|
|
|
if (value >= 0) {
|
|
writeUInt32(buffer, value, offset, isBigEndian, noAssert);
|
|
} else {
|
|
writeUInt32(buffer, 0xffffffff + value + 1, offset, isBigEndian, noAssert);
|
|
}
|
|
}
|
|
|
|
Buffer.prototype.writeInt32LE = function(value, offset, noAssert) {
|
|
writeInt32(this, value, offset, false, noAssert);
|
|
};
|
|
|
|
Buffer.prototype.writeInt32BE = function(value, offset, noAssert) {
|
|
writeInt32(this, value, offset, true, noAssert);
|
|
};
|
|
|
|
function writeFloat(buffer, value, offset, isBigEndian, noAssert) {
|
|
if (!noAssert) {
|
|
assert.ok(value !== undefined && value !== null,
|
|
'missing value');
|
|
|
|
assert.ok(typeof (isBigEndian) === 'boolean',
|
|
'missing or invalid endian');
|
|
|
|
assert.ok(offset !== undefined && offset !== null,
|
|
'missing offset');
|
|
|
|
assert.ok(offset + 3 < buffer.length,
|
|
'Trying to write beyond buffer length');
|
|
|
|
verifIEEE754(value, 3.4028234663852886e+38, -3.4028234663852886e+38);
|
|
}
|
|
|
|
require('./buffer_ieee754').writeIEEE754(buffer, value, offset, isBigEndian,
|
|
23, 4);
|
|
}
|
|
|
|
Buffer.prototype.writeFloatLE = function(value, offset, noAssert) {
|
|
writeFloat(this, value, offset, false, noAssert);
|
|
};
|
|
|
|
Buffer.prototype.writeFloatBE = function(value, offset, noAssert) {
|
|
writeFloat(this, value, offset, true, noAssert);
|
|
};
|
|
|
|
function writeDouble(buffer, value, offset, isBigEndian, noAssert) {
|
|
if (!noAssert) {
|
|
assert.ok(value !== undefined && value !== null,
|
|
'missing value');
|
|
|
|
assert.ok(typeof (isBigEndian) === 'boolean',
|
|
'missing or invalid endian');
|
|
|
|
assert.ok(offset !== undefined && offset !== null,
|
|
'missing offset');
|
|
|
|
assert.ok(offset + 7 < buffer.length,
|
|
'Trying to write beyond buffer length');
|
|
|
|
verifIEEE754(value, 1.7976931348623157E+308, -1.7976931348623157E+308);
|
|
}
|
|
|
|
require('./buffer_ieee754').writeIEEE754(buffer, value, offset, isBigEndian,
|
|
52, 8);
|
|
}
|
|
|
|
Buffer.prototype.writeDoubleLE = function(value, offset, noAssert) {
|
|
writeDouble(this, value, offset, false, noAssert);
|
|
};
|
|
|
|
Buffer.prototype.writeDoubleBE = function(value, offset, noAssert) {
|
|
writeDouble(this, value, offset, true, noAssert);
|
|
};
|
|
|
|
},{"./buffer_ieee754":57,"assert":54,"base64-js":59}],59:[function(require,module,exports){
|
|
(function (exports) {
|
|
'use strict';
|
|
|
|
var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
|
|
|
function b64ToByteArray(b64) {
|
|
var i, j, l, tmp, placeHolders, arr;
|
|
|
|
if (b64.length % 4 > 0) {
|
|
throw 'Invalid string. Length must be a multiple of 4';
|
|
}
|
|
|
|
// the number of equal signs (place holders)
|
|
// if there are two placeholders, than the two characters before it
|
|
// represent one byte
|
|
// if there is only one, then the three characters before it represent 2 bytes
|
|
// this is just a cheap hack to not do indexOf twice
|
|
placeHolders = b64.indexOf('=');
|
|
placeHolders = placeHolders > 0 ? b64.length - placeHolders : 0;
|
|
|
|
// base64 is 4/3 + up to two characters of the original data
|
|
arr = [];//new Uint8Array(b64.length * 3 / 4 - placeHolders);
|
|
|
|
// if there are placeholders, only get up to the last complete 4 chars
|
|
l = placeHolders > 0 ? b64.length - 4 : b64.length;
|
|
|
|
for (i = 0, j = 0; i < l; i += 4, j += 3) {
|
|
tmp = (lookup.indexOf(b64[i]) << 18) | (lookup.indexOf(b64[i + 1]) << 12) | (lookup.indexOf(b64[i + 2]) << 6) | lookup.indexOf(b64[i + 3]);
|
|
arr.push((tmp & 0xFF0000) >> 16);
|
|
arr.push((tmp & 0xFF00) >> 8);
|
|
arr.push(tmp & 0xFF);
|
|
}
|
|
|
|
if (placeHolders === 2) {
|
|
tmp = (lookup.indexOf(b64[i]) << 2) | (lookup.indexOf(b64[i + 1]) >> 4);
|
|
arr.push(tmp & 0xFF);
|
|
} else if (placeHolders === 1) {
|
|
tmp = (lookup.indexOf(b64[i]) << 10) | (lookup.indexOf(b64[i + 1]) << 4) | (lookup.indexOf(b64[i + 2]) >> 2);
|
|
arr.push((tmp >> 8) & 0xFF);
|
|
arr.push(tmp & 0xFF);
|
|
}
|
|
|
|
return arr;
|
|
}
|
|
|
|
function uint8ToBase64(uint8) {
|
|
var i,
|
|
extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes
|
|
output = "",
|
|
temp, length;
|
|
|
|
function tripletToBase64 (num) {
|
|
return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F];
|
|
};
|
|
|
|
// go through the array every three bytes, we'll deal with trailing stuff later
|
|
for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) {
|
|
temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]);
|
|
output += tripletToBase64(temp);
|
|
}
|
|
|
|
// pad the end with zeros, but make sure to not forget the extra bytes
|
|
switch (extraBytes) {
|
|
case 1:
|
|
temp = uint8[uint8.length - 1];
|
|
output += lookup[temp >> 2];
|
|
output += lookup[(temp << 4) & 0x3F];
|
|
output += '==';
|
|
break;
|
|
case 2:
|
|
temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1]);
|
|
output += lookup[temp >> 10];
|
|
output += lookup[(temp >> 4) & 0x3F];
|
|
output += lookup[(temp << 2) & 0x3F];
|
|
output += '=';
|
|
break;
|
|
}
|
|
|
|
return output;
|
|
}
|
|
|
|
module.exports.toByteArray = b64ToByteArray;
|
|
module.exports.fromByteArray = uint8ToBase64;
|
|
}());
|
|
|
|
},{}],60:[function(require,module,exports){
|
|
var Buffer = require('buffer').Buffer
|
|
var sha = require('./sha')
|
|
var sha256 = require('./sha256')
|
|
var rng = require('./rng')
|
|
var md5 = require('./md5')
|
|
|
|
var algorithms = {
|
|
sha1: {
|
|
hex: sha.hex_sha1,
|
|
base64: sha.b64_sha1,
|
|
binary: sha.str_sha1
|
|
},
|
|
sha256: {
|
|
hex: sha256.hex_sha256,
|
|
base64: sha256.b64_sha256,
|
|
binary: sha256.str_sha256
|
|
},
|
|
md5: {
|
|
hex: md5.hex_md5,
|
|
base64: md5.b64_md5,
|
|
binary: md5.bin_md5
|
|
}
|
|
}
|
|
|
|
var algorithmsHmac = {
|
|
sha1: {
|
|
hex: sha.hex_hmac_sha1,
|
|
base64: sha.b64_hmac_sha1,
|
|
binary: sha.str_hmac_sha1
|
|
},
|
|
sha256: {
|
|
hex: sha256.hex_hmac_sha256,
|
|
base64: sha256.b64_hmac_sha256,
|
|
binary: sha256.str_hmac_sha256
|
|
},
|
|
md5: {
|
|
hex: md5.hex_hmac_md5,
|
|
base64: md5.b64_hmac_md5,
|
|
binary: md5.bin_hmac_md5
|
|
}
|
|
}
|
|
|
|
|
|
function error () {
|
|
var m = [].slice.call(arguments).join(' ')
|
|
throw new Error([
|
|
m,
|
|
'we accept pull requests',
|
|
'http://github.com/dominictarr/crypto-browserify'
|
|
].join('\n'))
|
|
}
|
|
|
|
exports.createHash = function (alg) {
|
|
alg = alg || 'sha1'
|
|
if(!algorithms[alg])
|
|
error('algorithm:', alg, 'is not yet supported')
|
|
var s = ''
|
|
var _alg = algorithms[alg]
|
|
return {
|
|
update: function (data) {
|
|
s += data
|
|
return this
|
|
},
|
|
digest: function (enc) {
|
|
enc = enc || 'binary'
|
|
var fn
|
|
if(!(fn = _alg[enc]))
|
|
error('encoding:', enc , 'is not yet supported for algorithm', alg)
|
|
var r = fn(s)
|
|
s = null //not meant to use the hash after you've called digest.
|
|
return r
|
|
}
|
|
}
|
|
}
|
|
|
|
exports.createHmac = function (alg, key) {
|
|
if (!algorithmsHmac[alg])
|
|
error('algorithm:', alg, 'is not yet supported')
|
|
if (typeof key != 'string')
|
|
key = key.toString('binary')
|
|
var s = ''
|
|
var _alg = algorithmsHmac[alg]
|
|
return {
|
|
update: function (data) {
|
|
s += data
|
|
return this
|
|
},
|
|
digest: function (enc) {
|
|
enc = enc || 'binary'
|
|
var fn
|
|
if (!(fn = _alg[enc]))
|
|
error('encoding:', enc, 'is not yet support for algorithm', alg)
|
|
var r = fn(key, s)
|
|
s = null
|
|
return r
|
|
}
|
|
}
|
|
}
|
|
|
|
exports.randomBytes = function(size, callback) {
|
|
if (callback && callback.call) {
|
|
try {
|
|
callback.call(this, undefined, new Buffer(rng(size)));
|
|
} catch (err) { callback(err); }
|
|
} else {
|
|
return new Buffer(rng(size));
|
|
}
|
|
}
|
|
|
|
function each(a, f) {
|
|
for(var i in a)
|
|
f(a[i], i)
|
|
}
|
|
|
|
// the least I can do is make error messages for the rest of the node.js/crypto api.
|
|
each(['createCredentials'
|
|
, 'createCipher'
|
|
, 'createCipheriv'
|
|
, 'createDecipher'
|
|
, 'createDecipheriv'
|
|
, 'createSign'
|
|
, 'createVerify'
|
|
, 'createDiffieHellman'
|
|
, 'pbkdf2'], function (name) {
|
|
exports[name] = function () {
|
|
error('sorry,', name, 'is not implemented yet')
|
|
}
|
|
})
|
|
|
|
},{"./md5":61,"./rng":62,"./sha":63,"./sha256":64,"buffer":58}],61:[function(require,module,exports){
|
|
/*
|
|
* A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
|
|
* Digest Algorithm, as defined in RFC 1321.
|
|
* Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
|
|
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
|
|
* Distributed under the BSD License
|
|
* See http://pajhome.org.uk/crypt/md5 for more info.
|
|
*/
|
|
|
|
/*
|
|
* Configurable variables. You may need to tweak these to be compatible with
|
|
* the server-side, but the defaults work in most cases.
|
|
*/
|
|
var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
|
|
var b64pad = "="; /* base-64 pad character. "=" for strict RFC compliance */
|
|
var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */
|
|
|
|
/*
|
|
* These are the functions you'll usually want to call
|
|
* They take string arguments and return either hex or base-64 encoded strings
|
|
*/
|
|
function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));}
|
|
function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));}
|
|
function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));}
|
|
function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); }
|
|
function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); }
|
|
function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); }
|
|
|
|
/*
|
|
* Perform a simple self-test to see if the VM is working
|
|
*/
|
|
function md5_vm_test()
|
|
{
|
|
return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72";
|
|
}
|
|
|
|
/*
|
|
* Calculate the MD5 of an array of little-endian words, and a bit length
|
|
*/
|
|
function core_md5(x, len)
|
|
{
|
|
/* append padding */
|
|
x[len >> 5] |= 0x80 << ((len) % 32);
|
|
x[(((len + 64) >>> 9) << 4) + 14] = len;
|
|
|
|
var a = 1732584193;
|
|
var b = -271733879;
|
|
var c = -1732584194;
|
|
var d = 271733878;
|
|
|
|
for(var i = 0; i < x.length; i += 16)
|
|
{
|
|
var olda = a;
|
|
var oldb = b;
|
|
var oldc = c;
|
|
var oldd = d;
|
|
|
|
a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
|
|
d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
|
|
c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819);
|
|
b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
|
|
a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
|
|
d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426);
|
|
c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
|
|
b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
|
|
a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416);
|
|
d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
|
|
c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
|
|
b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
|
|
a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682);
|
|
d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
|
|
c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
|
|
b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329);
|
|
|
|
a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
|
|
d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
|
|
c = md5_gg(c, d, a, b, x[i+11], 14, 643717713);
|
|
b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
|
|
a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
|
|
d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083);
|
|
c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
|
|
b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
|
|
a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438);
|
|
d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
|
|
c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
|
|
b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501);
|
|
a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
|
|
d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
|
|
c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473);
|
|
b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
|
|
|
|
a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
|
|
d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
|
|
c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562);
|
|
b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
|
|
a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
|
|
d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353);
|
|
c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
|
|
b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
|
|
a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174);
|
|
d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
|
|
c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
|
|
b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189);
|
|
a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
|
|
d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
|
|
c = md5_hh(c, d, a, b, x[i+15], 16, 530742520);
|
|
b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
|
|
|
|
a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
|
|
d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415);
|
|
c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
|
|
b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
|
|
a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571);
|
|
d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
|
|
c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
|
|
b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
|
|
a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359);
|
|
d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
|
|
c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
|
|
b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649);
|
|
a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
|
|
d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
|
|
c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259);
|
|
b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
|
|
|
|
a = safe_add(a, olda);
|
|
b = safe_add(b, oldb);
|
|
c = safe_add(c, oldc);
|
|
d = safe_add(d, oldd);
|
|
}
|
|
return Array(a, b, c, d);
|
|
|
|
}
|
|
|
|
/*
|
|
* These functions implement the four basic operations the algorithm uses.
|
|
*/
|
|
function md5_cmn(q, a, b, x, s, t)
|
|
{
|
|
return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
|
|
}
|
|
function md5_ff(a, b, c, d, x, s, t)
|
|
{
|
|
return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
|
|
}
|
|
function md5_gg(a, b, c, d, x, s, t)
|
|
{
|
|
return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
|
|
}
|
|
function md5_hh(a, b, c, d, x, s, t)
|
|
{
|
|
return md5_cmn(b ^ c ^ d, a, b, x, s, t);
|
|
}
|
|
function md5_ii(a, b, c, d, x, s, t)
|
|
{
|
|
return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
|
|
}
|
|
|
|
/*
|
|
* Calculate the HMAC-MD5, of a key and some data
|
|
*/
|
|
function core_hmac_md5(key, data)
|
|
{
|
|
var bkey = str2binl(key);
|
|
if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz);
|
|
|
|
var ipad = Array(16), opad = Array(16);
|
|
for(var i = 0; i < 16; i++)
|
|
{
|
|
ipad[i] = bkey[i] ^ 0x36363636;
|
|
opad[i] = bkey[i] ^ 0x5C5C5C5C;
|
|
}
|
|
|
|
var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz);
|
|
return core_md5(opad.concat(hash), 512 + 128);
|
|
}
|
|
|
|
/*
|
|
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
|
|
* to work around bugs in some JS interpreters.
|
|
*/
|
|
function safe_add(x, y)
|
|
{
|
|
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
|
|
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
|
|
return (msw << 16) | (lsw & 0xFFFF);
|
|
}
|
|
|
|
/*
|
|
* Bitwise rotate a 32-bit number to the left.
|
|
*/
|
|
function bit_rol(num, cnt)
|
|
{
|
|
return (num << cnt) | (num >>> (32 - cnt));
|
|
}
|
|
|
|
/*
|
|
* Convert a string to an array of little-endian words
|
|
* If chrsz is ASCII, characters >255 have their hi-byte silently ignored.
|
|
*/
|
|
function str2binl(str)
|
|
{
|
|
var bin = Array();
|
|
var mask = (1 << chrsz) - 1;
|
|
for(var i = 0; i < str.length * chrsz; i += chrsz)
|
|
bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);
|
|
return bin;
|
|
}
|
|
|
|
/*
|
|
* Convert an array of little-endian words to a string
|
|
*/
|
|
function binl2str(bin)
|
|
{
|
|
var str = "";
|
|
var mask = (1 << chrsz) - 1;
|
|
for(var i = 0; i < bin.length * 32; i += chrsz)
|
|
str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask);
|
|
return str;
|
|
}
|
|
|
|
/*
|
|
* Convert an array of little-endian words to a hex string.
|
|
*/
|
|
function binl2hex(binarray)
|
|
{
|
|
var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
|
|
var str = "";
|
|
for(var i = 0; i < binarray.length * 4; i++)
|
|
{
|
|
str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +
|
|
hex_tab.charAt((binarray[i>>2] >> ((i%4)*8 )) & 0xF);
|
|
}
|
|
return str;
|
|
}
|
|
|
|
/*
|
|
* Convert an array of little-endian words to a base-64 string
|
|
*/
|
|
function binl2b64(binarray)
|
|
{
|
|
var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
var str = "";
|
|
for(var i = 0; i < binarray.length * 4; i += 3)
|
|
{
|
|
var triplet = (((binarray[i >> 2] >> 8 * ( i %4)) & 0xFF) << 16)
|
|
| (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 )
|
|
| ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF);
|
|
for(var j = 0; j < 4; j++)
|
|
{
|
|
if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
|
|
else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
|
|
}
|
|
}
|
|
return str;
|
|
}
|
|
|
|
exports.hex_md5 = hex_md5;
|
|
exports.b64_md5 = b64_md5;
|
|
exports.bin_md5 = str_md5;
|
|
exports.hex_hmac_md5 = hex_hmac_md5;
|
|
exports.b64_hmac_md5 = b64_hmac_md5;
|
|
exports.bin_hmac_md5 = str_hmac_md5;
|
|
|
|
},{}],62:[function(require,module,exports){
|
|
// Original code adapted from Robert Kieffer.
|
|
// details at https://github.com/broofa/node-uuid
|
|
(function() {
|
|
var _global = this;
|
|
|
|
var mathRNG, whatwgRNG;
|
|
|
|
// NOTE: Math.random() does not guarantee "cryptographic quality"
|
|
mathRNG = function(size) {
|
|
var bytes = new Array(size);
|
|
var r;
|
|
|
|
for (var i = 0, r; i < size; i++) {
|
|
if ((i & 0x03) == 0) r = Math.random() * 0x100000000;
|
|
bytes[i] = r >>> ((i & 0x03) << 3) & 0xff;
|
|
}
|
|
|
|
return bytes;
|
|
}
|
|
|
|
if (_global.crypto && crypto.getRandomValues) {
|
|
var _rnds = new Uint32Array(4);
|
|
whatwgRNG = function(size) {
|
|
var bytes = new Array(size);
|
|
crypto.getRandomValues(_rnds);
|
|
|
|
for (var c = 0 ; c < size; c++) {
|
|
bytes[c] = _rnds[c >> 2] >>> ((c & 0x03) * 8) & 0xff;
|
|
}
|
|
return bytes;
|
|
}
|
|
}
|
|
|
|
module.exports = whatwgRNG || mathRNG;
|
|
|
|
}())
|
|
|
|
},{}],63:[function(require,module,exports){
|
|
/*
|
|
* A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined
|
|
* in FIPS PUB 180-1
|
|
* Version 2.1a Copyright Paul Johnston 2000 - 2002.
|
|
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
|
|
* Distributed under the BSD License
|
|
* See http://pajhome.org.uk/crypt/md5 for details.
|
|
*/
|
|
|
|
exports.hex_sha1 = hex_sha1;
|
|
exports.b64_sha1 = b64_sha1;
|
|
exports.str_sha1 = str_sha1;
|
|
exports.hex_hmac_sha1 = hex_hmac_sha1;
|
|
exports.b64_hmac_sha1 = b64_hmac_sha1;
|
|
exports.str_hmac_sha1 = str_hmac_sha1;
|
|
|
|
/*
|
|
* Configurable variables. You may need to tweak these to be compatible with
|
|
* the server-side, but the defaults work in most cases.
|
|
*/
|
|
var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
|
|
var b64pad = "="; /* base-64 pad character. "=" for strict RFC compliance */
|
|
var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */
|
|
|
|
/*
|
|
* These are the functions you'll usually want to call
|
|
* They take string arguments and return either hex or base-64 encoded strings
|
|
*/
|
|
function hex_sha1(s){return binb2hex(core_sha1(str2binb(s),s.length * chrsz));}
|
|
function b64_sha1(s){return binb2b64(core_sha1(str2binb(s),s.length * chrsz));}
|
|
function str_sha1(s){return binb2str(core_sha1(str2binb(s),s.length * chrsz));}
|
|
function hex_hmac_sha1(key, data){ return binb2hex(core_hmac_sha1(key, data));}
|
|
function b64_hmac_sha1(key, data){ return binb2b64(core_hmac_sha1(key, data));}
|
|
function str_hmac_sha1(key, data){ return binb2str(core_hmac_sha1(key, data));}
|
|
|
|
/*
|
|
* Perform a simple self-test to see if the VM is working
|
|
*/
|
|
function sha1_vm_test()
|
|
{
|
|
return hex_sha1("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d";
|
|
}
|
|
|
|
/*
|
|
* Calculate the SHA-1 of an array of big-endian words, and a bit length
|
|
*/
|
|
function core_sha1(x, len)
|
|
{
|
|
/* append padding */
|
|
x[len >> 5] |= 0x80 << (24 - len % 32);
|
|
x[((len + 64 >> 9) << 4) + 15] = len;
|
|
|
|
var w = Array(80);
|
|
var a = 1732584193;
|
|
var b = -271733879;
|
|
var c = -1732584194;
|
|
var d = 271733878;
|
|
var e = -1009589776;
|
|
|
|
for(var i = 0; i < x.length; i += 16)
|
|
{
|
|
var olda = a;
|
|
var oldb = b;
|
|
var oldc = c;
|
|
var oldd = d;
|
|
var olde = e;
|
|
|
|
for(var j = 0; j < 80; j++)
|
|
{
|
|
if(j < 16) w[j] = x[i + j];
|
|
else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
|
|
var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)),
|
|
safe_add(safe_add(e, w[j]), sha1_kt(j)));
|
|
e = d;
|
|
d = c;
|
|
c = rol(b, 30);
|
|
b = a;
|
|
a = t;
|
|
}
|
|
|
|
a = safe_add(a, olda);
|
|
b = safe_add(b, oldb);
|
|
c = safe_add(c, oldc);
|
|
d = safe_add(d, oldd);
|
|
e = safe_add(e, olde);
|
|
}
|
|
return Array(a, b, c, d, e);
|
|
|
|
}
|
|
|
|
/*
|
|
* Perform the appropriate triplet combination function for the current
|
|
* iteration
|
|
*/
|
|
function sha1_ft(t, b, c, d)
|
|
{
|
|
if(t < 20) return (b & c) | ((~b) & d);
|
|
if(t < 40) return b ^ c ^ d;
|
|
if(t < 60) return (b & c) | (b & d) | (c & d);
|
|
return b ^ c ^ d;
|
|
}
|
|
|
|
/*
|
|
* Determine the appropriate additive constant for the current iteration
|
|
*/
|
|
function sha1_kt(t)
|
|
{
|
|
return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 :
|
|
(t < 60) ? -1894007588 : -899497514;
|
|
}
|
|
|
|
/*
|
|
* Calculate the HMAC-SHA1 of a key and some data
|
|
*/
|
|
function core_hmac_sha1(key, data)
|
|
{
|
|
var bkey = str2binb(key);
|
|
if(bkey.length > 16) bkey = core_sha1(bkey, key.length * chrsz);
|
|
|
|
var ipad = Array(16), opad = Array(16);
|
|
for(var i = 0; i < 16; i++)
|
|
{
|
|
ipad[i] = bkey[i] ^ 0x36363636;
|
|
opad[i] = bkey[i] ^ 0x5C5C5C5C;
|
|
}
|
|
|
|
var hash = core_sha1(ipad.concat(str2binb(data)), 512 + data.length * chrsz);
|
|
return core_sha1(opad.concat(hash), 512 + 160);
|
|
}
|
|
|
|
/*
|
|
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
|
|
* to work around bugs in some JS interpreters.
|
|
*/
|
|
function safe_add(x, y)
|
|
{
|
|
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
|
|
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
|
|
return (msw << 16) | (lsw & 0xFFFF);
|
|
}
|
|
|
|
/*
|
|
* Bitwise rotate a 32-bit number to the left.
|
|
*/
|
|
function rol(num, cnt)
|
|
{
|
|
return (num << cnt) | (num >>> (32 - cnt));
|
|
}
|
|
|
|
/*
|
|
* Convert an 8-bit or 16-bit string to an array of big-endian words
|
|
* In 8-bit function, characters >255 have their hi-byte silently ignored.
|
|
*/
|
|
function str2binb(str)
|
|
{
|
|
var bin = Array();
|
|
var mask = (1 << chrsz) - 1;
|
|
for(var i = 0; i < str.length * chrsz; i += chrsz)
|
|
bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (32 - chrsz - i%32);
|
|
return bin;
|
|
}
|
|
|
|
/*
|
|
* Convert an array of big-endian words to a string
|
|
*/
|
|
function binb2str(bin)
|
|
{
|
|
var str = "";
|
|
var mask = (1 << chrsz) - 1;
|
|
for(var i = 0; i < bin.length * 32; i += chrsz)
|
|
str += String.fromCharCode((bin[i>>5] >>> (32 - chrsz - i%32)) & mask);
|
|
return str;
|
|
}
|
|
|
|
/*
|
|
* Convert an array of big-endian words to a hex string.
|
|
*/
|
|
function binb2hex(binarray)
|
|
{
|
|
var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
|
|
var str = "";
|
|
for(var i = 0; i < binarray.length * 4; i++)
|
|
{
|
|
str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) +
|
|
hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF);
|
|
}
|
|
return str;
|
|
}
|
|
|
|
/*
|
|
* Convert an array of big-endian words to a base-64 string
|
|
*/
|
|
function binb2b64(binarray)
|
|
{
|
|
var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
var str = "";
|
|
for(var i = 0; i < binarray.length * 4; i += 3)
|
|
{
|
|
var triplet = (((binarray[i >> 2] >> 8 * (3 - i %4)) & 0xFF) << 16)
|
|
| (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 )
|
|
| ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF);
|
|
for(var j = 0; j < 4; j++)
|
|
{
|
|
if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
|
|
else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
|
|
}
|
|
}
|
|
return str;
|
|
}
|
|
|
|
|
|
},{}],64:[function(require,module,exports){
|
|
|
|
/**
|
|
* A JavaScript implementation of the Secure Hash Algorithm, SHA-256, as defined
|
|
* in FIPS 180-2
|
|
* Version 2.2-beta Copyright Angel Marin, Paul Johnston 2000 - 2009.
|
|
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
|
|
*
|
|
*/
|
|
|
|
exports.hex_sha256 = hex_sha256;
|
|
exports.b64_sha256 = b64_sha256;
|
|
exports.str_sha256 = str_sha256;
|
|
exports.hex_hmac_sha256 = hex_hmac_sha256;
|
|
exports.b64_hmac_sha256 = b64_hmac_sha256;
|
|
exports.str_hmac_sha256 = str_hmac_sha256;
|
|
|
|
/*
|
|
* Configurable variables. You may need to tweak these to be compatible with
|
|
* the server-side, but the defaults work in most cases.
|
|
*/
|
|
var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
|
|
var b64pad = "="; /* base-64 pad character. "=" for strict RFC compliance */
|
|
var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */
|
|
|
|
/*
|
|
* These are the functions you'll usually want to call
|
|
* They take string arguments and return either hex or base-64 encoded strings
|
|
*/
|
|
function hex_sha256(s){return binb2hex(core_sha256(str2binb(s),s.length * chrsz));}
|
|
function b64_sha256(s){return binb2b64(core_sha256(str2binb(s),s.length * chrsz));}
|
|
function str_sha256(s){return binb2str(core_sha256(str2binb(s),s.length * chrsz));}
|
|
function hex_hmac_sha256(key, data){ return binb2hex(core_hmac_sha256(key, data));}
|
|
function b64_hmac_sha256(key, data){ return binb2b64(core_hmac_sha256(key, data));}
|
|
function str_hmac_sha256(key, data){ return binb2str(core_hmac_sha256(key, data));}
|
|
|
|
var safe_add = function(x, y) {
|
|
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
|
|
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
|
|
return (msw << 16) | (lsw & 0xFFFF);
|
|
};
|
|
|
|
var S = function(X, n) {
|
|
return (X >>> n) | (X << (32 - n));
|
|
};
|
|
|
|
var R = function(X, n) {
|
|
return (X >>> n);
|
|
};
|
|
|
|
var Ch = function(x, y, z) {
|
|
return ((x & y) ^ ((~x) & z));
|
|
};
|
|
|
|
var Maj = function(x, y, z) {
|
|
return ((x & y) ^ (x & z) ^ (y & z));
|
|
};
|
|
|
|
var Sigma0256 = function(x) {
|
|
return (S(x, 2) ^ S(x, 13) ^ S(x, 22));
|
|
};
|
|
|
|
var Sigma1256 = function(x) {
|
|
return (S(x, 6) ^ S(x, 11) ^ S(x, 25));
|
|
};
|
|
|
|
var Gamma0256 = function(x) {
|
|
return (S(x, 7) ^ S(x, 18) ^ R(x, 3));
|
|
};
|
|
|
|
var Gamma1256 = function(x) {
|
|
return (S(x, 17) ^ S(x, 19) ^ R(x, 10));
|
|
};
|
|
|
|
var core_sha256 = function(m, l) {
|
|
var K = new Array(0x428A2F98,0x71374491,0xB5C0FBCF,0xE9B5DBA5,0x3956C25B,0x59F111F1,0x923F82A4,0xAB1C5ED5,0xD807AA98,0x12835B01,0x243185BE,0x550C7DC3,0x72BE5D74,0x80DEB1FE,0x9BDC06A7,0xC19BF174,0xE49B69C1,0xEFBE4786,0xFC19DC6,0x240CA1CC,0x2DE92C6F,0x4A7484AA,0x5CB0A9DC,0x76F988DA,0x983E5152,0xA831C66D,0xB00327C8,0xBF597FC7,0xC6E00BF3,0xD5A79147,0x6CA6351,0x14292967,0x27B70A85,0x2E1B2138,0x4D2C6DFC,0x53380D13,0x650A7354,0x766A0ABB,0x81C2C92E,0x92722C85,0xA2BFE8A1,0xA81A664B,0xC24B8B70,0xC76C51A3,0xD192E819,0xD6990624,0xF40E3585,0x106AA070,0x19A4C116,0x1E376C08,0x2748774C,0x34B0BCB5,0x391C0CB3,0x4ED8AA4A,0x5B9CCA4F,0x682E6FF3,0x748F82EE,0x78A5636F,0x84C87814,0x8CC70208,0x90BEFFFA,0xA4506CEB,0xBEF9A3F7,0xC67178F2);
|
|
var HASH = new Array(0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19);
|
|
var W = new Array(64);
|
|
var a, b, c, d, e, f, g, h, i, j;
|
|
var T1, T2;
|
|
/* append padding */
|
|
m[l >> 5] |= 0x80 << (24 - l % 32);
|
|
m[((l + 64 >> 9) << 4) + 15] = l;
|
|
for (var i = 0; i < m.length; i += 16) {
|
|
a = HASH[0]; b = HASH[1]; c = HASH[2]; d = HASH[3]; e = HASH[4]; f = HASH[5]; g = HASH[6]; h = HASH[7];
|
|
for (var j = 0; j < 64; j++) {
|
|
if (j < 16) {
|
|
W[j] = m[j + i];
|
|
} else {
|
|
W[j] = safe_add(safe_add(safe_add(Gamma1256(W[j - 2]), W[j - 7]), Gamma0256(W[j - 15])), W[j - 16]);
|
|
}
|
|
T1 = safe_add(safe_add(safe_add(safe_add(h, Sigma1256(e)), Ch(e, f, g)), K[j]), W[j]);
|
|
T2 = safe_add(Sigma0256(a), Maj(a, b, c));
|
|
h = g; g = f; f = e; e = safe_add(d, T1); d = c; c = b; b = a; a = safe_add(T1, T2);
|
|
}
|
|
HASH[0] = safe_add(a, HASH[0]); HASH[1] = safe_add(b, HASH[1]); HASH[2] = safe_add(c, HASH[2]); HASH[3] = safe_add(d, HASH[3]);
|
|
HASH[4] = safe_add(e, HASH[4]); HASH[5] = safe_add(f, HASH[5]); HASH[6] = safe_add(g, HASH[6]); HASH[7] = safe_add(h, HASH[7]);
|
|
}
|
|
return HASH;
|
|
};
|
|
|
|
var str2binb = function(str) {
|
|
var bin = Array();
|
|
var mask = (1 << chrsz) - 1;
|
|
for (var i = 0; i < str.length * chrsz; i += chrsz) {
|
|
bin[i >> 5] |= (str.charCodeAt(i / chrsz) & mask) << (24 - i % 32);
|
|
}
|
|
return bin;
|
|
};
|
|
|
|
/*
|
|
* Convert an array of big-endian words to a string
|
|
*/
|
|
function binb2str(bin)
|
|
{
|
|
var str = "";
|
|
var mask = (1 << chrsz) - 1;
|
|
for (var i = 0; i < bin.length * 32; i += chrsz)
|
|
str += String.fromCharCode((bin[i >> 5] >>> (32 - chrsz - i % 32)) & mask);
|
|
return str;
|
|
}
|
|
|
|
var hex2binb = function(a) {
|
|
var b = [], length = a.length, i, num;
|
|
for (i = 0; i < length; i += 2) {
|
|
num = parseInt(a.substr(i, 2), 16);
|
|
if (!isNaN(num)) {
|
|
b[i >> 3] |= num << (24 - (4 * (i % 8)));
|
|
} else {
|
|
return "INVALID HEX STRING";
|
|
}
|
|
}
|
|
return b;
|
|
};
|
|
|
|
var binb2hex = function(binarray) {
|
|
//var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
|
|
var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
|
|
var str = "";
|
|
for (var i = 0; i < binarray.length * 4; i++) {
|
|
str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) + hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF);
|
|
}
|
|
return str;
|
|
};
|
|
|
|
var binb2b64 = function(a) {
|
|
var b = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + "0123456789+/", str = "", length = a.length * 4, i, j, triplet;
|
|
var b64pad = "=";
|
|
for (i = 0; i < length; i += 3) {
|
|
triplet = (((a[i >> 2] >> 8 * (3 - i % 4)) & 0xFF) << 16) | (((a[i + 1 >> 2] >> 8 * (3 - (i + 1) % 4)) & 0xFF) << 8) | ((a[i + 2 >> 2] >> 8 * (3 - (i + 2) % 4)) & 0xFF);
|
|
for (j = 0; j < 4; j += 1) {
|
|
if (i * 8 + j * 6 <= a.length * 32) {
|
|
str += b.charAt((triplet >> 6 * (3 - j)) & 0x3F);
|
|
} else {
|
|
str += b64pad;
|
|
}
|
|
}
|
|
}
|
|
return str;
|
|
};
|
|
|
|
var core_hmac_sha256 = function(key, data) {
|
|
var bkey = str2binb(key);
|
|
if (bkey.length > 16) {
|
|
bkey = core_sha256(bkey, key.length * chrsz);
|
|
}
|
|
var ipad = Array(16), opad = Array(16);
|
|
for (var i = 0; i < 16; i++) {
|
|
ipad[i] = bkey[i] ^ 0x36363636;
|
|
opad[i] = bkey[i] ^ 0x5C5C5C5C;
|
|
}
|
|
var hash = core_sha256(ipad.concat(str2binb(data)), 512 + data.length * chrsz);
|
|
return core_sha256(opad.concat(hash), 512 + 256);
|
|
};
|
|
|
|
|
|
},{}],65:[function(require,module,exports){
|
|
require=(function(e,t,n,r){function i(r){if(!n[r]){if(!t[r]){if(e)return e(r);throw new Error("Cannot find module '"+r+"'")}var s=n[r]={exports:{}};t[r][0](function(e){var n=t[r][1][e];return i(n?n:e)},s,s.exports)}return n[r].exports}for(var s=0;s<r.length;s++)i(r[s]);return i})(typeof require!=="undefined"&&require,{1:[function(require,module,exports){
|
|
// UTILITY
|
|
var util = require('util');
|
|
var Buffer = require("buffer").Buffer;
|
|
var pSlice = Array.prototype.slice;
|
|
|
|
function objectKeys(object) {
|
|
if (Object.keys) return Object.keys(object);
|
|
var result = [];
|
|
for (var name in object) {
|
|
if (Object.prototype.hasOwnProperty.call(object, name)) {
|
|
result.push(name);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
// 1. The assert module provides functions that throw
|
|
// AssertionError's when particular conditions are not met. The
|
|
// assert module must conform to the following interface.
|
|
|
|
var assert = module.exports = ok;
|
|
|
|
// 2. The AssertionError is defined in assert.
|
|
// new assert.AssertionError({ message: message,
|
|
// actual: actual,
|
|
// expected: expected })
|
|
|
|
assert.AssertionError = function AssertionError(options) {
|
|
this.name = 'AssertionError';
|
|
this.message = options.message;
|
|
this.actual = options.actual;
|
|
this.expected = options.expected;
|
|
this.operator = options.operator;
|
|
var stackStartFunction = options.stackStartFunction || fail;
|
|
|
|
if (Error.captureStackTrace) {
|
|
Error.captureStackTrace(this, stackStartFunction);
|
|
}
|
|
};
|
|
util.inherits(assert.AssertionError, Error);
|
|
|
|
function replacer(key, value) {
|
|
if (value === undefined) {
|
|
return '' + value;
|
|
}
|
|
if (typeof value === 'number' && (isNaN(value) || !isFinite(value))) {
|
|
return value.toString();
|
|
}
|
|
if (typeof value === 'function' || value instanceof RegExp) {
|
|
return value.toString();
|
|
}
|
|
return value;
|
|
}
|
|
|
|
function truncate(s, n) {
|
|
if (typeof s == 'string') {
|
|
return s.length < n ? s : s.slice(0, n);
|
|
} else {
|
|
return s;
|
|
}
|
|
}
|
|
|
|
assert.AssertionError.prototype.toString = function() {
|
|
if (this.message) {
|
|
return [this.name + ':', this.message].join(' ');
|
|
} else {
|
|
return [
|
|
this.name + ':',
|
|
truncate(JSON.stringify(this.actual, replacer), 128),
|
|
this.operator,
|
|
truncate(JSON.stringify(this.expected, replacer), 128)
|
|
].join(' ');
|
|
}
|
|
};
|
|
|
|
// assert.AssertionError instanceof Error
|
|
|
|
assert.AssertionError.__proto__ = Error.prototype;
|
|
|
|
// At present only the three keys mentioned above are used and
|
|
// understood by the spec. Implementations or sub modules can pass
|
|
// other keys to the AssertionError's constructor - they will be
|
|
// ignored.
|
|
|
|
// 3. All of the following functions must throw an AssertionError
|
|
// when a corresponding condition is not met, with a message that
|
|
// may be undefined if not provided. All assertion methods provide
|
|
// both the actual and expected values to the assertion error for
|
|
// display purposes.
|
|
|
|
function fail(actual, expected, message, operator, stackStartFunction) {
|
|
throw new assert.AssertionError({
|
|
message: message,
|
|
actual: actual,
|
|
expected: expected,
|
|
operator: operator,
|
|
stackStartFunction: stackStartFunction
|
|
});
|
|
}
|
|
|
|
// EXTENSION! allows for well behaved errors defined elsewhere.
|
|
assert.fail = fail;
|
|
|
|
// 4. Pure assertion tests whether a value is truthy, as determined
|
|
// by !!guard.
|
|
// assert.ok(guard, message_opt);
|
|
// This statement is equivalent to assert.equal(true, guard,
|
|
// message_opt);. To test strictly for the value true, use
|
|
// assert.strictEqual(true, guard, message_opt);.
|
|
|
|
function ok(value, message) {
|
|
if (!!!value) fail(value, true, message, '==', assert.ok);
|
|
}
|
|
assert.ok = ok;
|
|
|
|
// 5. The equality assertion tests shallow, coercive equality with
|
|
// ==.
|
|
// assert.equal(actual, expected, message_opt);
|
|
|
|
assert.equal = function equal(actual, expected, message) {
|
|
if (actual != expected) fail(actual, expected, message, '==', assert.equal);
|
|
};
|
|
|
|
// 6. The non-equality assertion tests for whether two objects are not equal
|
|
// with != assert.notEqual(actual, expected, message_opt);
|
|
|
|
assert.notEqual = function notEqual(actual, expected, message) {
|
|
if (actual == expected) {
|
|
fail(actual, expected, message, '!=', assert.notEqual);
|
|
}
|
|
};
|
|
|
|
// 7. The equivalence assertion tests a deep equality relation.
|
|
// assert.deepEqual(actual, expected, message_opt);
|
|
|
|
assert.deepEqual = function deepEqual(actual, expected, message) {
|
|
if (!_deepEqual(actual, expected)) {
|
|
fail(actual, expected, message, 'deepEqual', assert.deepEqual);
|
|
}
|
|
};
|
|
|
|
function _deepEqual(actual, expected) {
|
|
// 7.1. All identical values are equivalent, as determined by ===.
|
|
if (actual === expected) {
|
|
return true;
|
|
|
|
} else if (Buffer.isBuffer(actual) && Buffer.isBuffer(expected)) {
|
|
if (actual.length != expected.length) return false;
|
|
|
|
for (var i = 0; i < actual.length; i++) {
|
|
if (actual[i] !== expected[i]) return false;
|
|
}
|
|
|
|
return true;
|
|
|
|
// 7.2. If the expected value is a Date object, the actual value is
|
|
// equivalent if it is also a Date object that refers to the same time.
|
|
} else if (actual instanceof Date && expected instanceof Date) {
|
|
return actual.getTime() === expected.getTime();
|
|
|
|
// 7.3. Other pairs that do not both pass typeof value == 'object',
|
|
// equivalence is determined by ==.
|
|
} else if (typeof actual != 'object' && typeof expected != 'object') {
|
|
return actual == expected;
|
|
|
|
// 7.4. For all other Object pairs, including Array objects, equivalence is
|
|
// determined by having the same number of owned properties (as verified
|
|
// with Object.prototype.hasOwnProperty.call), the same set of keys
|
|
// (although not necessarily the same order), equivalent values for every
|
|
// corresponding key, and an identical 'prototype' property. Note: this
|
|
// accounts for both named and indexed properties on Arrays.
|
|
} else {
|
|
return objEquiv(actual, expected);
|
|
}
|
|
}
|
|
|
|
function isUndefinedOrNull(value) {
|
|
return value === null || value === undefined;
|
|
}
|
|
|
|
function isArguments(object) {
|
|
return Object.prototype.toString.call(object) == '[object Arguments]';
|
|
}
|
|
|
|
function objEquiv(a, b) {
|
|
if (isUndefinedOrNull(a) || isUndefinedOrNull(b))
|
|
return false;
|
|
// an identical 'prototype' property.
|
|
if (a.prototype !== b.prototype) return false;
|
|
//~~~I've managed to break Object.keys through screwy arguments passing.
|
|
// Converting to array solves the problem.
|
|
if (isArguments(a)) {
|
|
if (!isArguments(b)) {
|
|
return false;
|
|
}
|
|
a = pSlice.call(a);
|
|
b = pSlice.call(b);
|
|
return _deepEqual(a, b);
|
|
}
|
|
try {
|
|
var ka = objectKeys(a),
|
|
kb = objectKeys(b),
|
|
key, i;
|
|
} catch (e) {//happens when one is a string literal and the other isn't
|
|
return false;
|
|
}
|
|
// having the same number of owned properties (keys incorporates
|
|
// hasOwnProperty)
|
|
if (ka.length != kb.length)
|
|
return false;
|
|
//the same set of keys (although not necessarily the same order),
|
|
ka.sort();
|
|
kb.sort();
|
|
//~~~cheap key test
|
|
for (i = ka.length - 1; i >= 0; i--) {
|
|
if (ka[i] != kb[i])
|
|
return false;
|
|
}
|
|
//equivalent values for every corresponding key, and
|
|
//~~~possibly expensive deep test
|
|
for (i = ka.length - 1; i >= 0; i--) {
|
|
key = ka[i];
|
|
if (!_deepEqual(a[key], b[key])) return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// 8. The non-equivalence assertion tests for any deep inequality.
|
|
// assert.notDeepEqual(actual, expected, message_opt);
|
|
|
|
assert.notDeepEqual = function notDeepEqual(actual, expected, message) {
|
|
if (_deepEqual(actual, expected)) {
|
|
fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual);
|
|
}
|
|
};
|
|
|
|
// 9. The strict equality assertion tests strict equality, as determined by ===.
|
|
// assert.strictEqual(actual, expected, message_opt);
|
|
|
|
assert.strictEqual = function strictEqual(actual, expected, message) {
|
|
if (actual !== expected) {
|
|
fail(actual, expected, message, '===', assert.strictEqual);
|
|
}
|
|
};
|
|
|
|
// 10. The strict non-equality assertion tests for strict inequality, as
|
|
// determined by !==. assert.notStrictEqual(actual, expected, message_opt);
|
|
|
|
assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
|
|
if (actual === expected) {
|
|
fail(actual, expected, message, '!==', assert.notStrictEqual);
|
|
}
|
|
};
|
|
|
|
function expectedException(actual, expected) {
|
|
if (!actual || !expected) {
|
|
return false;
|
|
}
|
|
|
|
if (expected instanceof RegExp) {
|
|
return expected.test(actual);
|
|
} else if (actual instanceof expected) {
|
|
return true;
|
|
} else if (expected.call({}, actual) === true) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
function _throws(shouldThrow, block, expected, message) {
|
|
var actual;
|
|
|
|
if (typeof expected === 'string') {
|
|
message = expected;
|
|
expected = null;
|
|
}
|
|
|
|
try {
|
|
block();
|
|
} catch (e) {
|
|
actual = e;
|
|
}
|
|
|
|
message = (expected && expected.name ? ' (' + expected.name + ').' : '.') +
|
|
(message ? ' ' + message : '.');
|
|
|
|
if (shouldThrow && !actual) {
|
|
fail('Missing expected exception' + message);
|
|
}
|
|
|
|
if (!shouldThrow && expectedException(actual, expected)) {
|
|
fail('Got unwanted exception' + message);
|
|
}
|
|
|
|
if ((shouldThrow && actual && expected &&
|
|
!expectedException(actual, expected)) || (!shouldThrow && actual)) {
|
|
throw actual;
|
|
}
|
|
}
|
|
|
|
// 11. Expected to throw an error:
|
|
// assert.throws(block, Error_opt, message_opt);
|
|
|
|
assert.throws = function(block, /*optional*/error, /*optional*/message) {
|
|
_throws.apply(this, [true].concat(pSlice.call(arguments)));
|
|
};
|
|
|
|
// EXTENSION! This is annoying to write outside this module.
|
|
assert.doesNotThrow = function(block, /*optional*/error, /*optional*/message) {
|
|
_throws.apply(this, [false].concat(pSlice.call(arguments)));
|
|
};
|
|
|
|
assert.ifError = function(err) { if (err) {throw err;}};
|
|
|
|
},{"util":2,"buffer":3}],2:[function(require,module,exports){
|
|
var events = require('events');
|
|
|
|
exports.isArray = isArray;
|
|
exports.isDate = function(obj){return Object.prototype.toString.call(obj) === '[object Date]'};
|
|
exports.isRegExp = function(obj){return Object.prototype.toString.call(obj) === '[object RegExp]'};
|
|
|
|
|
|
exports.print = function () {};
|
|
exports.puts = function () {};
|
|
exports.debug = function() {};
|
|
|
|
exports.inspect = function(obj, showHidden, depth, colors) {
|
|
var seen = [];
|
|
|
|
var stylize = function(str, styleType) {
|
|
// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
|
|
var styles =
|
|
{ 'bold' : [1, 22],
|
|
'italic' : [3, 23],
|
|
'underline' : [4, 24],
|
|
'inverse' : [7, 27],
|
|
'white' : [37, 39],
|
|
'grey' : [90, 39],
|
|
'black' : [30, 39],
|
|
'blue' : [34, 39],
|
|
'cyan' : [36, 39],
|
|
'green' : [32, 39],
|
|
'magenta' : [35, 39],
|
|
'red' : [31, 39],
|
|
'yellow' : [33, 39] };
|
|
|
|
var style =
|
|
{ 'special': 'cyan',
|
|
'number': 'blue',
|
|
'boolean': 'yellow',
|
|
'undefined': 'grey',
|
|
'null': 'bold',
|
|
'string': 'green',
|
|
'date': 'magenta',
|
|
// "name": intentionally not styling
|
|
'regexp': 'red' }[styleType];
|
|
|
|
if (style) {
|
|
return '\033[' + styles[style][0] + 'm' + str +
|
|
'\033[' + styles[style][1] + 'm';
|
|
} else {
|
|
return str;
|
|
}
|
|
};
|
|
if (! colors) {
|
|
stylize = function(str, styleType) { return str; };
|
|
}
|
|
|
|
function format(value, recurseTimes) {
|
|
// Provide a hook for user-specified inspect functions.
|
|
// Check that value is an object with an inspect function on it
|
|
if (value && typeof value.inspect === 'function' &&
|
|
// Filter out the util module, it's inspect function is special
|
|
value !== exports &&
|
|
// Also filter out any prototype objects using the circular check.
|
|
!(value.constructor && value.constructor.prototype === value)) {
|
|
return value.inspect(recurseTimes);
|
|
}
|
|
|
|
// Primitive types cannot have properties
|
|
switch (typeof value) {
|
|
case 'undefined':
|
|
return stylize('undefined', 'undefined');
|
|
|
|
case 'string':
|
|
var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
|
|
.replace(/'/g, "\\'")
|
|
.replace(/\\"/g, '"') + '\'';
|
|
return stylize(simple, 'string');
|
|
|
|
case 'number':
|
|
return stylize('' + value, 'number');
|
|
|
|
case 'boolean':
|
|
return stylize('' + value, 'boolean');
|
|
}
|
|
// For some reason typeof null is "object", so special case here.
|
|
if (value === null) {
|
|
return stylize('null', 'null');
|
|
}
|
|
|
|
// Look up the keys of the object.
|
|
var visible_keys = Object_keys(value);
|
|
var keys = showHidden ? Object_getOwnPropertyNames(value) : visible_keys;
|
|
|
|
// Functions without properties can be shortcutted.
|
|
if (typeof value === 'function' && keys.length === 0) {
|
|
if (isRegExp(value)) {
|
|
return stylize('' + value, 'regexp');
|
|
} else {
|
|
var name = value.name ? ': ' + value.name : '';
|
|
return stylize('[Function' + name + ']', 'special');
|
|
}
|
|
}
|
|
|
|
// Dates without properties can be shortcutted
|
|
if (isDate(value) && keys.length === 0) {
|
|
return stylize(value.toUTCString(), 'date');
|
|
}
|
|
|
|
var base, type, braces;
|
|
// Determine the object type
|
|
if (isArray(value)) {
|
|
type = 'Array';
|
|
braces = ['[', ']'];
|
|
} else {
|
|
type = 'Object';
|
|
braces = ['{', '}'];
|
|
}
|
|
|
|
// Make functions say that they are functions
|
|
if (typeof value === 'function') {
|
|
var n = value.name ? ': ' + value.name : '';
|
|
base = (isRegExp(value)) ? ' ' + value : ' [Function' + n + ']';
|
|
} else {
|
|
base = '';
|
|
}
|
|
|
|
// Make dates with properties first say the date
|
|
if (isDate(value)) {
|
|
base = ' ' + value.toUTCString();
|
|
}
|
|
|
|
if (keys.length === 0) {
|
|
return braces[0] + base + braces[1];
|
|
}
|
|
|
|
if (recurseTimes < 0) {
|
|
if (isRegExp(value)) {
|
|
return stylize('' + value, 'regexp');
|
|
} else {
|
|
return stylize('[Object]', 'special');
|
|
}
|
|
}
|
|
|
|
seen.push(value);
|
|
|
|
var output = keys.map(function(key) {
|
|
var name, str;
|
|
if (value.__lookupGetter__) {
|
|
if (value.__lookupGetter__(key)) {
|
|
if (value.__lookupSetter__(key)) {
|
|
str = stylize('[Getter/Setter]', 'special');
|
|
} else {
|
|
str = stylize('[Getter]', 'special');
|
|
}
|
|
} else {
|
|
if (value.__lookupSetter__(key)) {
|
|
str = stylize('[Setter]', 'special');
|
|
}
|
|
}
|
|
}
|
|
if (visible_keys.indexOf(key) < 0) {
|
|
name = '[' + key + ']';
|
|
}
|
|
if (!str) {
|
|
if (seen.indexOf(value[key]) < 0) {
|
|
if (recurseTimes === null) {
|
|
str = format(value[key]);
|
|
} else {
|
|
str = format(value[key], recurseTimes - 1);
|
|
}
|
|
if (str.indexOf('\n') > -1) {
|
|
if (isArray(value)) {
|
|
str = str.split('\n').map(function(line) {
|
|
return ' ' + line;
|
|
}).join('\n').substr(2);
|
|
} else {
|
|
str = '\n' + str.split('\n').map(function(line) {
|
|
return ' ' + line;
|
|
}).join('\n');
|
|
}
|
|
}
|
|
} else {
|
|
str = stylize('[Circular]', 'special');
|
|
}
|
|
}
|
|
if (typeof name === 'undefined') {
|
|
if (type === 'Array' && key.match(/^\d+$/)) {
|
|
return str;
|
|
}
|
|
name = JSON.stringify('' + key);
|
|
if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
|
|
name = name.substr(1, name.length - 2);
|
|
name = stylize(name, 'name');
|
|
} else {
|
|
name = name.replace(/'/g, "\\'")
|
|
.replace(/\\"/g, '"')
|
|
.replace(/(^"|"$)/g, "'");
|
|
name = stylize(name, 'string');
|
|
}
|
|
}
|
|
|
|
return name + ': ' + str;
|
|
});
|
|
|
|
seen.pop();
|
|
|
|
var numLinesEst = 0;
|
|
var length = output.reduce(function(prev, cur) {
|
|
numLinesEst++;
|
|
if (cur.indexOf('\n') >= 0) numLinesEst++;
|
|
return prev + cur.length + 1;
|
|
}, 0);
|
|
|
|
if (length > 50) {
|
|
output = braces[0] +
|
|
(base === '' ? '' : base + '\n ') +
|
|
' ' +
|
|
output.join(',\n ') +
|
|
' ' +
|
|
braces[1];
|
|
|
|
} else {
|
|
output = braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
|
|
}
|
|
|
|
return output;
|
|
}
|
|
return format(obj, (typeof depth === 'undefined' ? 2 : depth));
|
|
};
|
|
|
|
|
|
function isArray(ar) {
|
|
return ar instanceof Array ||
|
|
Array.isArray(ar) ||
|
|
(ar && ar !== Object.prototype && isArray(ar.__proto__));
|
|
}
|
|
|
|
|
|
function isRegExp(re) {
|
|
return re instanceof RegExp ||
|
|
(typeof re === 'object' && Object.prototype.toString.call(re) === '[object RegExp]');
|
|
}
|
|
|
|
|
|
function isDate(d) {
|
|
if (d instanceof Date) return true;
|
|
if (typeof d !== 'object') return false;
|
|
var properties = Date.prototype && Object_getOwnPropertyNames(Date.prototype);
|
|
var proto = d.__proto__ && Object_getOwnPropertyNames(d.__proto__);
|
|
return JSON.stringify(proto) === JSON.stringify(properties);
|
|
}
|
|
|
|
function pad(n) {
|
|
return n < 10 ? '0' + n.toString(10) : n.toString(10);
|
|
}
|
|
|
|
var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
|
|
'Oct', 'Nov', 'Dec'];
|
|
|
|
// 26 Feb 16:19:34
|
|
function timestamp() {
|
|
var d = new Date();
|
|
var time = [pad(d.getHours()),
|
|
pad(d.getMinutes()),
|
|
pad(d.getSeconds())].join(':');
|
|
return [d.getDate(), months[d.getMonth()], time].join(' ');
|
|
}
|
|
|
|
exports.log = function (msg) {};
|
|
|
|
exports.pump = null;
|
|
|
|
var Object_keys = Object.keys || function (obj) {
|
|
var res = [];
|
|
for (var key in obj) res.push(key);
|
|
return res;
|
|
};
|
|
|
|
var Object_getOwnPropertyNames = Object.getOwnPropertyNames || function (obj) {
|
|
var res = [];
|
|
for (var key in obj) {
|
|
if (Object.hasOwnProperty.call(obj, key)) res.push(key);
|
|
}
|
|
return res;
|
|
};
|
|
|
|
var Object_create = Object.create || function (prototype, properties) {
|
|
// from es5-shim
|
|
var object;
|
|
if (prototype === null) {
|
|
object = { '__proto__' : null };
|
|
}
|
|
else {
|
|
if (typeof prototype !== 'object') {
|
|
throw new TypeError(
|
|
'typeof prototype[' + (typeof prototype) + '] != \'object\''
|
|
);
|
|
}
|
|
var Type = function () {};
|
|
Type.prototype = prototype;
|
|
object = new Type();
|
|
object.__proto__ = prototype;
|
|
}
|
|
if (typeof properties !== 'undefined' && Object.defineProperties) {
|
|
Object.defineProperties(object, properties);
|
|
}
|
|
return object;
|
|
};
|
|
|
|
exports.inherits = function(ctor, superCtor) {
|
|
ctor.super_ = superCtor;
|
|
ctor.prototype = Object_create(superCtor.prototype, {
|
|
constructor: {
|
|
value: ctor,
|
|
enumerable: false,
|
|
writable: true,
|
|
configurable: true
|
|
}
|
|
});
|
|
};
|
|
|
|
var formatRegExp = /%[sdj%]/g;
|
|
exports.format = function(f) {
|
|
if (typeof f !== 'string') {
|
|
var objects = [];
|
|
for (var i = 0; i < arguments.length; i++) {
|
|
objects.push(exports.inspect(arguments[i]));
|
|
}
|
|
return objects.join(' ');
|
|
}
|
|
|
|
var i = 1;
|
|
var args = arguments;
|
|
var len = args.length;
|
|
var str = String(f).replace(formatRegExp, function(x) {
|
|
if (x === '%%') return '%';
|
|
if (i >= len) return x;
|
|
switch (x) {
|
|
case '%s': return String(args[i++]);
|
|
case '%d': return Number(args[i++]);
|
|
case '%j': return JSON.stringify(args[i++]);
|
|
default:
|
|
return x;
|
|
}
|
|
});
|
|
for(var x = args[i]; i < len; x = args[++i]){
|
|
if (x === null || typeof x !== 'object') {
|
|
str += ' ' + x;
|
|
} else {
|
|
str += ' ' + exports.inspect(x);
|
|
}
|
|
}
|
|
return str;
|
|
};
|
|
|
|
},{"events":4}],5:[function(require,module,exports){
|
|
exports.readIEEE754 = function(buffer, offset, isBE, mLen, nBytes) {
|
|
var e, m,
|
|
eLen = nBytes * 8 - mLen - 1,
|
|
eMax = (1 << eLen) - 1,
|
|
eBias = eMax >> 1,
|
|
nBits = -7,
|
|
i = isBE ? 0 : (nBytes - 1),
|
|
d = isBE ? 1 : -1,
|
|
s = buffer[offset + i];
|
|
|
|
i += d;
|
|
|
|
e = s & ((1 << (-nBits)) - 1);
|
|
s >>= (-nBits);
|
|
nBits += eLen;
|
|
for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8);
|
|
|
|
m = e & ((1 << (-nBits)) - 1);
|
|
e >>= (-nBits);
|
|
nBits += mLen;
|
|
for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8);
|
|
|
|
if (e === 0) {
|
|
e = 1 - eBias;
|
|
} else if (e === eMax) {
|
|
return m ? NaN : ((s ? -1 : 1) * Infinity);
|
|
} else {
|
|
m = m + Math.pow(2, mLen);
|
|
e = e - eBias;
|
|
}
|
|
return (s ? -1 : 1) * m * Math.pow(2, e - mLen);
|
|
};
|
|
|
|
exports.writeIEEE754 = function(buffer, value, offset, isBE, mLen, nBytes) {
|
|
var e, m, c,
|
|
eLen = nBytes * 8 - mLen - 1,
|
|
eMax = (1 << eLen) - 1,
|
|
eBias = eMax >> 1,
|
|
rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0),
|
|
i = isBE ? (nBytes - 1) : 0,
|
|
d = isBE ? -1 : 1,
|
|
s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0;
|
|
|
|
value = Math.abs(value);
|
|
|
|
if (isNaN(value) || value === Infinity) {
|
|
m = isNaN(value) ? 1 : 0;
|
|
e = eMax;
|
|
} else {
|
|
e = Math.floor(Math.log(value) / Math.LN2);
|
|
if (value * (c = Math.pow(2, -e)) < 1) {
|
|
e--;
|
|
c *= 2;
|
|
}
|
|
if (e + eBias >= 1) {
|
|
value += rt / c;
|
|
} else {
|
|
value += rt * Math.pow(2, 1 - eBias);
|
|
}
|
|
if (value * c >= 2) {
|
|
e++;
|
|
c /= 2;
|
|
}
|
|
|
|
if (e + eBias >= eMax) {
|
|
m = 0;
|
|
e = eMax;
|
|
} else if (e + eBias >= 1) {
|
|
m = (value * c - 1) * Math.pow(2, mLen);
|
|
e = e + eBias;
|
|
} else {
|
|
m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen);
|
|
e = 0;
|
|
}
|
|
}
|
|
|
|
for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8);
|
|
|
|
e = (e << mLen) | m;
|
|
eLen += mLen;
|
|
for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8);
|
|
|
|
buffer[offset + i - d] |= s * 128;
|
|
};
|
|
|
|
},{}],6:[function(require,module,exports){
|
|
// shim for using process in browser
|
|
|
|
var process = module.exports = {};
|
|
|
|
process.nextTick = (function () {
|
|
var canSetImmediate = typeof window !== 'undefined'
|
|
&& window.setImmediate;
|
|
var canPost = typeof window !== 'undefined'
|
|
&& window.postMessage && window.addEventListener
|
|
;
|
|
|
|
if (canSetImmediate) {
|
|
return function (f) { return window.setImmediate(f) };
|
|
}
|
|
|
|
if (canPost) {
|
|
var queue = [];
|
|
window.addEventListener('message', function (ev) {
|
|
if (ev.source === window && ev.data === 'process-tick') {
|
|
ev.stopPropagation();
|
|
if (queue.length > 0) {
|
|
var fn = queue.shift();
|
|
fn();
|
|
}
|
|
}
|
|
}, true);
|
|
|
|
return function nextTick(fn) {
|
|
queue.push(fn);
|
|
window.postMessage('process-tick', '*');
|
|
};
|
|
}
|
|
|
|
return function nextTick(fn) {
|
|
setTimeout(fn, 0);
|
|
};
|
|
})();
|
|
|
|
process.title = 'browser';
|
|
process.browser = true;
|
|
process.env = {};
|
|
process.argv = [];
|
|
|
|
process.binding = function (name) {
|
|
throw new Error('process.binding is not supported');
|
|
}
|
|
|
|
// TODO(shtylman)
|
|
process.cwd = function () { return '/' };
|
|
process.chdir = function (dir) {
|
|
throw new Error('process.chdir is not supported');
|
|
};
|
|
|
|
},{}],4:[function(require,module,exports){
|
|
(function(process){if (!process.EventEmitter) process.EventEmitter = function () {};
|
|
|
|
var EventEmitter = exports.EventEmitter = process.EventEmitter;
|
|
var isArray = typeof Array.isArray === 'function'
|
|
? Array.isArray
|
|
: function (xs) {
|
|
return Object.prototype.toString.call(xs) === '[object Array]'
|
|
}
|
|
;
|
|
function indexOf (xs, x) {
|
|
if (xs.indexOf) return xs.indexOf(x);
|
|
for (var i = 0; i < xs.length; i++) {
|
|
if (x === xs[i]) return i;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
// By default EventEmitters will print a warning if more than
|
|
// 10 listeners are added to it. This is a useful default which
|
|
// helps finding memory leaks.
|
|
//
|
|
// Obviously not all Emitters should be limited to 10. This function allows
|
|
// that to be increased. Set to zero for unlimited.
|
|
var defaultMaxListeners = 10;
|
|
EventEmitter.prototype.setMaxListeners = function(n) {
|
|
if (!this._events) this._events = {};
|
|
this._events.maxListeners = n;
|
|
};
|
|
|
|
|
|
EventEmitter.prototype.emit = function(type) {
|
|
// If there is no 'error' event listener then throw.
|
|
if (type === 'error') {
|
|
if (!this._events || !this._events.error ||
|
|
(isArray(this._events.error) && !this._events.error.length))
|
|
{
|
|
if (arguments[1] instanceof Error) {
|
|
throw arguments[1]; // Unhandled 'error' event
|
|
} else {
|
|
throw new Error("Uncaught, unspecified 'error' event.");
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (!this._events) return false;
|
|
var handler = this._events[type];
|
|
if (!handler) return false;
|
|
|
|
if (typeof handler == 'function') {
|
|
switch (arguments.length) {
|
|
// fast cases
|
|
case 1:
|
|
handler.call(this);
|
|
break;
|
|
case 2:
|
|
handler.call(this, arguments[1]);
|
|
break;
|
|
case 3:
|
|
handler.call(this, arguments[1], arguments[2]);
|
|
break;
|
|
// slower
|
|
default:
|
|
var args = Array.prototype.slice.call(arguments, 1);
|
|
handler.apply(this, args);
|
|
}
|
|
return true;
|
|
|
|
} else if (isArray(handler)) {
|
|
var args = Array.prototype.slice.call(arguments, 1);
|
|
|
|
var listeners = handler.slice();
|
|
for (var i = 0, l = listeners.length; i < l; i++) {
|
|
listeners[i].apply(this, args);
|
|
}
|
|
return true;
|
|
|
|
} else {
|
|
return false;
|
|
}
|
|
};
|
|
|
|
// EventEmitter is defined in src/node_events.cc
|
|
// EventEmitter.prototype.emit() is also defined there.
|
|
EventEmitter.prototype.addListener = function(type, listener) {
|
|
if ('function' !== typeof listener) {
|
|
throw new Error('addListener only takes instances of Function');
|
|
}
|
|
|
|
if (!this._events) this._events = {};
|
|
|
|
// To avoid recursion in the case that type == "newListeners"! Before
|
|
// adding it to the listeners, first emit "newListeners".
|
|
this.emit('newListener', type, listener);
|
|
|
|
if (!this._events[type]) {
|
|
// Optimize the case of one listener. Don't need the extra array object.
|
|
this._events[type] = listener;
|
|
} else if (isArray(this._events[type])) {
|
|
|
|
// Check for listener leak
|
|
if (!this._events[type].warned) {
|
|
var m;
|
|
if (this._events.maxListeners !== undefined) {
|
|
m = this._events.maxListeners;
|
|
} else {
|
|
m = defaultMaxListeners;
|
|
}
|
|
|
|
if (m && m > 0 && this._events[type].length > m) {
|
|
this._events[type].warned = true;
|
|
console.error('(node) warning: possible EventEmitter memory ' +
|
|
'leak detected. %d listeners added. ' +
|
|
'Use emitter.setMaxListeners() to increase limit.',
|
|
this._events[type].length);
|
|
console.trace();
|
|
}
|
|
}
|
|
|
|
// If we've already got an array, just append.
|
|
this._events[type].push(listener);
|
|
} else {
|
|
// Adding the second element, need to change to array.
|
|
this._events[type] = [this._events[type], listener];
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
EventEmitter.prototype.on = EventEmitter.prototype.addListener;
|
|
|
|
EventEmitter.prototype.once = function(type, listener) {
|
|
var self = this;
|
|
self.on(type, function g() {
|
|
self.removeListener(type, g);
|
|
listener.apply(this, arguments);
|
|
});
|
|
|
|
return this;
|
|
};
|
|
|
|
EventEmitter.prototype.removeListener = function(type, listener) {
|
|
if ('function' !== typeof listener) {
|
|
throw new Error('removeListener only takes instances of Function');
|
|
}
|
|
|
|
// does not use listeners(), so no side effect of creating _events[type]
|
|
if (!this._events || !this._events[type]) return this;
|
|
|
|
var list = this._events[type];
|
|
|
|
if (isArray(list)) {
|
|
var i = indexOf(list, listener);
|
|
if (i < 0) return this;
|
|
list.splice(i, 1);
|
|
if (list.length == 0)
|
|
delete this._events[type];
|
|
} else if (this._events[type] === listener) {
|
|
delete this._events[type];
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
EventEmitter.prototype.removeAllListeners = function(type) {
|
|
if (arguments.length === 0) {
|
|
this._events = {};
|
|
return this;
|
|
}
|
|
|
|
// does not use listeners(), so no side effect of creating _events[type]
|
|
if (type && this._events && this._events[type]) this._events[type] = null;
|
|
return this;
|
|
};
|
|
|
|
EventEmitter.prototype.listeners = function(type) {
|
|
if (!this._events) this._events = {};
|
|
if (!this._events[type]) this._events[type] = [];
|
|
if (!isArray(this._events[type])) {
|
|
this._events[type] = [this._events[type]];
|
|
}
|
|
return this._events[type];
|
|
};
|
|
|
|
})(require("__browserify_process"))
|
|
},{"__browserify_process":6}],"buffer-browserify":[function(require,module,exports){
|
|
module.exports=require('q9TxCC');
|
|
},{}],"q9TxCC":[function(require,module,exports){
|
|
function SlowBuffer (size) {
|
|
this.length = size;
|
|
};
|
|
|
|
var assert = require('assert');
|
|
|
|
exports.INSPECT_MAX_BYTES = 50;
|
|
|
|
|
|
function toHex(n) {
|
|
if (n < 16) return '0' + n.toString(16);
|
|
return n.toString(16);
|
|
}
|
|
|
|
function utf8ToBytes(str) {
|
|
var byteArray = [];
|
|
for (var i = 0; i < str.length; i++)
|
|
if (str.charCodeAt(i) <= 0x7F)
|
|
byteArray.push(str.charCodeAt(i));
|
|
else {
|
|
var h = encodeURIComponent(str.charAt(i)).substr(1).split('%');
|
|
for (var j = 0; j < h.length; j++)
|
|
byteArray.push(parseInt(h[j], 16));
|
|
}
|
|
|
|
return byteArray;
|
|
}
|
|
|
|
function asciiToBytes(str) {
|
|
var byteArray = []
|
|
for (var i = 0; i < str.length; i++ )
|
|
// Node's code seems to be doing this and not & 0x7F..
|
|
byteArray.push( str.charCodeAt(i) & 0xFF );
|
|
|
|
return byteArray;
|
|
}
|
|
|
|
function base64ToBytes(str) {
|
|
return require("base64-js").toByteArray(str);
|
|
}
|
|
|
|
SlowBuffer.byteLength = function (str, encoding) {
|
|
switch (encoding || "utf8") {
|
|
case 'hex':
|
|
return str.length / 2;
|
|
|
|
case 'utf8':
|
|
case 'utf-8':
|
|
return utf8ToBytes(str).length;
|
|
|
|
case 'ascii':
|
|
case 'binary':
|
|
return str.length;
|
|
|
|
case 'base64':
|
|
return base64ToBytes(str).length;
|
|
|
|
default:
|
|
throw new Error('Unknown encoding');
|
|
}
|
|
};
|
|
|
|
function blitBuffer(src, dst, offset, length) {
|
|
var pos, i = 0;
|
|
while (i < length) {
|
|
if ((i+offset >= dst.length) || (i >= src.length))
|
|
break;
|
|
|
|
dst[i + offset] = src[i];
|
|
i++;
|
|
}
|
|
return i;
|
|
}
|
|
|
|
SlowBuffer.prototype.utf8Write = function (string, offset, length) {
|
|
var bytes, pos;
|
|
return SlowBuffer._charsWritten = blitBuffer(utf8ToBytes(string), this, offset, length);
|
|
};
|
|
|
|
SlowBuffer.prototype.asciiWrite = function (string, offset, length) {
|
|
var bytes, pos;
|
|
return SlowBuffer._charsWritten = blitBuffer(asciiToBytes(string), this, offset, length);
|
|
};
|
|
|
|
SlowBuffer.prototype.binaryWrite = SlowBuffer.prototype.asciiWrite;
|
|
|
|
SlowBuffer.prototype.base64Write = function (string, offset, length) {
|
|
var bytes, pos;
|
|
return SlowBuffer._charsWritten = blitBuffer(base64ToBytes(string), this, offset, length);
|
|
};
|
|
|
|
SlowBuffer.prototype.base64Slice = function (start, end) {
|
|
var bytes = Array.prototype.slice.apply(this, arguments)
|
|
return require("base64-js").fromByteArray(bytes);
|
|
}
|
|
|
|
function decodeUtf8Char(str) {
|
|
try {
|
|
return decodeURIComponent(str);
|
|
} catch (err) {
|
|
return String.fromCharCode(0xFFFD); // UTF 8 invalid char
|
|
}
|
|
}
|
|
|
|
SlowBuffer.prototype.utf8Slice = function () {
|
|
var bytes = Array.prototype.slice.apply(this, arguments);
|
|
var res = "";
|
|
var tmp = "";
|
|
var i = 0;
|
|
while (i < bytes.length) {
|
|
if (bytes[i] <= 0x7F) {
|
|
res += decodeUtf8Char(tmp) + String.fromCharCode(bytes[i]);
|
|
tmp = "";
|
|
} else
|
|
tmp += "%" + bytes[i].toString(16);
|
|
|
|
i++;
|
|
}
|
|
|
|
return res + decodeUtf8Char(tmp);
|
|
}
|
|
|
|
SlowBuffer.prototype.asciiSlice = function () {
|
|
var bytes = Array.prototype.slice.apply(this, arguments);
|
|
var ret = "";
|
|
for (var i = 0; i < bytes.length; i++)
|
|
ret += String.fromCharCode(bytes[i]);
|
|
return ret;
|
|
}
|
|
|
|
SlowBuffer.prototype.binarySlice = SlowBuffer.prototype.asciiSlice;
|
|
|
|
SlowBuffer.prototype.inspect = function() {
|
|
var out = [],
|
|
len = this.length;
|
|
for (var i = 0; i < len; i++) {
|
|
out[i] = toHex(this[i]);
|
|
if (i == exports.INSPECT_MAX_BYTES) {
|
|
out[i + 1] = '...';
|
|
break;
|
|
}
|
|
}
|
|
return '<SlowBuffer ' + out.join(' ') + '>';
|
|
};
|
|
|
|
|
|
SlowBuffer.prototype.hexSlice = function(start, end) {
|
|
var len = this.length;
|
|
|
|
if (!start || start < 0) start = 0;
|
|
if (!end || end < 0 || end > len) end = len;
|
|
|
|
var out = '';
|
|
for (var i = start; i < end; i++) {
|
|
out += toHex(this[i]);
|
|
}
|
|
return out;
|
|
};
|
|
|
|
|
|
SlowBuffer.prototype.toString = function(encoding, start, end) {
|
|
encoding = String(encoding || 'utf8').toLowerCase();
|
|
start = +start || 0;
|
|
if (typeof end == 'undefined') end = this.length;
|
|
|
|
// Fastpath empty strings
|
|
if (+end == start) {
|
|
return '';
|
|
}
|
|
|
|
switch (encoding) {
|
|
case 'hex':
|
|
return this.hexSlice(start, end);
|
|
|
|
case 'utf8':
|
|
case 'utf-8':
|
|
return this.utf8Slice(start, end);
|
|
|
|
case 'ascii':
|
|
return this.asciiSlice(start, end);
|
|
|
|
case 'binary':
|
|
return this.binarySlice(start, end);
|
|
|
|
case 'base64':
|
|
return this.base64Slice(start, end);
|
|
|
|
case 'ucs2':
|
|
case 'ucs-2':
|
|
return this.ucs2Slice(start, end);
|
|
|
|
default:
|
|
throw new Error('Unknown encoding');
|
|
}
|
|
};
|
|
|
|
|
|
SlowBuffer.prototype.hexWrite = function(string, offset, length) {
|
|
offset = +offset || 0;
|
|
var remaining = this.length - offset;
|
|
if (!length) {
|
|
length = remaining;
|
|
} else {
|
|
length = +length;
|
|
if (length > remaining) {
|
|
length = remaining;
|
|
}
|
|
}
|
|
|
|
// must be an even number of digits
|
|
var strLen = string.length;
|
|
if (strLen % 2) {
|
|
throw new Error('Invalid hex string');
|
|
}
|
|
if (length > strLen / 2) {
|
|
length = strLen / 2;
|
|
}
|
|
for (var i = 0; i < length; i++) {
|
|
var byte = parseInt(string.substr(i * 2, 2), 16);
|
|
if (isNaN(byte)) throw new Error('Invalid hex string');
|
|
this[offset + i] = byte;
|
|
}
|
|
SlowBuffer._charsWritten = i * 2;
|
|
return i;
|
|
};
|
|
|
|
|
|
SlowBuffer.prototype.write = function(string, offset, length, encoding) {
|
|
// Support both (string, offset, length, encoding)
|
|
// and the legacy (string, encoding, offset, length)
|
|
if (isFinite(offset)) {
|
|
if (!isFinite(length)) {
|
|
encoding = length;
|
|
length = undefined;
|
|
}
|
|
} else { // legacy
|
|
var swap = encoding;
|
|
encoding = offset;
|
|
offset = length;
|
|
length = swap;
|
|
}
|
|
|
|
offset = +offset || 0;
|
|
var remaining = this.length - offset;
|
|
if (!length) {
|
|
length = remaining;
|
|
} else {
|
|
length = +length;
|
|
if (length > remaining) {
|
|
length = remaining;
|
|
}
|
|
}
|
|
encoding = String(encoding || 'utf8').toLowerCase();
|
|
|
|
switch (encoding) {
|
|
case 'hex':
|
|
return this.hexWrite(string, offset, length);
|
|
|
|
case 'utf8':
|
|
case 'utf-8':
|
|
return this.utf8Write(string, offset, length);
|
|
|
|
case 'ascii':
|
|
return this.asciiWrite(string, offset, length);
|
|
|
|
case 'binary':
|
|
return this.binaryWrite(string, offset, length);
|
|
|
|
case 'base64':
|
|
return this.base64Write(string, offset, length);
|
|
|
|
case 'ucs2':
|
|
case 'ucs-2':
|
|
return this.ucs2Write(string, offset, length);
|
|
|
|
default:
|
|
throw new Error('Unknown encoding');
|
|
}
|
|
};
|
|
|
|
|
|
// slice(start, end)
|
|
SlowBuffer.prototype.slice = function(start, end) {
|
|
if (end === undefined) end = this.length;
|
|
|
|
if (end > this.length) {
|
|
throw new Error('oob');
|
|
}
|
|
if (start > end) {
|
|
throw new Error('oob');
|
|
}
|
|
|
|
return new Buffer(this, end - start, +start);
|
|
};
|
|
|
|
SlowBuffer.prototype.copy = function(target, targetstart, sourcestart, sourceend) {
|
|
var temp = [];
|
|
for (var i=sourcestart; i<sourceend; i++) {
|
|
assert.ok(typeof this[i] !== 'undefined', "copying undefined buffer bytes!");
|
|
temp.push(this[i]);
|
|
}
|
|
|
|
for (var i=targetstart; i<targetstart+temp.length; i++) {
|
|
target[i] = temp[i-targetstart];
|
|
}
|
|
};
|
|
|
|
SlowBuffer.prototype.fill = function(value, start, end) {
|
|
if (end > this.length) {
|
|
throw new Error('oob');
|
|
}
|
|
if (start > end) {
|
|
throw new Error('oob');
|
|
}
|
|
|
|
for (var i = start; i < end; i++) {
|
|
this[i] = value;
|
|
}
|
|
}
|
|
|
|
function coerce(length) {
|
|
// Coerce length to a number (possibly NaN), round up
|
|
// in case it's fractional (e.g. 123.456) then do a
|
|
// double negate to coerce a NaN to 0. Easy, right?
|
|
length = ~~Math.ceil(+length);
|
|
return length < 0 ? 0 : length;
|
|
}
|
|
|
|
|
|
// Buffer
|
|
|
|
function Buffer(subject, encoding, offset) {
|
|
if (!(this instanceof Buffer)) {
|
|
return new Buffer(subject, encoding, offset);
|
|
}
|
|
|
|
var type;
|
|
|
|
// Are we slicing?
|
|
if (typeof offset === 'number') {
|
|
this.length = coerce(encoding);
|
|
this.parent = subject;
|
|
this.offset = offset;
|
|
} else {
|
|
// Find the length
|
|
switch (type = typeof subject) {
|
|
case 'number':
|
|
this.length = coerce(subject);
|
|
break;
|
|
|
|
case 'string':
|
|
this.length = Buffer.byteLength(subject, encoding);
|
|
break;
|
|
|
|
case 'object': // Assume object is an array
|
|
this.length = coerce(subject.length);
|
|
break;
|
|
|
|
default:
|
|
throw new Error('First argument needs to be a number, ' +
|
|
'array or string.');
|
|
}
|
|
|
|
if (this.length > Buffer.poolSize) {
|
|
// Big buffer, just alloc one.
|
|
this.parent = new SlowBuffer(this.length);
|
|
this.offset = 0;
|
|
|
|
} else {
|
|
// Small buffer.
|
|
if (!pool || pool.length - pool.used < this.length) allocPool();
|
|
this.parent = pool;
|
|
this.offset = pool.used;
|
|
pool.used += this.length;
|
|
}
|
|
|
|
// Treat array-ish objects as a byte array.
|
|
if (isArrayIsh(subject)) {
|
|
for (var i = 0; i < this.length; i++) {
|
|
if (subject instanceof Buffer) {
|
|
this.parent[i + this.offset] = subject.readUInt8(i);
|
|
}
|
|
else {
|
|
this.parent[i + this.offset] = subject[i];
|
|
}
|
|
}
|
|
} else if (type == 'string') {
|
|
// We are a string
|
|
this.length = this.write(subject, 0, encoding);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
function isArrayIsh(subject) {
|
|
return Array.isArray(subject) || Buffer.isBuffer(subject) ||
|
|
subject && typeof subject === 'object' &&
|
|
typeof subject.length === 'number';
|
|
}
|
|
|
|
exports.SlowBuffer = SlowBuffer;
|
|
exports.Buffer = Buffer;
|
|
|
|
Buffer.poolSize = 8 * 1024;
|
|
var pool;
|
|
|
|
function allocPool() {
|
|
pool = new SlowBuffer(Buffer.poolSize);
|
|
pool.used = 0;
|
|
}
|
|
|
|
|
|
// Static methods
|
|
Buffer.isBuffer = function isBuffer(b) {
|
|
return b instanceof Buffer || b instanceof SlowBuffer;
|
|
};
|
|
|
|
Buffer.concat = function (list, totalLength) {
|
|
if (!Array.isArray(list)) {
|
|
throw new Error("Usage: Buffer.concat(list, [totalLength])\n \
|
|
list should be an Array.");
|
|
}
|
|
|
|
if (list.length === 0) {
|
|
return new Buffer(0);
|
|
} else if (list.length === 1) {
|
|
return list[0];
|
|
}
|
|
|
|
if (typeof totalLength !== 'number') {
|
|
totalLength = 0;
|
|
for (var i = 0; i < list.length; i++) {
|
|
var buf = list[i];
|
|
totalLength += buf.length;
|
|
}
|
|
}
|
|
|
|
var buffer = new Buffer(totalLength);
|
|
var pos = 0;
|
|
for (var i = 0; i < list.length; i++) {
|
|
var buf = list[i];
|
|
buf.copy(buffer, pos);
|
|
pos += buf.length;
|
|
}
|
|
return buffer;
|
|
};
|
|
|
|
// Inspect
|
|
Buffer.prototype.inspect = function inspect() {
|
|
var out = [],
|
|
len = this.length;
|
|
|
|
for (var i = 0; i < len; i++) {
|
|
out[i] = toHex(this.parent[i + this.offset]);
|
|
if (i == exports.INSPECT_MAX_BYTES) {
|
|
out[i + 1] = '...';
|
|
break;
|
|
}
|
|
}
|
|
|
|
return '<Buffer ' + out.join(' ') + '>';
|
|
};
|
|
|
|
|
|
Buffer.prototype.get = function get(i) {
|
|
if (i < 0 || i >= this.length) throw new Error('oob');
|
|
return this.parent[this.offset + i];
|
|
};
|
|
|
|
|
|
Buffer.prototype.set = function set(i, v) {
|
|
if (i < 0 || i >= this.length) throw new Error('oob');
|
|
return this.parent[this.offset + i] = v;
|
|
};
|
|
|
|
|
|
// write(string, offset = 0, length = buffer.length-offset, encoding = 'utf8')
|
|
Buffer.prototype.write = function(string, offset, length, encoding) {
|
|
// Support both (string, offset, length, encoding)
|
|
// and the legacy (string, encoding, offset, length)
|
|
if (isFinite(offset)) {
|
|
if (!isFinite(length)) {
|
|
encoding = length;
|
|
length = undefined;
|
|
}
|
|
} else { // legacy
|
|
var swap = encoding;
|
|
encoding = offset;
|
|
offset = length;
|
|
length = swap;
|
|
}
|
|
|
|
offset = +offset || 0;
|
|
var remaining = this.length - offset;
|
|
if (!length) {
|
|
length = remaining;
|
|
} else {
|
|
length = +length;
|
|
if (length > remaining) {
|
|
length = remaining;
|
|
}
|
|
}
|
|
encoding = String(encoding || 'utf8').toLowerCase();
|
|
|
|
var ret;
|
|
switch (encoding) {
|
|
case 'hex':
|
|
ret = this.parent.hexWrite(string, this.offset + offset, length);
|
|
break;
|
|
|
|
case 'utf8':
|
|
case 'utf-8':
|
|
ret = this.parent.utf8Write(string, this.offset + offset, length);
|
|
break;
|
|
|
|
case 'ascii':
|
|
ret = this.parent.asciiWrite(string, this.offset + offset, length);
|
|
break;
|
|
|
|
case 'binary':
|
|
ret = this.parent.binaryWrite(string, this.offset + offset, length);
|
|
break;
|
|
|
|
case 'base64':
|
|
// Warning: maxLength not taken into account in base64Write
|
|
ret = this.parent.base64Write(string, this.offset + offset, length);
|
|
break;
|
|
|
|
case 'ucs2':
|
|
case 'ucs-2':
|
|
ret = this.parent.ucs2Write(string, this.offset + offset, length);
|
|
break;
|
|
|
|
default:
|
|
throw new Error('Unknown encoding');
|
|
}
|
|
|
|
Buffer._charsWritten = SlowBuffer._charsWritten;
|
|
|
|
return ret;
|
|
};
|
|
|
|
|
|
// toString(encoding, start=0, end=buffer.length)
|
|
Buffer.prototype.toString = function(encoding, start, end) {
|
|
encoding = String(encoding || 'utf8').toLowerCase();
|
|
|
|
if (typeof start == 'undefined' || start < 0) {
|
|
start = 0;
|
|
} else if (start > this.length) {
|
|
start = this.length;
|
|
}
|
|
|
|
if (typeof end == 'undefined' || end > this.length) {
|
|
end = this.length;
|
|
} else if (end < 0) {
|
|
end = 0;
|
|
}
|
|
|
|
start = start + this.offset;
|
|
end = end + this.offset;
|
|
|
|
switch (encoding) {
|
|
case 'hex':
|
|
return this.parent.hexSlice(start, end);
|
|
|
|
case 'utf8':
|
|
case 'utf-8':
|
|
return this.parent.utf8Slice(start, end);
|
|
|
|
case 'ascii':
|
|
return this.parent.asciiSlice(start, end);
|
|
|
|
case 'binary':
|
|
return this.parent.binarySlice(start, end);
|
|
|
|
case 'base64':
|
|
return this.parent.base64Slice(start, end);
|
|
|
|
case 'ucs2':
|
|
case 'ucs-2':
|
|
return this.parent.ucs2Slice(start, end);
|
|
|
|
default:
|
|
throw new Error('Unknown encoding');
|
|
}
|
|
};
|
|
|
|
|
|
// byteLength
|
|
Buffer.byteLength = SlowBuffer.byteLength;
|
|
|
|
|
|
// fill(value, start=0, end=buffer.length)
|
|
Buffer.prototype.fill = function fill(value, start, end) {
|
|
value || (value = 0);
|
|
start || (start = 0);
|
|
end || (end = this.length);
|
|
|
|
if (typeof value === 'string') {
|
|
value = value.charCodeAt(0);
|
|
}
|
|
if (!(typeof value === 'number') || isNaN(value)) {
|
|
throw new Error('value is not a number');
|
|
}
|
|
|
|
if (end < start) throw new Error('end < start');
|
|
|
|
// Fill 0 bytes; we're done
|
|
if (end === start) return 0;
|
|
if (this.length == 0) return 0;
|
|
|
|
if (start < 0 || start >= this.length) {
|
|
throw new Error('start out of bounds');
|
|
}
|
|
|
|
if (end < 0 || end > this.length) {
|
|
throw new Error('end out of bounds');
|
|
}
|
|
|
|
return this.parent.fill(value,
|
|
start + this.offset,
|
|
end + this.offset);
|
|
};
|
|
|
|
|
|
// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
|
|
Buffer.prototype.copy = function(target, target_start, start, end) {
|
|
var source = this;
|
|
start || (start = 0);
|
|
end || (end = this.length);
|
|
target_start || (target_start = 0);
|
|
|
|
if (end < start) throw new Error('sourceEnd < sourceStart');
|
|
|
|
// Copy 0 bytes; we're done
|
|
if (end === start) return 0;
|
|
if (target.length == 0 || source.length == 0) return 0;
|
|
|
|
if (target_start < 0 || target_start >= target.length) {
|
|
throw new Error('targetStart out of bounds');
|
|
}
|
|
|
|
if (start < 0 || start >= source.length) {
|
|
throw new Error('sourceStart out of bounds');
|
|
}
|
|
|
|
if (end < 0 || end > source.length) {
|
|
throw new Error('sourceEnd out of bounds');
|
|
}
|
|
|
|
// Are we oob?
|
|
if (end > this.length) {
|
|
end = this.length;
|
|
}
|
|
|
|
if (target.length - target_start < end - start) {
|
|
end = target.length - target_start + start;
|
|
}
|
|
|
|
return this.parent.copy(target.parent,
|
|
target_start + target.offset,
|
|
start + this.offset,
|
|
end + this.offset);
|
|
};
|
|
|
|
|
|
// slice(start, end)
|
|
Buffer.prototype.slice = function(start, end) {
|
|
if (end === undefined) end = this.length;
|
|
if (end > this.length) throw new Error('oob');
|
|
if (start > end) throw new Error('oob');
|
|
|
|
return new Buffer(this.parent, end - start, +start + this.offset);
|
|
};
|
|
|
|
|
|
// Legacy methods for backwards compatibility.
|
|
|
|
Buffer.prototype.utf8Slice = function(start, end) {
|
|
return this.toString('utf8', start, end);
|
|
};
|
|
|
|
Buffer.prototype.binarySlice = function(start, end) {
|
|
return this.toString('binary', start, end);
|
|
};
|
|
|
|
Buffer.prototype.asciiSlice = function(start, end) {
|
|
return this.toString('ascii', start, end);
|
|
};
|
|
|
|
Buffer.prototype.utf8Write = function(string, offset) {
|
|
return this.write(string, offset, 'utf8');
|
|
};
|
|
|
|
Buffer.prototype.binaryWrite = function(string, offset) {
|
|
return this.write(string, offset, 'binary');
|
|
};
|
|
|
|
Buffer.prototype.asciiWrite = function(string, offset) {
|
|
return this.write(string, offset, 'ascii');
|
|
};
|
|
|
|
Buffer.prototype.readUInt8 = function(offset, noAssert) {
|
|
var buffer = this;
|
|
|
|
if (!noAssert) {
|
|
assert.ok(offset !== undefined && offset !== null,
|
|
'missing offset');
|
|
|
|
assert.ok(offset < buffer.length,
|
|
'Trying to read beyond buffer length');
|
|
}
|
|
|
|
if (offset >= buffer.length) return;
|
|
|
|
return buffer.parent[buffer.offset + offset];
|
|
};
|
|
|
|
function readUInt16(buffer, offset, isBigEndian, noAssert) {
|
|
var val = 0;
|
|
|
|
|
|
if (!noAssert) {
|
|
assert.ok(typeof (isBigEndian) === 'boolean',
|
|
'missing or invalid endian');
|
|
|
|
assert.ok(offset !== undefined && offset !== null,
|
|
'missing offset');
|
|
|
|
assert.ok(offset + 1 < buffer.length,
|
|
'Trying to read beyond buffer length');
|
|
}
|
|
|
|
if (offset >= buffer.length) return 0;
|
|
|
|
if (isBigEndian) {
|
|
val = buffer.parent[buffer.offset + offset] << 8;
|
|
if (offset + 1 < buffer.length) {
|
|
val |= buffer.parent[buffer.offset + offset + 1];
|
|
}
|
|
} else {
|
|
val = buffer.parent[buffer.offset + offset];
|
|
if (offset + 1 < buffer.length) {
|
|
val |= buffer.parent[buffer.offset + offset + 1] << 8;
|
|
}
|
|
}
|
|
|
|
return val;
|
|
}
|
|
|
|
Buffer.prototype.readUInt16LE = function(offset, noAssert) {
|
|
return readUInt16(this, offset, false, noAssert);
|
|
};
|
|
|
|
Buffer.prototype.readUInt16BE = function(offset, noAssert) {
|
|
return readUInt16(this, offset, true, noAssert);
|
|
};
|
|
|
|
function readUInt32(buffer, offset, isBigEndian, noAssert) {
|
|
var val = 0;
|
|
|
|
if (!noAssert) {
|
|
assert.ok(typeof (isBigEndian) === 'boolean',
|
|
'missing or invalid endian');
|
|
|
|
assert.ok(offset !== undefined && offset !== null,
|
|
'missing offset');
|
|
|
|
assert.ok(offset + 3 < buffer.length,
|
|
'Trying to read beyond buffer length');
|
|
}
|
|
|
|
if (offset >= buffer.length) return 0;
|
|
|
|
if (isBigEndian) {
|
|
if (offset + 1 < buffer.length)
|
|
val = buffer.parent[buffer.offset + offset + 1] << 16;
|
|
if (offset + 2 < buffer.length)
|
|
val |= buffer.parent[buffer.offset + offset + 2] << 8;
|
|
if (offset + 3 < buffer.length)
|
|
val |= buffer.parent[buffer.offset + offset + 3];
|
|
val = val + (buffer.parent[buffer.offset + offset] << 24 >>> 0);
|
|
} else {
|
|
if (offset + 2 < buffer.length)
|
|
val = buffer.parent[buffer.offset + offset + 2] << 16;
|
|
if (offset + 1 < buffer.length)
|
|
val |= buffer.parent[buffer.offset + offset + 1] << 8;
|
|
val |= buffer.parent[buffer.offset + offset];
|
|
if (offset + 3 < buffer.length)
|
|
val = val + (buffer.parent[buffer.offset + offset + 3] << 24 >>> 0);
|
|
}
|
|
|
|
return val;
|
|
}
|
|
|
|
Buffer.prototype.readUInt32LE = function(offset, noAssert) {
|
|
return readUInt32(this, offset, false, noAssert);
|
|
};
|
|
|
|
Buffer.prototype.readUInt32BE = function(offset, noAssert) {
|
|
return readUInt32(this, offset, true, noAssert);
|
|
};
|
|
|
|
|
|
/*
|
|
* Signed integer types, yay team! A reminder on how two's complement actually
|
|
* works. The first bit is the signed bit, i.e. tells us whether or not the
|
|
* number should be positive or negative. If the two's complement value is
|
|
* positive, then we're done, as it's equivalent to the unsigned representation.
|
|
*
|
|
* Now if the number is positive, you're pretty much done, you can just leverage
|
|
* the unsigned translations and return those. Unfortunately, negative numbers
|
|
* aren't quite that straightforward.
|
|
*
|
|
* At first glance, one might be inclined to use the traditional formula to
|
|
* translate binary numbers between the positive and negative values in two's
|
|
* complement. (Though it doesn't quite work for the most negative value)
|
|
* Mainly:
|
|
* - invert all the bits
|
|
* - add one to the result
|
|
*
|
|
* Of course, this doesn't quite work in Javascript. Take for example the value
|
|
* of -128. This could be represented in 16 bits (big-endian) as 0xff80. But of
|
|
* course, Javascript will do the following:
|
|
*
|
|
* > ~0xff80
|
|
* -65409
|
|
*
|
|
* Whoh there, Javascript, that's not quite right. But wait, according to
|
|
* Javascript that's perfectly correct. When Javascript ends up seeing the
|
|
* constant 0xff80, it has no notion that it is actually a signed number. It
|
|
* assumes that we've input the unsigned value 0xff80. Thus, when it does the
|
|
* binary negation, it casts it into a signed value, (positive 0xff80). Then
|
|
* when you perform binary negation on that, it turns it into a negative number.
|
|
*
|
|
* Instead, we're going to have to use the following general formula, that works
|
|
* in a rather Javascript friendly way. I'm glad we don't support this kind of
|
|
* weird numbering scheme in the kernel.
|
|
*
|
|
* (BIT-MAX - (unsigned)val + 1) * -1
|
|
*
|
|
* The astute observer, may think that this doesn't make sense for 8-bit numbers
|
|
* (really it isn't necessary for them). However, when you get 16-bit numbers,
|
|
* you do. Let's go back to our prior example and see how this will look:
|
|
*
|
|
* (0xffff - 0xff80 + 1) * -1
|
|
* (0x007f + 1) * -1
|
|
* (0x0080) * -1
|
|
*/
|
|
Buffer.prototype.readInt8 = function(offset, noAssert) {
|
|
var buffer = this;
|
|
var neg;
|
|
|
|
if (!noAssert) {
|
|
assert.ok(offset !== undefined && offset !== null,
|
|
'missing offset');
|
|
|
|
assert.ok(offset < buffer.length,
|
|
'Trying to read beyond buffer length');
|
|
}
|
|
|
|
if (offset >= buffer.length) return;
|
|
|
|
neg = buffer.parent[buffer.offset + offset] & 0x80;
|
|
if (!neg) {
|
|
return (buffer.parent[buffer.offset + offset]);
|
|
}
|
|
|
|
return ((0xff - buffer.parent[buffer.offset + offset] + 1) * -1);
|
|
};
|
|
|
|
function readInt16(buffer, offset, isBigEndian, noAssert) {
|
|
var neg, val;
|
|
|
|
if (!noAssert) {
|
|
assert.ok(typeof (isBigEndian) === 'boolean',
|
|
'missing or invalid endian');
|
|
|
|
assert.ok(offset !== undefined && offset !== null,
|
|
'missing offset');
|
|
|
|
assert.ok(offset + 1 < buffer.length,
|
|
'Trying to read beyond buffer length');
|
|
}
|
|
|
|
val = readUInt16(buffer, offset, isBigEndian, noAssert);
|
|
neg = val & 0x8000;
|
|
if (!neg) {
|
|
return val;
|
|
}
|
|
|
|
return (0xffff - val + 1) * -1;
|
|
}
|
|
|
|
Buffer.prototype.readInt16LE = function(offset, noAssert) {
|
|
return readInt16(this, offset, false, noAssert);
|
|
};
|
|
|
|
Buffer.prototype.readInt16BE = function(offset, noAssert) {
|
|
return readInt16(this, offset, true, noAssert);
|
|
};
|
|
|
|
function readInt32(buffer, offset, isBigEndian, noAssert) {
|
|
var neg, val;
|
|
|
|
if (!noAssert) {
|
|
assert.ok(typeof (isBigEndian) === 'boolean',
|
|
'missing or invalid endian');
|
|
|
|
assert.ok(offset !== undefined && offset !== null,
|
|
'missing offset');
|
|
|
|
assert.ok(offset + 3 < buffer.length,
|
|
'Trying to read beyond buffer length');
|
|
}
|
|
|
|
val = readUInt32(buffer, offset, isBigEndian, noAssert);
|
|
neg = val & 0x80000000;
|
|
if (!neg) {
|
|
return (val);
|
|
}
|
|
|
|
return (0xffffffff - val + 1) * -1;
|
|
}
|
|
|
|
Buffer.prototype.readInt32LE = function(offset, noAssert) {
|
|
return readInt32(this, offset, false, noAssert);
|
|
};
|
|
|
|
Buffer.prototype.readInt32BE = function(offset, noAssert) {
|
|
return readInt32(this, offset, true, noAssert);
|
|
};
|
|
|
|
function readFloat(buffer, offset, isBigEndian, noAssert) {
|
|
if (!noAssert) {
|
|
assert.ok(typeof (isBigEndian) === 'boolean',
|
|
'missing or invalid endian');
|
|
|
|
assert.ok(offset + 3 < buffer.length,
|
|
'Trying to read beyond buffer length');
|
|
}
|
|
|
|
return require('./buffer_ieee754').readIEEE754(buffer, offset, isBigEndian,
|
|
23, 4);
|
|
}
|
|
|
|
Buffer.prototype.readFloatLE = function(offset, noAssert) {
|
|
return readFloat(this, offset, false, noAssert);
|
|
};
|
|
|
|
Buffer.prototype.readFloatBE = function(offset, noAssert) {
|
|
return readFloat(this, offset, true, noAssert);
|
|
};
|
|
|
|
function readDouble(buffer, offset, isBigEndian, noAssert) {
|
|
if (!noAssert) {
|
|
assert.ok(typeof (isBigEndian) === 'boolean',
|
|
'missing or invalid endian');
|
|
|
|
assert.ok(offset + 7 < buffer.length,
|
|
'Trying to read beyond buffer length');
|
|
}
|
|
|
|
return require('./buffer_ieee754').readIEEE754(buffer, offset, isBigEndian,
|
|
52, 8);
|
|
}
|
|
|
|
Buffer.prototype.readDoubleLE = function(offset, noAssert) {
|
|
return readDouble(this, offset, false, noAssert);
|
|
};
|
|
|
|
Buffer.prototype.readDoubleBE = function(offset, noAssert) {
|
|
return readDouble(this, offset, true, noAssert);
|
|
};
|
|
|
|
|
|
/*
|
|
* We have to make sure that the value is a valid integer. This means that it is
|
|
* non-negative. It has no fractional component and that it does not exceed the
|
|
* maximum allowed value.
|
|
*
|
|
* value The number to check for validity
|
|
*
|
|
* max The maximum value
|
|
*/
|
|
function verifuint(value, max) {
|
|
assert.ok(typeof (value) == 'number',
|
|
'cannot write a non-number as a number');
|
|
|
|
assert.ok(value >= 0,
|
|
'specified a negative value for writing an unsigned value');
|
|
|
|
assert.ok(value <= max, 'value is larger than maximum value for type');
|
|
|
|
assert.ok(Math.floor(value) === value, 'value has a fractional component');
|
|
}
|
|
|
|
Buffer.prototype.writeUInt8 = function(value, offset, noAssert) {
|
|
var buffer = this;
|
|
|
|
if (!noAssert) {
|
|
assert.ok(value !== undefined && value !== null,
|
|
'missing value');
|
|
|
|
assert.ok(offset !== undefined && offset !== null,
|
|
'missing offset');
|
|
|
|
assert.ok(offset < buffer.length,
|
|
'trying to write beyond buffer length');
|
|
|
|
verifuint(value, 0xff);
|
|
}
|
|
|
|
if (offset < buffer.length) {
|
|
buffer.parent[buffer.offset + offset] = value;
|
|
}
|
|
};
|
|
|
|
function writeUInt16(buffer, value, offset, isBigEndian, noAssert) {
|
|
if (!noAssert) {
|
|
assert.ok(value !== undefined && value !== null,
|
|
'missing value');
|
|
|
|
assert.ok(typeof (isBigEndian) === 'boolean',
|
|
'missing or invalid endian');
|
|
|
|
assert.ok(offset !== undefined && offset !== null,
|
|
'missing offset');
|
|
|
|
assert.ok(offset + 1 < buffer.length,
|
|
'trying to write beyond buffer length');
|
|
|
|
verifuint(value, 0xffff);
|
|
}
|
|
|
|
for (var i = 0; i < Math.min(buffer.length - offset, 2); i++) {
|
|
buffer.parent[buffer.offset + offset + i] =
|
|
(value & (0xff << (8 * (isBigEndian ? 1 - i : i)))) >>>
|
|
(isBigEndian ? 1 - i : i) * 8;
|
|
}
|
|
|
|
}
|
|
|
|
Buffer.prototype.writeUInt16LE = function(value, offset, noAssert) {
|
|
writeUInt16(this, value, offset, false, noAssert);
|
|
};
|
|
|
|
Buffer.prototype.writeUInt16BE = function(value, offset, noAssert) {
|
|
writeUInt16(this, value, offset, true, noAssert);
|
|
};
|
|
|
|
function writeUInt32(buffer, value, offset, isBigEndian, noAssert) {
|
|
if (!noAssert) {
|
|
assert.ok(value !== undefined && value !== null,
|
|
'missing value');
|
|
|
|
assert.ok(typeof (isBigEndian) === 'boolean',
|
|
'missing or invalid endian');
|
|
|
|
assert.ok(offset !== undefined && offset !== null,
|
|
'missing offset');
|
|
|
|
assert.ok(offset + 3 < buffer.length,
|
|
'trying to write beyond buffer length');
|
|
|
|
verifuint(value, 0xffffffff);
|
|
}
|
|
|
|
for (var i = 0; i < Math.min(buffer.length - offset, 4); i++) {
|
|
buffer.parent[buffer.offset + offset + i] =
|
|
(value >>> (isBigEndian ? 3 - i : i) * 8) & 0xff;
|
|
}
|
|
}
|
|
|
|
Buffer.prototype.writeUInt32LE = function(value, offset, noAssert) {
|
|
writeUInt32(this, value, offset, false, noAssert);
|
|
};
|
|
|
|
Buffer.prototype.writeUInt32BE = function(value, offset, noAssert) {
|
|
writeUInt32(this, value, offset, true, noAssert);
|
|
};
|
|
|
|
|
|
/*
|
|
* We now move onto our friends in the signed number category. Unlike unsigned
|
|
* numbers, we're going to have to worry a bit more about how we put values into
|
|
* arrays. Since we are only worrying about signed 32-bit values, we're in
|
|
* slightly better shape. Unfortunately, we really can't do our favorite binary
|
|
* & in this system. It really seems to do the wrong thing. For example:
|
|
*
|
|
* > -32 & 0xff
|
|
* 224
|
|
*
|
|
* What's happening above is really: 0xe0 & 0xff = 0xe0. However, the results of
|
|
* this aren't treated as a signed number. Ultimately a bad thing.
|
|
*
|
|
* What we're going to want to do is basically create the unsigned equivalent of
|
|
* our representation and pass that off to the wuint* functions. To do that
|
|
* we're going to do the following:
|
|
*
|
|
* - if the value is positive
|
|
* we can pass it directly off to the equivalent wuint
|
|
* - if the value is negative
|
|
* we do the following computation:
|
|
* mb + val + 1, where
|
|
* mb is the maximum unsigned value in that byte size
|
|
* val is the Javascript negative integer
|
|
*
|
|
*
|
|
* As a concrete value, take -128. In signed 16 bits this would be 0xff80. If
|
|
* you do out the computations:
|
|
*
|
|
* 0xffff - 128 + 1
|
|
* 0xffff - 127
|
|
* 0xff80
|
|
*
|
|
* You can then encode this value as the signed version. This is really rather
|
|
* hacky, but it should work and get the job done which is our goal here.
|
|
*/
|
|
|
|
/*
|
|
* A series of checks to make sure we actually have a signed 32-bit number
|
|
*/
|
|
function verifsint(value, max, min) {
|
|
assert.ok(typeof (value) == 'number',
|
|
'cannot write a non-number as a number');
|
|
|
|
assert.ok(value <= max, 'value larger than maximum allowed value');
|
|
|
|
assert.ok(value >= min, 'value smaller than minimum allowed value');
|
|
|
|
assert.ok(Math.floor(value) === value, 'value has a fractional component');
|
|
}
|
|
|
|
function verifIEEE754(value, max, min) {
|
|
assert.ok(typeof (value) == 'number',
|
|
'cannot write a non-number as a number');
|
|
|
|
assert.ok(value <= max, 'value larger than maximum allowed value');
|
|
|
|
assert.ok(value >= min, 'value smaller than minimum allowed value');
|
|
}
|
|
|
|
Buffer.prototype.writeInt8 = function(value, offset, noAssert) {
|
|
var buffer = this;
|
|
|
|
if (!noAssert) {
|
|
assert.ok(value !== undefined && value !== null,
|
|
'missing value');
|
|
|
|
assert.ok(offset !== undefined && offset !== null,
|
|
'missing offset');
|
|
|
|
assert.ok(offset < buffer.length,
|
|
'Trying to write beyond buffer length');
|
|
|
|
verifsint(value, 0x7f, -0x80);
|
|
}
|
|
|
|
if (value >= 0) {
|
|
buffer.writeUInt8(value, offset, noAssert);
|
|
} else {
|
|
buffer.writeUInt8(0xff + value + 1, offset, noAssert);
|
|
}
|
|
};
|
|
|
|
function writeInt16(buffer, value, offset, isBigEndian, noAssert) {
|
|
if (!noAssert) {
|
|
assert.ok(value !== undefined && value !== null,
|
|
'missing value');
|
|
|
|
assert.ok(typeof (isBigEndian) === 'boolean',
|
|
'missing or invalid endian');
|
|
|
|
assert.ok(offset !== undefined && offset !== null,
|
|
'missing offset');
|
|
|
|
assert.ok(offset + 1 < buffer.length,
|
|
'Trying to write beyond buffer length');
|
|
|
|
verifsint(value, 0x7fff, -0x8000);
|
|
}
|
|
|
|
if (value >= 0) {
|
|
writeUInt16(buffer, value, offset, isBigEndian, noAssert);
|
|
} else {
|
|
writeUInt16(buffer, 0xffff + value + 1, offset, isBigEndian, noAssert);
|
|
}
|
|
}
|
|
|
|
Buffer.prototype.writeInt16LE = function(value, offset, noAssert) {
|
|
writeInt16(this, value, offset, false, noAssert);
|
|
};
|
|
|
|
Buffer.prototype.writeInt16BE = function(value, offset, noAssert) {
|
|
writeInt16(this, value, offset, true, noAssert);
|
|
};
|
|
|
|
function writeInt32(buffer, value, offset, isBigEndian, noAssert) {
|
|
if (!noAssert) {
|
|
assert.ok(value !== undefined && value !== null,
|
|
'missing value');
|
|
|
|
assert.ok(typeof (isBigEndian) === 'boolean',
|
|
'missing or invalid endian');
|
|
|
|
assert.ok(offset !== undefined && offset !== null,
|
|
'missing offset');
|
|
|
|
assert.ok(offset + 3 < buffer.length,
|
|
'Trying to write beyond buffer length');
|
|
|
|
verifsint(value, 0x7fffffff, -0x80000000);
|
|
}
|
|
|
|
if (value >= 0) {
|
|
writeUInt32(buffer, value, offset, isBigEndian, noAssert);
|
|
} else {
|
|
writeUInt32(buffer, 0xffffffff + value + 1, offset, isBigEndian, noAssert);
|
|
}
|
|
}
|
|
|
|
Buffer.prototype.writeInt32LE = function(value, offset, noAssert) {
|
|
writeInt32(this, value, offset, false, noAssert);
|
|
};
|
|
|
|
Buffer.prototype.writeInt32BE = function(value, offset, noAssert) {
|
|
writeInt32(this, value, offset, true, noAssert);
|
|
};
|
|
|
|
function writeFloat(buffer, value, offset, isBigEndian, noAssert) {
|
|
if (!noAssert) {
|
|
assert.ok(value !== undefined && value !== null,
|
|
'missing value');
|
|
|
|
assert.ok(typeof (isBigEndian) === 'boolean',
|
|
'missing or invalid endian');
|
|
|
|
assert.ok(offset !== undefined && offset !== null,
|
|
'missing offset');
|
|
|
|
assert.ok(offset + 3 < buffer.length,
|
|
'Trying to write beyond buffer length');
|
|
|
|
verifIEEE754(value, 3.4028234663852886e+38, -3.4028234663852886e+38);
|
|
}
|
|
|
|
require('./buffer_ieee754').writeIEEE754(buffer, value, offset, isBigEndian,
|
|
23, 4);
|
|
}
|
|
|
|
Buffer.prototype.writeFloatLE = function(value, offset, noAssert) {
|
|
writeFloat(this, value, offset, false, noAssert);
|
|
};
|
|
|
|
Buffer.prototype.writeFloatBE = function(value, offset, noAssert) {
|
|
writeFloat(this, value, offset, true, noAssert);
|
|
};
|
|
|
|
function writeDouble(buffer, value, offset, isBigEndian, noAssert) {
|
|
if (!noAssert) {
|
|
assert.ok(value !== undefined && value !== null,
|
|
'missing value');
|
|
|
|
assert.ok(typeof (isBigEndian) === 'boolean',
|
|
'missing or invalid endian');
|
|
|
|
assert.ok(offset !== undefined && offset !== null,
|
|
'missing offset');
|
|
|
|
assert.ok(offset + 7 < buffer.length,
|
|
'Trying to write beyond buffer length');
|
|
|
|
verifIEEE754(value, 1.7976931348623157E+308, -1.7976931348623157E+308);
|
|
}
|
|
|
|
require('./buffer_ieee754').writeIEEE754(buffer, value, offset, isBigEndian,
|
|
52, 8);
|
|
}
|
|
|
|
Buffer.prototype.writeDoubleLE = function(value, offset, noAssert) {
|
|
writeDouble(this, value, offset, false, noAssert);
|
|
};
|
|
|
|
Buffer.prototype.writeDoubleBE = function(value, offset, noAssert) {
|
|
writeDouble(this, value, offset, true, noAssert);
|
|
};
|
|
|
|
SlowBuffer.prototype.readUInt8 = Buffer.prototype.readUInt8;
|
|
SlowBuffer.prototype.readUInt16LE = Buffer.prototype.readUInt16LE;
|
|
SlowBuffer.prototype.readUInt16BE = Buffer.prototype.readUInt16BE;
|
|
SlowBuffer.prototype.readUInt32LE = Buffer.prototype.readUInt32LE;
|
|
SlowBuffer.prototype.readUInt32BE = Buffer.prototype.readUInt32BE;
|
|
SlowBuffer.prototype.readInt8 = Buffer.prototype.readInt8;
|
|
SlowBuffer.prototype.readInt16LE = Buffer.prototype.readInt16LE;
|
|
SlowBuffer.prototype.readInt16BE = Buffer.prototype.readInt16BE;
|
|
SlowBuffer.prototype.readInt32LE = Buffer.prototype.readInt32LE;
|
|
SlowBuffer.prototype.readInt32BE = Buffer.prototype.readInt32BE;
|
|
SlowBuffer.prototype.readFloatLE = Buffer.prototype.readFloatLE;
|
|
SlowBuffer.prototype.readFloatBE = Buffer.prototype.readFloatBE;
|
|
SlowBuffer.prototype.readDoubleLE = Buffer.prototype.readDoubleLE;
|
|
SlowBuffer.prototype.readDoubleBE = Buffer.prototype.readDoubleBE;
|
|
SlowBuffer.prototype.writeUInt8 = Buffer.prototype.writeUInt8;
|
|
SlowBuffer.prototype.writeUInt16LE = Buffer.prototype.writeUInt16LE;
|
|
SlowBuffer.prototype.writeUInt16BE = Buffer.prototype.writeUInt16BE;
|
|
SlowBuffer.prototype.writeUInt32LE = Buffer.prototype.writeUInt32LE;
|
|
SlowBuffer.prototype.writeUInt32BE = Buffer.prototype.writeUInt32BE;
|
|
SlowBuffer.prototype.writeInt8 = Buffer.prototype.writeInt8;
|
|
SlowBuffer.prototype.writeInt16LE = Buffer.prototype.writeInt16LE;
|
|
SlowBuffer.prototype.writeInt16BE = Buffer.prototype.writeInt16BE;
|
|
SlowBuffer.prototype.writeInt32LE = Buffer.prototype.writeInt32LE;
|
|
SlowBuffer.prototype.writeInt32BE = Buffer.prototype.writeInt32BE;
|
|
SlowBuffer.prototype.writeFloatLE = Buffer.prototype.writeFloatLE;
|
|
SlowBuffer.prototype.writeFloatBE = Buffer.prototype.writeFloatBE;
|
|
SlowBuffer.prototype.writeDoubleLE = Buffer.prototype.writeDoubleLE;
|
|
SlowBuffer.prototype.writeDoubleBE = Buffer.prototype.writeDoubleBE;
|
|
|
|
},{"assert":1,"./buffer_ieee754":5,"base64-js":7}],7:[function(require,module,exports){
|
|
(function (exports) {
|
|
'use strict';
|
|
|
|
var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
|
|
|
function b64ToByteArray(b64) {
|
|
var i, j, l, tmp, placeHolders, arr;
|
|
|
|
if (b64.length % 4 > 0) {
|
|
throw 'Invalid string. Length must be a multiple of 4';
|
|
}
|
|
|
|
// the number of equal signs (place holders)
|
|
// if there are two placeholders, than the two characters before it
|
|
// represent one byte
|
|
// if there is only one, then the three characters before it represent 2 bytes
|
|
// this is just a cheap hack to not do indexOf twice
|
|
placeHolders = b64.indexOf('=');
|
|
placeHolders = placeHolders > 0 ? b64.length - placeHolders : 0;
|
|
|
|
// base64 is 4/3 + up to two characters of the original data
|
|
arr = [];//new Uint8Array(b64.length * 3 / 4 - placeHolders);
|
|
|
|
// if there are placeholders, only get up to the last complete 4 chars
|
|
l = placeHolders > 0 ? b64.length - 4 : b64.length;
|
|
|
|
for (i = 0, j = 0; i < l; i += 4, j += 3) {
|
|
tmp = (lookup.indexOf(b64[i]) << 18) | (lookup.indexOf(b64[i + 1]) << 12) | (lookup.indexOf(b64[i + 2]) << 6) | lookup.indexOf(b64[i + 3]);
|
|
arr.push((tmp & 0xFF0000) >> 16);
|
|
arr.push((tmp & 0xFF00) >> 8);
|
|
arr.push(tmp & 0xFF);
|
|
}
|
|
|
|
if (placeHolders === 2) {
|
|
tmp = (lookup.indexOf(b64[i]) << 2) | (lookup.indexOf(b64[i + 1]) >> 4);
|
|
arr.push(tmp & 0xFF);
|
|
} else if (placeHolders === 1) {
|
|
tmp = (lookup.indexOf(b64[i]) << 10) | (lookup.indexOf(b64[i + 1]) << 4) | (lookup.indexOf(b64[i + 2]) >> 2);
|
|
arr.push((tmp >> 8) & 0xFF);
|
|
arr.push(tmp & 0xFF);
|
|
}
|
|
|
|
return arr;
|
|
}
|
|
|
|
function uint8ToBase64(uint8) {
|
|
var i,
|
|
extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes
|
|
output = "",
|
|
temp, length;
|
|
|
|
function tripletToBase64 (num) {
|
|
return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F];
|
|
};
|
|
|
|
// go through the array every three bytes, we'll deal with trailing stuff later
|
|
for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) {
|
|
temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]);
|
|
output += tripletToBase64(temp);
|
|
}
|
|
|
|
// pad the end with zeros, but make sure to not forget the extra bytes
|
|
switch (extraBytes) {
|
|
case 1:
|
|
temp = uint8[uint8.length - 1];
|
|
output += lookup[temp >> 2];
|
|
output += lookup[(temp << 4) & 0x3F];
|
|
output += '==';
|
|
break;
|
|
case 2:
|
|
temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1]);
|
|
output += lookup[temp >> 10];
|
|
output += lookup[(temp >> 4) & 0x3F];
|
|
output += lookup[(temp << 2) & 0x3F];
|
|
output += '=';
|
|
break;
|
|
}
|
|
|
|
return output;
|
|
}
|
|
|
|
module.exports.toByteArray = b64ToByteArray;
|
|
module.exports.fromByteArray = uint8ToBase64;
|
|
}());
|
|
|
|
},{}],8:[function(require,module,exports){
|
|
exports.readIEEE754 = function(buffer, offset, isBE, mLen, nBytes) {
|
|
var e, m,
|
|
eLen = nBytes * 8 - mLen - 1,
|
|
eMax = (1 << eLen) - 1,
|
|
eBias = eMax >> 1,
|
|
nBits = -7,
|
|
i = isBE ? 0 : (nBytes - 1),
|
|
d = isBE ? 1 : -1,
|
|
s = buffer[offset + i];
|
|
|
|
i += d;
|
|
|
|
e = s & ((1 << (-nBits)) - 1);
|
|
s >>= (-nBits);
|
|
nBits += eLen;
|
|
for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8);
|
|
|
|
m = e & ((1 << (-nBits)) - 1);
|
|
e >>= (-nBits);
|
|
nBits += mLen;
|
|
for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8);
|
|
|
|
if (e === 0) {
|
|
e = 1 - eBias;
|
|
} else if (e === eMax) {
|
|
return m ? NaN : ((s ? -1 : 1) * Infinity);
|
|
} else {
|
|
m = m + Math.pow(2, mLen);
|
|
e = e - eBias;
|
|
}
|
|
return (s ? -1 : 1) * m * Math.pow(2, e - mLen);
|
|
};
|
|
|
|
exports.writeIEEE754 = function(buffer, value, offset, isBE, mLen, nBytes) {
|
|
var e, m, c,
|
|
eLen = nBytes * 8 - mLen - 1,
|
|
eMax = (1 << eLen) - 1,
|
|
eBias = eMax >> 1,
|
|
rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0),
|
|
i = isBE ? (nBytes - 1) : 0,
|
|
d = isBE ? -1 : 1,
|
|
s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0;
|
|
|
|
value = Math.abs(value);
|
|
|
|
if (isNaN(value) || value === Infinity) {
|
|
m = isNaN(value) ? 1 : 0;
|
|
e = eMax;
|
|
} else {
|
|
e = Math.floor(Math.log(value) / Math.LN2);
|
|
if (value * (c = Math.pow(2, -e)) < 1) {
|
|
e--;
|
|
c *= 2;
|
|
}
|
|
if (e + eBias >= 1) {
|
|
value += rt / c;
|
|
} else {
|
|
value += rt * Math.pow(2, 1 - eBias);
|
|
}
|
|
if (value * c >= 2) {
|
|
e++;
|
|
c /= 2;
|
|
}
|
|
|
|
if (e + eBias >= eMax) {
|
|
m = 0;
|
|
e = eMax;
|
|
} else if (e + eBias >= 1) {
|
|
m = (value * c - 1) * Math.pow(2, mLen);
|
|
e = e + eBias;
|
|
} else {
|
|
m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen);
|
|
e = 0;
|
|
}
|
|
}
|
|
|
|
for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8);
|
|
|
|
e = (e << mLen) | m;
|
|
eLen += mLen;
|
|
for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8);
|
|
|
|
buffer[offset + i - d] |= s * 128;
|
|
};
|
|
|
|
},{}],3:[function(require,module,exports){
|
|
function SlowBuffer (size) {
|
|
this.length = size;
|
|
};
|
|
|
|
var assert = require('assert');
|
|
|
|
exports.INSPECT_MAX_BYTES = 50;
|
|
|
|
|
|
function toHex(n) {
|
|
if (n < 16) return '0' + n.toString(16);
|
|
return n.toString(16);
|
|
}
|
|
|
|
function utf8ToBytes(str) {
|
|
var byteArray = [];
|
|
for (var i = 0; i < str.length; i++)
|
|
if (str.charCodeAt(i) <= 0x7F)
|
|
byteArray.push(str.charCodeAt(i));
|
|
else {
|
|
var h = encodeURIComponent(str.charAt(i)).substr(1).split('%');
|
|
for (var j = 0; j < h.length; j++)
|
|
byteArray.push(parseInt(h[j], 16));
|
|
}
|
|
|
|
return byteArray;
|
|
}
|
|
|
|
function asciiToBytes(str) {
|
|
var byteArray = []
|
|
for (var i = 0; i < str.length; i++ )
|
|
// Node's code seems to be doing this and not & 0x7F..
|
|
byteArray.push( str.charCodeAt(i) & 0xFF );
|
|
|
|
return byteArray;
|
|
}
|
|
|
|
function base64ToBytes(str) {
|
|
return require("base64-js").toByteArray(str);
|
|
}
|
|
|
|
SlowBuffer.byteLength = function (str, encoding) {
|
|
switch (encoding || "utf8") {
|
|
case 'hex':
|
|
return str.length / 2;
|
|
|
|
case 'utf8':
|
|
case 'utf-8':
|
|
return utf8ToBytes(str).length;
|
|
|
|
case 'ascii':
|
|
return str.length;
|
|
|
|
case 'base64':
|
|
return base64ToBytes(str).length;
|
|
|
|
default:
|
|
throw new Error('Unknown encoding');
|
|
}
|
|
};
|
|
|
|
function blitBuffer(src, dst, offset, length) {
|
|
var pos, i = 0;
|
|
while (i < length) {
|
|
if ((i+offset >= dst.length) || (i >= src.length))
|
|
break;
|
|
|
|
dst[i + offset] = src[i];
|
|
i++;
|
|
}
|
|
return i;
|
|
}
|
|
|
|
SlowBuffer.prototype.utf8Write = function (string, offset, length) {
|
|
var bytes, pos;
|
|
return SlowBuffer._charsWritten = blitBuffer(utf8ToBytes(string), this, offset, length);
|
|
};
|
|
|
|
SlowBuffer.prototype.asciiWrite = function (string, offset, length) {
|
|
var bytes, pos;
|
|
return SlowBuffer._charsWritten = blitBuffer(asciiToBytes(string), this, offset, length);
|
|
};
|
|
|
|
SlowBuffer.prototype.base64Write = function (string, offset, length) {
|
|
var bytes, pos;
|
|
return SlowBuffer._charsWritten = blitBuffer(base64ToBytes(string), this, offset, length);
|
|
};
|
|
|
|
SlowBuffer.prototype.base64Slice = function (start, end) {
|
|
var bytes = Array.prototype.slice.apply(this, arguments)
|
|
return require("base64-js").fromByteArray(bytes);
|
|
}
|
|
|
|
function decodeUtf8Char(str) {
|
|
try {
|
|
return decodeURIComponent(str);
|
|
} catch (err) {
|
|
return String.fromCharCode(0xFFFD); // UTF 8 invalid char
|
|
}
|
|
}
|
|
|
|
SlowBuffer.prototype.utf8Slice = function () {
|
|
var bytes = Array.prototype.slice.apply(this, arguments);
|
|
var res = "";
|
|
var tmp = "";
|
|
var i = 0;
|
|
while (i < bytes.length) {
|
|
if (bytes[i] <= 0x7F) {
|
|
res += decodeUtf8Char(tmp) + String.fromCharCode(bytes[i]);
|
|
tmp = "";
|
|
} else
|
|
tmp += "%" + bytes[i].toString(16);
|
|
|
|
i++;
|
|
}
|
|
|
|
return res + decodeUtf8Char(tmp);
|
|
}
|
|
|
|
SlowBuffer.prototype.asciiSlice = function () {
|
|
var bytes = Array.prototype.slice.apply(this, arguments);
|
|
var ret = "";
|
|
for (var i = 0; i < bytes.length; i++)
|
|
ret += String.fromCharCode(bytes[i]);
|
|
return ret;
|
|
}
|
|
|
|
SlowBuffer.prototype.inspect = function() {
|
|
var out = [],
|
|
len = this.length;
|
|
for (var i = 0; i < len; i++) {
|
|
out[i] = toHex(this[i]);
|
|
if (i == exports.INSPECT_MAX_BYTES) {
|
|
out[i + 1] = '...';
|
|
break;
|
|
}
|
|
}
|
|
return '<SlowBuffer ' + out.join(' ') + '>';
|
|
};
|
|
|
|
|
|
SlowBuffer.prototype.hexSlice = function(start, end) {
|
|
var len = this.length;
|
|
|
|
if (!start || start < 0) start = 0;
|
|
if (!end || end < 0 || end > len) end = len;
|
|
|
|
var out = '';
|
|
for (var i = start; i < end; i++) {
|
|
out += toHex(this[i]);
|
|
}
|
|
return out;
|
|
};
|
|
|
|
|
|
SlowBuffer.prototype.toString = function(encoding, start, end) {
|
|
encoding = String(encoding || 'utf8').toLowerCase();
|
|
start = +start || 0;
|
|
if (typeof end == 'undefined') end = this.length;
|
|
|
|
// Fastpath empty strings
|
|
if (+end == start) {
|
|
return '';
|
|
}
|
|
|
|
switch (encoding) {
|
|
case 'hex':
|
|
return this.hexSlice(start, end);
|
|
|
|
case 'utf8':
|
|
case 'utf-8':
|
|
return this.utf8Slice(start, end);
|
|
|
|
case 'ascii':
|
|
return this.asciiSlice(start, end);
|
|
|
|
case 'binary':
|
|
return this.binarySlice(start, end);
|
|
|
|
case 'base64':
|
|
return this.base64Slice(start, end);
|
|
|
|
case 'ucs2':
|
|
case 'ucs-2':
|
|
return this.ucs2Slice(start, end);
|
|
|
|
default:
|
|
throw new Error('Unknown encoding');
|
|
}
|
|
};
|
|
|
|
|
|
SlowBuffer.prototype.hexWrite = function(string, offset, length) {
|
|
offset = +offset || 0;
|
|
var remaining = this.length - offset;
|
|
if (!length) {
|
|
length = remaining;
|
|
} else {
|
|
length = +length;
|
|
if (length > remaining) {
|
|
length = remaining;
|
|
}
|
|
}
|
|
|
|
// must be an even number of digits
|
|
var strLen = string.length;
|
|
if (strLen % 2) {
|
|
throw new Error('Invalid hex string');
|
|
}
|
|
if (length > strLen / 2) {
|
|
length = strLen / 2;
|
|
}
|
|
for (var i = 0; i < length; i++) {
|
|
var byte = parseInt(string.substr(i * 2, 2), 16);
|
|
if (isNaN(byte)) throw new Error('Invalid hex string');
|
|
this[offset + i] = byte;
|
|
}
|
|
SlowBuffer._charsWritten = i * 2;
|
|
return i;
|
|
};
|
|
|
|
|
|
SlowBuffer.prototype.write = function(string, offset, length, encoding) {
|
|
// Support both (string, offset, length, encoding)
|
|
// and the legacy (string, encoding, offset, length)
|
|
if (isFinite(offset)) {
|
|
if (!isFinite(length)) {
|
|
encoding = length;
|
|
length = undefined;
|
|
}
|
|
} else { // legacy
|
|
var swap = encoding;
|
|
encoding = offset;
|
|
offset = length;
|
|
length = swap;
|
|
}
|
|
|
|
offset = +offset || 0;
|
|
var remaining = this.length - offset;
|
|
if (!length) {
|
|
length = remaining;
|
|
} else {
|
|
length = +length;
|
|
if (length > remaining) {
|
|
length = remaining;
|
|
}
|
|
}
|
|
encoding = String(encoding || 'utf8').toLowerCase();
|
|
|
|
switch (encoding) {
|
|
case 'hex':
|
|
return this.hexWrite(string, offset, length);
|
|
|
|
case 'utf8':
|
|
case 'utf-8':
|
|
return this.utf8Write(string, offset, length);
|
|
|
|
case 'ascii':
|
|
return this.asciiWrite(string, offset, length);
|
|
|
|
case 'binary':
|
|
return this.binaryWrite(string, offset, length);
|
|
|
|
case 'base64':
|
|
return this.base64Write(string, offset, length);
|
|
|
|
case 'ucs2':
|
|
case 'ucs-2':
|
|
return this.ucs2Write(string, offset, length);
|
|
|
|
default:
|
|
throw new Error('Unknown encoding');
|
|
}
|
|
};
|
|
|
|
|
|
// slice(start, end)
|
|
SlowBuffer.prototype.slice = function(start, end) {
|
|
if (end === undefined) end = this.length;
|
|
|
|
if (end > this.length) {
|
|
throw new Error('oob');
|
|
}
|
|
if (start > end) {
|
|
throw new Error('oob');
|
|
}
|
|
|
|
return new Buffer(this, end - start, +start);
|
|
};
|
|
|
|
SlowBuffer.prototype.copy = function(target, targetstart, sourcestart, sourceend) {
|
|
var temp = [];
|
|
for (var i=sourcestart; i<sourceend; i++) {
|
|
assert.ok(typeof this[i] !== 'undefined', "copying undefined buffer bytes!");
|
|
temp.push(this[i]);
|
|
}
|
|
|
|
for (var i=targetstart; i<targetstart+temp.length; i++) {
|
|
target[i] = temp[i-targetstart];
|
|
}
|
|
};
|
|
|
|
function coerce(length) {
|
|
// Coerce length to a number (possibly NaN), round up
|
|
// in case it's fractional (e.g. 123.456) then do a
|
|
// double negate to coerce a NaN to 0. Easy, right?
|
|
length = ~~Math.ceil(+length);
|
|
return length < 0 ? 0 : length;
|
|
}
|
|
|
|
|
|
// Buffer
|
|
|
|
function Buffer(subject, encoding, offset) {
|
|
if (!(this instanceof Buffer)) {
|
|
return new Buffer(subject, encoding, offset);
|
|
}
|
|
|
|
var type;
|
|
|
|
// Are we slicing?
|
|
if (typeof offset === 'number') {
|
|
this.length = coerce(encoding);
|
|
this.parent = subject;
|
|
this.offset = offset;
|
|
} else {
|
|
// Find the length
|
|
switch (type = typeof subject) {
|
|
case 'number':
|
|
this.length = coerce(subject);
|
|
break;
|
|
|
|
case 'string':
|
|
this.length = Buffer.byteLength(subject, encoding);
|
|
break;
|
|
|
|
case 'object': // Assume object is an array
|
|
this.length = coerce(subject.length);
|
|
break;
|
|
|
|
default:
|
|
throw new Error('First argument needs to be a number, ' +
|
|
'array or string.');
|
|
}
|
|
|
|
if (this.length > Buffer.poolSize) {
|
|
// Big buffer, just alloc one.
|
|
this.parent = new SlowBuffer(this.length);
|
|
this.offset = 0;
|
|
|
|
} else {
|
|
// Small buffer.
|
|
if (!pool || pool.length - pool.used < this.length) allocPool();
|
|
this.parent = pool;
|
|
this.offset = pool.used;
|
|
pool.used += this.length;
|
|
}
|
|
|
|
// Treat array-ish objects as a byte array.
|
|
if (isArrayIsh(subject)) {
|
|
for (var i = 0; i < this.length; i++) {
|
|
this.parent[i + this.offset] = subject[i];
|
|
}
|
|
} else if (type == 'string') {
|
|
// We are a string
|
|
this.length = this.write(subject, 0, encoding);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
function isArrayIsh(subject) {
|
|
return Array.isArray(subject) || Buffer.isBuffer(subject) ||
|
|
subject && typeof subject === 'object' &&
|
|
typeof subject.length === 'number';
|
|
}
|
|
|
|
exports.SlowBuffer = SlowBuffer;
|
|
exports.Buffer = Buffer;
|
|
|
|
Buffer.poolSize = 8 * 1024;
|
|
var pool;
|
|
|
|
function allocPool() {
|
|
pool = new SlowBuffer(Buffer.poolSize);
|
|
pool.used = 0;
|
|
}
|
|
|
|
|
|
// Static methods
|
|
Buffer.isBuffer = function isBuffer(b) {
|
|
return b instanceof Buffer || b instanceof SlowBuffer;
|
|
};
|
|
|
|
Buffer.concat = function (list, totalLength) {
|
|
if (!Array.isArray(list)) {
|
|
throw new Error("Usage: Buffer.concat(list, [totalLength])\n \
|
|
list should be an Array.");
|
|
}
|
|
|
|
if (list.length === 0) {
|
|
return new Buffer(0);
|
|
} else if (list.length === 1) {
|
|
return list[0];
|
|
}
|
|
|
|
if (typeof totalLength !== 'number') {
|
|
totalLength = 0;
|
|
for (var i = 0; i < list.length; i++) {
|
|
var buf = list[i];
|
|
totalLength += buf.length;
|
|
}
|
|
}
|
|
|
|
var buffer = new Buffer(totalLength);
|
|
var pos = 0;
|
|
for (var i = 0; i < list.length; i++) {
|
|
var buf = list[i];
|
|
buf.copy(buffer, pos);
|
|
pos += buf.length;
|
|
}
|
|
return buffer;
|
|
};
|
|
|
|
// Inspect
|
|
Buffer.prototype.inspect = function inspect() {
|
|
var out = [],
|
|
len = this.length;
|
|
|
|
for (var i = 0; i < len; i++) {
|
|
out[i] = toHex(this.parent[i + this.offset]);
|
|
if (i == exports.INSPECT_MAX_BYTES) {
|
|
out[i + 1] = '...';
|
|
break;
|
|
}
|
|
}
|
|
|
|
return '<Buffer ' + out.join(' ') + '>';
|
|
};
|
|
|
|
|
|
Buffer.prototype.get = function get(i) {
|
|
if (i < 0 || i >= this.length) throw new Error('oob');
|
|
return this.parent[this.offset + i];
|
|
};
|
|
|
|
|
|
Buffer.prototype.set = function set(i, v) {
|
|
if (i < 0 || i >= this.length) throw new Error('oob');
|
|
return this.parent[this.offset + i] = v;
|
|
};
|
|
|
|
|
|
// write(string, offset = 0, length = buffer.length-offset, encoding = 'utf8')
|
|
Buffer.prototype.write = function(string, offset, length, encoding) {
|
|
// Support both (string, offset, length, encoding)
|
|
// and the legacy (string, encoding, offset, length)
|
|
if (isFinite(offset)) {
|
|
if (!isFinite(length)) {
|
|
encoding = length;
|
|
length = undefined;
|
|
}
|
|
} else { // legacy
|
|
var swap = encoding;
|
|
encoding = offset;
|
|
offset = length;
|
|
length = swap;
|
|
}
|
|
|
|
offset = +offset || 0;
|
|
var remaining = this.length - offset;
|
|
if (!length) {
|
|
length = remaining;
|
|
} else {
|
|
length = +length;
|
|
if (length > remaining) {
|
|
length = remaining;
|
|
}
|
|
}
|
|
encoding = String(encoding || 'utf8').toLowerCase();
|
|
|
|
var ret;
|
|
switch (encoding) {
|
|
case 'hex':
|
|
ret = this.parent.hexWrite(string, this.offset + offset, length);
|
|
break;
|
|
|
|
case 'utf8':
|
|
case 'utf-8':
|
|
ret = this.parent.utf8Write(string, this.offset + offset, length);
|
|
break;
|
|
|
|
case 'ascii':
|
|
ret = this.parent.asciiWrite(string, this.offset + offset, length);
|
|
break;
|
|
|
|
case 'binary':
|
|
ret = this.parent.binaryWrite(string, this.offset + offset, length);
|
|
break;
|
|
|
|
case 'base64':
|
|
// Warning: maxLength not taken into account in base64Write
|
|
ret = this.parent.base64Write(string, this.offset + offset, length);
|
|
break;
|
|
|
|
case 'ucs2':
|
|
case 'ucs-2':
|
|
ret = this.parent.ucs2Write(string, this.offset + offset, length);
|
|
break;
|
|
|
|
default:
|
|
throw new Error('Unknown encoding');
|
|
}
|
|
|
|
Buffer._charsWritten = SlowBuffer._charsWritten;
|
|
|
|
return ret;
|
|
};
|
|
|
|
|
|
// toString(encoding, start=0, end=buffer.length)
|
|
Buffer.prototype.toString = function(encoding, start, end) {
|
|
encoding = String(encoding || 'utf8').toLowerCase();
|
|
|
|
if (typeof start == 'undefined' || start < 0) {
|
|
start = 0;
|
|
} else if (start > this.length) {
|
|
start = this.length;
|
|
}
|
|
|
|
if (typeof end == 'undefined' || end > this.length) {
|
|
end = this.length;
|
|
} else if (end < 0) {
|
|
end = 0;
|
|
}
|
|
|
|
start = start + this.offset;
|
|
end = end + this.offset;
|
|
|
|
switch (encoding) {
|
|
case 'hex':
|
|
return this.parent.hexSlice(start, end);
|
|
|
|
case 'utf8':
|
|
case 'utf-8':
|
|
return this.parent.utf8Slice(start, end);
|
|
|
|
case 'ascii':
|
|
return this.parent.asciiSlice(start, end);
|
|
|
|
case 'binary':
|
|
return this.parent.binarySlice(start, end);
|
|
|
|
case 'base64':
|
|
return this.parent.base64Slice(start, end);
|
|
|
|
case 'ucs2':
|
|
case 'ucs-2':
|
|
return this.parent.ucs2Slice(start, end);
|
|
|
|
default:
|
|
throw new Error('Unknown encoding');
|
|
}
|
|
};
|
|
|
|
|
|
// byteLength
|
|
Buffer.byteLength = SlowBuffer.byteLength;
|
|
|
|
|
|
// fill(value, start=0, end=buffer.length)
|
|
Buffer.prototype.fill = function fill(value, start, end) {
|
|
value || (value = 0);
|
|
start || (start = 0);
|
|
end || (end = this.length);
|
|
|
|
if (typeof value === 'string') {
|
|
value = value.charCodeAt(0);
|
|
}
|
|
if (!(typeof value === 'number') || isNaN(value)) {
|
|
throw new Error('value is not a number');
|
|
}
|
|
|
|
if (end < start) throw new Error('end < start');
|
|
|
|
// Fill 0 bytes; we're done
|
|
if (end === start) return 0;
|
|
if (this.length == 0) return 0;
|
|
|
|
if (start < 0 || start >= this.length) {
|
|
throw new Error('start out of bounds');
|
|
}
|
|
|
|
if (end < 0 || end > this.length) {
|
|
throw new Error('end out of bounds');
|
|
}
|
|
|
|
return this.parent.fill(value,
|
|
start + this.offset,
|
|
end + this.offset);
|
|
};
|
|
|
|
|
|
// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
|
|
Buffer.prototype.copy = function(target, target_start, start, end) {
|
|
var source = this;
|
|
start || (start = 0);
|
|
end || (end = this.length);
|
|
target_start || (target_start = 0);
|
|
|
|
if (end < start) throw new Error('sourceEnd < sourceStart');
|
|
|
|
// Copy 0 bytes; we're done
|
|
if (end === start) return 0;
|
|
if (target.length == 0 || source.length == 0) return 0;
|
|
|
|
if (target_start < 0 || target_start >= target.length) {
|
|
throw new Error('targetStart out of bounds');
|
|
}
|
|
|
|
if (start < 0 || start >= source.length) {
|
|
throw new Error('sourceStart out of bounds');
|
|
}
|
|
|
|
if (end < 0 || end > source.length) {
|
|
throw new Error('sourceEnd out of bounds');
|
|
}
|
|
|
|
// Are we oob?
|
|
if (end > this.length) {
|
|
end = this.length;
|
|
}
|
|
|
|
if (target.length - target_start < end - start) {
|
|
end = target.length - target_start + start;
|
|
}
|
|
|
|
return this.parent.copy(target.parent,
|
|
target_start + target.offset,
|
|
start + this.offset,
|
|
end + this.offset);
|
|
};
|
|
|
|
|
|
// slice(start, end)
|
|
Buffer.prototype.slice = function(start, end) {
|
|
if (end === undefined) end = this.length;
|
|
if (end > this.length) throw new Error('oob');
|
|
if (start > end) throw new Error('oob');
|
|
|
|
return new Buffer(this.parent, end - start, +start + this.offset);
|
|
};
|
|
|
|
|
|
// Legacy methods for backwards compatibility.
|
|
|
|
Buffer.prototype.utf8Slice = function(start, end) {
|
|
return this.toString('utf8', start, end);
|
|
};
|
|
|
|
Buffer.prototype.binarySlice = function(start, end) {
|
|
return this.toString('binary', start, end);
|
|
};
|
|
|
|
Buffer.prototype.asciiSlice = function(start, end) {
|
|
return this.toString('ascii', start, end);
|
|
};
|
|
|
|
Buffer.prototype.utf8Write = function(string, offset) {
|
|
return this.write(string, offset, 'utf8');
|
|
};
|
|
|
|
Buffer.prototype.binaryWrite = function(string, offset) {
|
|
return this.write(string, offset, 'binary');
|
|
};
|
|
|
|
Buffer.prototype.asciiWrite = function(string, offset) {
|
|
return this.write(string, offset, 'ascii');
|
|
};
|
|
|
|
Buffer.prototype.readUInt8 = function(offset, noAssert) {
|
|
var buffer = this;
|
|
|
|
if (!noAssert) {
|
|
assert.ok(offset !== undefined && offset !== null,
|
|
'missing offset');
|
|
|
|
assert.ok(offset < buffer.length,
|
|
'Trying to read beyond buffer length');
|
|
}
|
|
|
|
return buffer.parent[buffer.offset + offset];
|
|
};
|
|
|
|
function readUInt16(buffer, offset, isBigEndian, noAssert) {
|
|
var val = 0;
|
|
|
|
|
|
if (!noAssert) {
|
|
assert.ok(typeof (isBigEndian) === 'boolean',
|
|
'missing or invalid endian');
|
|
|
|
assert.ok(offset !== undefined && offset !== null,
|
|
'missing offset');
|
|
|
|
assert.ok(offset + 1 < buffer.length,
|
|
'Trying to read beyond buffer length');
|
|
}
|
|
|
|
if (isBigEndian) {
|
|
val = buffer.parent[buffer.offset + offset] << 8;
|
|
val |= buffer.parent[buffer.offset + offset + 1];
|
|
} else {
|
|
val = buffer.parent[buffer.offset + offset];
|
|
val |= buffer.parent[buffer.offset + offset + 1] << 8;
|
|
}
|
|
|
|
return val;
|
|
}
|
|
|
|
Buffer.prototype.readUInt16LE = function(offset, noAssert) {
|
|
return readUInt16(this, offset, false, noAssert);
|
|
};
|
|
|
|
Buffer.prototype.readUInt16BE = function(offset, noAssert) {
|
|
return readUInt16(this, offset, true, noAssert);
|
|
};
|
|
|
|
function readUInt32(buffer, offset, isBigEndian, noAssert) {
|
|
var val = 0;
|
|
|
|
if (!noAssert) {
|
|
assert.ok(typeof (isBigEndian) === 'boolean',
|
|
'missing or invalid endian');
|
|
|
|
assert.ok(offset !== undefined && offset !== null,
|
|
'missing offset');
|
|
|
|
assert.ok(offset + 3 < buffer.length,
|
|
'Trying to read beyond buffer length');
|
|
}
|
|
|
|
if (isBigEndian) {
|
|
val = buffer.parent[buffer.offset + offset + 1] << 16;
|
|
val |= buffer.parent[buffer.offset + offset + 2] << 8;
|
|
val |= buffer.parent[buffer.offset + offset + 3];
|
|
val = val + (buffer.parent[buffer.offset + offset] << 24 >>> 0);
|
|
} else {
|
|
val = buffer.parent[buffer.offset + offset + 2] << 16;
|
|
val |= buffer.parent[buffer.offset + offset + 1] << 8;
|
|
val |= buffer.parent[buffer.offset + offset];
|
|
val = val + (buffer.parent[buffer.offset + offset + 3] << 24 >>> 0);
|
|
}
|
|
|
|
return val;
|
|
}
|
|
|
|
Buffer.prototype.readUInt32LE = function(offset, noAssert) {
|
|
return readUInt32(this, offset, false, noAssert);
|
|
};
|
|
|
|
Buffer.prototype.readUInt32BE = function(offset, noAssert) {
|
|
return readUInt32(this, offset, true, noAssert);
|
|
};
|
|
|
|
|
|
/*
|
|
* Signed integer types, yay team! A reminder on how two's complement actually
|
|
* works. The first bit is the signed bit, i.e. tells us whether or not the
|
|
* number should be positive or negative. If the two's complement value is
|
|
* positive, then we're done, as it's equivalent to the unsigned representation.
|
|
*
|
|
* Now if the number is positive, you're pretty much done, you can just leverage
|
|
* the unsigned translations and return those. Unfortunately, negative numbers
|
|
* aren't quite that straightforward.
|
|
*
|
|
* At first glance, one might be inclined to use the traditional formula to
|
|
* translate binary numbers between the positive and negative values in two's
|
|
* complement. (Though it doesn't quite work for the most negative value)
|
|
* Mainly:
|
|
* - invert all the bits
|
|
* - add one to the result
|
|
*
|
|
* Of course, this doesn't quite work in Javascript. Take for example the value
|
|
* of -128. This could be represented in 16 bits (big-endian) as 0xff80. But of
|
|
* course, Javascript will do the following:
|
|
*
|
|
* > ~0xff80
|
|
* -65409
|
|
*
|
|
* Whoh there, Javascript, that's not quite right. But wait, according to
|
|
* Javascript that's perfectly correct. When Javascript ends up seeing the
|
|
* constant 0xff80, it has no notion that it is actually a signed number. It
|
|
* assumes that we've input the unsigned value 0xff80. Thus, when it does the
|
|
* binary negation, it casts it into a signed value, (positive 0xff80). Then
|
|
* when you perform binary negation on that, it turns it into a negative number.
|
|
*
|
|
* Instead, we're going to have to use the following general formula, that works
|
|
* in a rather Javascript friendly way. I'm glad we don't support this kind of
|
|
* weird numbering scheme in the kernel.
|
|
*
|
|
* (BIT-MAX - (unsigned)val + 1) * -1
|
|
*
|
|
* The astute observer, may think that this doesn't make sense for 8-bit numbers
|
|
* (really it isn't necessary for them). However, when you get 16-bit numbers,
|
|
* you do. Let's go back to our prior example and see how this will look:
|
|
*
|
|
* (0xffff - 0xff80 + 1) * -1
|
|
* (0x007f + 1) * -1
|
|
* (0x0080) * -1
|
|
*/
|
|
Buffer.prototype.readInt8 = function(offset, noAssert) {
|
|
var buffer = this;
|
|
var neg;
|
|
|
|
if (!noAssert) {
|
|
assert.ok(offset !== undefined && offset !== null,
|
|
'missing offset');
|
|
|
|
assert.ok(offset < buffer.length,
|
|
'Trying to read beyond buffer length');
|
|
}
|
|
|
|
neg = buffer.parent[buffer.offset + offset] & 0x80;
|
|
if (!neg) {
|
|
return (buffer.parent[buffer.offset + offset]);
|
|
}
|
|
|
|
return ((0xff - buffer.parent[buffer.offset + offset] + 1) * -1);
|
|
};
|
|
|
|
function readInt16(buffer, offset, isBigEndian, noAssert) {
|
|
var neg, val;
|
|
|
|
if (!noAssert) {
|
|
assert.ok(typeof (isBigEndian) === 'boolean',
|
|
'missing or invalid endian');
|
|
|
|
assert.ok(offset !== undefined && offset !== null,
|
|
'missing offset');
|
|
|
|
assert.ok(offset + 1 < buffer.length,
|
|
'Trying to read beyond buffer length');
|
|
}
|
|
|
|
val = readUInt16(buffer, offset, isBigEndian, noAssert);
|
|
neg = val & 0x8000;
|
|
if (!neg) {
|
|
return val;
|
|
}
|
|
|
|
return (0xffff - val + 1) * -1;
|
|
}
|
|
|
|
Buffer.prototype.readInt16LE = function(offset, noAssert) {
|
|
return readInt16(this, offset, false, noAssert);
|
|
};
|
|
|
|
Buffer.prototype.readInt16BE = function(offset, noAssert) {
|
|
return readInt16(this, offset, true, noAssert);
|
|
};
|
|
|
|
function readInt32(buffer, offset, isBigEndian, noAssert) {
|
|
var neg, val;
|
|
|
|
if (!noAssert) {
|
|
assert.ok(typeof (isBigEndian) === 'boolean',
|
|
'missing or invalid endian');
|
|
|
|
assert.ok(offset !== undefined && offset !== null,
|
|
'missing offset');
|
|
|
|
assert.ok(offset + 3 < buffer.length,
|
|
'Trying to read beyond buffer length');
|
|
}
|
|
|
|
val = readUInt32(buffer, offset, isBigEndian, noAssert);
|
|
neg = val & 0x80000000;
|
|
if (!neg) {
|
|
return (val);
|
|
}
|
|
|
|
return (0xffffffff - val + 1) * -1;
|
|
}
|
|
|
|
Buffer.prototype.readInt32LE = function(offset, noAssert) {
|
|
return readInt32(this, offset, false, noAssert);
|
|
};
|
|
|
|
Buffer.prototype.readInt32BE = function(offset, noAssert) {
|
|
return readInt32(this, offset, true, noAssert);
|
|
};
|
|
|
|
function readFloat(buffer, offset, isBigEndian, noAssert) {
|
|
if (!noAssert) {
|
|
assert.ok(typeof (isBigEndian) === 'boolean',
|
|
'missing or invalid endian');
|
|
|
|
assert.ok(offset + 3 < buffer.length,
|
|
'Trying to read beyond buffer length');
|
|
}
|
|
|
|
return require('./buffer_ieee754').readIEEE754(buffer, offset, isBigEndian,
|
|
23, 4);
|
|
}
|
|
|
|
Buffer.prototype.readFloatLE = function(offset, noAssert) {
|
|
return readFloat(this, offset, false, noAssert);
|
|
};
|
|
|
|
Buffer.prototype.readFloatBE = function(offset, noAssert) {
|
|
return readFloat(this, offset, true, noAssert);
|
|
};
|
|
|
|
function readDouble(buffer, offset, isBigEndian, noAssert) {
|
|
if (!noAssert) {
|
|
assert.ok(typeof (isBigEndian) === 'boolean',
|
|
'missing or invalid endian');
|
|
|
|
assert.ok(offset + 7 < buffer.length,
|
|
'Trying to read beyond buffer length');
|
|
}
|
|
|
|
return require('./buffer_ieee754').readIEEE754(buffer, offset, isBigEndian,
|
|
52, 8);
|
|
}
|
|
|
|
Buffer.prototype.readDoubleLE = function(offset, noAssert) {
|
|
return readDouble(this, offset, false, noAssert);
|
|
};
|
|
|
|
Buffer.prototype.readDoubleBE = function(offset, noAssert) {
|
|
return readDouble(this, offset, true, noAssert);
|
|
};
|
|
|
|
|
|
/*
|
|
* We have to make sure that the value is a valid integer. This means that it is
|
|
* non-negative. It has no fractional component and that it does not exceed the
|
|
* maximum allowed value.
|
|
*
|
|
* value The number to check for validity
|
|
*
|
|
* max The maximum value
|
|
*/
|
|
function verifuint(value, max) {
|
|
assert.ok(typeof (value) == 'number',
|
|
'cannot write a non-number as a number');
|
|
|
|
assert.ok(value >= 0,
|
|
'specified a negative value for writing an unsigned value');
|
|
|
|
assert.ok(value <= max, 'value is larger than maximum value for type');
|
|
|
|
assert.ok(Math.floor(value) === value, 'value has a fractional component');
|
|
}
|
|
|
|
Buffer.prototype.writeUInt8 = function(value, offset, noAssert) {
|
|
var buffer = this;
|
|
|
|
if (!noAssert) {
|
|
assert.ok(value !== undefined && value !== null,
|
|
'missing value');
|
|
|
|
assert.ok(offset !== undefined && offset !== null,
|
|
'missing offset');
|
|
|
|
assert.ok(offset < buffer.length,
|
|
'trying to write beyond buffer length');
|
|
|
|
verifuint(value, 0xff);
|
|
}
|
|
|
|
buffer.parent[buffer.offset + offset] = value;
|
|
};
|
|
|
|
function writeUInt16(buffer, value, offset, isBigEndian, noAssert) {
|
|
if (!noAssert) {
|
|
assert.ok(value !== undefined && value !== null,
|
|
'missing value');
|
|
|
|
assert.ok(typeof (isBigEndian) === 'boolean',
|
|
'missing or invalid endian');
|
|
|
|
assert.ok(offset !== undefined && offset !== null,
|
|
'missing offset');
|
|
|
|
assert.ok(offset + 1 < buffer.length,
|
|
'trying to write beyond buffer length');
|
|
|
|
verifuint(value, 0xffff);
|
|
}
|
|
|
|
if (isBigEndian) {
|
|
buffer.parent[buffer.offset + offset] = (value & 0xff00) >>> 8;
|
|
buffer.parent[buffer.offset + offset + 1] = value & 0x00ff;
|
|
} else {
|
|
buffer.parent[buffer.offset + offset + 1] = (value & 0xff00) >>> 8;
|
|
buffer.parent[buffer.offset + offset] = value & 0x00ff;
|
|
}
|
|
}
|
|
|
|
Buffer.prototype.writeUInt16LE = function(value, offset, noAssert) {
|
|
writeUInt16(this, value, offset, false, noAssert);
|
|
};
|
|
|
|
Buffer.prototype.writeUInt16BE = function(value, offset, noAssert) {
|
|
writeUInt16(this, value, offset, true, noAssert);
|
|
};
|
|
|
|
function writeUInt32(buffer, value, offset, isBigEndian, noAssert) {
|
|
if (!noAssert) {
|
|
assert.ok(value !== undefined && value !== null,
|
|
'missing value');
|
|
|
|
assert.ok(typeof (isBigEndian) === 'boolean',
|
|
'missing or invalid endian');
|
|
|
|
assert.ok(offset !== undefined && offset !== null,
|
|
'missing offset');
|
|
|
|
assert.ok(offset + 3 < buffer.length,
|
|
'trying to write beyond buffer length');
|
|
|
|
verifuint(value, 0xffffffff);
|
|
}
|
|
|
|
if (isBigEndian) {
|
|
buffer.parent[buffer.offset + offset] = (value >>> 24) & 0xff;
|
|
buffer.parent[buffer.offset + offset + 1] = (value >>> 16) & 0xff;
|
|
buffer.parent[buffer.offset + offset + 2] = (value >>> 8) & 0xff;
|
|
buffer.parent[buffer.offset + offset + 3] = value & 0xff;
|
|
} else {
|
|
buffer.parent[buffer.offset + offset + 3] = (value >>> 24) & 0xff;
|
|
buffer.parent[buffer.offset + offset + 2] = (value >>> 16) & 0xff;
|
|
buffer.parent[buffer.offset + offset + 1] = (value >>> 8) & 0xff;
|
|
buffer.parent[buffer.offset + offset] = value & 0xff;
|
|
}
|
|
}
|
|
|
|
Buffer.prototype.writeUInt32LE = function(value, offset, noAssert) {
|
|
writeUInt32(this, value, offset, false, noAssert);
|
|
};
|
|
|
|
Buffer.prototype.writeUInt32BE = function(value, offset, noAssert) {
|
|
writeUInt32(this, value, offset, true, noAssert);
|
|
};
|
|
|
|
|
|
/*
|
|
* We now move onto our friends in the signed number category. Unlike unsigned
|
|
* numbers, we're going to have to worry a bit more about how we put values into
|
|
* arrays. Since we are only worrying about signed 32-bit values, we're in
|
|
* slightly better shape. Unfortunately, we really can't do our favorite binary
|
|
* & in this system. It really seems to do the wrong thing. For example:
|
|
*
|
|
* > -32 & 0xff
|
|
* 224
|
|
*
|
|
* What's happening above is really: 0xe0 & 0xff = 0xe0. However, the results of
|
|
* this aren't treated as a signed number. Ultimately a bad thing.
|
|
*
|
|
* What we're going to want to do is basically create the unsigned equivalent of
|
|
* our representation and pass that off to the wuint* functions. To do that
|
|
* we're going to do the following:
|
|
*
|
|
* - if the value is positive
|
|
* we can pass it directly off to the equivalent wuint
|
|
* - if the value is negative
|
|
* we do the following computation:
|
|
* mb + val + 1, where
|
|
* mb is the maximum unsigned value in that byte size
|
|
* val is the Javascript negative integer
|
|
*
|
|
*
|
|
* As a concrete value, take -128. In signed 16 bits this would be 0xff80. If
|
|
* you do out the computations:
|
|
*
|
|
* 0xffff - 128 + 1
|
|
* 0xffff - 127
|
|
* 0xff80
|
|
*
|
|
* You can then encode this value as the signed version. This is really rather
|
|
* hacky, but it should work and get the job done which is our goal here.
|
|
*/
|
|
|
|
/*
|
|
* A series of checks to make sure we actually have a signed 32-bit number
|
|
*/
|
|
function verifsint(value, max, min) {
|
|
assert.ok(typeof (value) == 'number',
|
|
'cannot write a non-number as a number');
|
|
|
|
assert.ok(value <= max, 'value larger than maximum allowed value');
|
|
|
|
assert.ok(value >= min, 'value smaller than minimum allowed value');
|
|
|
|
assert.ok(Math.floor(value) === value, 'value has a fractional component');
|
|
}
|
|
|
|
function verifIEEE754(value, max, min) {
|
|
assert.ok(typeof (value) == 'number',
|
|
'cannot write a non-number as a number');
|
|
|
|
assert.ok(value <= max, 'value larger than maximum allowed value');
|
|
|
|
assert.ok(value >= min, 'value smaller than minimum allowed value');
|
|
}
|
|
|
|
Buffer.prototype.writeInt8 = function(value, offset, noAssert) {
|
|
var buffer = this;
|
|
|
|
if (!noAssert) {
|
|
assert.ok(value !== undefined && value !== null,
|
|
'missing value');
|
|
|
|
assert.ok(offset !== undefined && offset !== null,
|
|
'missing offset');
|
|
|
|
assert.ok(offset < buffer.length,
|
|
'Trying to write beyond buffer length');
|
|
|
|
verifsint(value, 0x7f, -0x80);
|
|
}
|
|
|
|
if (value >= 0) {
|
|
buffer.writeUInt8(value, offset, noAssert);
|
|
} else {
|
|
buffer.writeUInt8(0xff + value + 1, offset, noAssert);
|
|
}
|
|
};
|
|
|
|
function writeInt16(buffer, value, offset, isBigEndian, noAssert) {
|
|
if (!noAssert) {
|
|
assert.ok(value !== undefined && value !== null,
|
|
'missing value');
|
|
|
|
assert.ok(typeof (isBigEndian) === 'boolean',
|
|
'missing or invalid endian');
|
|
|
|
assert.ok(offset !== undefined && offset !== null,
|
|
'missing offset');
|
|
|
|
assert.ok(offset + 1 < buffer.length,
|
|
'Trying to write beyond buffer length');
|
|
|
|
verifsint(value, 0x7fff, -0x8000);
|
|
}
|
|
|
|
if (value >= 0) {
|
|
writeUInt16(buffer, value, offset, isBigEndian, noAssert);
|
|
} else {
|
|
writeUInt16(buffer, 0xffff + value + 1, offset, isBigEndian, noAssert);
|
|
}
|
|
}
|
|
|
|
Buffer.prototype.writeInt16LE = function(value, offset, noAssert) {
|
|
writeInt16(this, value, offset, false, noAssert);
|
|
};
|
|
|
|
Buffer.prototype.writeInt16BE = function(value, offset, noAssert) {
|
|
writeInt16(this, value, offset, true, noAssert);
|
|
};
|
|
|
|
function writeInt32(buffer, value, offset, isBigEndian, noAssert) {
|
|
if (!noAssert) {
|
|
assert.ok(value !== undefined && value !== null,
|
|
'missing value');
|
|
|
|
assert.ok(typeof (isBigEndian) === 'boolean',
|
|
'missing or invalid endian');
|
|
|
|
assert.ok(offset !== undefined && offset !== null,
|
|
'missing offset');
|
|
|
|
assert.ok(offset + 3 < buffer.length,
|
|
'Trying to write beyond buffer length');
|
|
|
|
verifsint(value, 0x7fffffff, -0x80000000);
|
|
}
|
|
|
|
if (value >= 0) {
|
|
writeUInt32(buffer, value, offset, isBigEndian, noAssert);
|
|
} else {
|
|
writeUInt32(buffer, 0xffffffff + value + 1, offset, isBigEndian, noAssert);
|
|
}
|
|
}
|
|
|
|
Buffer.prototype.writeInt32LE = function(value, offset, noAssert) {
|
|
writeInt32(this, value, offset, false, noAssert);
|
|
};
|
|
|
|
Buffer.prototype.writeInt32BE = function(value, offset, noAssert) {
|
|
writeInt32(this, value, offset, true, noAssert);
|
|
};
|
|
|
|
function writeFloat(buffer, value, offset, isBigEndian, noAssert) {
|
|
if (!noAssert) {
|
|
assert.ok(value !== undefined && value !== null,
|
|
'missing value');
|
|
|
|
assert.ok(typeof (isBigEndian) === 'boolean',
|
|
'missing or invalid endian');
|
|
|
|
assert.ok(offset !== undefined && offset !== null,
|
|
'missing offset');
|
|
|
|
assert.ok(offset + 3 < buffer.length,
|
|
'Trying to write beyond buffer length');
|
|
|
|
verifIEEE754(value, 3.4028234663852886e+38, -3.4028234663852886e+38);
|
|
}
|
|
|
|
require('./buffer_ieee754').writeIEEE754(buffer, value, offset, isBigEndian,
|
|
23, 4);
|
|
}
|
|
|
|
Buffer.prototype.writeFloatLE = function(value, offset, noAssert) {
|
|
writeFloat(this, value, offset, false, noAssert);
|
|
};
|
|
|
|
Buffer.prototype.writeFloatBE = function(value, offset, noAssert) {
|
|
writeFloat(this, value, offset, true, noAssert);
|
|
};
|
|
|
|
function writeDouble(buffer, value, offset, isBigEndian, noAssert) {
|
|
if (!noAssert) {
|
|
assert.ok(value !== undefined && value !== null,
|
|
'missing value');
|
|
|
|
assert.ok(typeof (isBigEndian) === 'boolean',
|
|
'missing or invalid endian');
|
|
|
|
assert.ok(offset !== undefined && offset !== null,
|
|
'missing offset');
|
|
|
|
assert.ok(offset + 7 < buffer.length,
|
|
'Trying to write beyond buffer length');
|
|
|
|
verifIEEE754(value, 1.7976931348623157E+308, -1.7976931348623157E+308);
|
|
}
|
|
|
|
require('./buffer_ieee754').writeIEEE754(buffer, value, offset, isBigEndian,
|
|
52, 8);
|
|
}
|
|
|
|
Buffer.prototype.writeDoubleLE = function(value, offset, noAssert) {
|
|
writeDouble(this, value, offset, false, noAssert);
|
|
};
|
|
|
|
Buffer.prototype.writeDoubleBE = function(value, offset, noAssert) {
|
|
writeDouble(this, value, offset, true, noAssert);
|
|
};
|
|
|
|
SlowBuffer.prototype.readUInt8 = Buffer.prototype.readUInt8;
|
|
SlowBuffer.prototype.readUInt16LE = Buffer.prototype.readUInt16LE;
|
|
SlowBuffer.prototype.readUInt16BE = Buffer.prototype.readUInt16BE;
|
|
SlowBuffer.prototype.readUInt32LE = Buffer.prototype.readUInt32LE;
|
|
SlowBuffer.prototype.readUInt32BE = Buffer.prototype.readUInt32BE;
|
|
SlowBuffer.prototype.readInt8 = Buffer.prototype.readInt8;
|
|
SlowBuffer.prototype.readInt16LE = Buffer.prototype.readInt16LE;
|
|
SlowBuffer.prototype.readInt16BE = Buffer.prototype.readInt16BE;
|
|
SlowBuffer.prototype.readInt32LE = Buffer.prototype.readInt32LE;
|
|
SlowBuffer.prototype.readInt32BE = Buffer.prototype.readInt32BE;
|
|
SlowBuffer.prototype.readFloatLE = Buffer.prototype.readFloatLE;
|
|
SlowBuffer.prototype.readFloatBE = Buffer.prototype.readFloatBE;
|
|
SlowBuffer.prototype.readDoubleLE = Buffer.prototype.readDoubleLE;
|
|
SlowBuffer.prototype.readDoubleBE = Buffer.prototype.readDoubleBE;
|
|
SlowBuffer.prototype.writeUInt8 = Buffer.prototype.writeUInt8;
|
|
SlowBuffer.prototype.writeUInt16LE = Buffer.prototype.writeUInt16LE;
|
|
SlowBuffer.prototype.writeUInt16BE = Buffer.prototype.writeUInt16BE;
|
|
SlowBuffer.prototype.writeUInt32LE = Buffer.prototype.writeUInt32LE;
|
|
SlowBuffer.prototype.writeUInt32BE = Buffer.prototype.writeUInt32BE;
|
|
SlowBuffer.prototype.writeInt8 = Buffer.prototype.writeInt8;
|
|
SlowBuffer.prototype.writeInt16LE = Buffer.prototype.writeInt16LE;
|
|
SlowBuffer.prototype.writeInt16BE = Buffer.prototype.writeInt16BE;
|
|
SlowBuffer.prototype.writeInt32LE = Buffer.prototype.writeInt32LE;
|
|
SlowBuffer.prototype.writeInt32BE = Buffer.prototype.writeInt32BE;
|
|
SlowBuffer.prototype.writeFloatLE = Buffer.prototype.writeFloatLE;
|
|
SlowBuffer.prototype.writeFloatBE = Buffer.prototype.writeFloatBE;
|
|
SlowBuffer.prototype.writeDoubleLE = Buffer.prototype.writeDoubleLE;
|
|
SlowBuffer.prototype.writeDoubleBE = Buffer.prototype.writeDoubleBE;
|
|
|
|
},{"assert":1,"./buffer_ieee754":8,"base64-js":9}],9:[function(require,module,exports){
|
|
(function (exports) {
|
|
'use strict';
|
|
|
|
var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
|
|
|
function b64ToByteArray(b64) {
|
|
var i, j, l, tmp, placeHolders, arr;
|
|
|
|
if (b64.length % 4 > 0) {
|
|
throw 'Invalid string. Length must be a multiple of 4';
|
|
}
|
|
|
|
// the number of equal signs (place holders)
|
|
// if there are two placeholders, than the two characters before it
|
|
// represent one byte
|
|
// if there is only one, then the three characters before it represent 2 bytes
|
|
// this is just a cheap hack to not do indexOf twice
|
|
placeHolders = b64.indexOf('=');
|
|
placeHolders = placeHolders > 0 ? b64.length - placeHolders : 0;
|
|
|
|
// base64 is 4/3 + up to two characters of the original data
|
|
arr = [];//new Uint8Array(b64.length * 3 / 4 - placeHolders);
|
|
|
|
// if there are placeholders, only get up to the last complete 4 chars
|
|
l = placeHolders > 0 ? b64.length - 4 : b64.length;
|
|
|
|
for (i = 0, j = 0; i < l; i += 4, j += 3) {
|
|
tmp = (lookup.indexOf(b64[i]) << 18) | (lookup.indexOf(b64[i + 1]) << 12) | (lookup.indexOf(b64[i + 2]) << 6) | lookup.indexOf(b64[i + 3]);
|
|
arr.push((tmp & 0xFF0000) >> 16);
|
|
arr.push((tmp & 0xFF00) >> 8);
|
|
arr.push(tmp & 0xFF);
|
|
}
|
|
|
|
if (placeHolders === 2) {
|
|
tmp = (lookup.indexOf(b64[i]) << 2) | (lookup.indexOf(b64[i + 1]) >> 4);
|
|
arr.push(tmp & 0xFF);
|
|
} else if (placeHolders === 1) {
|
|
tmp = (lookup.indexOf(b64[i]) << 10) | (lookup.indexOf(b64[i + 1]) << 4) | (lookup.indexOf(b64[i + 2]) >> 2);
|
|
arr.push((tmp >> 8) & 0xFF);
|
|
arr.push(tmp & 0xFF);
|
|
}
|
|
|
|
return arr;
|
|
}
|
|
|
|
function uint8ToBase64(uint8) {
|
|
var i,
|
|
extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes
|
|
output = "",
|
|
temp, length;
|
|
|
|
function tripletToBase64 (num) {
|
|
return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F];
|
|
};
|
|
|
|
// go through the array every three bytes, we'll deal with trailing stuff later
|
|
for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) {
|
|
temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]);
|
|
output += tripletToBase64(temp);
|
|
}
|
|
|
|
// pad the end with zeros, but make sure to not forget the extra bytes
|
|
switch (extraBytes) {
|
|
case 1:
|
|
temp = uint8[uint8.length - 1];
|
|
output += lookup[temp >> 2];
|
|
output += lookup[(temp << 4) & 0x3F];
|
|
output += '==';
|
|
break;
|
|
case 2:
|
|
temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1]);
|
|
output += lookup[temp >> 10];
|
|
output += lookup[(temp >> 4) & 0x3F];
|
|
output += lookup[(temp << 2) & 0x3F];
|
|
output += '=';
|
|
break;
|
|
}
|
|
|
|
return output;
|
|
}
|
|
|
|
module.exports.toByteArray = b64ToByteArray;
|
|
module.exports.fromByteArray = uint8ToBase64;
|
|
}());
|
|
|
|
},{}]},{},[])
|
|
;;module.exports=require("buffer-browserify")
|
|
|
|
},{}],66:[function(require,module,exports){
|
|
// shim for using process in browser
|
|
|
|
var process = module.exports = {};
|
|
|
|
process.nextTick = (function () {
|
|
var canSetImmediate = typeof window !== 'undefined'
|
|
&& window.setImmediate;
|
|
var canPost = typeof window !== 'undefined'
|
|
&& window.postMessage && window.addEventListener
|
|
;
|
|
|
|
if (canSetImmediate) {
|
|
return function (f) { return window.setImmediate(f) };
|
|
}
|
|
|
|
if (canPost) {
|
|
var queue = [];
|
|
window.addEventListener('message', function (ev) {
|
|
if (ev.source === window && ev.data === 'process-tick') {
|
|
ev.stopPropagation();
|
|
if (queue.length > 0) {
|
|
var fn = queue.shift();
|
|
fn();
|
|
}
|
|
}
|
|
}, true);
|
|
|
|
return function nextTick(fn) {
|
|
queue.push(fn);
|
|
window.postMessage('process-tick', '*');
|
|
};
|
|
}
|
|
|
|
return function nextTick(fn) {
|
|
setTimeout(fn, 0);
|
|
};
|
|
})();
|
|
|
|
process.title = 'browser';
|
|
process.browser = true;
|
|
process.env = {};
|
|
process.argv = [];
|
|
|
|
process.binding = function (name) {
|
|
throw new Error('process.binding is not supported');
|
|
}
|
|
|
|
// TODO(shtylman)
|
|
process.cwd = function () { return '/' };
|
|
process.chdir = function (dir) {
|
|
throw new Error('process.chdir is not supported');
|
|
};
|
|
|
|
},{}],67:[function(require,module,exports){
|
|
var _ = require('./vendor/lodash');
|
|
var async = require('async');
|
|
var jxt = require('jxt');
|
|
var request = require('xhr');
|
|
var parser = new DOMParser();
|
|
|
|
|
|
function XRD(data, xml) {
|
|
return jxt.init(this, xml, data);
|
|
}
|
|
XRD.prototype = {
|
|
constructor: {
|
|
value: XRD
|
|
},
|
|
NS: 'http://docs.oasis-open.org/ns/xri/xrd-1.0',
|
|
EL: 'XRD',
|
|
toString: jxt.toString,
|
|
toJSON: jxt.toJSON,
|
|
get subject() {
|
|
return jxt.getSubText(this.xml, this.NS, 'Subject');
|
|
},
|
|
get expires() {
|
|
return new Date(jxt.getSubText(this.xml, this.NS, 'Expires'));
|
|
},
|
|
get aliases() {
|
|
return jxt.getMultiSubText(this.xml, this.NS, 'Alias');
|
|
},
|
|
get properties() {
|
|
var results = {};
|
|
var props = jxt.find(this.xml, this.NS, 'Property');
|
|
_.each(props, function (property) {
|
|
var type = jxt.getAttribute(property, 'type');
|
|
results[type] = property.textContent;
|
|
});
|
|
return results;
|
|
},
|
|
get links() {
|
|
var results = [];
|
|
var links = jxt.find(this.xml, this.NS, 'Link');
|
|
_.each(links, function (link) {
|
|
var item = {
|
|
rel: jxt.getAttribute(link, 'rel'),
|
|
href: jxt.getAttribute(link, 'href'),
|
|
type: jxt.getAttribute(link, 'type'),
|
|
template: jxt.getAttribute(link, 'template'),
|
|
titles: jxt.getSubLangText(link, this.NS, 'Title', 'default'),
|
|
properties: {}
|
|
};
|
|
var props = jxt.find(link, this.NS, 'Property');
|
|
_.each(props, function (property) {
|
|
var type = jxt.getAttribute(property, 'type');
|
|
item.properties[type] = property.textContent;
|
|
});
|
|
results.push(item);
|
|
});
|
|
return results;
|
|
}
|
|
};
|
|
|
|
|
|
module.exports = function (opts, cb) {
|
|
if (typeof opts === 'string') {
|
|
opts = {host: opts};
|
|
}
|
|
|
|
opts = _.extend({
|
|
ssl: true,
|
|
json: true
|
|
}, opts);
|
|
|
|
var scheme = opts.ssl ? 'https://' : 'http://';
|
|
|
|
async.parallel({
|
|
json: function (jsonCb) {
|
|
if (!opts.json) return jsonCb(null, {});
|
|
request({
|
|
uri: scheme + opts.host + '/.well-known/host-meta.json'
|
|
}, function (err, resp, body) {
|
|
if (err) return jsonCb();
|
|
try {
|
|
jsonCb('completed', JSON.parse(body));
|
|
} catch (e) {
|
|
jsonCb(null, {});
|
|
}
|
|
});
|
|
},
|
|
xrd: function (xrdCb) {
|
|
request({
|
|
uri: scheme + opts.host + '/.well-known/host-meta'
|
|
}, function (err, resp) {
|
|
if (err) return xrdCb(null, {});
|
|
try {
|
|
var body = parser.parseFromString(resp.body, 'application/xml').childNodes[0];
|
|
var xrd = new XRD({}, body);
|
|
xrdCb('completed', xrd.toJSON());
|
|
} catch (e) {
|
|
xrdCb(null, {});
|
|
}
|
|
});
|
|
}
|
|
}, function (completed, data) {
|
|
if (completed) {
|
|
if (Object.keys(data.json).length) {
|
|
return cb(false, data.json);
|
|
} else if (Object.keys(data.xrd).length) {
|
|
return cb(false, data.xrd);
|
|
}
|
|
}
|
|
cb('no-host-meta', {});
|
|
});
|
|
};
|
|
|
|
},{"./vendor/lodash":73,"async":53,"jxt":68,"xhr":70}],68:[function(require,module,exports){
|
|
var _ = require('./vendor/lodash');
|
|
var serializer = new XMLSerializer();
|
|
var XML_NS = 'http://www.w3.org/XML/1998/namespace';
|
|
var TOP_LEVEL_LOOKUP = {};
|
|
var LOOKUP = {};
|
|
var LOOKUP_EXT = {};
|
|
|
|
|
|
var find = exports.find = function (xml, NS, selector) {
|
|
var children = xml.querySelectorAll(selector);
|
|
return _.filter(children, function (child) {
|
|
return child.namespaceURI === NS && child.parentNode == xml;
|
|
});
|
|
};
|
|
|
|
exports.findOrCreate = function (xml, NS, selector) {
|
|
var existing = find(xml, NS, selector);
|
|
if (existing.length) {
|
|
return existing[0];
|
|
} else {
|
|
var created = document.createElementNS(NS, selector);
|
|
xml.appendChild(created);
|
|
return created;
|
|
}
|
|
};
|
|
|
|
exports.init = function (self, xml, data) {
|
|
self.xml = xml || document.createElementNS(self.NS, self.EL);
|
|
if (!self.xml.parentNode || self.xml.parentNode.namespaceURI !== self.NS) {
|
|
self.xml.setAttribute('xmlns', self.NS);
|
|
}
|
|
|
|
self._extensions = {};
|
|
_.each(self.xml.childNodes, function (child) {
|
|
var childName = child.namespaceURI + '|' + child.localName;
|
|
var ChildJXT = LOOKUP[childName];
|
|
if (ChildJXT !== undefined) {
|
|
var name = ChildJXT.prototype._name;
|
|
self._extensions[name] = new ChildJXT(null, child);
|
|
self._extensions[name].parent = self;
|
|
}
|
|
});
|
|
|
|
_.extend(self, data);
|
|
return self;
|
|
};
|
|
|
|
exports.getSubText = function (xml, NS, element) {
|
|
var subs = find(xml, NS, element);
|
|
if (!subs) {
|
|
return '';
|
|
}
|
|
|
|
for (var i = 0; i < subs.length; i++) {
|
|
if (subs[i].namespaceURI === NS) {
|
|
return subs[i].textContent || '';
|
|
}
|
|
}
|
|
|
|
return '';
|
|
};
|
|
|
|
exports.getMultiSubText = function (xml, NS, element, extractor) {
|
|
var subs = find(xml, NS, element);
|
|
var results = [];
|
|
extractor = extractor || function (sub) {
|
|
return sub.textContent || '';
|
|
};
|
|
|
|
for (var i = 0; i < subs.length; i++) {
|
|
if (subs[i].namespaceURI === NS) {
|
|
results.push(extractor(subs[i]));
|
|
}
|
|
}
|
|
|
|
return results;
|
|
};
|
|
|
|
exports.getSubLangText = function (xml, NS, element, defaultLang) {
|
|
var subs = find(xml, NS, element);
|
|
if (!subs) {
|
|
return {};
|
|
}
|
|
|
|
var lang, sub;
|
|
var results = {};
|
|
var langs = [];
|
|
|
|
for (var i = 0; i < subs.length; i++) {
|
|
sub = subs[i];
|
|
if (sub.namespaceURI === NS) {
|
|
lang = sub.getAttributeNS(XML_NS, 'lang') || defaultLang;
|
|
langs.push(lang);
|
|
results[lang] = sub.textContent || '';
|
|
}
|
|
}
|
|
|
|
return results;
|
|
};
|
|
|
|
|
|
exports.setSubText = function (xml, NS, element, value) {
|
|
var subs = find(xml, NS, element);
|
|
if (!subs.length) {
|
|
if (value) {
|
|
var sub = document.createElementNS(NS, element);
|
|
sub.textContent = value;
|
|
xml.appendChild(sub);
|
|
}
|
|
} else {
|
|
for (var i = 0; i < subs.length; i++) {
|
|
if (subs[i].namespaceURI === NS) {
|
|
if (value) {
|
|
subs[i].textContent = value;
|
|
return;
|
|
} else {
|
|
xml.removeChild(subs[i]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
exports.setMultiSubText = function (xml, NS, element, value, builder) {
|
|
var subs = find(xml, NS, element);
|
|
var values = [];
|
|
builder = builder || function (value) {
|
|
var sub = document.createElementNS(NS, element);
|
|
sub.textContent = value;
|
|
xml.appendChild(sub);
|
|
};
|
|
if (typeof value === 'string') {
|
|
values = (value || '').split('\n');
|
|
} else {
|
|
values = value;
|
|
}
|
|
_.forEach(subs, function (sub) {
|
|
xml.removeChild(sub);
|
|
});
|
|
_.forEach(values, function (val) {
|
|
if (val) {
|
|
builder(val);
|
|
}
|
|
});
|
|
};
|
|
|
|
exports.setSubLangText = function (xml, NS, element, value, defaultLang) {
|
|
var sub, lang;
|
|
var subs = find(xml, NS, element);
|
|
if (subs.length) {
|
|
for (var i = 0; i < subs.length; i++) {
|
|
sub = subs[i];
|
|
if (sub.namespaceURI === NS) {
|
|
xml.removeChild(sub);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (typeof value === 'string') {
|
|
sub = document.createElementNS(NS, element);
|
|
sub.textContent = value;
|
|
xml.appendChild(sub);
|
|
} else if (typeof value === 'object') {
|
|
for (lang in value) {
|
|
if (value.hasOwnProperty(lang)) {
|
|
sub = document.createElementNS(NS, element);
|
|
if (lang !== defaultLang) {
|
|
sub.setAttributeNS(XML_NS, 'lang', lang);
|
|
}
|
|
sub.textContent = value[lang];
|
|
xml.appendChild(sub);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
exports.getAttribute = function (xml, attr, defaultVal) {
|
|
return xml.getAttribute(attr) || defaultVal || '';
|
|
};
|
|
|
|
exports.setAttribute = function (xml, attr, value, force) {
|
|
if (value || force) {
|
|
xml.setAttribute(attr, value);
|
|
} else {
|
|
xml.removeAttribute(attr);
|
|
}
|
|
};
|
|
|
|
exports.getBoolAttribute = function (xml, attr, defaultVal) {
|
|
var val = xml.getAttribute(attr) || defaultVal || '';
|
|
return val === 'true' || val === '1';
|
|
};
|
|
|
|
exports.setBoolAttribute = function (xml, attr, value) {
|
|
if (value) {
|
|
xml.setAttribute(attr, '1');
|
|
} else {
|
|
xml.removeAttribute(attr);
|
|
}
|
|
};
|
|
|
|
exports.getSubAttribute = function (xml, NS, sub, attr, defaultVal) {
|
|
var subs = find(xml, NS, sub);
|
|
if (!subs) {
|
|
return '';
|
|
}
|
|
|
|
for (var i = 0; i < subs.length; i++) {
|
|
if (subs[i].namespaceURI === NS) {
|
|
return subs[i].getAttribute(attr) || defaultVal || '';
|
|
}
|
|
}
|
|
|
|
return '';
|
|
};
|
|
|
|
exports.setSubAttribute = function (xml, NS, sub, attr, value) {
|
|
var subs = find(xml, NS, sub);
|
|
if (!subs.length) {
|
|
if (value) {
|
|
sub = document.createElementNS(NS, sub);
|
|
sub.setAttribute(attr, value);
|
|
xml.appendChild(sub);
|
|
}
|
|
} else {
|
|
for (var i = 0; i < subs.length; i++) {
|
|
if (subs[i].namespaceURI === NS) {
|
|
if (value) {
|
|
subs[i].setAttribute(attr, value);
|
|
return;
|
|
} else {
|
|
subs[i].removeAttribute(attr);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
exports.toString = function () {
|
|
return serializer.serializeToString(this.xml);
|
|
};
|
|
|
|
exports.toJSON = function () {
|
|
var prop;
|
|
var result = {};
|
|
var exclude = {
|
|
constructor: true,
|
|
NS: true,
|
|
EL: true,
|
|
toString: true,
|
|
toJSON: true,
|
|
_extensions: true,
|
|
prototype: true,
|
|
xml: true,
|
|
parent: true,
|
|
_name: true
|
|
};
|
|
for (prop in this._extensions) {
|
|
if (this._extensions[prop].toJSON) {
|
|
result[prop] = this._extensions[prop].toJSON();
|
|
}
|
|
}
|
|
for (prop in this) {
|
|
if (!exclude[prop] && !((LOOKUP_EXT[this.NS + '|' + this.EL] || {})[prop]) && !this._extensions[prop] && prop[0] !== '_') {
|
|
var val = this[prop];
|
|
if (typeof val == 'function') continue;
|
|
var type = Object.prototype.toString.call(val);
|
|
if (type.indexOf('Object') >= 0) {
|
|
if (Object.keys(val).length > 0) {
|
|
result[prop] = val;
|
|
}
|
|
} else if (type.indexOf('Array') >= 0) {
|
|
if (val.length > 0) {
|
|
result[prop] = val;
|
|
}
|
|
} else if (!!val) {
|
|
result[prop] = val;
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
};
|
|
|
|
exports.extend = function (ParentJXT, ChildJXT) {
|
|
var parentName = ParentJXT.prototype.NS + '|' + ParentJXT.prototype.EL;
|
|
var name = ChildJXT.prototype._name;
|
|
var qName = ChildJXT.prototype.NS + '|' + ChildJXT.prototype.EL;
|
|
|
|
LOOKUP[qName] = ChildJXT;
|
|
if (!LOOKUP_EXT[qName]) {
|
|
LOOKUP_EXT[qName] = {};
|
|
}
|
|
if (!LOOKUP_EXT[parentName]) {
|
|
LOOKUP_EXT[parentName] = {};
|
|
}
|
|
LOOKUP_EXT[parentName][name] = ChildJXT;
|
|
|
|
ParentJXT.prototype.__defineGetter__(name, function () {
|
|
if (!this._extensions[name]) {
|
|
var existing = exports.find(this.xml, ChildJXT.prototype.NS, ChildJXT.prototype.EL);
|
|
if (!existing.length) {
|
|
this._extensions[name] = new ChildJXT();
|
|
this.xml.appendChild(this._extensions[name].xml);
|
|
} else {
|
|
this._extensions[name] = new ChildJXT(null, existing[0]);
|
|
}
|
|
this._extensions[name].parent = this;
|
|
}
|
|
return this._extensions[name];
|
|
});
|
|
ParentJXT.prototype.__defineSetter__(name, function (value) {
|
|
var child = this[name];
|
|
_.extend(child, value);
|
|
});
|
|
};
|
|
|
|
exports.topLevel = function (JXT) {
|
|
var name = JXT.prototype.NS + '|' + JXT.prototype.EL;
|
|
LOOKUP[name] = JXT;
|
|
TOP_LEVEL_LOOKUP[name] = JXT;
|
|
};
|
|
|
|
exports.build = function (xml) {
|
|
var JXT = TOP_LEVEL_LOOKUP[xml.namespaceURI + '|' + xml.localName];
|
|
if (JXT) {
|
|
return new JXT(null, xml);
|
|
}
|
|
};
|
|
|
|
exports.XML_NS = XML_NS;
|
|
exports.TOP_LEVEL_LOOKUP = TOP_LEVEL_LOOKUP;
|
|
exports.LOOKUP_EXT = LOOKUP_EXT;
|
|
exports.LOOKUP = LOOKUP;
|
|
|
|
},{"./vendor/lodash":69}],69:[function(require,module,exports){
|
|
var global=self;/**
|
|
* @license
|
|
* Lo-Dash 1.3.1 (Custom Build) lodash.com/license
|
|
* Build: `lodash include="each,extend,filter"`
|
|
* Underscore.js 1.4.4 underscorejs.org/LICENSE
|
|
*/
|
|
;!function(t){function r(t){return typeof t.toString!="function"&&typeof(t+"")=="string"}function e(t){t.length=0,g.length<y&&g.push(t)}function n(t){var r=t.k;r&&n(r),t.b=t.k=t.object=t.number=t.string=null,h.length<y&&h.push(t)}function o(){}function u(){var t=h.pop()||{a:"",b:null,c:"",k:null,"false":!1,d:"",e:"",f:"","null":!1,number:null,object:null,push:null,g:null,string:null,h:"","true":!1,undefined:!1,i:!1,j:!1};t.g=v,t.b=t.c=t.f=t.h="",t.e="r",t.i=!0,t.j=!!X;for(var r,e=0;r=arguments[e];e++)for(var u in r)t[u]=r[u];
|
|
e=t.a,t.d=/^[^,]+/.exec(e)[0],r=Function,e="return function("+e+"){",u="var m,r="+t.d+",C="+t.e+";if(!r)return C;"+t.h+";",t.b?(u+="var s=r.length;m=-1;if("+t.b+"){",K.unindexedChars&&(u+="if(q(r)){r=r.split('')}"),u+="while(++m<s){"+t.f+";}}else{"):K.nonEnumArgs&&(u+="var s=r.length;m=-1;if(s&&n(r)){while(++m<s){m+='';"+t.f+";}}else{"),K.enumPrototypes&&(u+="var E=typeof r=='function';"),K.enumErrorProps&&(u+="var D=r===j||r instanceof Error;");var c=[];if(K.enumPrototypes&&c.push('!(E&&m=="prototype")'),K.enumErrorProps&&c.push('!(D&&(m=="message"||m=="name"))'),t.i&&t.j)u+="var A=-1,B=z[typeof r]&&t(r),s=B?B.length:0;while(++A<s){m=B[A];",c.length&&(u+="if("+c.join("&&")+"){"),u+=t.f+";",c.length&&(u+="}"),u+="}";
|
|
else if(u+="for(m in r){",t.i&&c.push("l.call(r, m)"),c.length&&(u+="if("+c.join("&&")+"){"),u+=t.f+";",c.length&&(u+="}"),u+="}",K.nonEnumShadows){for(u+="if(r!==y){var h=r.constructor,p=r===(h&&h.prototype),e=r===H?G:r===j?i:J.call(r),v=w[e];",k=0;7>k;k++)u+="m='"+t.g[k]+"';if((!(p&&v[m])&&l.call(r,m))",t.i||(u+="||(!v[m]&&r[m]!==y[m])"),u+="){"+t.f+"}";u+="}"}return(t.b||K.nonEnumArgs)&&(u+="}"),u+=t.c+";return C",r=r("i,j,l,n,o,q,t,u,y,z,w,G,H,J",e+u+"}"),n(t),r(_,z,R,a,U,l,X,o,D,P,V,A,N,M)}function a(t){return M.call(t)==j
|
|
}function c(t,n,u,i,l,s){var p=u===b;if(typeof u=="function"&&!p){u=o.createCallback(u,i,2);var m=u(t,n);if(typeof m!="undefined")return!!m}if(t===n)return 0!==t||1/t==1/n;var h=typeof t,y=typeof n;if(t===t&&(!t||"function"!=h&&"object"!=h)&&(!n||"function"!=y&&"object"!=y))return!1;if(null==t||null==n)return t===n;if(y=M.call(t),h=M.call(n),y==j&&(y=w),h==j&&(h=w),y!=h)return!1;switch(y){case O:case E:return+t==+n;case x:return t!=+t?n!=+n:0==t?1/t==1/n:t==+n;case S:case A:return t==n+""}if(h=y==C,!h){if(R.call(t,"__wrapped__")||R.call(n,"__wrapped__"))return c(t.__wrapped__||t,n.__wrapped__||n,u,i,l,s);
|
|
if(y!=w||!K.nodeClass&&(r(t)||r(n)))return!1;var y=!K.argsObject&&a(t)?Object:t.constructor,d=!K.argsObject&&a(n)?Object:n.constructor;if(y!=d&&(!f(y)||!(y instanceof y&&f(d)&&d instanceof d)))return!1}for(d=!l,l||(l=g.pop()||[]),s||(s=g.pop()||[]),y=l.length;y--;)if(l[y]==t)return s[y]==n;var v=0,m=!0;if(l.push(t),s.push(n),h){if(y=t.length,v=n.length,m=v==t.length,!m&&!p)return m;for(;v--;)if(h=y,d=n[v],p)for(;h--&&!(m=c(t[h],d,u,i,l,s)););else if(!(m=c(t[v],d,u,i,l,s)))break;return m}return Z(n,function(r,e,n){return R.call(n,e)?(v++,m=R.call(t,e)&&c(t[e],r,u,i,l,s)):void 0
|
|
}),m&&!p&&Z(t,function(t,r,e){return R.call(e,r)?m=-1<--v:void 0}),d&&(e(l),e(s)),m}function f(t){return typeof t=="function"}function i(t){return!(!t||!P[typeof t])}function l(t){return typeof t=="string"||M.call(t)==A}function s(t,r,e){var n=[];if(r=o.createCallback(r,e),U(t)){e=-1;for(var u=t.length;++e<u;){var a=t[e];r(a,e,t)&&n.push(a)}}else Y(t,function(t,e,o){r(t,e,o)&&n.push(t)});return n}function p(t,r,e){if(r&&typeof e=="undefined"&&U(t)){e=-1;for(var n=t.length;++e<n&&false!==r(t[e],e,t););}else Y(t,r,e);
|
|
return t}function m(t){return t}var g=[],h=[],b={},y=40,d=(d=/\bthis\b/)&&d.test(function(){return this})&&d,v="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),j="[object Arguments]",C="[object Array]",O="[object Boolean]",E="[object Date]",_="[object Error]",x="[object Number]",w="[object Object]",S="[object RegExp]",A="[object String]",P={"boolean":!1,"function":!0,object:!0,number:!1,string:!1,undefined:!1},I=P[typeof exports]&&exports,B=P[typeof module]&&module&&module.exports==I&&module,F=P[typeof global]&&global;
|
|
!F||F.global!==F&&F.window!==F||(t=F);var z=Error.prototype,D=Object.prototype,N=String.prototype,F=RegExp("^"+(D.valueOf+"").replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/valueOf|for [^\]]+/g,".+?")+"$"),q=Function.prototype.toString,R=D.hasOwnProperty,$=D.propertyIsEnumerable,M=D.toString,T=F.test(T=M.bind)&&T,G=F.test(G=Object.create)&&G,H=F.test(H=Array.isArray)&&H,J=F.test(J=Object.keys)&&J,G=F.test(t.attachEvent),L=T&&!/\n|true/.test(T+G),V={};V[C]=V[E]=V[x]={constructor:!0,toLocaleString:!0,toString:!0,valueOf:!0},V[O]=V[A]={constructor:!0,toString:!0,valueOf:!0},V[_]=V["[object Function]"]=V[S]={constructor:!0,toString:!0},V[w]={constructor:!0},function(){for(var t=v.length;t--;){var r,e=v[t];
|
|
for(r in V)R.call(V,r)&&!R.call(V[r],e)&&(V[r][e]=!1)}}();var K=o.support={};!function(){var t=function(){this.x=1},r=[];t.prototype={valueOf:1,y:1};for(var e in new t)r.push(e);for(e in arguments);K.argsObject=arguments.constructor==Object&&!(arguments instanceof Array),K.argsClass=a(arguments),K.enumErrorProps=$.call(z,"message")||$.call(z,"name"),K.enumPrototypes=$.call(t,"prototype"),K.fastBind=T&&!L,K.nonEnumArgs=0!=e,K.nonEnumShadows=!/valueOf/.test(r),K.unindexedChars="xx"!="x"[0]+Object("x")[0];
|
|
try{K.nodeClass=!(M.call(document)==w&&!({toString:0}+""))}catch(n){K.nodeClass=!0}}(1);var Q={a:"x,F,k",h:"var a=arguments,b=0,c=typeof k=='number'?2:a.length;while(++b<c){r=a[b];if(r&&z[typeof r]){",f:"if(typeof C[m]=='undefined')C[m]=r[m]",c:"}}"},G={a:"f,d,I",h:"d=d&&typeof I=='undefined'?d:u.createCallback(d,I)",b:"typeof s=='number'",f:"if(d(r[m],m,f)===false)return C"},F={h:"if(!z[typeof r])return C;"+G.h,b:!1};K.argsClass||(a=function(t){return t?R.call(t,"callee"):!1});var U=H||function(t){return t?typeof t=="object"&&M.call(t)==C:!1
|
|
},W=u({a:"x",e:"[]",h:"if(!(z[typeof x]))return C",f:"C.push(m)"}),X=J?function(t){return i(t)?K.enumPrototypes&&typeof t=="function"||K.nonEnumArgs&&t.length&&a(t)?W(t):J(t):[]}:W,Y=u(G),H=u(Q,{h:Q.h.replace(";",";if(c>3&&typeof a[c-2]=='function'){var d=u.createCallback(a[--c-1],a[c--],2)}else if(c>2&&typeof a[c-1]=='function'){d=a[--c]}"),f:"C[m]=d?d(C[m],r[m]):r[m]"}),Z=u(G,F,{i:!1});f(/x/)&&(f=function(t){return typeof t=="function"&&"[object Function]"==M.call(t)}),o.assign=H,o.createCallback=function(t,r,e){if(null==t)return m;
|
|
var n=typeof t;if("function"!=n){if("object"!=n)return function(r){return r[t]};var o=X(t);return function(r){for(var e=o.length,n=!1;e--&&(n=c(r[o[e]],t[o[e]],b)););return n}}return typeof r=="undefined"||d&&!d.test(q.call(t))?t:1===e?function(e){return t.call(r,e)}:2===e?function(e,n){return t.call(r,e,n)}:4===e?function(e,n,o,u){return t.call(r,e,n,o,u)}:function(e,n,o){return t.call(r,e,n,o)}},o.filter=s,o.forEach=p,o.forIn=Z,o.keys=X,o.each=p,o.extend=H,o.select=s,o.identity=m,o.isArguments=a,o.isArray=U,o.isEqual=c,o.isFunction=f,o.isObject=i,o.isString=l,o.VERSION="1.3.1",typeof define=="function"&&typeof define.amd=="object"&&define.amd?(t._=o, define(function(){return o
|
|
})):I&&!I.nodeType?B?(B.exports=o)._=o:I._=o:t._=o}(this);
|
|
},{}],70:[function(require,module,exports){
|
|
var window = require("global/window")
|
|
var once = require("once")
|
|
|
|
var messages = {
|
|
"0": "Internal XMLHttpRequest Error",
|
|
"4": "4xx Client Error",
|
|
"5": "5xx Server Error"
|
|
}
|
|
|
|
var XHR = window.XMLHttpRequest || noop
|
|
var XDR = "withCredentials" in (new XHR()) ?
|
|
window.XMLHttpRequest : window.XDomainRequest
|
|
|
|
module.exports = createXHR
|
|
|
|
function createXHR(options, callback) {
|
|
if (typeof options === "string") {
|
|
options = { uri: options }
|
|
}
|
|
|
|
options = options || {}
|
|
callback = once(callback)
|
|
|
|
var xhr
|
|
|
|
if (options.cors) {
|
|
xhr = new XDR()
|
|
xhr.withCredentials = true
|
|
} else {
|
|
xhr = new XHR()
|
|
}
|
|
|
|
var uri = xhr.url = options.uri
|
|
var method = xhr.method = options.method || "GET"
|
|
var body = options.body || options.data
|
|
var headers = xhr.headers = options.headers || {}
|
|
var isJson = false
|
|
|
|
if ("json" in options) {
|
|
isJson = true
|
|
headers["Content-Type"] = "application/json"
|
|
body = JSON.stringify(options.json)
|
|
}
|
|
|
|
xhr.onreadystatechange = readystatechange
|
|
xhr.onload = load
|
|
xhr.onerror = error
|
|
// IE9 must have onprogress be set to a unique function.
|
|
xhr.onprogress = function () {
|
|
// IE must die
|
|
}
|
|
// hate IE
|
|
xhr.ontimeout = noop
|
|
xhr.open(method, uri)
|
|
xhr.timeout = "timeout" in options ? options.timeout : 5000
|
|
|
|
if ( xhr.setRequestHeader) {
|
|
Object.keys(headers).forEach(function (key) {
|
|
xhr.setRequestHeader(key, headers[key])
|
|
})
|
|
}
|
|
|
|
xhr.send(body)
|
|
|
|
return xhr
|
|
|
|
function readystatechange() {
|
|
if (xhr.readyState === 4) {
|
|
load()
|
|
}
|
|
}
|
|
|
|
function load() {
|
|
var error = null
|
|
var status = xhr.statusCode = xhr.status
|
|
var body = xhr.body = xhr.response ||
|
|
xhr.responseText || xhr.responseXML
|
|
|
|
if (status === 0 || (status >= 400 && status < 600)) {
|
|
var message = xhr.responseText ||
|
|
messages[String(xhr.status).charAt(0)]
|
|
error = new Error(message)
|
|
|
|
error.statusCode = xhr.status
|
|
}
|
|
|
|
if (isJson) {
|
|
try {
|
|
body = xhr.body = JSON.parse(body)
|
|
} catch (e) {}
|
|
}
|
|
|
|
callback(error, xhr, body)
|
|
}
|
|
|
|
function error(evt) {
|
|
callback(evt, xhr)
|
|
}
|
|
}
|
|
|
|
|
|
function noop() {}
|
|
|
|
},{"global/window":71,"once":72}],71:[function(require,module,exports){
|
|
var global=self;if (typeof window !== "undefined") {
|
|
module.exports = window
|
|
} else if (typeof global !== "undefined") {
|
|
module.exports = global
|
|
} else {
|
|
module.exports = {}
|
|
}
|
|
|
|
},{}],72:[function(require,module,exports){
|
|
module.exports = once
|
|
|
|
once.proto = once(function () {
|
|
Object.defineProperty(Function.prototype, 'once', {
|
|
value: function () {
|
|
return once(this)
|
|
},
|
|
configurable: true
|
|
})
|
|
})
|
|
|
|
function once (fn) {
|
|
var called = false
|
|
return function () {
|
|
if (called) return
|
|
called = true
|
|
return fn.apply(this, arguments)
|
|
}
|
|
}
|
|
|
|
},{}],73:[function(require,module,exports){
|
|
var global=self;/**
|
|
* @license
|
|
* Lo-Dash 1.3.1 (Custom Build) lodash.com/license
|
|
* Build: `lodash include="each,extend"`
|
|
* Underscore.js 1.4.4 underscorejs.org/LICENSE
|
|
*/
|
|
;!function(t){function r(t){return typeof t.toString!="function"&&typeof(t+"")=="string"}function e(t){t.length=0,m.length<y&&m.push(t)}function n(t){var r=t.k;r&&n(r),t.b=t.k=t.object=t.number=t.string=null,g.length<y&&g.push(t)}function o(){}function u(){var t=g.pop()||{a:"",b:null,c:"",k:null,"false":!1,d:"",e:"",f:"","null":!1,number:null,object:null,push:null,g:null,string:null,h:"","true":!1,undefined:!1,i:!1,j:!1};t.g=d,t.b=t.c=t.f=t.h="",t.e="r",t.i=!0,t.j=!!W;for(var r,e=0;r=arguments[e];e++)for(var u in r)t[u]=r[u];
|
|
e=t.a,t.d=/^[^,]+/.exec(e)[0],r=Function,e="return function("+e+"){",u="var m,r="+t.d+",C="+t.e+";if(!r)return C;"+t.h+";",t.b?(u+="var s=r.length;m=-1;if("+t.b+"){",V.unindexedChars&&(u+="if(q(r)){r=r.split('')}"),u+="while(++m<s){"+t.f+";}}else{"):V.nonEnumArgs&&(u+="var s=r.length;m=-1;if(s&&n(r)){while(++m<s){m+='';"+t.f+";}}else{"),V.enumPrototypes&&(u+="var E=typeof r=='function';"),V.enumErrorProps&&(u+="var D=r===j||r instanceof Error;");var c=[];if(V.enumPrototypes&&c.push('!(E&&m=="prototype")'),V.enumErrorProps&&c.push('!(D&&(m=="message"||m=="name"))'),t.i&&t.j)u+="var A=-1,B=z[typeof r]&&t(r),s=B?B.length:0;while(++A<s){m=B[A];",c.length&&(u+="if("+c.join("&&")+"){"),u+=t.f+";",c.length&&(u+="}"),u+="}";
|
|
else if(u+="for(m in r){",t.i&&c.push("l.call(r, m)"),c.length&&(u+="if("+c.join("&&")+"){"),u+=t.f+";",c.length&&(u+="}"),u+="}",V.nonEnumShadows){for(u+="if(r!==y){var h=r.constructor,p=r===(h&&h.prototype),e=r===H?G:r===j?i:J.call(r),v=w[e];",k=0;7>k;k++)u+="m='"+t.g[k]+"';if((!(p&&v[m])&&l.call(r,m))",t.i||(u+="||(!v[m]&&r[m]!==y[m])"),u+="){"+t.f+"}";u+="}"}return(t.b||V.nonEnumArgs)&&(u+="}"),u+=t.c+";return C",r=r("i,j,l,n,o,q,t,u,y,z,w,G,H,J",e+u+"}"),n(t),r(E,F,q,a,Q,l,W,o,z,A,L,S,D,$)}function a(t){return $.call(t)==v
|
|
}function c(t,n,u,i,l,s){var p=u===h;if(typeof u=="function"&&!p){u=o.createCallback(u,i,2);var g=u(t,n);if(typeof g!="undefined")return!!g}if(t===n)return 0!==t||1/t==1/n;var y=typeof t,b=typeof n;if(t===t&&(!t||"function"!=y&&"object"!=y)&&(!n||"function"!=b&&"object"!=b))return!1;if(null==t||null==n)return t===n;if(b=$.call(t),y=$.call(n),b==v&&(b=x),y==v&&(y=x),b!=y)return!1;switch(b){case O:case C:return+t==+n;case _:return t!=+t?n!=+n:0==t?1/t==1/n:t==+n;case w:case S:return t==n+""}if(y=b==j,!y){if(q.call(t,"__wrapped__")||q.call(n,"__wrapped__"))return c(t.__wrapped__||t,n.__wrapped__||n,u,i,l,s);
|
|
if(b!=x||!V.nodeClass&&(r(t)||r(n)))return!1;var b=!V.argsObject&&a(t)?Object:t.constructor,d=!V.argsObject&&a(n)?Object:n.constructor;if(b!=d&&(!f(b)||!(b instanceof b&&f(d)&&d instanceof d)))return!1}for(d=!l,l||(l=m.pop()||[]),s||(s=m.pop()||[]),b=l.length;b--;)if(l[b]==t)return s[b]==n;var E=0,g=!0;if(l.push(t),s.push(n),y){if(b=t.length,E=n.length,g=E==t.length,!g&&!p)return g;for(;E--;)if(y=b,d=n[E],p)for(;y--&&!(g=c(t[y],d,u,i,l,s)););else if(!(g=c(t[E],d,u,i,l,s)))break;return g}return Y(n,function(r,e,n){return q.call(n,e)?(E++,g=q.call(t,e)&&c(t[e],r,u,i,l,s)):void 0
|
|
}),g&&!p&&Y(t,function(t,r,e){return q.call(e,r)?g=-1<--E:void 0}),d&&(e(l),e(s)),g}function f(t){return typeof t=="function"}function i(t){return!(!t||!A[typeof t])}function l(t){return typeof t=="string"||$.call(t)==S}function s(t,r,e){if(r&&typeof e=="undefined"&&Q(t)){e=-1;for(var n=t.length;++e<n&&false!==r(t[e],e,t););}else X(t,r,e);return t}function p(t){return t}var m=[],g=[],h={},y=40,b=(b=/\bthis\b/)&&b.test(function(){return this})&&b,d="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),v="[object Arguments]",j="[object Array]",O="[object Boolean]",C="[object Date]",E="[object Error]",_="[object Number]",x="[object Object]",w="[object RegExp]",S="[object String]",A={"boolean":!1,"function":!0,object:!0,number:!1,string:!1,undefined:!1},P=A[typeof exports]&&exports,I=A[typeof module]&&module&&module.exports==P&&module,B=A[typeof global]&&global;
|
|
!B||B.global!==B&&B.window!==B||(t=B);var F=Error.prototype,z=Object.prototype,D=String.prototype,B=RegExp("^"+(z.valueOf+"").replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/valueOf|for [^\]]+/g,".+?")+"$"),N=Function.prototype.toString,q=z.hasOwnProperty,R=z.propertyIsEnumerable,$=z.toString,M=B.test(M=$.bind)&&M,T=B.test(T=Object.create)&&T,G=B.test(G=Array.isArray)&&G,H=B.test(H=Object.keys)&&H,T=B.test(t.attachEvent),J=M&&!/\n|true/.test(M+T),L={};L[j]=L[C]=L[_]={constructor:!0,toLocaleString:!0,toString:!0,valueOf:!0},L[O]=L[S]={constructor:!0,toString:!0,valueOf:!0},L[E]=L["[object Function]"]=L[w]={constructor:!0,toString:!0},L[x]={constructor:!0},function(){for(var t=d.length;t--;){var r,e=d[t];
|
|
for(r in L)q.call(L,r)&&!q.call(L[r],e)&&(L[r][e]=!1)}}();var V=o.support={};!function(){var t=function(){this.x=1},r=[];t.prototype={valueOf:1,y:1};for(var e in new t)r.push(e);for(e in arguments);V.argsObject=arguments.constructor==Object&&!(arguments instanceof Array),V.argsClass=a(arguments),V.enumErrorProps=R.call(F,"message")||R.call(F,"name"),V.enumPrototypes=R.call(t,"prototype"),V.fastBind=M&&!J,V.nonEnumArgs=0!=e,V.nonEnumShadows=!/valueOf/.test(r),V.unindexedChars="xx"!="x"[0]+Object("x")[0];
|
|
try{V.nodeClass=!($.call(document)==x&&!({toString:0}+""))}catch(n){V.nodeClass=!0}}(1);var K={a:"x,F,k",h:"var a=arguments,b=0,c=typeof k=='number'?2:a.length;while(++b<c){r=a[b];if(r&&z[typeof r]){",f:"if(typeof C[m]=='undefined')C[m]=r[m]",c:"}}"},T={a:"f,d,I",h:"d=d&&typeof I=='undefined'?d:u.createCallback(d,I)",b:"typeof s=='number'",f:"if(d(r[m],m,f)===false)return C"},B={h:"if(!z[typeof r])return C;"+T.h,b:!1};V.argsClass||(a=function(t){return t?q.call(t,"callee"):!1});var Q=G||function(t){return t?typeof t=="object"&&$.call(t)==j:!1
|
|
},U=u({a:"x",e:"[]",h:"if(!(z[typeof x]))return C",f:"C.push(m)"}),W=H?function(t){return i(t)?V.enumPrototypes&&typeof t=="function"||V.nonEnumArgs&&t.length&&a(t)?U(t):H(t):[]}:U,X=u(T),G=u(K,{h:K.h.replace(";",";if(c>3&&typeof a[c-2]=='function'){var d=u.createCallback(a[--c-1],a[c--],2)}else if(c>2&&typeof a[c-1]=='function'){d=a[--c]}"),f:"C[m]=d?d(C[m],r[m]):r[m]"}),Y=u(T,B,{i:!1});f(/x/)&&(f=function(t){return typeof t=="function"&&"[object Function]"==$.call(t)}),o.assign=G,o.createCallback=function(t,r,e){if(null==t)return p;
|
|
var n=typeof t;if("function"!=n){if("object"!=n)return function(r){return r[t]};var o=W(t);return function(r){for(var e=o.length,n=!1;e--&&(n=c(r[o[e]],t[o[e]],h)););return n}}return typeof r=="undefined"||b&&!b.test(N.call(t))?t:1===e?function(e){return t.call(r,e)}:2===e?function(e,n){return t.call(r,e,n)}:4===e?function(e,n,o,u){return t.call(r,e,n,o,u)}:function(e,n,o){return t.call(r,e,n,o)}},o.forEach=s,o.forIn=Y,o.keys=W,o.each=s,o.extend=G,o.identity=p,o.isArguments=a,o.isArray=Q,o.isEqual=c,o.isFunction=f,o.isObject=i,o.isString=l,o.VERSION="1.3.1",typeof define=="function"&&typeof define.amd=="object"&&define.amd?(t._=o, define(function(){return o
|
|
})):P&&!P.nodeType?I?(I.exports=o)._=o:P._=o:t._=o}(this);
|
|
},{}],74:[function(require,module,exports){
|
|
var _ = require('lodash');
|
|
var serializer = new XMLSerializer();
|
|
var XML_NS = 'http://www.w3.org/XML/1998/namespace';
|
|
var TOP_LEVEL_LOOKUP = {};
|
|
var LOOKUP = {};
|
|
var LOOKUP_EXT = {};
|
|
|
|
|
|
var find = exports.find = function (xml, NS, selector) {
|
|
var children = xml.querySelectorAll(selector);
|
|
return _.filter(children, function (child) {
|
|
return child.namespaceURI === NS && child.parentNode == xml;
|
|
});
|
|
};
|
|
|
|
exports.findOrCreate = function (xml, NS, selector) {
|
|
var existing = find(xml, NS, selector);
|
|
if (existing.length) {
|
|
return existing[0];
|
|
} else {
|
|
var created = document.createElementNS(NS, selector);
|
|
xml.appendChild(created);
|
|
return created;
|
|
}
|
|
};
|
|
|
|
exports.init = function (self, xml, data, parentNS) {
|
|
self.xml = xml || document.createElementNS(self.NS, self.EL);
|
|
if (parentNS && parentNS !== self.NS || !self.xml.parentNode || self.xml.parentNode.namespaceURI !== self.NS) {
|
|
self.xml.setAttribute('xmlns', self.NS);
|
|
}
|
|
|
|
self._extensions = {};
|
|
_.each(self.xml.childNodes, function (child) {
|
|
var childName = child.namespaceURI + '|' + child.localName;
|
|
var ChildJXT = LOOKUP[childName];
|
|
if (ChildJXT !== undefined) {
|
|
var name = ChildJXT.prototype._name;
|
|
self._extensions[name] = new ChildJXT(null, child);
|
|
self._extensions[name].parent = self;
|
|
}
|
|
});
|
|
|
|
_.extend(self, data);
|
|
return self;
|
|
};
|
|
|
|
exports.getSubText = function (xml, NS, element) {
|
|
var subs = find(xml, NS, element);
|
|
if (!subs) {
|
|
return '';
|
|
}
|
|
|
|
for (var i = 0; i < subs.length; i++) {
|
|
if (subs[i].namespaceURI === NS) {
|
|
return subs[i].textContent || '';
|
|
}
|
|
}
|
|
|
|
return '';
|
|
};
|
|
|
|
exports.getMultiSubText = function (xml, NS, element, extractor) {
|
|
var subs = find(xml, NS, element);
|
|
var results = [];
|
|
extractor = extractor || function (sub) {
|
|
return sub.textContent || '';
|
|
};
|
|
|
|
for (var i = 0; i < subs.length; i++) {
|
|
if (subs[i].namespaceURI === NS) {
|
|
results.push(extractor(subs[i]));
|
|
}
|
|
}
|
|
|
|
return results;
|
|
};
|
|
|
|
exports.getSubLangText = function (xml, NS, element, defaultLang) {
|
|
var subs = find(xml, NS, element);
|
|
if (!subs) {
|
|
return {};
|
|
}
|
|
|
|
var lang, sub;
|
|
var results = {};
|
|
var langs = [];
|
|
|
|
for (var i = 0; i < subs.length; i++) {
|
|
sub = subs[i];
|
|
if (sub.namespaceURI === NS) {
|
|
lang = sub.getAttributeNS(XML_NS, 'lang') || defaultLang;
|
|
langs.push(lang);
|
|
results[lang] = sub.textContent || '';
|
|
}
|
|
}
|
|
|
|
return results;
|
|
};
|
|
|
|
|
|
exports.setSubText = function (xml, NS, element, value) {
|
|
var subs = find(xml, NS, element);
|
|
if (!subs.length) {
|
|
if (value) {
|
|
var sub = document.createElementNS(NS, element);
|
|
sub.textContent = value;
|
|
xml.appendChild(sub);
|
|
}
|
|
} else {
|
|
for (var i = 0; i < subs.length; i++) {
|
|
if (subs[i].namespaceURI === NS) {
|
|
if (value) {
|
|
subs[i].textContent = value;
|
|
return;
|
|
} else {
|
|
xml.removeChild(subs[i]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
exports.setMultiSubText = function (xml, NS, element, value, builder) {
|
|
var subs = find(xml, NS, element);
|
|
var values = [];
|
|
builder = builder || function (value) {
|
|
var sub = document.createElementNS(NS, element);
|
|
sub.textContent = value;
|
|
xml.appendChild(sub);
|
|
};
|
|
if (typeof value === 'string') {
|
|
values = (value || '').split('\n');
|
|
} else {
|
|
values = value;
|
|
}
|
|
_.forEach(subs, function (sub) {
|
|
xml.removeChild(sub);
|
|
});
|
|
_.forEach(values, function (val) {
|
|
if (val) {
|
|
builder(val);
|
|
}
|
|
});
|
|
};
|
|
|
|
exports.setSubLangText = function (xml, NS, element, value, defaultLang) {
|
|
var sub, lang;
|
|
var subs = find(xml, NS, element);
|
|
if (subs.length) {
|
|
for (var i = 0; i < subs.length; i++) {
|
|
sub = subs[i];
|
|
if (sub.namespaceURI === NS) {
|
|
xml.removeChild(sub);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (typeof value === 'string') {
|
|
sub = document.createElementNS(NS, element);
|
|
sub.textContent = value;
|
|
xml.appendChild(sub);
|
|
} else if (typeof value === 'object') {
|
|
for (lang in value) {
|
|
if (value.hasOwnProperty(lang)) {
|
|
sub = document.createElementNS(NS, element);
|
|
if (lang !== defaultLang) {
|
|
sub.setAttributeNS(XML_NS, 'lang', lang);
|
|
}
|
|
sub.textContent = value[lang];
|
|
xml.appendChild(sub);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
exports.getAttribute = function (xml, attr, defaultVal) {
|
|
return xml.getAttribute(attr) || defaultVal || '';
|
|
};
|
|
|
|
exports.setAttribute = function (xml, attr, value, force) {
|
|
if (value || force) {
|
|
xml.setAttribute(attr, value);
|
|
} else {
|
|
xml.removeAttribute(attr);
|
|
}
|
|
};
|
|
|
|
exports.getBoolAttribute = function (xml, attr, defaultVal) {
|
|
var val = xml.getAttribute(attr) || defaultVal || '';
|
|
return val === 'true' || val === '1';
|
|
};
|
|
|
|
exports.setBoolAttribute = function (xml, attr, value) {
|
|
if (value) {
|
|
xml.setAttribute(attr, '1');
|
|
} else {
|
|
xml.removeAttribute(attr);
|
|
}
|
|
};
|
|
|
|
exports.getSubAttribute = function (xml, NS, sub, attr, defaultVal) {
|
|
var subs = find(xml, NS, sub);
|
|
if (!subs) {
|
|
return '';
|
|
}
|
|
|
|
for (var i = 0; i < subs.length; i++) {
|
|
if (subs[i].namespaceURI === NS) {
|
|
return subs[i].getAttribute(attr) || defaultVal || '';
|
|
}
|
|
}
|
|
|
|
return '';
|
|
};
|
|
|
|
exports.setSubAttribute = function (xml, NS, sub, attr, value) {
|
|
var subs = find(xml, NS, sub);
|
|
if (!subs.length) {
|
|
if (value) {
|
|
sub = document.createElementNS(NS, sub);
|
|
sub.setAttribute(attr, value);
|
|
xml.appendChild(sub);
|
|
}
|
|
} else {
|
|
for (var i = 0; i < subs.length; i++) {
|
|
if (subs[i].namespaceURI === NS) {
|
|
if (value) {
|
|
subs[i].setAttribute(attr, value);
|
|
return;
|
|
} else {
|
|
subs[i].removeAttribute(attr);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
exports.toString = function () {
|
|
return serializer.serializeToString(this.xml);
|
|
};
|
|
|
|
exports.toJSON = function () {
|
|
var prop;
|
|
var result = {};
|
|
var exclude = {
|
|
constructor: true,
|
|
NS: true,
|
|
EL: true,
|
|
toString: true,
|
|
toJSON: true,
|
|
_extensions: true,
|
|
prototype: true,
|
|
xml: true,
|
|
parent: true,
|
|
_name: true
|
|
};
|
|
for (prop in this._extensions) {
|
|
if (this._extensions[prop].toJSON) {
|
|
result[prop] = this._extensions[prop].toJSON();
|
|
}
|
|
}
|
|
for (prop in this) {
|
|
if (!exclude[prop] && !((LOOKUP_EXT[this.NS + '|' + this.EL] || {})[prop]) && !this._extensions[prop] && prop[0] !== '_') {
|
|
var val = this[prop];
|
|
if (typeof val == 'function') continue;
|
|
var type = Object.prototype.toString.call(val);
|
|
if (type.indexOf('Object') >= 0) {
|
|
if (Object.keys(val).length > 0) {
|
|
result[prop] = val;
|
|
}
|
|
} else if (type.indexOf('Array') >= 0) {
|
|
if (val.length > 0) {
|
|
result[prop] = val;
|
|
}
|
|
} else if (!!val) {
|
|
result[prop] = val;
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
};
|
|
|
|
exports.extend = function (ParentJXT, ChildJXT) {
|
|
var parentName = ParentJXT.prototype.NS + '|' + ParentJXT.prototype.EL;
|
|
var name = ChildJXT.prototype._name;
|
|
var qName = ChildJXT.prototype.NS + '|' + ChildJXT.prototype.EL;
|
|
|
|
LOOKUP[qName] = ChildJXT;
|
|
if (!LOOKUP_EXT[qName]) {
|
|
LOOKUP_EXT[qName] = {};
|
|
}
|
|
if (!LOOKUP_EXT[parentName]) {
|
|
LOOKUP_EXT[parentName] = {};
|
|
}
|
|
LOOKUP_EXT[parentName][name] = ChildJXT;
|
|
|
|
ParentJXT.prototype.__defineGetter__(name, function () {
|
|
if (!this._extensions[name]) {
|
|
var existing = exports.find(this.xml, ChildJXT.prototype.NS, ChildJXT.prototype.EL);
|
|
if (!existing.length) {
|
|
this._extensions[name] = new ChildJXT();
|
|
this.xml.appendChild(this._extensions[name].xml);
|
|
} else {
|
|
this._extensions[name] = new ChildJXT(null, existing[0]);
|
|
}
|
|
this._extensions[name].parent = this;
|
|
}
|
|
return this._extensions[name];
|
|
});
|
|
ParentJXT.prototype.__defineSetter__(name, function (value) {
|
|
var child = this[name];
|
|
_.extend(child, value);
|
|
});
|
|
};
|
|
|
|
exports.topLevel = function (JXT) {
|
|
var name = JXT.prototype.NS + '|' + JXT.prototype.EL;
|
|
LOOKUP[name] = JXT;
|
|
TOP_LEVEL_LOOKUP[name] = JXT;
|
|
};
|
|
|
|
exports.build = function (xml) {
|
|
var JXT = TOP_LEVEL_LOOKUP[xml.namespaceURI + '|' + xml.localName];
|
|
if (JXT) {
|
|
return new JXT(null, xml);
|
|
}
|
|
};
|
|
|
|
exports.XML_NS = XML_NS;
|
|
exports.TOP_LEVEL_LOOKUP = TOP_LEVEL_LOOKUP;
|
|
exports.LOOKUP_EXT = LOOKUP_EXT;
|
|
exports.LOOKUP = LOOKUP;
|
|
|
|
},{"lodash":75}],75:[function(require,module,exports){
|
|
var global=self;/**
|
|
* @license
|
|
* Lo-Dash 1.0.1 (Custom Build) <http://lodash.com/>
|
|
* Build: `lodash modern -o ./dist/lodash.js`
|
|
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
|
|
* Based on Underscore.js 1.4.4 <http://underscorejs.org/>
|
|
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud Inc.
|
|
* Available under MIT license <http://lodash.com/license>
|
|
*/
|
|
;(function(window, undefined) {
|
|
|
|
/** Detect free variable `exports` */
|
|
var freeExports = typeof exports == 'object' && exports;
|
|
|
|
/** Detect free variable `module` */
|
|
var freeModule = typeof module == 'object' && module && module.exports == freeExports && module;
|
|
|
|
/** Detect free variable `global` and use it as `window` */
|
|
var freeGlobal = typeof global == 'object' && global;
|
|
if (freeGlobal.global === freeGlobal) {
|
|
window = freeGlobal;
|
|
}
|
|
|
|
/** Used for array and object method references */
|
|
var arrayRef = [],
|
|
objectRef = {};
|
|
|
|
/** Used to generate unique IDs */
|
|
var idCounter = 0;
|
|
|
|
/** Used internally to indicate various things */
|
|
var indicatorObject = objectRef;
|
|
|
|
/** Used by `cachedContains` as the default size when optimizations are enabled for large arrays */
|
|
var largeArraySize = 30;
|
|
|
|
/** Used to restore the original `_` reference in `noConflict` */
|
|
var oldDash = window._;
|
|
|
|
/** Used to match HTML entities */
|
|
var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g;
|
|
|
|
/** Used to match empty string literals in compiled template source */
|
|
var reEmptyStringLeading = /\b__p \+= '';/g,
|
|
reEmptyStringMiddle = /\b(__p \+=) '' \+/g,
|
|
reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
|
|
|
|
/** Used to match regexp flags from their coerced string values */
|
|
var reFlags = /\w*$/;
|
|
|
|
/** Used to detect if a method is native */
|
|
var reNative = RegExp('^' +
|
|
(objectRef.valueOf + '')
|
|
.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
.replace(/valueOf|for [^\]]+/g, '.+?') + '$'
|
|
);
|
|
|
|
/**
|
|
* Used to match ES6 template delimiters
|
|
* http://people.mozilla.org/~jorendorff/es6-draft.html#sec-7.8.6
|
|
*/
|
|
var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
|
|
|
|
/** Used to match "interpolate" template delimiters */
|
|
var reInterpolate = /<%=([\s\S]+?)%>/g;
|
|
|
|
/** Used to ensure capturing order of template delimiters */
|
|
var reNoMatch = /($^)/;
|
|
|
|
/** Used to match HTML characters */
|
|
var reUnescapedHtml = /[&<>"']/g;
|
|
|
|
/** Used to match unescaped characters in compiled string literals */
|
|
var reUnescapedString = /['\n\r\t\u2028\u2029\\]/g;
|
|
|
|
/** Used to make template sourceURLs easier to identify */
|
|
var templateCounter = 0;
|
|
|
|
/** Native method shortcuts */
|
|
var ceil = Math.ceil,
|
|
concat = arrayRef.concat,
|
|
floor = Math.floor,
|
|
getPrototypeOf = reNative.test(getPrototypeOf = Object.getPrototypeOf) && getPrototypeOf,
|
|
hasOwnProperty = objectRef.hasOwnProperty,
|
|
push = arrayRef.push,
|
|
toString = objectRef.toString;
|
|
|
|
/* Native method shortcuts for methods with the same name as other `lodash` methods */
|
|
var nativeBind = reNative.test(nativeBind = slice.bind) && nativeBind,
|
|
nativeIsArray = reNative.test(nativeIsArray = Array.isArray) && nativeIsArray,
|
|
nativeIsFinite = window.isFinite,
|
|
nativeIsNaN = window.isNaN,
|
|
nativeKeys = reNative.test(nativeKeys = Object.keys) && nativeKeys,
|
|
nativeMax = Math.max,
|
|
nativeMin = Math.min,
|
|
nativeRandom = Math.random;
|
|
|
|
/** `Object#toString` result shortcuts */
|
|
var argsClass = '[object Arguments]',
|
|
arrayClass = '[object Array]',
|
|
boolClass = '[object Boolean]',
|
|
dateClass = '[object Date]',
|
|
funcClass = '[object Function]',
|
|
numberClass = '[object Number]',
|
|
objectClass = '[object Object]',
|
|
regexpClass = '[object RegExp]',
|
|
stringClass = '[object String]';
|
|
|
|
/** Detect various environments */
|
|
var isIeOpera = !!window.attachEvent,
|
|
isV8 = nativeBind && !/\n|true/.test(nativeBind + isIeOpera);
|
|
|
|
/* Detect if `Function#bind` exists and is inferred to be fast (all but V8) */
|
|
var isBindFast = nativeBind && !isV8;
|
|
|
|
/* Detect if `Object.keys` exists and is inferred to be fast (IE, Opera, V8) */
|
|
var isKeysFast = nativeKeys && (isIeOpera || isV8);
|
|
|
|
/** Used to identify object classifications that `_.clone` supports */
|
|
var cloneableClasses = {};
|
|
cloneableClasses[funcClass] = false;
|
|
cloneableClasses[argsClass] = cloneableClasses[arrayClass] =
|
|
cloneableClasses[boolClass] = cloneableClasses[dateClass] =
|
|
cloneableClasses[numberClass] = cloneableClasses[objectClass] =
|
|
cloneableClasses[regexpClass] = cloneableClasses[stringClass] = true;
|
|
|
|
/** Used to lookup a built-in constructor by [[Class]] */
|
|
var ctorByClass = {};
|
|
ctorByClass[arrayClass] = Array;
|
|
ctorByClass[boolClass] = Boolean;
|
|
ctorByClass[dateClass] = Date;
|
|
ctorByClass[objectClass] = Object;
|
|
ctorByClass[numberClass] = Number;
|
|
ctorByClass[regexpClass] = RegExp;
|
|
ctorByClass[stringClass] = String;
|
|
|
|
/** Used to determine if values are of the language type Object */
|
|
var objectTypes = {
|
|
'boolean': false,
|
|
'function': true,
|
|
'object': true,
|
|
'number': false,
|
|
'string': false,
|
|
'undefined': false
|
|
};
|
|
|
|
/** Used to escape characters for inclusion in compiled string literals */
|
|
var stringEscapes = {
|
|
'\\': '\\',
|
|
"'": "'",
|
|
'\n': 'n',
|
|
'\r': 'r',
|
|
'\t': 't',
|
|
'\u2028': 'u2028',
|
|
'\u2029': 'u2029'
|
|
};
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* Creates a `lodash` object, that wraps the given `value`, to enable method
|
|
* chaining.
|
|
*
|
|
* In addition to Lo-Dash methods, wrappers also have the following `Array` methods:
|
|
* `concat`, `join`, `pop`, `push`, `reverse`, `shift`, `slice`, `sort`, `splice`,
|
|
* and `unshift`
|
|
*
|
|
* The chainable wrapper functions are:
|
|
* `after`, `assign`, `bind`, `bindAll`, `bindKey`, `chain`, `compact`, `compose`,
|
|
* `concat`, `countBy`, `debounce`, `defaults`, `defer`, `delay`, `difference`,
|
|
* `filter`, `flatten`, `forEach`, `forIn`, `forOwn`, `functions`, `groupBy`,
|
|
* `initial`, `intersection`, `invert`, `invoke`, `keys`, `map`, `max`, `memoize`,
|
|
* `merge`, `min`, `object`, `omit`, `once`, `pairs`, `partial`, `partialRight`,
|
|
* `pick`, `pluck`, `push`, `range`, `reject`, `rest`, `reverse`, `shuffle`,
|
|
* `slice`, `sort`, `sortBy`, `splice`, `tap`, `throttle`, `times`, `toArray`,
|
|
* `union`, `uniq`, `unshift`, `values`, `where`, `without`, `wrap`, and `zip`
|
|
*
|
|
* The non-chainable wrapper functions are:
|
|
* `clone`, `cloneDeep`, `contains`, `escape`, `every`, `find`, `has`, `identity`,
|
|
* `indexOf`, `isArguments`, `isArray`, `isBoolean`, `isDate`, `isElement`, `isEmpty`,
|
|
* `isEqual`, `isFinite`, `isFunction`, `isNaN`, `isNull`, `isNumber`, `isObject`,
|
|
* `isPlainObject`, `isRegExp`, `isString`, `isUndefined`, `join`, `lastIndexOf`,
|
|
* `mixin`, `noConflict`, `pop`, `random`, `reduce`, `reduceRight`, `result`,
|
|
* `shift`, `size`, `some`, `sortedIndex`, `template`, `unescape`, and `uniqueId`
|
|
*
|
|
* The wrapper functions `first` and `last` return wrapped values when `n` is
|
|
* passed, otherwise they return unwrapped values.
|
|
*
|
|
* @name _
|
|
* @constructor
|
|
* @category Chaining
|
|
* @param {Mixed} value The value to wrap in a `lodash` instance.
|
|
* @returns {Object} Returns a `lodash` instance.
|
|
*/
|
|
function lodash(value) {
|
|
// exit early if already wrapped, even if wrapped by a different `lodash` constructor
|
|
if (value && typeof value == 'object' && value.__wrapped__) {
|
|
return value;
|
|
}
|
|
// allow invoking `lodash` without the `new` operator
|
|
if (!(this instanceof lodash)) {
|
|
return new lodash(value);
|
|
}
|
|
this.__wrapped__ = value;
|
|
}
|
|
|
|
/**
|
|
* By default, the template delimiters used by Lo-Dash are similar to those in
|
|
* embedded Ruby (ERB). Change the following template settings to use alternative
|
|
* delimiters.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @type Object
|
|
*/
|
|
lodash.templateSettings = {
|
|
|
|
/**
|
|
* Used to detect `data` property values to be HTML-escaped.
|
|
*
|
|
* @memberOf _.templateSettings
|
|
* @type RegExp
|
|
*/
|
|
'escape': /<%-([\s\S]+?)%>/g,
|
|
|
|
/**
|
|
* Used to detect code to be evaluated.
|
|
*
|
|
* @memberOf _.templateSettings
|
|
* @type RegExp
|
|
*/
|
|
'evaluate': /<%([\s\S]+?)%>/g,
|
|
|
|
/**
|
|
* Used to detect `data` property values to inject.
|
|
*
|
|
* @memberOf _.templateSettings
|
|
* @type RegExp
|
|
*/
|
|
'interpolate': reInterpolate,
|
|
|
|
/**
|
|
* Used to reference the data object in the template text.
|
|
*
|
|
* @memberOf _.templateSettings
|
|
* @type String
|
|
*/
|
|
'variable': '',
|
|
|
|
/**
|
|
* Used to import variables into the compiled template.
|
|
*
|
|
* @memberOf _.templateSettings
|
|
* @type Object
|
|
*/
|
|
'imports': {
|
|
|
|
/**
|
|
* A reference to the `lodash` function.
|
|
*
|
|
* @memberOf _.templateSettings.imports
|
|
* @type Function
|
|
*/
|
|
'_': lodash
|
|
}
|
|
};
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* The template used to create iterator functions.
|
|
*
|
|
* @private
|
|
* @param {Obect} data The data object used to populate the text.
|
|
* @returns {String} Returns the interpolated text.
|
|
*/
|
|
var iteratorTemplate = function(obj) {
|
|
|
|
var __p = 'var index, iterable = ' +
|
|
(obj.firstArg ) +
|
|
', result = iterable;\nif (!iterable) return result;\n' +
|
|
(obj.top ) +
|
|
';\n';
|
|
if (obj.arrays) {
|
|
__p += 'var length = iterable.length; index = -1;\nif (' +
|
|
(obj.arrays ) +
|
|
') {\n while (++index < length) {\n ' +
|
|
(obj.loop ) +
|
|
'\n }\n}\nelse { ';
|
|
} ;
|
|
|
|
if (obj.isKeysFast && obj.useHas) {
|
|
__p += '\n var ownIndex = -1,\n ownProps = objectTypes[typeof iterable] ? nativeKeys(iterable) : [],\n length = ownProps.length;\n\n while (++ownIndex < length) {\n index = ownProps[ownIndex];\n ' +
|
|
(obj.loop ) +
|
|
'\n } ';
|
|
} else {
|
|
__p += '\n for (index in iterable) {';
|
|
if (obj.useHas) {
|
|
__p += '\n if (';
|
|
if (obj.useHas) {
|
|
__p += 'hasOwnProperty.call(iterable, index)';
|
|
} ;
|
|
__p += ') { ';
|
|
} ;
|
|
__p +=
|
|
(obj.loop ) +
|
|
'; ';
|
|
if (obj.useHas) {
|
|
__p += '\n }';
|
|
} ;
|
|
__p += '\n } ';
|
|
} ;
|
|
|
|
if (obj.arrays) {
|
|
__p += '\n}';
|
|
} ;
|
|
__p +=
|
|
(obj.bottom ) +
|
|
';\nreturn result';
|
|
|
|
|
|
return __p
|
|
};
|
|
|
|
/** Reusable iterator options for `assign` and `defaults` */
|
|
var defaultsIteratorOptions = {
|
|
'args': 'object, source, guard',
|
|
'top':
|
|
'var args = arguments,\n' +
|
|
' argsIndex = 0,\n' +
|
|
" argsLength = typeof guard == 'number' ? 2 : args.length;\n" +
|
|
'while (++argsIndex < argsLength) {\n' +
|
|
' iterable = args[argsIndex];\n' +
|
|
' if (iterable && objectTypes[typeof iterable]) {',
|
|
'loop': "if (typeof result[index] == 'undefined') result[index] = iterable[index]",
|
|
'bottom': ' }\n}'
|
|
};
|
|
|
|
/** Reusable iterator options shared by `each`, `forIn`, and `forOwn` */
|
|
var eachIteratorOptions = {
|
|
'args': 'collection, callback, thisArg',
|
|
'top': "callback = callback && typeof thisArg == 'undefined' ? callback : createCallback(callback, thisArg)",
|
|
'arrays': "typeof length == 'number'",
|
|
'loop': 'if (callback(iterable[index], index, collection) === false) return result'
|
|
};
|
|
|
|
/** Reusable iterator options for `forIn` and `forOwn` */
|
|
var forOwnIteratorOptions = {
|
|
'top': 'if (!objectTypes[typeof iterable]) return result;\n' + eachIteratorOptions.top,
|
|
'arrays': false
|
|
};
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* Creates a function optimized to search large arrays for a given `value`,
|
|
* starting at `fromIndex`, using strict equality for comparisons, i.e. `===`.
|
|
*
|
|
* @private
|
|
* @param {Array} array The array to search.
|
|
* @param {Mixed} value The value to search for.
|
|
* @param {Number} [fromIndex=0] The index to search from.
|
|
* @param {Number} [largeSize=30] The length at which an array is considered large.
|
|
* @returns {Boolean} Returns `true`, if `value` is found, else `false`.
|
|
*/
|
|
function cachedContains(array, fromIndex, largeSize) {
|
|
fromIndex || (fromIndex = 0);
|
|
|
|
var length = array.length,
|
|
isLarge = (length - fromIndex) >= (largeSize || largeArraySize);
|
|
|
|
if (isLarge) {
|
|
var cache = {},
|
|
index = fromIndex - 1;
|
|
|
|
while (++index < length) {
|
|
// manually coerce `value` to a string because `hasOwnProperty`, in some
|
|
// older versions of Firefox, coerces objects incorrectly
|
|
var key = array[index] + '';
|
|
(hasOwnProperty.call(cache, key) ? cache[key] : (cache[key] = [])).push(array[index]);
|
|
}
|
|
}
|
|
return function(value) {
|
|
if (isLarge) {
|
|
var key = value + '';
|
|
return hasOwnProperty.call(cache, key) && indexOf(cache[key], value) > -1;
|
|
}
|
|
return indexOf(array, value, fromIndex) > -1;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Used by `_.max` and `_.min` as the default `callback` when a given
|
|
* `collection` is a string value.
|
|
*
|
|
* @private
|
|
* @param {String} value The character to inspect.
|
|
* @returns {Number} Returns the code unit of given character.
|
|
*/
|
|
function charAtCallback(value) {
|
|
return value.charCodeAt(0);
|
|
}
|
|
|
|
/**
|
|
* Used by `sortBy` to compare transformed `collection` values, stable sorting
|
|
* them in ascending order.
|
|
*
|
|
* @private
|
|
* @param {Object} a The object to compare to `b`.
|
|
* @param {Object} b The object to compare to `a`.
|
|
* @returns {Number} Returns the sort order indicator of `1` or `-1`.
|
|
*/
|
|
function compareAscending(a, b) {
|
|
var ai = a.index,
|
|
bi = b.index;
|
|
|
|
a = a.criteria;
|
|
b = b.criteria;
|
|
|
|
// ensure a stable sort in V8 and other engines
|
|
// http://code.google.com/p/v8/issues/detail?id=90
|
|
if (a !== b) {
|
|
if (a > b || typeof a == 'undefined') {
|
|
return 1;
|
|
}
|
|
if (a < b || typeof b == 'undefined') {
|
|
return -1;
|
|
}
|
|
}
|
|
return ai < bi ? -1 : 1;
|
|
}
|
|
|
|
/**
|
|
* Creates a function that, when called, invokes `func` with the `this` binding
|
|
* of `thisArg` and prepends any `partialArgs` to the arguments passed to the
|
|
* bound function.
|
|
*
|
|
* @private
|
|
* @param {Function|String} func The function to bind or the method name.
|
|
* @param {Mixed} [thisArg] The `this` binding of `func`.
|
|
* @param {Array} partialArgs An array of arguments to be partially applied.
|
|
* @param {Object} [rightIndicator] Used to indicate partially applying arguments from the right.
|
|
* @returns {Function} Returns the new bound function.
|
|
*/
|
|
function createBound(func, thisArg, partialArgs, rightIndicator) {
|
|
var isFunc = isFunction(func),
|
|
isPartial = !partialArgs,
|
|
key = thisArg;
|
|
|
|
// juggle arguments
|
|
if (isPartial) {
|
|
partialArgs = thisArg;
|
|
}
|
|
if (!isFunc) {
|
|
thisArg = func;
|
|
}
|
|
|
|
function bound() {
|
|
// `Function#bind` spec
|
|
// http://es5.github.com/#x15.3.4.5
|
|
var args = arguments,
|
|
thisBinding = isPartial ? this : thisArg;
|
|
|
|
if (!isFunc) {
|
|
func = thisArg[key];
|
|
}
|
|
if (partialArgs.length) {
|
|
args = args.length
|
|
? (args = slice(args), rightIndicator ? args.concat(partialArgs) : partialArgs.concat(args))
|
|
: partialArgs;
|
|
}
|
|
if (this instanceof bound) {
|
|
// ensure `new bound` is an instance of `bound` and `func`
|
|
noop.prototype = func.prototype;
|
|
thisBinding = new noop;
|
|
noop.prototype = null;
|
|
|
|
// mimic the constructor's `return` behavior
|
|
// http://es5.github.com/#x13.2.2
|
|
var result = func.apply(thisBinding, args);
|
|
return isObject(result) ? result : thisBinding;
|
|
}
|
|
return func.apply(thisBinding, args);
|
|
}
|
|
return bound;
|
|
}
|
|
|
|
/**
|
|
* Produces a callback bound to an optional `thisArg`. If `func` is a property
|
|
* name, the created callback will return the property value for a given element.
|
|
* If `func` is an object, the created callback will return `true` for elements
|
|
* that contain the equivalent object properties, otherwise it will return `false`.
|
|
*
|
|
* @private
|
|
* @param {Mixed} [func=identity] The value to convert to a callback.
|
|
* @param {Mixed} [thisArg] The `this` binding of the created callback.
|
|
* @param {Number} [argCount=3] The number of arguments the callback accepts.
|
|
* @returns {Function} Returns a callback function.
|
|
*/
|
|
function createCallback(func, thisArg, argCount) {
|
|
if (func == null) {
|
|
return identity;
|
|
}
|
|
var type = typeof func;
|
|
if (type != 'function') {
|
|
if (type != 'object') {
|
|
return function(object) {
|
|
return object[func];
|
|
};
|
|
}
|
|
var props = keys(func);
|
|
return function(object) {
|
|
var length = props.length,
|
|
result = false;
|
|
while (length--) {
|
|
if (!(result = isEqual(object[props[length]], func[props[length]], indicatorObject))) {
|
|
break;
|
|
}
|
|
}
|
|
return result;
|
|
};
|
|
}
|
|
if (typeof thisArg != 'undefined') {
|
|
if (argCount === 1) {
|
|
return function(value) {
|
|
return func.call(thisArg, value);
|
|
};
|
|
}
|
|
if (argCount === 2) {
|
|
return function(a, b) {
|
|
return func.call(thisArg, a, b);
|
|
};
|
|
}
|
|
if (argCount === 4) {
|
|
return function(accumulator, value, index, object) {
|
|
return func.call(thisArg, accumulator, value, index, object);
|
|
};
|
|
}
|
|
return function(value, index, object) {
|
|
return func.call(thisArg, value, index, object);
|
|
};
|
|
}
|
|
return func;
|
|
}
|
|
|
|
/**
|
|
* Creates compiled iteration functions.
|
|
*
|
|
* @private
|
|
* @param {Object} [options1, options2, ...] The compile options object(s).
|
|
* arrays - A string of code to determine if the iterable is an array or array-like.
|
|
* useHas - A boolean to specify using `hasOwnProperty` checks in the object loop.
|
|
* args - A string of comma separated arguments the iteration function will accept.
|
|
* top - A string of code to execute before the iteration branches.
|
|
* loop - A string of code to execute in the object loop.
|
|
* bottom - A string of code to execute after the iteration branches.
|
|
*
|
|
* @returns {Function} Returns the compiled function.
|
|
*/
|
|
function createIterator() {
|
|
var data = {
|
|
// support properties
|
|
'isKeysFast': isKeysFast,
|
|
|
|
// iterator options
|
|
'arrays': 'isArray(iterable)',
|
|
'bottom': '',
|
|
'loop': '',
|
|
'top': '',
|
|
'useHas': true
|
|
};
|
|
|
|
// merge options into a template data object
|
|
for (var object, index = 0; object = arguments[index]; index++) {
|
|
for (var key in object) {
|
|
data[key] = object[key];
|
|
}
|
|
}
|
|
var args = data.args;
|
|
data.firstArg = /^[^,]+/.exec(args)[0];
|
|
|
|
// create the function factory
|
|
var factory = Function(
|
|
'createCallback, hasOwnProperty, isArguments, isArray, isString, ' +
|
|
'objectTypes, nativeKeys',
|
|
'return function(' + args + ') {\n' + iteratorTemplate(data) + '\n}'
|
|
);
|
|
// return the compiled function
|
|
return factory(
|
|
createCallback, hasOwnProperty, isArguments, isArray, isString,
|
|
objectTypes, nativeKeys
|
|
);
|
|
}
|
|
|
|
/**
|
|
* A function compiled to iterate `arguments` objects, arrays, objects, and
|
|
* strings consistenly across environments, executing the `callback` for each
|
|
* element in the `collection`. The `callback` is bound to `thisArg` and invoked
|
|
* with three arguments; (value, index|key, collection). Callbacks may exit
|
|
* iteration early by explicitly returning `false`.
|
|
*
|
|
* @private
|
|
* @type Function
|
|
* @param {Array|Object|String} collection The collection to iterate over.
|
|
* @param {Function} [callback=identity] The function called per iteration.
|
|
* @param {Mixed} [thisArg] The `this` binding of `callback`.
|
|
* @returns {Array|Object|String} Returns `collection`.
|
|
*/
|
|
var each = createIterator(eachIteratorOptions);
|
|
|
|
/**
|
|
* Used by `template` to escape characters for inclusion in compiled
|
|
* string literals.
|
|
*
|
|
* @private
|
|
* @param {String} match The matched character to escape.
|
|
* @returns {String} Returns the escaped character.
|
|
*/
|
|
function escapeStringChar(match) {
|
|
return '\\' + stringEscapes[match];
|
|
}
|
|
|
|
/**
|
|
* Used by `escape` to convert characters to HTML entities.
|
|
*
|
|
* @private
|
|
* @param {String} match The matched character to escape.
|
|
* @returns {String} Returns the escaped character.
|
|
*/
|
|
function escapeHtmlChar(match) {
|
|
return htmlEscapes[match];
|
|
}
|
|
|
|
/**
|
|
* Checks if `value` is a DOM node in IE < 9.
|
|
*
|
|
* @private
|
|
* @param {Mixed} value The value to check.
|
|
* @returns {Boolean} Returns `true` if the `value` is a DOM node, else `false`.
|
|
*/
|
|
function isNode(value) {
|
|
// IE < 9 presents DOM nodes as `Object` objects except they have `toString`
|
|
// methods that are `typeof` "string" and still can coerce nodes to strings
|
|
return typeof value.toString != 'function' && typeof (value + '') == 'string';
|
|
}
|
|
|
|
/**
|
|
* A no-operation function.
|
|
*
|
|
* @private
|
|
*/
|
|
function noop() {
|
|
// no operation performed
|
|
}
|
|
|
|
/**
|
|
* Slices the `collection` from the `start` index up to, but not including,
|
|
* the `end` index.
|
|
*
|
|
* Note: This function is used, instead of `Array#slice`, to support node lists
|
|
* in IE < 9 and to ensure dense arrays are returned.
|
|
*
|
|
* @private
|
|
* @param {Array|Object|String} collection The collection to slice.
|
|
* @param {Number} start The start index.
|
|
* @param {Number} end The end index.
|
|
* @returns {Array} Returns the new array.
|
|
*/
|
|
function slice(array, start, end) {
|
|
start || (start = 0);
|
|
if (typeof end == 'undefined') {
|
|
end = array ? array.length : 0;
|
|
}
|
|
var index = -1,
|
|
length = end - start || 0,
|
|
result = Array(length < 0 ? 0 : length);
|
|
|
|
while (++index < length) {
|
|
result[index] = array[start + index];
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Used by `unescape` to convert HTML entities to characters.
|
|
*
|
|
* @private
|
|
* @param {String} match The matched character to unescape.
|
|
* @returns {String} Returns the unescaped character.
|
|
*/
|
|
function unescapeHtmlChar(match) {
|
|
return htmlUnescapes[match];
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* Checks if `value` is an `arguments` object.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Objects
|
|
* @param {Mixed} value The value to check.
|
|
* @returns {Boolean} Returns `true`, if the `value` is an `arguments` object, else `false`.
|
|
* @example
|
|
*
|
|
* (function() { return _.isArguments(arguments); })(1, 2, 3);
|
|
* // => true
|
|
*
|
|
* _.isArguments([1, 2, 3]);
|
|
* // => false
|
|
*/
|
|
function isArguments(value) {
|
|
return toString.call(value) == argsClass;
|
|
}
|
|
|
|
/**
|
|
* Iterates over `object`'s own and inherited enumerable properties, executing
|
|
* the `callback` for each property. The `callback` is bound to `thisArg` and
|
|
* invoked with three arguments; (value, key, object). Callbacks may exit iteration
|
|
* early by explicitly returning `false`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @type Function
|
|
* @category Objects
|
|
* @param {Object} object The object to iterate over.
|
|
* @param {Function} [callback=identity] The function called per iteration.
|
|
* @param {Mixed} [thisArg] The `this` binding of `callback`.
|
|
* @returns {Object} Returns `object`.
|
|
* @example
|
|
*
|
|
* function Dog(name) {
|
|
* this.name = name;
|
|
* }
|
|
*
|
|
* Dog.prototype.bark = function() {
|
|
* alert('Woof, woof!');
|
|
* };
|
|
*
|
|
* _.forIn(new Dog('Dagny'), function(value, key) {
|
|
* alert(key);
|
|
* });
|
|
* // => alerts 'name' and 'bark' (order is not guaranteed)
|
|
*/
|
|
var forIn = createIterator(eachIteratorOptions, forOwnIteratorOptions, {
|
|
'useHas': false
|
|
});
|
|
|
|
/**
|
|
* Iterates over an object's own enumerable properties, executing the `callback`
|
|
* for each property. The `callback` is bound to `thisArg` and invoked with three
|
|
* arguments; (value, key, object). Callbacks may exit iteration early by explicitly
|
|
* returning `false`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @type Function
|
|
* @category Objects
|
|
* @param {Object} object The object to iterate over.
|
|
* @param {Function} [callback=identity] The function called per iteration.
|
|
* @param {Mixed} [thisArg] The `this` binding of `callback`.
|
|
* @returns {Object} Returns `object`.
|
|
* @example
|
|
*
|
|
* _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) {
|
|
* alert(key);
|
|
* });
|
|
* // => alerts '0', '1', and 'length' (order is not guaranteed)
|
|
*/
|
|
var forOwn = createIterator(eachIteratorOptions, forOwnIteratorOptions);
|
|
|
|
/**
|
|
* Checks if `value` is an array.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Objects
|
|
* @param {Mixed} value The value to check.
|
|
* @returns {Boolean} Returns `true`, if the `value` is an array, else `false`.
|
|
* @example
|
|
*
|
|
* (function() { return _.isArray(arguments); })();
|
|
* // => false
|
|
*
|
|
* _.isArray([1, 2, 3]);
|
|
* // => true
|
|
*/
|
|
var isArray = nativeIsArray || function(value) {
|
|
// `instanceof` may cause a memory leak in IE 7 if `value` is a host object
|
|
// http://ajaxian.com/archives/working-aroung-the-instanceof-memory-leak
|
|
return value instanceof Array || toString.call(value) == arrayClass;
|
|
};
|
|
|
|
/**
|
|
* Creates an array composed of the own enumerable property names of `object`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Objects
|
|
* @param {Object} object The object to inspect.
|
|
* @returns {Array} Returns a new array of property names.
|
|
* @example
|
|
*
|
|
* _.keys({ 'one': 1, 'two': 2, 'three': 3 });
|
|
* // => ['one', 'two', 'three'] (order is not guaranteed)
|
|
*/
|
|
var keys = !nativeKeys ? shimKeys : function(object) {
|
|
if (!isObject(object)) {
|
|
return [];
|
|
}
|
|
return nativeKeys(object);
|
|
};
|
|
|
|
/**
|
|
* A fallback implementation of `isPlainObject` that checks if a given `value`
|
|
* is an object created by the `Object` constructor, assuming objects created
|
|
* by the `Object` constructor have no inherited enumerable properties and that
|
|
* there are no `Object.prototype` extensions.
|
|
*
|
|
* @private
|
|
* @param {Mixed} value The value to check.
|
|
* @returns {Boolean} Returns `true`, if `value` is a plain object, else `false`.
|
|
*/
|
|
function shimIsPlainObject(value) {
|
|
// avoid non-objects and false positives for `arguments` objects
|
|
var result = false;
|
|
if (!(value && typeof value == 'object') || isArguments(value)) {
|
|
return result;
|
|
}
|
|
// check that the constructor is `Object` (i.e. `Object instanceof Object`)
|
|
var ctor = value.constructor;
|
|
if ((!isFunction(ctor)) || ctor instanceof ctor) {
|
|
// In most environments an object's own properties are iterated before
|
|
// its inherited properties. If the last iterated property is an object's
|
|
// own property then there are no inherited enumerable properties.
|
|
forIn(value, function(value, key) {
|
|
result = key;
|
|
});
|
|
return result === false || hasOwnProperty.call(value, result);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* A fallback implementation of `Object.keys` that produces an array of the
|
|
* given object's own enumerable property names.
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to inspect.
|
|
* @returns {Array} Returns a new array of property names.
|
|
*/
|
|
function shimKeys(object) {
|
|
var result = [];
|
|
forOwn(object, function(value, key) {
|
|
result.push(key);
|
|
});
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Used to convert characters to HTML entities:
|
|
*
|
|
* Though the `>` character is escaped for symmetry, characters like `>` and `/`
|
|
* don't require escaping in HTML and have no special meaning unless they're part
|
|
* of a tag or an unquoted attribute value.
|
|
* http://mathiasbynens.be/notes/ambiguous-ampersands (under "semi-related fun fact")
|
|
*/
|
|
var htmlEscapes = {
|
|
'&': '&',
|
|
'<': '<',
|
|
'>': '>',
|
|
'"': '"',
|
|
"'": '''
|
|
};
|
|
|
|
/** Used to convert HTML entities to characters */
|
|
var htmlUnescapes = invert(htmlEscapes);
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* Assigns own enumerable properties of source object(s) to the destination
|
|
* object. Subsequent sources will overwrite propery assignments of previous
|
|
* sources. If a `callback` function is passed, it will be executed to produce
|
|
* the assigned values. The `callback` is bound to `thisArg` and invoked with
|
|
* two arguments; (objectValue, sourceValue).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @type Function
|
|
* @alias extend
|
|
* @category Objects
|
|
* @param {Object} object The destination object.
|
|
* @param {Object} [source1, source2, ...] The source objects.
|
|
* @param {Function} [callback] The function to customize assigning values.
|
|
* @param {Mixed} [thisArg] The `this` binding of `callback`.
|
|
* @returns {Object} Returns the destination object.
|
|
* @example
|
|
*
|
|
* _.assign({ 'name': 'moe' }, { 'age': 40 });
|
|
* // => { 'name': 'moe', 'age': 40 }
|
|
*
|
|
* var defaults = _.partialRight(_.assign, function(a, b) {
|
|
* return typeof a == 'undefined' ? b : a;
|
|
* });
|
|
*
|
|
* var food = { 'name': 'apple' };
|
|
* defaults(food, { 'name': 'banana', 'type': 'fruit' });
|
|
* // => { 'name': 'apple', 'type': 'fruit' }
|
|
*/
|
|
var assign = createIterator(defaultsIteratorOptions, {
|
|
'top':
|
|
defaultsIteratorOptions.top.replace(';',
|
|
';\n' +
|
|
"if (argsLength > 3 && typeof args[argsLength - 2] == 'function') {\n" +
|
|
' var callback = createCallback(args[--argsLength - 1], args[argsLength--], 2);\n' +
|
|
"} else if (argsLength > 2 && typeof args[argsLength - 1] == 'function') {\n" +
|
|
' callback = args[--argsLength];\n' +
|
|
'}'
|
|
),
|
|
'loop': 'result[index] = callback ? callback(result[index], iterable[index]) : iterable[index]'
|
|
});
|
|
|
|
/**
|
|
* Creates a clone of `value`. If `deep` is `true`, nested objects will also
|
|
* be cloned, otherwise they will be assigned by reference. If a `callback`
|
|
* function is passed, it will be executed to produce the cloned values. If
|
|
* `callback` returns `undefined`, cloning will be handled by the method instead.
|
|
* The `callback` is bound to `thisArg` and invoked with one argument; (value).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Objects
|
|
* @param {Mixed} value The value to clone.
|
|
* @param {Boolean} [deep=false] A flag to indicate a deep clone.
|
|
* @param {Function} [callback] The function to customize cloning values.
|
|
* @param {Mixed} [thisArg] The `this` binding of `callback`.
|
|
* @param- {Array} [stackA=[]] Internally used to track traversed source objects.
|
|
* @param- {Array} [stackB=[]] Internally used to associate clones with source counterparts.
|
|
* @returns {Mixed} Returns the cloned `value`.
|
|
* @example
|
|
*
|
|
* var stooges = [
|
|
* { 'name': 'moe', 'age': 40 },
|
|
* { 'name': 'larry', 'age': 50 }
|
|
* ];
|
|
*
|
|
* var shallow = _.clone(stooges);
|
|
* shallow[0] === stooges[0];
|
|
* // => true
|
|
*
|
|
* var deep = _.clone(stooges, true);
|
|
* deep[0] === stooges[0];
|
|
* // => false
|
|
*
|
|
* _.mixin({
|
|
* 'clone': _.partialRight(_.clone, function(value) {
|
|
* return _.isElement(value) ? value.cloneNode(false) : undefined;
|
|
* })
|
|
* });
|
|
*
|
|
* var clone = _.clone(document.body);
|
|
* clone.childNodes.length;
|
|
* // => 0
|
|
*/
|
|
function clone(value, deep, callback, thisArg, stackA, stackB) {
|
|
var result = value;
|
|
|
|
// allows working with "Collections" methods without using their `callback`
|
|
// argument, `index|key`, for this method's `callback`
|
|
if (typeof deep == 'function') {
|
|
thisArg = callback;
|
|
callback = deep;
|
|
deep = false;
|
|
}
|
|
if (typeof callback == 'function') {
|
|
callback = typeof thisArg == 'undefined' ? callback : createCallback(callback, thisArg, 1);
|
|
result = callback(result);
|
|
|
|
var done = typeof result != 'undefined';
|
|
if (!done) {
|
|
result = value;
|
|
}
|
|
}
|
|
// inspect [[Class]]
|
|
var isObj = isObject(result);
|
|
if (isObj) {
|
|
var className = toString.call(result);
|
|
if (!cloneableClasses[className]) {
|
|
return result;
|
|
}
|
|
var isArr = isArray(result);
|
|
}
|
|
// shallow clone
|
|
if (!isObj || !deep) {
|
|
return isObj && !done
|
|
? (isArr ? slice(result) : assign({}, result))
|
|
: result;
|
|
}
|
|
var ctor = ctorByClass[className];
|
|
switch (className) {
|
|
case boolClass:
|
|
case dateClass:
|
|
return done ? result : new ctor(+result);
|
|
|
|
case numberClass:
|
|
case stringClass:
|
|
return done ? result : new ctor(result);
|
|
|
|
case regexpClass:
|
|
return done ? result : ctor(result.source, reFlags.exec(result));
|
|
}
|
|
// check for circular references and return corresponding clone
|
|
stackA || (stackA = []);
|
|
stackB || (stackB = []);
|
|
|
|
var length = stackA.length;
|
|
while (length--) {
|
|
if (stackA[length] == value) {
|
|
return stackB[length];
|
|
}
|
|
}
|
|
// init cloned object
|
|
if (!done) {
|
|
result = isArr ? ctor(result.length) : {};
|
|
|
|
// add array properties assigned by `RegExp#exec`
|
|
if (isArr) {
|
|
if (hasOwnProperty.call(value, 'index')) {
|
|
result.index = value.index;
|
|
}
|
|
if (hasOwnProperty.call(value, 'input')) {
|
|
result.input = value.input;
|
|
}
|
|
}
|
|
}
|
|
// add the source value to the stack of traversed objects
|
|
// and associate it with its clone
|
|
stackA.push(value);
|
|
stackB.push(result);
|
|
|
|
// recursively populate clone (susceptible to call stack limits)
|
|
(isArr ? forEach : forOwn)(done ? result : value, function(objValue, key) {
|
|
result[key] = clone(objValue, deep, callback, undefined, stackA, stackB);
|
|
});
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Creates a deep clone of `value`. If a `callback` function is passed, it will
|
|
* be executed to produce the cloned values. If `callback` returns the value it
|
|
* was passed, cloning will be handled by the method instead. The `callback` is
|
|
* bound to `thisArg` and invoked with one argument; (value).
|
|
*
|
|
* Note: This function is loosely based on the structured clone algorithm. Functions
|
|
* and DOM nodes are **not** cloned. The enumerable properties of `arguments` objects and
|
|
* objects created by constructors other than `Object` are cloned to plain `Object` objects.
|
|
* See http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Objects
|
|
* @param {Mixed} value The value to deep clone.
|
|
* @param {Function} [callback] The function to customize cloning values.
|
|
* @param {Mixed} [thisArg] The `this` binding of `callback`.
|
|
* @returns {Mixed} Returns the deep cloned `value`.
|
|
* @example
|
|
*
|
|
* var stooges = [
|
|
* { 'name': 'moe', 'age': 40 },
|
|
* { 'name': 'larry', 'age': 50 }
|
|
* ];
|
|
*
|
|
* var deep = _.cloneDeep(stooges);
|
|
* deep[0] === stooges[0];
|
|
* // => false
|
|
*
|
|
* var view = {
|
|
* 'label': 'docs',
|
|
* 'node': element
|
|
* };
|
|
*
|
|
* var clone = _.cloneDeep(view, function(value) {
|
|
* return _.isElement(value) ? value.cloneNode(true) : value;
|
|
* });
|
|
*
|
|
* clone.node == view.node;
|
|
* // => false
|
|
*/
|
|
function cloneDeep(value, callback, thisArg) {
|
|
return clone(value, true, callback, thisArg);
|
|
}
|
|
|
|
/**
|
|
* Assigns own enumerable properties of source object(s) to the destination
|
|
* object for all destination properties that resolve to `undefined`. Once a
|
|
* property is set, additional defaults of the same property will be ignored.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @type Function
|
|
* @category Objects
|
|
* @param {Object} object The destination object.
|
|
* @param {Object} [source1, source2, ...] The source objects.
|
|
* @param- {Object} [guard] Internally used to allow working with `_.reduce`
|
|
* without using its callback's `key` and `object` arguments as sources.
|
|
* @returns {Object} Returns the destination object.
|
|
* @example
|
|
*
|
|
* var food = { 'name': 'apple' };
|
|
* _.defaults(food, { 'name': 'banana', 'type': 'fruit' });
|
|
* // => { 'name': 'apple', 'type': 'fruit' }
|
|
*/
|
|
var defaults = createIterator(defaultsIteratorOptions);
|
|
|
|
/**
|
|
* Creates a sorted array of all enumerable properties, own and inherited,
|
|
* of `object` that have function values.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @alias methods
|
|
* @category Objects
|
|
* @param {Object} object The object to inspect.
|
|
* @returns {Array} Returns a new array of property names that have function values.
|
|
* @example
|
|
*
|
|
* _.functions(_);
|
|
* // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...]
|
|
*/
|
|
function functions(object) {
|
|
var result = [];
|
|
forIn(object, function(value, key) {
|
|
if (isFunction(value)) {
|
|
result.push(key);
|
|
}
|
|
});
|
|
return result.sort();
|
|
}
|
|
|
|
/**
|
|
* Checks if the specified object `property` exists and is a direct property,
|
|
* instead of an inherited property.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Objects
|
|
* @param {Object} object The object to check.
|
|
* @param {String} property The property to check for.
|
|
* @returns {Boolean} Returns `true` if key is a direct property, else `false`.
|
|
* @example
|
|
*
|
|
* _.has({ 'a': 1, 'b': 2, 'c': 3 }, 'b');
|
|
* // => true
|
|
*/
|
|
function has(object, property) {
|
|
return object ? hasOwnProperty.call(object, property) : false;
|
|
}
|
|
|
|
/**
|
|
* Creates an object composed of the inverted keys and values of the given `object`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Objects
|
|
* @param {Object} object The object to invert.
|
|
* @returns {Object} Returns the created inverted object.
|
|
* @example
|
|
*
|
|
* _.invert({ 'first': 'moe', 'second': 'larry' });
|
|
* // => { 'moe': 'first', 'larry': 'second' } (order is not guaranteed)
|
|
*/
|
|
function invert(object) {
|
|
var index = -1,
|
|
props = keys(object),
|
|
length = props.length,
|
|
result = {};
|
|
|
|
while (++index < length) {
|
|
var key = props[index];
|
|
result[object[key]] = key;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Checks if `value` is a boolean value.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Objects
|
|
* @param {Mixed} value The value to check.
|
|
* @returns {Boolean} Returns `true`, if the `value` is a boolean value, else `false`.
|
|
* @example
|
|
*
|
|
* _.isBoolean(null);
|
|
* // => false
|
|
*/
|
|
function isBoolean(value) {
|
|
return value === true || value === false || toString.call(value) == boolClass;
|
|
}
|
|
|
|
/**
|
|
* Checks if `value` is a date.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Objects
|
|
* @param {Mixed} value The value to check.
|
|
* @returns {Boolean} Returns `true`, if the `value` is a date, else `false`.
|
|
* @example
|
|
*
|
|
* _.isDate(new Date);
|
|
* // => true
|
|
*/
|
|
function isDate(value) {
|
|
return value instanceof Date || toString.call(value) == dateClass;
|
|
}
|
|
|
|
/**
|
|
* Checks if `value` is a DOM element.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Objects
|
|
* @param {Mixed} value The value to check.
|
|
* @returns {Boolean} Returns `true`, if the `value` is a DOM element, else `false`.
|
|
* @example
|
|
*
|
|
* _.isElement(document.body);
|
|
* // => true
|
|
*/
|
|
function isElement(value) {
|
|
return value ? value.nodeType === 1 : false;
|
|
}
|
|
|
|
/**
|
|
* Checks if `value` is empty. Arrays, strings, or `arguments` objects with a
|
|
* length of `0` and objects with no own enumerable properties are considered
|
|
* "empty".
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Objects
|
|
* @param {Array|Object|String} value The value to inspect.
|
|
* @returns {Boolean} Returns `true`, if the `value` is empty, else `false`.
|
|
* @example
|
|
*
|
|
* _.isEmpty([1, 2, 3]);
|
|
* // => false
|
|
*
|
|
* _.isEmpty({});
|
|
* // => true
|
|
*
|
|
* _.isEmpty('');
|
|
* // => true
|
|
*/
|
|
function isEmpty(value) {
|
|
var result = true;
|
|
if (!value) {
|
|
return result;
|
|
}
|
|
var className = toString.call(value),
|
|
length = value.length;
|
|
|
|
if ((className == arrayClass || className == stringClass ||
|
|
className == argsClass) ||
|
|
(className == objectClass && typeof length == 'number' && isFunction(value.splice))) {
|
|
return !length;
|
|
}
|
|
forOwn(value, function() {
|
|
return (result = false);
|
|
});
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Performs a deep comparison between two values to determine if they are
|
|
* equivalent to each other. If `callback` is passed, it will be executed to
|
|
* compare values. If `callback` returns `undefined`, comparisons will be handled
|
|
* by the method instead. The `callback` is bound to `thisArg` and invoked with
|
|
* two arguments; (a, b).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Objects
|
|
* @param {Mixed} a The value to compare.
|
|
* @param {Mixed} b The other value to compare.
|
|
* @param {Function} [callback] The function to customize comparing values.
|
|
* @param {Mixed} [thisArg] The `this` binding of `callback`.
|
|
* @param- {Object} [stackA=[]] Internally used track traversed `a` objects.
|
|
* @param- {Object} [stackB=[]] Internally used track traversed `b` objects.
|
|
* @returns {Boolean} Returns `true`, if the values are equvalent, else `false`.
|
|
* @example
|
|
*
|
|
* var moe = { 'name': 'moe', 'age': 40 };
|
|
* var copy = { 'name': 'moe', 'age': 40 };
|
|
*
|
|
* moe == copy;
|
|
* // => false
|
|
*
|
|
* _.isEqual(moe, copy);
|
|
* // => true
|
|
*
|
|
* var words = ['hello', 'goodbye'];
|
|
* var otherWords = ['hi', 'goodbye'];
|
|
*
|
|
* _.isEqual(words, otherWords, function(a, b) {
|
|
* var reGreet = /^(?:hello|hi)$/i,
|
|
* aGreet = _.isString(a) && reGreet.test(a),
|
|
* bGreet = _.isString(b) && reGreet.test(b);
|
|
*
|
|
* return (aGreet || bGreet) ? (aGreet == bGreet) : undefined;
|
|
* });
|
|
* // => true
|
|
*/
|
|
function isEqual(a, b, callback, thisArg, stackA, stackB) {
|
|
// used to indicate that when comparing objects, `a` has at least the properties of `b`
|
|
var whereIndicator = callback === indicatorObject;
|
|
if (callback && !whereIndicator) {
|
|
callback = typeof thisArg == 'undefined' ? callback : createCallback(callback, thisArg, 2);
|
|
var result = callback(a, b);
|
|
if (typeof result != 'undefined') {
|
|
return !!result;
|
|
}
|
|
}
|
|
// exit early for identical values
|
|
if (a === b) {
|
|
// treat `+0` vs. `-0` as not equal
|
|
return a !== 0 || (1 / a == 1 / b);
|
|
}
|
|
var type = typeof a,
|
|
otherType = typeof b;
|
|
|
|
// exit early for unlike primitive values
|
|
if (a === a &&
|
|
(!a || (type != 'function' && type != 'object')) &&
|
|
(!b || (otherType != 'function' && otherType != 'object'))) {
|
|
return false;
|
|
}
|
|
// exit early for `null` and `undefined`, avoiding ES3's Function#call behavior
|
|
// http://es5.github.com/#x15.3.4.4
|
|
if (a == null || b == null) {
|
|
return a === b;
|
|
}
|
|
// compare [[Class]] names
|
|
var className = toString.call(a),
|
|
otherClass = toString.call(b);
|
|
|
|
if (className == argsClass) {
|
|
className = objectClass;
|
|
}
|
|
if (otherClass == argsClass) {
|
|
otherClass = objectClass;
|
|
}
|
|
if (className != otherClass) {
|
|
return false;
|
|
}
|
|
switch (className) {
|
|
case boolClass:
|
|
case dateClass:
|
|
// coerce dates and booleans to numbers, dates to milliseconds and booleans
|
|
// to `1` or `0`, treating invalid dates coerced to `NaN` as not equal
|
|
return +a == +b;
|
|
|
|
case numberClass:
|
|
// treat `NaN` vs. `NaN` as equal
|
|
return a != +a
|
|
? b != +b
|
|
// but treat `+0` vs. `-0` as not equal
|
|
: (a == 0 ? (1 / a == 1 / b) : a == +b);
|
|
|
|
case regexpClass:
|
|
case stringClass:
|
|
// coerce regexes to strings (http://es5.github.com/#x15.10.6.4)
|
|
// treat string primitives and their corresponding object instances as equal
|
|
return a == b + '';
|
|
}
|
|
var isArr = className == arrayClass;
|
|
if (!isArr) {
|
|
// unwrap any `lodash` wrapped values
|
|
if (a.__wrapped__ || b.__wrapped__) {
|
|
return isEqual(a.__wrapped__ || a, b.__wrapped__ || b, callback, thisArg, stackA, stackB);
|
|
}
|
|
// exit for functions and DOM nodes
|
|
if (className != objectClass) {
|
|
return false;
|
|
}
|
|
// in older versions of Opera, `arguments` objects have `Array` constructors
|
|
var ctorA = a.constructor,
|
|
ctorB = b.constructor;
|
|
|
|
// non `Object` object instances with different constructors are not equal
|
|
if (ctorA != ctorB && !(
|
|
isFunction(ctorA) && ctorA instanceof ctorA &&
|
|
isFunction(ctorB) && ctorB instanceof ctorB
|
|
)) {
|
|
return false;
|
|
}
|
|
}
|
|
// assume cyclic structures are equal
|
|
// the algorithm for detecting cyclic structures is adapted from ES 5.1
|
|
// section 15.12.3, abstract operation `JO` (http://es5.github.com/#x15.12.3)
|
|
stackA || (stackA = []);
|
|
stackB || (stackB = []);
|
|
|
|
var length = stackA.length;
|
|
while (length--) {
|
|
if (stackA[length] == a) {
|
|
return stackB[length] == b;
|
|
}
|
|
}
|
|
var size = 0;
|
|
result = true;
|
|
|
|
// add `a` and `b` to the stack of traversed objects
|
|
stackA.push(a);
|
|
stackB.push(b);
|
|
|
|
// recursively compare objects and arrays (susceptible to call stack limits)
|
|
if (isArr) {
|
|
length = a.length;
|
|
size = b.length;
|
|
|
|
// compare lengths to determine if a deep comparison is necessary
|
|
result = size == a.length;
|
|
if (!result && !whereIndicator) {
|
|
return result;
|
|
}
|
|
// deep compare the contents, ignoring non-numeric properties
|
|
while (size--) {
|
|
var index = length,
|
|
value = b[size];
|
|
|
|
if (whereIndicator) {
|
|
while (index--) {
|
|
if ((result = isEqual(a[index], value, callback, thisArg, stackA, stackB))) {
|
|
break;
|
|
}
|
|
}
|
|
} else if (!(result = isEqual(a[size], value, callback, thisArg, stackA, stackB))) {
|
|
break;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
// deep compare objects using `forIn`, instead of `forOwn`, to avoid `Object.keys`
|
|
// which, in this case, is more costly
|
|
forIn(b, function(value, key, b) {
|
|
if (hasOwnProperty.call(b, key)) {
|
|
// count the number of properties.
|
|
size++;
|
|
// deep compare each property value.
|
|
return (result = hasOwnProperty.call(a, key) && isEqual(a[key], value, callback, thisArg, stackA, stackB));
|
|
}
|
|
});
|
|
|
|
if (result && !whereIndicator) {
|
|
// ensure both objects have the same number of properties
|
|
forIn(a, function(value, key, a) {
|
|
if (hasOwnProperty.call(a, key)) {
|
|
// `size` will be `-1` if `a` has more properties than `b`
|
|
return (result = --size > -1);
|
|
}
|
|
});
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Checks if `value` is, or can be coerced to, a finite number.
|
|
*
|
|
* Note: This is not the same as native `isFinite`, which will return true for
|
|
* booleans and empty strings. See http://es5.github.com/#x15.1.2.5.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Objects
|
|
* @param {Mixed} value The value to check.
|
|
* @returns {Boolean} Returns `true`, if the `value` is finite, else `false`.
|
|
* @example
|
|
*
|
|
* _.isFinite(-101);
|
|
* // => true
|
|
*
|
|
* _.isFinite('10');
|
|
* // => true
|
|
*
|
|
* _.isFinite(true);
|
|
* // => false
|
|
*
|
|
* _.isFinite('');
|
|
* // => false
|
|
*
|
|
* _.isFinite(Infinity);
|
|
* // => false
|
|
*/
|
|
function isFinite(value) {
|
|
return nativeIsFinite(value) && !nativeIsNaN(parseFloat(value));
|
|
}
|
|
|
|
/**
|
|
* Checks if `value` is a function.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Objects
|
|
* @param {Mixed} value The value to check.
|
|
* @returns {Boolean} Returns `true`, if the `value` is a function, else `false`.
|
|
* @example
|
|
*
|
|
* _.isFunction(_);
|
|
* // => true
|
|
*/
|
|
function isFunction(value) {
|
|
return typeof value == 'function';
|
|
}
|
|
// fallback for older versions of Chrome and Safari
|
|
if (isFunction(/x/)) {
|
|
isFunction = function(value) {
|
|
return value instanceof Function || toString.call(value) == funcClass;
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Checks if `value` is the language type of Object.
|
|
* (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Objects
|
|
* @param {Mixed} value The value to check.
|
|
* @returns {Boolean} Returns `true`, if the `value` is an object, else `false`.
|
|
* @example
|
|
*
|
|
* _.isObject({});
|
|
* // => true
|
|
*
|
|
* _.isObject([1, 2, 3]);
|
|
* // => true
|
|
*
|
|
* _.isObject(1);
|
|
* // => false
|
|
*/
|
|
function isObject(value) {
|
|
// check if the value is the ECMAScript language type of Object
|
|
// http://es5.github.com/#x8
|
|
// and avoid a V8 bug
|
|
// http://code.google.com/p/v8/issues/detail?id=2291
|
|
return value ? objectTypes[typeof value] : false;
|
|
}
|
|
|
|
/**
|
|
* Checks if `value` is `NaN`.
|
|
*
|
|
* Note: This is not the same as native `isNaN`, which will return `true` for
|
|
* `undefined` and other values. See http://es5.github.com/#x15.1.2.4.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Objects
|
|
* @param {Mixed} value The value to check.
|
|
* @returns {Boolean} Returns `true`, if the `value` is `NaN`, else `false`.
|
|
* @example
|
|
*
|
|
* _.isNaN(NaN);
|
|
* // => true
|
|
*
|
|
* _.isNaN(new Number(NaN));
|
|
* // => true
|
|
*
|
|
* isNaN(undefined);
|
|
* // => true
|
|
*
|
|
* _.isNaN(undefined);
|
|
* // => false
|
|
*/
|
|
function isNaN(value) {
|
|
// `NaN` as a primitive is the only value that is not equal to itself
|
|
// (perform the [[Class]] check first to avoid errors with some host objects in IE)
|
|
return isNumber(value) && value != +value
|
|
}
|
|
|
|
/**
|
|
* Checks if `value` is `null`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Objects
|
|
* @param {Mixed} value The value to check.
|
|
* @returns {Boolean} Returns `true`, if the `value` is `null`, else `false`.
|
|
* @example
|
|
*
|
|
* _.isNull(null);
|
|
* // => true
|
|
*
|
|
* _.isNull(undefined);
|
|
* // => false
|
|
*/
|
|
function isNull(value) {
|
|
return value === null;
|
|
}
|
|
|
|
/**
|
|
* Checks if `value` is a number.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Objects
|
|
* @param {Mixed} value The value to check.
|
|
* @returns {Boolean} Returns `true`, if the `value` is a number, else `false`.
|
|
* @example
|
|
*
|
|
* _.isNumber(8.4 * 5);
|
|
* // => true
|
|
*/
|
|
function isNumber(value) {
|
|
return typeof value == 'number' || toString.call(value) == numberClass;
|
|
}
|
|
|
|
/**
|
|
* Checks if a given `value` is an object created by the `Object` constructor.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Objects
|
|
* @param {Mixed} value The value to check.
|
|
* @returns {Boolean} Returns `true`, if `value` is a plain object, else `false`.
|
|
* @example
|
|
*
|
|
* function Stooge(name, age) {
|
|
* this.name = name;
|
|
* this.age = age;
|
|
* }
|
|
*
|
|
* _.isPlainObject(new Stooge('moe', 40));
|
|
* // => false
|
|
*
|
|
* _.isPlainObject([1, 2, 3]);
|
|
* // => false
|
|
*
|
|
* _.isPlainObject({ 'name': 'moe', 'age': 40 });
|
|
* // => true
|
|
*/
|
|
var isPlainObject = function(value) {
|
|
if (!(value && typeof value == 'object')) {
|
|
return false;
|
|
}
|
|
var valueOf = value.valueOf,
|
|
objProto = typeof valueOf == 'function' && (objProto = getPrototypeOf(valueOf)) && getPrototypeOf(objProto);
|
|
|
|
return objProto
|
|
? value == objProto || (getPrototypeOf(value) == objProto && !isArguments(value))
|
|
: shimIsPlainObject(value);
|
|
};
|
|
|
|
/**
|
|
* Checks if `value` is a regular expression.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Objects
|
|
* @param {Mixed} value The value to check.
|
|
* @returns {Boolean} Returns `true`, if the `value` is a regular expression, else `false`.
|
|
* @example
|
|
*
|
|
* _.isRegExp(/moe/);
|
|
* // => true
|
|
*/
|
|
function isRegExp(value) {
|
|
return value instanceof RegExp || toString.call(value) == regexpClass;
|
|
}
|
|
|
|
/**
|
|
* Checks if `value` is a string.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Objects
|
|
* @param {Mixed} value The value to check.
|
|
* @returns {Boolean} Returns `true`, if the `value` is a string, else `false`.
|
|
* @example
|
|
*
|
|
* _.isString('moe');
|
|
* // => true
|
|
*/
|
|
function isString(value) {
|
|
return typeof value == 'string' || toString.call(value) == stringClass;
|
|
}
|
|
|
|
/**
|
|
* Checks if `value` is `undefined`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Objects
|
|
* @param {Mixed} value The value to check.
|
|
* @returns {Boolean} Returns `true`, if the `value` is `undefined`, else `false`.
|
|
* @example
|
|
*
|
|
* _.isUndefined(void 0);
|
|
* // => true
|
|
*/
|
|
function isUndefined(value) {
|
|
return typeof value == 'undefined';
|
|
}
|
|
|
|
/**
|
|
* Recursively merges own enumerable properties of the source object(s), that
|
|
* don't resolve to `undefined`, into the destination object. Subsequent sources
|
|
* will overwrite propery assignments of previous sources. If a `callback` function
|
|
* is passed, it will be executed to produce the merged values of the destination
|
|
* and source properties. If `callback` returns `undefined`, merging will be
|
|
* handled by the method instead. The `callback` is bound to `thisArg` and
|
|
* invoked with two arguments; (objectValue, sourceValue).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Objects
|
|
* @param {Object} object The destination object.
|
|
* @param {Object} [source1, source2, ...] The source objects.
|
|
* @param {Function} [callback] The function to customize merging properties.
|
|
* @param {Mixed} [thisArg] The `this` binding of `callback`.
|
|
* @param- {Object} [deepIndicator] Internally used to indicate that `stackA`
|
|
* and `stackB` are arrays of traversed objects instead of source objects.
|
|
* @param- {Array} [stackA=[]] Internally used to track traversed source objects.
|
|
* @param- {Array} [stackB=[]] Internally used to associate values with their
|
|
* source counterparts.
|
|
* @returns {Object} Returns the destination object.
|
|
* @example
|
|
*
|
|
* var names = {
|
|
* 'stooges': [
|
|
* { 'name': 'moe' },
|
|
* { 'name': 'larry' }
|
|
* ]
|
|
* };
|
|
*
|
|
* var ages = {
|
|
* 'stooges': [
|
|
* { 'age': 40 },
|
|
* { 'age': 50 }
|
|
* ]
|
|
* };
|
|
*
|
|
* _.merge(names, ages);
|
|
* // => { 'stooges': [{ 'name': 'moe', 'age': 40 }, { 'name': 'larry', 'age': 50 }] }
|
|
*
|
|
* var food = {
|
|
* 'fruits': ['apple'],
|
|
* 'vegetables': ['beet']
|
|
* };
|
|
*
|
|
* var otherFood = {
|
|
* 'fruits': ['banana'],
|
|
* 'vegetables': ['carrot']
|
|
* };
|
|
*
|
|
* _.merge(food, otherFood, function(a, b) {
|
|
* return _.isArray(a) ? a.concat(b) : undefined;
|
|
* });
|
|
* // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot] }
|
|
*/
|
|
function merge(object, source, deepIndicator) {
|
|
var args = arguments,
|
|
index = 0,
|
|
length = 2;
|
|
|
|
if (!isObject(object)) {
|
|
return object;
|
|
}
|
|
if (deepIndicator === indicatorObject) {
|
|
var callback = args[3],
|
|
stackA = args[4],
|
|
stackB = args[5];
|
|
} else {
|
|
stackA = [];
|
|
stackB = [];
|
|
|
|
// allows working with `_.reduce` and `_.reduceRight` without
|
|
// using their `callback` arguments, `index|key` and `collection`
|
|
if (typeof deepIndicator != 'number') {
|
|
length = args.length;
|
|
}
|
|
if (length > 3 && typeof args[length - 2] == 'function') {
|
|
callback = createCallback(args[--length - 1], args[length--], 2);
|
|
} else if (length > 2 && typeof args[length - 1] == 'function') {
|
|
callback = args[--length];
|
|
}
|
|
}
|
|
while (++index < length) {
|
|
(isArray(args[index]) ? forEach : forOwn)(args[index], function(source, key) {
|
|
var found,
|
|
isArr,
|
|
result = source,
|
|
value = object[key];
|
|
|
|
if (source && ((isArr = isArray(source)) || isPlainObject(source))) {
|
|
// avoid merging previously merged cyclic sources
|
|
var stackLength = stackA.length;
|
|
while (stackLength--) {
|
|
if ((found = stackA[stackLength] == source)) {
|
|
value = stackB[stackLength];
|
|
break;
|
|
}
|
|
}
|
|
if (!found) {
|
|
value = isArr
|
|
? (isArray(value) ? value : [])
|
|
: (isPlainObject(value) ? value : {});
|
|
|
|
if (callback) {
|
|
result = callback(value, source);
|
|
if (typeof result != 'undefined') {
|
|
value = result;
|
|
}
|
|
}
|
|
// add `source` and associated `value` to the stack of traversed objects
|
|
stackA.push(source);
|
|
stackB.push(value);
|
|
|
|
// recursively merge objects and arrays (susceptible to call stack limits)
|
|
if (!callback) {
|
|
value = merge(value, source, indicatorObject, callback, stackA, stackB);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
if (callback) {
|
|
result = callback(value, source);
|
|
if (typeof result == 'undefined') {
|
|
result = source;
|
|
}
|
|
}
|
|
if (typeof result != 'undefined') {
|
|
value = result;
|
|
}
|
|
}
|
|
object[key] = value;
|
|
});
|
|
}
|
|
return object;
|
|
}
|
|
|
|
/**
|
|
* Creates a shallow clone of `object` excluding the specified properties.
|
|
* Property names may be specified as individual arguments or as arrays of
|
|
* property names. If a `callback` function is passed, it will be executed
|
|
* for each property in the `object`, omitting the properties `callback`
|
|
* returns truthy for. The `callback` is bound to `thisArg` and invoked
|
|
* with three arguments; (value, key, object).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Objects
|
|
* @param {Object} object The source object.
|
|
* @param {Function|String} callback|[prop1, prop2, ...] The properties to omit
|
|
* or the function called per iteration.
|
|
* @param {Mixed} [thisArg] The `this` binding of `callback`.
|
|
* @returns {Object} Returns an object without the omitted properties.
|
|
* @example
|
|
*
|
|
* _.omit({ 'name': 'moe', 'age': 40 }, 'age');
|
|
* // => { 'name': 'moe' }
|
|
*
|
|
* _.omit({ 'name': 'moe', 'age': 40 }, function(value) {
|
|
* return typeof value == 'number';
|
|
* });
|
|
* // => { 'name': 'moe' }
|
|
*/
|
|
function omit(object, callback, thisArg) {
|
|
var isFunc = typeof callback == 'function',
|
|
result = {};
|
|
|
|
if (isFunc) {
|
|
callback = createCallback(callback, thisArg);
|
|
} else {
|
|
var props = concat.apply(arrayRef, arguments);
|
|
}
|
|
forIn(object, function(value, key, object) {
|
|
if (isFunc
|
|
? !callback(value, key, object)
|
|
: indexOf(props, key, 1) < 0
|
|
) {
|
|
result[key] = value;
|
|
}
|
|
});
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Creates a two dimensional array of the given object's key-value pairs,
|
|
* i.e. `[[key1, value1], [key2, value2]]`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Objects
|
|
* @param {Object} object The object to inspect.
|
|
* @returns {Array} Returns new array of key-value pairs.
|
|
* @example
|
|
*
|
|
* _.pairs({ 'moe': 30, 'larry': 40 });
|
|
* // => [['moe', 30], ['larry', 40]] (order is not guaranteed)
|
|
*/
|
|
function pairs(object) {
|
|
var index = -1,
|
|
props = keys(object),
|
|
length = props.length,
|
|
result = Array(length);
|
|
|
|
while (++index < length) {
|
|
var key = props[index];
|
|
result[index] = [key, object[key]];
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Creates a shallow clone of `object` composed of the specified properties.
|
|
* Property names may be specified as individual arguments or as arrays of property
|
|
* names. If `callback` is passed, it will be executed for each property in the
|
|
* `object`, picking the properties `callback` returns truthy for. The `callback`
|
|
* is bound to `thisArg` and invoked with three arguments; (value, key, object).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Objects
|
|
* @param {Object} object The source object.
|
|
* @param {Array|Function|String} callback|[prop1, prop2, ...] The function called
|
|
* per iteration or properties to pick, either as individual arguments or arrays.
|
|
* @param {Mixed} [thisArg] The `this` binding of `callback`.
|
|
* @returns {Object} Returns an object composed of the picked properties.
|
|
* @example
|
|
*
|
|
* _.pick({ 'name': 'moe', '_userid': 'moe1' }, 'name');
|
|
* // => { 'name': 'moe' }
|
|
*
|
|
* _.pick({ 'name': 'moe', '_userid': 'moe1' }, function(value, key) {
|
|
* return key.charAt(0) != '_';
|
|
* });
|
|
* // => { 'name': 'moe' }
|
|
*/
|
|
function pick(object, callback, thisArg) {
|
|
var result = {};
|
|
if (typeof callback != 'function') {
|
|
var index = 0,
|
|
props = concat.apply(arrayRef, arguments),
|
|
length = isObject(object) ? props.length : 0;
|
|
|
|
while (++index < length) {
|
|
var key = props[index];
|
|
if (key in object) {
|
|
result[key] = object[key];
|
|
}
|
|
}
|
|
} else {
|
|
callback = createCallback(callback, thisArg);
|
|
forIn(object, function(value, key, object) {
|
|
if (callback(value, key, object)) {
|
|
result[key] = value;
|
|
}
|
|
});
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Creates an array composed of the own enumerable property values of `object`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Objects
|
|
* @param {Object} object The object to inspect.
|
|
* @returns {Array} Returns a new array of property values.
|
|
* @example
|
|
*
|
|
* _.values({ 'one': 1, 'two': 2, 'three': 3 });
|
|
* // => [1, 2, 3]
|
|
*/
|
|
function values(object) {
|
|
var index = -1,
|
|
props = keys(object),
|
|
length = props.length,
|
|
result = Array(length);
|
|
|
|
while (++index < length) {
|
|
result[index] = object[props[index]];
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* Creates an array of elements from the specified indexes, or keys, of the
|
|
* `collection`. Indexes may be specified as individual arguments or as arrays
|
|
* of indexes.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Collections
|
|
* @param {Array|Object|String} collection The collection to iterate over.
|
|
* @param {Array|Number|String} [index1, index2, ...] The indexes of
|
|
* `collection` to retrieve, either as individual arguments or arrays.
|
|
* @returns {Array} Returns a new array of elements corresponding to the
|
|
* provided indexes.
|
|
* @example
|
|
*
|
|
* _.at(['a', 'b', 'c', 'd', 'e'], [0, 2, 4]);
|
|
* // => ['a', 'c', 'e']
|
|
*
|
|
* _.at(['moe', 'larry', 'curly'], 0, 2);
|
|
* // => ['moe', 'curly']
|
|
*/
|
|
function at(collection) {
|
|
var index = -1,
|
|
props = concat.apply(arrayRef, slice(arguments, 1)),
|
|
length = props.length,
|
|
result = Array(length);
|
|
|
|
while(++index < length) {
|
|
result[index] = collection[props[index]];
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Checks if a given `target` element is present in a `collection` using strict
|
|
* equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used
|
|
* as the offset from the end of the collection.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @alias include
|
|
* @category Collections
|
|
* @param {Array|Object|String} collection The collection to iterate over.
|
|
* @param {Mixed} target The value to check for.
|
|
* @param {Number} [fromIndex=0] The index to search from.
|
|
* @returns {Boolean} Returns `true` if the `target` element is found, else `false`.
|
|
* @example
|
|
*
|
|
* _.contains([1, 2, 3], 1);
|
|
* // => true
|
|
*
|
|
* _.contains([1, 2, 3], 1, 2);
|
|
* // => false
|
|
*
|
|
* _.contains({ 'name': 'moe', 'age': 40 }, 'moe');
|
|
* // => true
|
|
*
|
|
* _.contains('curly', 'ur');
|
|
* // => true
|
|
*/
|
|
function contains(collection, target, fromIndex) {
|
|
var index = -1,
|
|
length = collection ? collection.length : 0,
|
|
result = false;
|
|
|
|
fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex) || 0;
|
|
if (typeof length == 'number') {
|
|
result = (isString(collection)
|
|
? collection.indexOf(target, fromIndex)
|
|
: indexOf(collection, target, fromIndex)
|
|
) > -1;
|
|
} else {
|
|
each(collection, function(value) {
|
|
if (++index >= fromIndex) {
|
|
return !(result = value === target);
|
|
}
|
|
});
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Creates an object composed of keys returned from running each element of the
|
|
* `collection` through the given `callback`. The corresponding value of each key
|
|
* is the number of times the key was returned by the `callback`. The `callback`
|
|
* is bound to `thisArg` and invoked with three arguments; (value, index|key, collection).
|
|
*
|
|
* If a property name is passed for `callback`, the created "_.pluck" style
|
|
* callback will return the property value of the given element.
|
|
*
|
|
* If an object is passed for `callback`, the created "_.where" style callback
|
|
* will return `true` for elements that have the propeties of the given object,
|
|
* else `false`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Collections
|
|
* @param {Array|Object|String} collection The collection to iterate over.
|
|
* @param {Function|Object|String} [callback=identity] The function called per
|
|
* iteration. If a property name or object is passed, it will be used to create
|
|
* a "_.pluck" or "_.where" style callback, respectively.
|
|
* @param {Mixed} [thisArg] The `this` binding of `callback`.
|
|
* @returns {Object} Returns the composed aggregate object.
|
|
* @example
|
|
*
|
|
* _.countBy([4.3, 6.1, 6.4], function(num) { return Math.floor(num); });
|
|
* // => { '4': 1, '6': 2 }
|
|
*
|
|
* _.countBy([4.3, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
|
|
* // => { '4': 1, '6': 2 }
|
|
*
|
|
* _.countBy(['one', 'two', 'three'], 'length');
|
|
* // => { '3': 2, '5': 1 }
|
|
*/
|
|
function countBy(collection, callback, thisArg) {
|
|
var result = {};
|
|
callback = createCallback(callback, thisArg);
|
|
|
|
forEach(collection, function(value, key, collection) {
|
|
key = callback(value, key, collection) + '';
|
|
(hasOwnProperty.call(result, key) ? result[key]++ : result[key] = 1);
|
|
});
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Checks if the `callback` returns a truthy value for **all** elements of a
|
|
* `collection`. The `callback` is bound to `thisArg` and invoked with three
|
|
* arguments; (value, index|key, collection).
|
|
*
|
|
* If a property name is passed for `callback`, the created "_.pluck" style
|
|
* callback will return the property value of the given element.
|
|
*
|
|
* If an object is passed for `callback`, the created "_.where" style callback
|
|
* will return `true` for elements that have the propeties of the given object,
|
|
* else `false`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @alias all
|
|
* @category Collections
|
|
* @param {Array|Object|String} collection The collection to iterate over.
|
|
* @param {Function|Object|String} [callback=identity] The function called per
|
|
* iteration. If a property name or object is passed, it will be used to create
|
|
* a "_.pluck" or "_.where" style callback, respectively.
|
|
* @param {Mixed} [thisArg] The `this` binding of `callback`.
|
|
* @returns {Boolean} Returns `true` if all elements pass the callback check,
|
|
* else `false`.
|
|
* @example
|
|
*
|
|
* _.every([true, 1, null, 'yes'], Boolean);
|
|
* // => false
|
|
*
|
|
* var stooges = [
|
|
* { 'name': 'moe', 'age': 40 },
|
|
* { 'name': 'larry', 'age': 50 }
|
|
* ];
|
|
*
|
|
* // using "_.pluck" callback shorthand
|
|
* _.every(stooges, 'age');
|
|
* // => true
|
|
*
|
|
* // using "_.where" callback shorthand
|
|
* _.every(stooges, { 'age': 50 });
|
|
* // => false
|
|
*/
|
|
function every(collection, callback, thisArg) {
|
|
var result = true;
|
|
callback = createCallback(callback, thisArg);
|
|
|
|
if (isArray(collection)) {
|
|
var index = -1,
|
|
length = collection.length;
|
|
|
|
while (++index < length) {
|
|
if (!(result = !!callback(collection[index], index, collection))) {
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
each(collection, function(value, index, collection) {
|
|
return (result = !!callback(value, index, collection));
|
|
});
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Examines each element in a `collection`, returning an array of all elements
|
|
* the `callback` returns truthy for. The `callback` is bound to `thisArg` and
|
|
* invoked with three arguments; (value, index|key, collection).
|
|
*
|
|
* If a property name is passed for `callback`, the created "_.pluck" style
|
|
* callback will return the property value of the given element.
|
|
*
|
|
* If an object is passed for `callback`, the created "_.where" style callback
|
|
* will return `true` for elements that have the propeties of the given object,
|
|
* else `false`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @alias select
|
|
* @category Collections
|
|
* @param {Array|Object|String} collection The collection to iterate over.
|
|
* @param {Function|Object|String} [callback=identity] The function called per
|
|
* iteration. If a property name or object is passed, it will be used to create
|
|
* a "_.pluck" or "_.where" style callback, respectively.
|
|
* @param {Mixed} [thisArg] The `this` binding of `callback`.
|
|
* @returns {Array} Returns a new array of elements that passed the callback check.
|
|
* @example
|
|
*
|
|
* var evens = _.filter([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
|
|
* // => [2, 4, 6]
|
|
*
|
|
* var food = [
|
|
* { 'name': 'apple', 'organic': false, 'type': 'fruit' },
|
|
* { 'name': 'carrot', 'organic': true, 'type': 'vegetable' }
|
|
* ];
|
|
*
|
|
* // using "_.pluck" callback shorthand
|
|
* _.filter(food, 'organic');
|
|
* // => [{ 'name': 'carrot', 'organic': true, 'type': 'vegetable' }]
|
|
*
|
|
* // using "_.where" callback shorthand
|
|
* _.filter(food, { 'type': 'fruit' });
|
|
* // => [{ 'name': 'apple', 'organic': false, 'type': 'fruit' }]
|
|
*/
|
|
function filter(collection, callback, thisArg) {
|
|
var result = [];
|
|
callback = createCallback(callback, thisArg);
|
|
|
|
if (isArray(collection)) {
|
|
var index = -1,
|
|
length = collection.length;
|
|
|
|
while (++index < length) {
|
|
var value = collection[index];
|
|
if (callback(value, index, collection)) {
|
|
result.push(value);
|
|
}
|
|
}
|
|
} else {
|
|
each(collection, function(value, index, collection) {
|
|
if (callback(value, index, collection)) {
|
|
result.push(value);
|
|
}
|
|
});
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Examines each element in a `collection`, returning the first that the `callback`
|
|
* returns truthy for. The `callback` is bound to `thisArg` and invoked with three
|
|
* arguments; (value, index|key, collection).
|
|
*
|
|
* If a property name is passed for `callback`, the created "_.pluck" style
|
|
* callback will return the property value of the given element.
|
|
*
|
|
* If an object is passed for `callback`, the created "_.where" style callback
|
|
* will return `true` for elements that have the propeties of the given object,
|
|
* else `false`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @alias detect
|
|
* @category Collections
|
|
* @param {Array|Object|String} collection The collection to iterate over.
|
|
* @param {Function|Object|String} [callback=identity] The function called per
|
|
* iteration. If a property name or object is passed, it will be used to create
|
|
* a "_.pluck" or "_.where" style callback, respectively.
|
|
* @param {Mixed} [thisArg] The `this` binding of `callback`.
|
|
* @returns {Mixed} Returns the element that passed the callback check,
|
|
* else `undefined`.
|
|
* @example
|
|
*
|
|
* var even = _.find([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
|
|
* // => 2
|
|
*
|
|
* var food = [
|
|
* { 'name': 'apple', 'organic': false, 'type': 'fruit' },
|
|
* { 'name': 'banana', 'organic': true, 'type': 'fruit' },
|
|
* { 'name': 'beet', 'organic': false, 'type': 'vegetable' },
|
|
* { 'name': 'carrot', 'organic': true, 'type': 'vegetable' }
|
|
* ];
|
|
*
|
|
* // using "_.where" callback shorthand
|
|
* var veggie = _.find(food, { 'type': 'vegetable' });
|
|
* // => { 'name': 'beet', 'organic': false, 'type': 'vegetable' }
|
|
*
|
|
* // using "_.pluck" callback shorthand
|
|
* var healthy = _.find(food, 'organic');
|
|
* // => { 'name': 'banana', 'organic': true, 'type': 'fruit' }
|
|
*/
|
|
function find(collection, callback, thisArg) {
|
|
var result;
|
|
callback = createCallback(callback, thisArg);
|
|
|
|
forEach(collection, function(value, index, collection) {
|
|
if (callback(value, index, collection)) {
|
|
result = value;
|
|
return false;
|
|
}
|
|
});
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Iterates over a `collection`, executing the `callback` for each element in
|
|
* the `collection`. The `callback` is bound to `thisArg` and invoked with three
|
|
* arguments; (value, index|key, collection). Callbacks may exit iteration early
|
|
* by explicitly returning `false`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @alias each
|
|
* @category Collections
|
|
* @param {Array|Object|String} collection The collection to iterate over.
|
|
* @param {Function} [callback=identity] The function called per iteration.
|
|
* @param {Mixed} [thisArg] The `this` binding of `callback`.
|
|
* @returns {Array|Object|String} Returns `collection`.
|
|
* @example
|
|
*
|
|
* _([1, 2, 3]).forEach(alert).join(',');
|
|
* // => alerts each number and returns '1,2,3'
|
|
*
|
|
* _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, alert);
|
|
* // => alerts each number value (order is not guaranteed)
|
|
*/
|
|
function forEach(collection, callback, thisArg) {
|
|
if (callback && typeof thisArg == 'undefined' && isArray(collection)) {
|
|
var index = -1,
|
|
length = collection.length;
|
|
|
|
while (++index < length) {
|
|
if (callback(collection[index], index, collection) === false) {
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
each(collection, callback, thisArg);
|
|
}
|
|
return collection;
|
|
}
|
|
|
|
/**
|
|
* Creates an object composed of keys returned from running each element of the
|
|
* `collection` through the `callback`. The corresponding value of each key is
|
|
* an array of elements passed to `callback` that returned the key. The `callback`
|
|
* is bound to `thisArg` and invoked with three arguments; (value, index|key, collection).
|
|
*
|
|
* If a property name is passed for `callback`, the created "_.pluck" style
|
|
* callback will return the property value of the given element.
|
|
*
|
|
* If an object is passed for `callback`, the created "_.where" style callback
|
|
* will return `true` for elements that have the propeties of the given object,
|
|
* else `false`
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Collections
|
|
* @param {Array|Object|String} collection The collection to iterate over.
|
|
* @param {Function|Object|String} [callback=identity] The function called per
|
|
* iteration. If a property name or object is passed, it will be used to create
|
|
* a "_.pluck" or "_.where" style callback, respectively.
|
|
* @param {Mixed} [thisArg] The `this` binding of `callback`.
|
|
* @returns {Object} Returns the composed aggregate object.
|
|
* @example
|
|
*
|
|
* _.groupBy([4.2, 6.1, 6.4], function(num) { return Math.floor(num); });
|
|
* // => { '4': [4.2], '6': [6.1, 6.4] }
|
|
*
|
|
* _.groupBy([4.2, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
|
|
* // => { '4': [4.2], '6': [6.1, 6.4] }
|
|
*
|
|
* // using "_.pluck" callback shorthand
|
|
* _.groupBy(['one', 'two', 'three'], 'length');
|
|
* // => { '3': ['one', 'two'], '5': ['three'] }
|
|
*/
|
|
function groupBy(collection, callback, thisArg) {
|
|
var result = {};
|
|
callback = createCallback(callback, thisArg);
|
|
|
|
forEach(collection, function(value, key, collection) {
|
|
key = callback(value, key, collection) + '';
|
|
(hasOwnProperty.call(result, key) ? result[key] : result[key] = []).push(value);
|
|
});
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Invokes the method named by `methodName` on each element in the `collection`,
|
|
* returning an array of the results of each invoked method. Additional arguments
|
|
* will be passed to each invoked method. If `methodName` is a function, it will
|
|
* be invoked for, and `this` bound to, each element in the `collection`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Collections
|
|
* @param {Array|Object|String} collection The collection to iterate over.
|
|
* @param {Function|String} methodName The name of the method to invoke or
|
|
* the function invoked per iteration.
|
|
* @param {Mixed} [arg1, arg2, ...] Arguments to invoke the method with.
|
|
* @returns {Array} Returns a new array of the results of each invoked method.
|
|
* @example
|
|
*
|
|
* _.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
|
|
* // => [[1, 5, 7], [1, 2, 3]]
|
|
*
|
|
* _.invoke([123, 456], String.prototype.split, '');
|
|
* // => [['1', '2', '3'], ['4', '5', '6']]
|
|
*/
|
|
function invoke(collection, methodName) {
|
|
var args = slice(arguments, 2),
|
|
index = -1,
|
|
isFunc = typeof methodName == 'function',
|
|
length = collection ? collection.length : 0,
|
|
result = Array(typeof length == 'number' ? length : 0);
|
|
|
|
forEach(collection, function(value) {
|
|
result[++index] = (isFunc ? methodName : value[methodName]).apply(value, args);
|
|
});
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Creates an array of values by running each element in the `collection`
|
|
* through the `callback`. The `callback` is bound to `thisArg` and invoked with
|
|
* three arguments; (value, index|key, collection).
|
|
*
|
|
* If a property name is passed for `callback`, the created "_.pluck" style
|
|
* callback will return the property value of the given element.
|
|
*
|
|
* If an object is passed for `callback`, the created "_.where" style callback
|
|
* will return `true` for elements that have the propeties of the given object,
|
|
* else `false`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @alias collect
|
|
* @category Collections
|
|
* @param {Array|Object|String} collection The collection to iterate over.
|
|
* @param {Function|Object|String} [callback=identity] The function called per
|
|
* iteration. If a property name or object is passed, it will be used to create
|
|
* a "_.pluck" or "_.where" style callback, respectively.
|
|
* @param {Mixed} [thisArg] The `this` binding of `callback`.
|
|
* @returns {Array} Returns a new array of the results of each `callback` execution.
|
|
* @example
|
|
*
|
|
* _.map([1, 2, 3], function(num) { return num * 3; });
|
|
* // => [3, 6, 9]
|
|
*
|
|
* _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { return num * 3; });
|
|
* // => [3, 6, 9] (order is not guaranteed)
|
|
*
|
|
* var stooges = [
|
|
* { 'name': 'moe', 'age': 40 },
|
|
* { 'name': 'larry', 'age': 50 }
|
|
* ];
|
|
*
|
|
* // using "_.pluck" callback shorthand
|
|
* _.map(stooges, 'name');
|
|
* // => ['moe', 'larry']
|
|
*/
|
|
function map(collection, callback, thisArg) {
|
|
var index = -1,
|
|
length = collection ? collection.length : 0,
|
|
result = Array(typeof length == 'number' ? length : 0);
|
|
|
|
callback = createCallback(callback, thisArg);
|
|
if (isArray(collection)) {
|
|
while (++index < length) {
|
|
result[index] = callback(collection[index], index, collection);
|
|
}
|
|
} else {
|
|
each(collection, function(value, key, collection) {
|
|
result[++index] = callback(value, key, collection);
|
|
});
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Retrieves the maximum value of an `array`. If `callback` is passed,
|
|
* it will be executed for each value in the `array` to generate the
|
|
* criterion by which the value is ranked. The `callback` is bound to
|
|
* `thisArg` and invoked with three arguments; (value, index, collection).
|
|
*
|
|
* If a property name is passed for `callback`, the created "_.pluck" style
|
|
* callback will return the property value of the given element.
|
|
*
|
|
* If an object is passed for `callback`, the created "_.where" style callback
|
|
* will return `true` for elements that have the propeties of the given object,
|
|
* else `false`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Collections
|
|
* @param {Array|Object|String} collection The collection to iterate over.
|
|
* @param {Function|Object|String} [callback=identity] The function called per
|
|
* iteration. If a property name or object is passed, it will be used to create
|
|
* a "_.pluck" or "_.where" style callback, respectively.
|
|
* @param {Mixed} [thisArg] The `this` binding of `callback`.
|
|
* @returns {Mixed} Returns the maximum value.
|
|
* @example
|
|
*
|
|
* _.max([4, 2, 8, 6]);
|
|
* // => 8
|
|
*
|
|
* var stooges = [
|
|
* { 'name': 'moe', 'age': 40 },
|
|
* { 'name': 'larry', 'age': 50 }
|
|
* ];
|
|
*
|
|
* _.max(stooges, function(stooge) { return stooge.age; });
|
|
* // => { 'name': 'larry', 'age': 50 };
|
|
*
|
|
* // using "_.pluck" callback shorthand
|
|
* _.max(stooges, 'age');
|
|
* // => { 'name': 'larry', 'age': 50 };
|
|
*/
|
|
function max(collection, callback, thisArg) {
|
|
var computed = -Infinity,
|
|
result = computed;
|
|
|
|
if (!callback && isArray(collection)) {
|
|
var index = -1,
|
|
length = collection.length;
|
|
|
|
while (++index < length) {
|
|
var value = collection[index];
|
|
if (value > result) {
|
|
result = value;
|
|
}
|
|
}
|
|
} else {
|
|
callback = !callback && isString(collection)
|
|
? charAtCallback
|
|
: createCallback(callback, thisArg);
|
|
|
|
each(collection, function(value, index, collection) {
|
|
var current = callback(value, index, collection);
|
|
if (current > computed) {
|
|
computed = current;
|
|
result = value;
|
|
}
|
|
});
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Retrieves the minimum value of an `array`. If `callback` is passed,
|
|
* it will be executed for each value in the `array` to generate the
|
|
* criterion by which the value is ranked. The `callback` is bound to `thisArg`
|
|
* and invoked with three arguments; (value, index, collection).
|
|
*
|
|
* If a property name is passed for `callback`, the created "_.pluck" style
|
|
* callback will return the property value of the given element.
|
|
*
|
|
* If an object is passed for `callback`, the created "_.where" style callback
|
|
* will return `true` for elements that have the propeties of the given object,
|
|
* else `false`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Collections
|
|
* @param {Array|Object|String} collection The collection to iterate over.
|
|
* @param {Function|Object|String} [callback=identity] The function called per
|
|
* iteration. If a property name or object is passed, it will be used to create
|
|
* a "_.pluck" or "_.where" style callback, respectively.
|
|
* @param {Mixed} [thisArg] The `this` binding of `callback`.
|
|
* @returns {Mixed} Returns the minimum value.
|
|
* @example
|
|
*
|
|
* _.min([4, 2, 8, 6]);
|
|
* // => 2
|
|
*
|
|
* var stooges = [
|
|
* { 'name': 'moe', 'age': 40 },
|
|
* { 'name': 'larry', 'age': 50 }
|
|
* ];
|
|
*
|
|
* _.min(stooges, function(stooge) { return stooge.age; });
|
|
* // => { 'name': 'moe', 'age': 40 };
|
|
*
|
|
* // using "_.pluck" callback shorthand
|
|
* _.min(stooges, 'age');
|
|
* // => { 'name': 'moe', 'age': 40 };
|
|
*/
|
|
function min(collection, callback, thisArg) {
|
|
var computed = Infinity,
|
|
result = computed;
|
|
|
|
if (!callback && isArray(collection)) {
|
|
var index = -1,
|
|
length = collection.length;
|
|
|
|
while (++index < length) {
|
|
var value = collection[index];
|
|
if (value < result) {
|
|
result = value;
|
|
}
|
|
}
|
|
} else {
|
|
callback = !callback && isString(collection)
|
|
? charAtCallback
|
|
: createCallback(callback, thisArg);
|
|
|
|
each(collection, function(value, index, collection) {
|
|
var current = callback(value, index, collection);
|
|
if (current < computed) {
|
|
computed = current;
|
|
result = value;
|
|
}
|
|
});
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Retrieves the value of a specified property from all elements in the `collection`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @type Function
|
|
* @category Collections
|
|
* @param {Array|Object|String} collection The collection to iterate over.
|
|
* @param {String} property The property to pluck.
|
|
* @returns {Array} Returns a new array of property values.
|
|
* @example
|
|
*
|
|
* var stooges = [
|
|
* { 'name': 'moe', 'age': 40 },
|
|
* { 'name': 'larry', 'age': 50 }
|
|
* ];
|
|
*
|
|
* _.pluck(stooges, 'name');
|
|
* // => ['moe', 'larry']
|
|
*/
|
|
var pluck = map;
|
|
|
|
/**
|
|
* Reduces a `collection` to a value that is the accumulated result of running
|
|
* each element in the `collection` through the `callback`, where each successive
|
|
* `callback` execution consumes the return value of the previous execution.
|
|
* If `accumulator` is not passed, the first element of the `collection` will be
|
|
* used as the initial `accumulator` value. The `callback` is bound to `thisArg`
|
|
* and invoked with four arguments; (accumulator, value, index|key, collection).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @alias foldl, inject
|
|
* @category Collections
|
|
* @param {Array|Object|String} collection The collection to iterate over.
|
|
* @param {Function} [callback=identity] The function called per iteration.
|
|
* @param {Mixed} [accumulator] Initial value of the accumulator.
|
|
* @param {Mixed} [thisArg] The `this` binding of `callback`.
|
|
* @returns {Mixed} Returns the accumulated value.
|
|
* @example
|
|
*
|
|
* var sum = _.reduce([1, 2, 3], function(sum, num) {
|
|
* return sum + num;
|
|
* });
|
|
* // => 6
|
|
*
|
|
* var mapped = _.reduce({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) {
|
|
* result[key] = num * 3;
|
|
* return result;
|
|
* }, {});
|
|
* // => { 'a': 3, 'b': 6, 'c': 9 }
|
|
*/
|
|
function reduce(collection, callback, accumulator, thisArg) {
|
|
var noaccum = arguments.length < 3;
|
|
callback = createCallback(callback, thisArg, 4);
|
|
|
|
if (isArray(collection)) {
|
|
var index = -1,
|
|
length = collection.length;
|
|
|
|
if (noaccum) {
|
|
accumulator = collection[++index];
|
|
}
|
|
while (++index < length) {
|
|
accumulator = callback(accumulator, collection[index], index, collection);
|
|
}
|
|
} else {
|
|
each(collection, function(value, index, collection) {
|
|
accumulator = noaccum
|
|
? (noaccum = false, value)
|
|
: callback(accumulator, value, index, collection)
|
|
});
|
|
}
|
|
return accumulator;
|
|
}
|
|
|
|
/**
|
|
* This method is similar to `_.reduce`, except that it iterates over a
|
|
* `collection` from right to left.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @alias foldr
|
|
* @category Collections
|
|
* @param {Array|Object|String} collection The collection to iterate over.
|
|
* @param {Function} [callback=identity] The function called per iteration.
|
|
* @param {Mixed} [accumulator] Initial value of the accumulator.
|
|
* @param {Mixed} [thisArg] The `this` binding of `callback`.
|
|
* @returns {Mixed} Returns the accumulated value.
|
|
* @example
|
|
*
|
|
* var list = [[0, 1], [2, 3], [4, 5]];
|
|
* var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []);
|
|
* // => [4, 5, 2, 3, 0, 1]
|
|
*/
|
|
function reduceRight(collection, callback, accumulator, thisArg) {
|
|
var iterable = collection,
|
|
length = collection ? collection.length : 0,
|
|
noaccum = arguments.length < 3;
|
|
|
|
if (typeof length != 'number') {
|
|
var props = keys(collection);
|
|
length = props.length;
|
|
}
|
|
callback = createCallback(callback, thisArg, 4);
|
|
forEach(collection, function(value, index, collection) {
|
|
index = props ? props[--length] : --length;
|
|
accumulator = noaccum
|
|
? (noaccum = false, iterable[index])
|
|
: callback(accumulator, iterable[index], index, collection);
|
|
});
|
|
return accumulator;
|
|
}
|
|
|
|
/**
|
|
* The opposite of `_.filter`, this method returns the elements of a
|
|
* `collection` that `callback` does **not** return truthy for.
|
|
*
|
|
* If a property name is passed for `callback`, the created "_.pluck" style
|
|
* callback will return the property value of the given element.
|
|
*
|
|
* If an object is passed for `callback`, the created "_.where" style callback
|
|
* will return `true` for elements that have the propeties of the given object,
|
|
* else `false`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Collections
|
|
* @param {Array|Object|String} collection The collection to iterate over.
|
|
* @param {Function|Object|String} [callback=identity] The function called per
|
|
* iteration. If a property name or object is passed, it will be used to create
|
|
* a "_.pluck" or "_.where" style callback, respectively.
|
|
* @param {Mixed} [thisArg] The `this` binding of `callback`.
|
|
* @returns {Array} Returns a new array of elements that did **not** pass the
|
|
* callback check.
|
|
* @example
|
|
*
|
|
* var odds = _.reject([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
|
|
* // => [1, 3, 5]
|
|
*
|
|
* var food = [
|
|
* { 'name': 'apple', 'organic': false, 'type': 'fruit' },
|
|
* { 'name': 'carrot', 'organic': true, 'type': 'vegetable' }
|
|
* ];
|
|
*
|
|
* // using "_.pluck" callback shorthand
|
|
* _.reject(food, 'organic');
|
|
* // => [{ 'name': 'apple', 'organic': false, 'type': 'fruit' }]
|
|
*
|
|
* // using "_.where" callback shorthand
|
|
* _.reject(food, { 'type': 'fruit' });
|
|
* // => [{ 'name': 'carrot', 'organic': true, 'type': 'vegetable' }]
|
|
*/
|
|
function reject(collection, callback, thisArg) {
|
|
callback = createCallback(callback, thisArg);
|
|
return filter(collection, function(value, index, collection) {
|
|
return !callback(value, index, collection);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Creates an array of shuffled `array` values, using a version of the
|
|
* Fisher-Yates shuffle. See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Collections
|
|
* @param {Array|Object|String} collection The collection to shuffle.
|
|
* @returns {Array} Returns a new shuffled collection.
|
|
* @example
|
|
*
|
|
* _.shuffle([1, 2, 3, 4, 5, 6]);
|
|
* // => [4, 1, 6, 3, 5, 2]
|
|
*/
|
|
function shuffle(collection) {
|
|
var index = -1,
|
|
length = collection ? collection.length : 0,
|
|
result = Array(typeof length == 'number' ? length : 0);
|
|
|
|
forEach(collection, function(value) {
|
|
var rand = floor(nativeRandom() * (++index + 1));
|
|
result[index] = result[rand];
|
|
result[rand] = value;
|
|
});
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Gets the size of the `collection` by returning `collection.length` for arrays
|
|
* and array-like objects or the number of own enumerable properties for objects.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Collections
|
|
* @param {Array|Object|String} collection The collection to inspect.
|
|
* @returns {Number} Returns `collection.length` or number of own enumerable properties.
|
|
* @example
|
|
*
|
|
* _.size([1, 2]);
|
|
* // => 2
|
|
*
|
|
* _.size({ 'one': 1, 'two': 2, 'three': 3 });
|
|
* // => 3
|
|
*
|
|
* _.size('curly');
|
|
* // => 5
|
|
*/
|
|
function size(collection) {
|
|
var length = collection ? collection.length : 0;
|
|
return typeof length == 'number' ? length : keys(collection).length;
|
|
}
|
|
|
|
/**
|
|
* Checks if the `callback` returns a truthy value for **any** element of a
|
|
* `collection`. The function returns as soon as it finds passing value, and
|
|
* does not iterate over the entire `collection`. The `callback` is bound to
|
|
* `thisArg` and invoked with three arguments; (value, index|key, collection).
|
|
*
|
|
* If a property name is passed for `callback`, the created "_.pluck" style
|
|
* callback will return the property value of the given element.
|
|
*
|
|
* If an object is passed for `callback`, the created "_.where" style callback
|
|
* will return `true` for elements that have the propeties of the given object,
|
|
* else `false`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @alias any
|
|
* @category Collections
|
|
* @param {Array|Object|String} collection The collection to iterate over.
|
|
* @param {Function|Object|String} [callback=identity] The function called per
|
|
* iteration. If a property name or object is passed, it will be used to create
|
|
* a "_.pluck" or "_.where" style callback, respectively.
|
|
* @param {Mixed} [thisArg] The `this` binding of `callback`.
|
|
* @returns {Boolean} Returns `true` if any element passes the callback check,
|
|
* else `false`.
|
|
* @example
|
|
*
|
|
* _.some([null, 0, 'yes', false], Boolean);
|
|
* // => true
|
|
*
|
|
* var food = [
|
|
* { 'name': 'apple', 'organic': false, 'type': 'fruit' },
|
|
* { 'name': 'carrot', 'organic': true, 'type': 'vegetable' }
|
|
* ];
|
|
*
|
|
* // using "_.pluck" callback shorthand
|
|
* _.some(food, 'organic');
|
|
* // => true
|
|
*
|
|
* // using "_.where" callback shorthand
|
|
* _.some(food, { 'type': 'meat' });
|
|
* // => false
|
|
*/
|
|
function some(collection, callback, thisArg) {
|
|
var result;
|
|
callback = createCallback(callback, thisArg);
|
|
|
|
if (isArray(collection)) {
|
|
var index = -1,
|
|
length = collection.length;
|
|
|
|
while (++index < length) {
|
|
if ((result = callback(collection[index], index, collection))) {
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
each(collection, function(value, index, collection) {
|
|
return !(result = callback(value, index, collection));
|
|
});
|
|
}
|
|
return !!result;
|
|
}
|
|
|
|
/**
|
|
* Creates an array of elements, sorted in ascending order by the results of
|
|
* running each element in the `collection` through the `callback`. This method
|
|
* performs a stable sort, that is, it will preserve the original sort order of
|
|
* equal elements. The `callback` is bound to `thisArg` and invoked with three
|
|
* arguments; (value, index|key, collection).
|
|
*
|
|
* If a property name is passed for `callback`, the created "_.pluck" style
|
|
* callback will return the property value of the given element.
|
|
*
|
|
* If an object is passed for `callback`, the created "_.where" style callback
|
|
* will return `true` for elements that have the propeties of the given object,
|
|
* else `false`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Collections
|
|
* @param {Array|Object|String} collection The collection to iterate over.
|
|
* @param {Function|Object|String} [callback=identity] The function called per
|
|
* iteration. If a property name or object is passed, it will be used to create
|
|
* a "_.pluck" or "_.where" style callback, respectively.
|
|
* @param {Mixed} [thisArg] The `this` binding of `callback`.
|
|
* @returns {Array} Returns a new array of sorted elements.
|
|
* @example
|
|
*
|
|
* _.sortBy([1, 2, 3], function(num) { return Math.sin(num); });
|
|
* // => [3, 1, 2]
|
|
*
|
|
* _.sortBy([1, 2, 3], function(num) { return this.sin(num); }, Math);
|
|
* // => [3, 1, 2]
|
|
*
|
|
* // using "_.pluck" callback shorthand
|
|
* _.sortBy(['banana', 'strawberry', 'apple'], 'length');
|
|
* // => ['apple', 'banana', 'strawberry']
|
|
*/
|
|
function sortBy(collection, callback, thisArg) {
|
|
var index = -1,
|
|
length = collection ? collection.length : 0,
|
|
result = Array(typeof length == 'number' ? length : 0);
|
|
|
|
callback = createCallback(callback, thisArg);
|
|
forEach(collection, function(value, key, collection) {
|
|
result[++index] = {
|
|
'criteria': callback(value, key, collection),
|
|
'index': index,
|
|
'value': value
|
|
};
|
|
});
|
|
|
|
length = result.length;
|
|
result.sort(compareAscending);
|
|
while (length--) {
|
|
result[length] = result[length].value;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts the `collection` to an array.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Collections
|
|
* @param {Array|Object|String} collection The collection to convert.
|
|
* @returns {Array} Returns the new converted array.
|
|
* @example
|
|
*
|
|
* (function() { return _.toArray(arguments).slice(1); })(1, 2, 3, 4);
|
|
* // => [2, 3, 4]
|
|
*/
|
|
function toArray(collection) {
|
|
if (collection && typeof collection.length == 'number') {
|
|
return slice(collection);
|
|
}
|
|
return values(collection);
|
|
}
|
|
|
|
/**
|
|
* Examines each element in a `collection`, returning an array of all elements
|
|
* that have the given `properties`. When checking `properties`, this method
|
|
* performs a deep comparison between values to determine if they are equivalent
|
|
* to each other.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @type Function
|
|
* @category Collections
|
|
* @param {Array|Object|String} collection The collection to iterate over.
|
|
* @param {Object} properties The object of property values to filter by.
|
|
* @returns {Array} Returns a new array of elements that have the given `properties`.
|
|
* @example
|
|
*
|
|
* var stooges = [
|
|
* { 'name': 'moe', 'age': 40 },
|
|
* { 'name': 'larry', 'age': 50 }
|
|
* ];
|
|
*
|
|
* _.where(stooges, { 'age': 40 });
|
|
* // => [{ 'name': 'moe', 'age': 40 }]
|
|
*/
|
|
var where = filter;
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* Creates an array with all falsey values of `array` removed. The values
|
|
* `false`, `null`, `0`, `""`, `undefined` and `NaN` are all falsey.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Arrays
|
|
* @param {Array} array The array to compact.
|
|
* @returns {Array} Returns a new filtered array.
|
|
* @example
|
|
*
|
|
* _.compact([0, 1, false, 2, '', 3]);
|
|
* // => [1, 2, 3]
|
|
*/
|
|
function compact(array) {
|
|
var index = -1,
|
|
length = array ? array.length : 0,
|
|
result = [];
|
|
|
|
while (++index < length) {
|
|
var value = array[index];
|
|
if (value) {
|
|
result.push(value);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Creates an array of `array` elements not present in the other arrays
|
|
* using strict equality for comparisons, i.e. `===`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Arrays
|
|
* @param {Array} array The array to process.
|
|
* @param {Array} [array1, array2, ...] Arrays to check.
|
|
* @returns {Array} Returns a new array of `array` elements not present in the
|
|
* other arrays.
|
|
* @example
|
|
*
|
|
* _.difference([1, 2, 3, 4, 5], [5, 2, 10]);
|
|
* // => [1, 3, 4]
|
|
*/
|
|
function difference(array) {
|
|
var index = -1,
|
|
length = array ? array.length : 0,
|
|
flattened = concat.apply(arrayRef, arguments),
|
|
contains = cachedContains(flattened, length),
|
|
result = [];
|
|
|
|
while (++index < length) {
|
|
var value = array[index];
|
|
if (!contains(value)) {
|
|
result.push(value);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Gets the first element of the `array`. If a number `n` is passed, the first
|
|
* `n` elements of the `array` are returned. If a `callback` function is passed,
|
|
* the first elements the `callback` returns truthy for are returned. The `callback`
|
|
* is bound to `thisArg` and invoked with three arguments; (value, index, array).
|
|
*
|
|
* If a property name is passed for `callback`, the created "_.pluck" style
|
|
* callback will return the property value of the given element.
|
|
*
|
|
* If an object is passed for `callback`, the created "_.where" style callback
|
|
* will return `true` for elements that have the propeties of the given object,
|
|
* else `false`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @alias head, take
|
|
* @category Arrays
|
|
* @param {Array} array The array to query.
|
|
* @param {Function|Object|Number|String} [callback|n] The function called
|
|
* per element or the number of elements to return. If a property name or
|
|
* object is passed, it will be used to create a "_.pluck" or "_.where"
|
|
* style callback, respectively.
|
|
* @param {Mixed} [thisArg] The `this` binding of `callback`.
|
|
* @returns {Mixed} Returns the first element(s) of `array`.
|
|
* @example
|
|
*
|
|
* _.first([1, 2, 3]);
|
|
* // => 1
|
|
*
|
|
* _.first([1, 2, 3], 2);
|
|
* // => [1, 2]
|
|
*
|
|
* _.first([1, 2, 3], function(num) {
|
|
* return num < 3;
|
|
* });
|
|
* // => [1, 2]
|
|
*
|
|
* var food = [
|
|
* { 'name': 'banana', 'organic': true },
|
|
* { 'name': 'beet', 'organic': false },
|
|
* ];
|
|
*
|
|
* // using "_.pluck" callback shorthand
|
|
* _.first(food, 'organic');
|
|
* // => [{ 'name': 'banana', 'organic': true }]
|
|
*
|
|
* var food = [
|
|
* { 'name': 'apple', 'type': 'fruit' },
|
|
* { 'name': 'banana', 'type': 'fruit' },
|
|
* { 'name': 'beet', 'type': 'vegetable' }
|
|
* ];
|
|
*
|
|
* // using "_.where" callback shorthand
|
|
* _.first(food, { 'type': 'fruit' });
|
|
* // => [{ 'name': 'apple', 'type': 'fruit' }, { 'name': 'banana', 'type': 'fruit' }]
|
|
*/
|
|
function first(array, callback, thisArg) {
|
|
if (array) {
|
|
var n = 0,
|
|
length = array.length;
|
|
|
|
if (typeof callback != 'number' && callback != null) {
|
|
var index = -1;
|
|
callback = createCallback(callback, thisArg);
|
|
while (++index < length && callback(array[index], index, array)) {
|
|
n++;
|
|
}
|
|
} else {
|
|
n = callback;
|
|
if (n == null || thisArg) {
|
|
return array[0];
|
|
}
|
|
}
|
|
return slice(array, 0, nativeMin(nativeMax(0, n), length));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Flattens a nested array (the nesting can be to any depth). If `shallow` is
|
|
* truthy, `array` will only be flattened a single level.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Arrays
|
|
* @param {Array} array The array to compact.
|
|
* @param {Boolean} shallow A flag to indicate only flattening a single level.
|
|
* @returns {Array} Returns a new flattened array.
|
|
* @example
|
|
*
|
|
* _.flatten([1, [2], [3, [[4]]]]);
|
|
* // => [1, 2, 3, 4];
|
|
*
|
|
* _.flatten([1, [2], [3, [[4]]]], true);
|
|
* // => [1, 2, 3, [[4]]];
|
|
*/
|
|
function flatten(array, shallow) {
|
|
var index = -1,
|
|
length = array ? array.length : 0,
|
|
result = [];
|
|
|
|
while (++index < length) {
|
|
var value = array[index];
|
|
|
|
// recursively flatten arrays (susceptible to call stack limits)
|
|
if (isArray(value)) {
|
|
push.apply(result, shallow ? value : flatten(value));
|
|
} else {
|
|
result.push(value);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Gets the index at which the first occurrence of `value` is found using
|
|
* strict equality for comparisons, i.e. `===`. If the `array` is already
|
|
* sorted, passing `true` for `fromIndex` will run a faster binary search.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Arrays
|
|
* @param {Array} array The array to search.
|
|
* @param {Mixed} value The value to search for.
|
|
* @param {Boolean|Number} [fromIndex=0] The index to search from or `true` to
|
|
* perform a binary search on a sorted `array`.
|
|
* @returns {Number} Returns the index of the matched value or `-1`.
|
|
* @example
|
|
*
|
|
* _.indexOf([1, 2, 3, 1, 2, 3], 2);
|
|
* // => 1
|
|
*
|
|
* _.indexOf([1, 2, 3, 1, 2, 3], 2, 3);
|
|
* // => 4
|
|
*
|
|
* _.indexOf([1, 1, 2, 2, 3, 3], 2, true);
|
|
* // => 2
|
|
*/
|
|
function indexOf(array, value, fromIndex) {
|
|
var index = -1,
|
|
length = array ? array.length : 0;
|
|
|
|
if (typeof fromIndex == 'number') {
|
|
index = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex || 0) - 1;
|
|
} else if (fromIndex) {
|
|
index = sortedIndex(array, value);
|
|
return array[index] === value ? index : -1;
|
|
}
|
|
while (++index < length) {
|
|
if (array[index] === value) {
|
|
return index;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* Gets all but the last element of `array`. If a number `n` is passed, the
|
|
* last `n` elements are excluded from the result. If a `callback` function
|
|
* is passed, the last elements the `callback` returns truthy for are excluded
|
|
* from the result. The `callback` is bound to `thisArg` and invoked with three
|
|
* arguments; (value, index, array).
|
|
*
|
|
* If a property name is passed for `callback`, the created "_.pluck" style
|
|
* callback will return the property value of the given element.
|
|
*
|
|
* If an object is passed for `callback`, the created "_.where" style callback
|
|
* will return `true` for elements that have the propeties of the given object,
|
|
* else `false`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Arrays
|
|
* @param {Array} array The array to query.
|
|
* @param {Function|Object|Number|String} [callback|n=1] The function called
|
|
* per element or the number of elements to exclude. If a property name or
|
|
* object is passed, it will be used to create a "_.pluck" or "_.where"
|
|
* style callback, respectively.
|
|
* @param {Mixed} [thisArg] The `this` binding of `callback`.
|
|
* @returns {Array} Returns a slice of `array`.
|
|
* @example
|
|
*
|
|
* _.initial([1, 2, 3]);
|
|
* // => [1, 2]
|
|
*
|
|
* _.initial([1, 2, 3], 2);
|
|
* // => [1]
|
|
*
|
|
* _.initial([1, 2, 3], function(num) {
|
|
* return num > 1;
|
|
* });
|
|
* // => [1]
|
|
*
|
|
* var food = [
|
|
* { 'name': 'beet', 'organic': false },
|
|
* { 'name': 'carrot', 'organic': true }
|
|
* ];
|
|
*
|
|
* // using "_.pluck" callback shorthand
|
|
* _.initial(food, 'organic');
|
|
* // => [{ 'name': 'beet', 'organic': false }]
|
|
*
|
|
* var food = [
|
|
* { 'name': 'banana', 'type': 'fruit' },
|
|
* { 'name': 'beet', 'type': 'vegetable' },
|
|
* { 'name': 'carrot', 'type': 'vegetable' }
|
|
* ];
|
|
*
|
|
* // using "_.where" callback shorthand
|
|
* _.initial(food, { 'type': 'vegetable' });
|
|
* // => [{ 'name': 'banana', 'type': 'fruit' }]
|
|
*/
|
|
function initial(array, callback, thisArg) {
|
|
if (!array) {
|
|
return [];
|
|
}
|
|
var n = 0,
|
|
length = array.length;
|
|
|
|
if (typeof callback != 'number' && callback != null) {
|
|
var index = length;
|
|
callback = createCallback(callback, thisArg);
|
|
while (index-- && callback(array[index], index, array)) {
|
|
n++;
|
|
}
|
|
} else {
|
|
n = (callback == null || thisArg) ? 1 : callback || n;
|
|
}
|
|
return slice(array, 0, nativeMin(nativeMax(0, length - n), length));
|
|
}
|
|
|
|
/**
|
|
* Computes the intersection of all the passed-in arrays using strict equality
|
|
* for comparisons, i.e. `===`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Arrays
|
|
* @param {Array} [array1, array2, ...] Arrays to process.
|
|
* @returns {Array} Returns a new array of unique elements that are present
|
|
* in **all** of the arrays.
|
|
* @example
|
|
*
|
|
* _.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]);
|
|
* // => [1, 2]
|
|
*/
|
|
function intersection(array) {
|
|
var args = arguments,
|
|
argsLength = args.length,
|
|
cache = { '0': {} },
|
|
index = -1,
|
|
length = array ? array.length : 0,
|
|
isLarge = length >= 100,
|
|
result = [],
|
|
seen = result;
|
|
|
|
outer:
|
|
while (++index < length) {
|
|
var value = array[index];
|
|
if (isLarge) {
|
|
var key = value + '';
|
|
var inited = hasOwnProperty.call(cache[0], key)
|
|
? !(seen = cache[0][key])
|
|
: (seen = cache[0][key] = []);
|
|
}
|
|
if (inited || indexOf(seen, value) < 0) {
|
|
if (isLarge) {
|
|
seen.push(value);
|
|
}
|
|
var argsIndex = argsLength;
|
|
while (--argsIndex) {
|
|
if (!(cache[argsIndex] || (cache[argsIndex] = cachedContains(args[argsIndex], 0, 100)))(value)) {
|
|
continue outer;
|
|
}
|
|
}
|
|
result.push(value);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Gets the last element of the `array`. If a number `n` is passed, the last
|
|
* `n` elements of the `array` are returned. If a `callback` function is passed,
|
|
* the last elements the `callback` returns truthy for are returned. The `callback`
|
|
* is bound to `thisArg` and invoked with three arguments; (value, index, array).
|
|
*
|
|
*
|
|
* If a property name is passed for `callback`, the created "_.pluck" style
|
|
* callback will return the property value of the given element.
|
|
*
|
|
* If an object is passed for `callback`, the created "_.where" style callback
|
|
* will return `true` for elements that have the propeties of the given object,
|
|
* else `false`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Arrays
|
|
* @param {Array} array The array to query.
|
|
* @param {Function|Object|Number|String} [callback|n] The function called
|
|
* per element or the number of elements to return. If a property name or
|
|
* object is passed, it will be used to create a "_.pluck" or "_.where"
|
|
* style callback, respectively.
|
|
* @param {Mixed} [thisArg] The `this` binding of `callback`.
|
|
* @returns {Mixed} Returns the last element(s) of `array`.
|
|
* @example
|
|
*
|
|
* _.last([1, 2, 3]);
|
|
* // => 3
|
|
*
|
|
* _.last([1, 2, 3], 2);
|
|
* // => [2, 3]
|
|
*
|
|
* _.last([1, 2, 3], function(num) {
|
|
* return num > 1;
|
|
* });
|
|
* // => [2, 3]
|
|
*
|
|
* var food = [
|
|
* { 'name': 'beet', 'organic': false },
|
|
* { 'name': 'carrot', 'organic': true }
|
|
* ];
|
|
*
|
|
* // using "_.pluck" callback shorthand
|
|
* _.last(food, 'organic');
|
|
* // => [{ 'name': 'carrot', 'organic': true }]
|
|
*
|
|
* var food = [
|
|
* { 'name': 'banana', 'type': 'fruit' },
|
|
* { 'name': 'beet', 'type': 'vegetable' },
|
|
* { 'name': 'carrot', 'type': 'vegetable' }
|
|
* ];
|
|
*
|
|
* // using "_.where" callback shorthand
|
|
* _.last(food, { 'type': 'vegetable' });
|
|
* // => [{ 'name': 'beet', 'type': 'vegetable' }, { 'name': 'carrot', 'type': 'vegetable' }]
|
|
*/
|
|
function last(array, callback, thisArg) {
|
|
if (array) {
|
|
var n = 0,
|
|
length = array.length;
|
|
|
|
if (typeof callback != 'number' && callback != null) {
|
|
var index = length;
|
|
callback = createCallback(callback, thisArg);
|
|
while (index-- && callback(array[index], index, array)) {
|
|
n++;
|
|
}
|
|
} else {
|
|
n = callback;
|
|
if (n == null || thisArg) {
|
|
return array[length - 1];
|
|
}
|
|
}
|
|
return slice(array, nativeMax(0, length - n));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Gets the index at which the last occurrence of `value` is found using strict
|
|
* equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used
|
|
* as the offset from the end of the collection.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Arrays
|
|
* @param {Array} array The array to search.
|
|
* @param {Mixed} value The value to search for.
|
|
* @param {Number} [fromIndex=array.length-1] The index to search from.
|
|
* @returns {Number} Returns the index of the matched value or `-1`.
|
|
* @example
|
|
*
|
|
* _.lastIndexOf([1, 2, 3, 1, 2, 3], 2);
|
|
* // => 4
|
|
*
|
|
* _.lastIndexOf([1, 2, 3, 1, 2, 3], 2, 3);
|
|
* // => 1
|
|
*/
|
|
function lastIndexOf(array, value, fromIndex) {
|
|
var index = array ? array.length : 0;
|
|
if (typeof fromIndex == 'number') {
|
|
index = (fromIndex < 0 ? nativeMax(0, index + fromIndex) : nativeMin(fromIndex, index - 1)) + 1;
|
|
}
|
|
while (index--) {
|
|
if (array[index] === value) {
|
|
return index;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* Creates an object composed from arrays of `keys` and `values`. Pass either
|
|
* a single two dimensional array, i.e. `[[key1, value1], [key2, value2]]`, or
|
|
* two arrays, one of `keys` and one of corresponding `values`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Arrays
|
|
* @param {Array} keys The array of keys.
|
|
* @param {Array} [values=[]] The array of values.
|
|
* @returns {Object} Returns an object composed of the given keys and
|
|
* corresponding values.
|
|
* @example
|
|
*
|
|
* _.object(['moe', 'larry'], [30, 40]);
|
|
* // => { 'moe': 30, 'larry': 40 }
|
|
*/
|
|
function object(keys, values) {
|
|
var index = -1,
|
|
length = keys ? keys.length : 0,
|
|
result = {};
|
|
|
|
while (++index < length) {
|
|
var key = keys[index];
|
|
if (values) {
|
|
result[key] = values[index];
|
|
} else {
|
|
result[key[0]] = key[1];
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Creates an array of numbers (positive and/or negative) progressing from
|
|
* `start` up to but not including `end`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Arrays
|
|
* @param {Number} [start=0] The start of the range.
|
|
* @param {Number} end The end of the range.
|
|
* @param {Number} [step=1] The value to increment or descrement by.
|
|
* @returns {Array} Returns a new range array.
|
|
* @example
|
|
*
|
|
* _.range(10);
|
|
* // => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
*
|
|
* _.range(1, 11);
|
|
* // => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
|
*
|
|
* _.range(0, 30, 5);
|
|
* // => [0, 5, 10, 15, 20, 25]
|
|
*
|
|
* _.range(0, -10, -1);
|
|
* // => [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
|
|
*
|
|
* _.range(0);
|
|
* // => []
|
|
*/
|
|
function range(start, end, step) {
|
|
start = +start || 0;
|
|
step = +step || 1;
|
|
|
|
if (end == null) {
|
|
end = start;
|
|
start = 0;
|
|
}
|
|
// use `Array(length)` so V8 will avoid the slower "dictionary" mode
|
|
// http://youtu.be/XAqIpGU8ZZk#t=17m25s
|
|
var index = -1,
|
|
length = nativeMax(0, ceil((end - start) / step)),
|
|
result = Array(length);
|
|
|
|
while (++index < length) {
|
|
result[index] = start;
|
|
start += step;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* The opposite of `_.initial`, this method gets all but the first value of `array`.
|
|
* If a number `n` is passed, the first `n` values are excluded from the result.
|
|
* If a `callback` function is passed, the first elements the `callback` returns
|
|
* truthy for are excluded from the result. The `callback` is bound to `thisArg`
|
|
* and invoked with three arguments; (value, index, array).
|
|
*
|
|
* If a property name is passed for `callback`, the created "_.pluck" style
|
|
* callback will return the property value of the given element.
|
|
*
|
|
* If an object is passed for `callback`, the created "_.where" style callback
|
|
* will return `true` for elements that have the propeties of the given object,
|
|
* else `false`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @alias drop, tail
|
|
* @category Arrays
|
|
* @param {Array} array The array to query.
|
|
* @param {Function|Object|Number|String} [callback|n=1] The function called
|
|
* per element or the number of elements to exclude. If a property name or
|
|
* object is passed, it will be used to create a "_.pluck" or "_.where"
|
|
* style callback, respectively.
|
|
* @param {Mixed} [thisArg] The `this` binding of `callback`.
|
|
* @returns {Array} Returns a slice of `array`.
|
|
* @example
|
|
*
|
|
* _.rest([1, 2, 3]);
|
|
* // => [2, 3]
|
|
*
|
|
* _.rest([1, 2, 3], 2);
|
|
* // => [3]
|
|
*
|
|
* _.rest([1, 2, 3], function(num) {
|
|
* return num < 3;
|
|
* });
|
|
* // => [3]
|
|
*
|
|
* var food = [
|
|
* { 'name': 'banana', 'organic': true },
|
|
* { 'name': 'beet', 'organic': false },
|
|
* ];
|
|
*
|
|
* // using "_.pluck" callback shorthand
|
|
* _.rest(food, 'organic');
|
|
* // => [{ 'name': 'beet', 'organic': false }]
|
|
*
|
|
* var food = [
|
|
* { 'name': 'apple', 'type': 'fruit' },
|
|
* { 'name': 'banana', 'type': 'fruit' },
|
|
* { 'name': 'beet', 'type': 'vegetable' }
|
|
* ];
|
|
*
|
|
* // using "_.where" callback shorthand
|
|
* _.rest(food, { 'type': 'fruit' });
|
|
* // => [{ 'name': 'beet', 'type': 'vegetable' }]
|
|
*/
|
|
function rest(array, callback, thisArg) {
|
|
if (typeof callback != 'number' && callback != null) {
|
|
var n = 0,
|
|
index = -1,
|
|
length = array ? array.length : 0;
|
|
|
|
callback = createCallback(callback, thisArg);
|
|
while (++index < length && callback(array[index], index, array)) {
|
|
n++;
|
|
}
|
|
} else {
|
|
n = (callback == null || thisArg) ? 1 : nativeMax(0, callback);
|
|
}
|
|
return slice(array, n);
|
|
}
|
|
|
|
/**
|
|
* Uses a binary search to determine the smallest index at which the `value`
|
|
* should be inserted into `array` in order to maintain the sort order of the
|
|
* sorted `array`. If `callback` is passed, it will be executed for `value` and
|
|
* each element in `array` to compute their sort ranking. The `callback` is
|
|
* bound to `thisArg` and invoked with one argument; (value).
|
|
*
|
|
* If a property name is passed for `callback`, the created "_.pluck" style
|
|
* callback will return the property value of the given element.
|
|
*
|
|
* If an object is passed for `callback`, the created "_.where" style callback
|
|
* will return `true` for elements that have the propeties of the given object,
|
|
* else `false`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Arrays
|
|
* @param {Array} array The array to iterate over.
|
|
* @param {Mixed} value The value to evaluate.
|
|
* @param {Function|Object|String} [callback=identity] The function called per
|
|
* iteration. If a property name or object is passed, it will be used to create
|
|
* a "_.pluck" or "_.where" style callback, respectively.
|
|
* @param {Mixed} [thisArg] The `this` binding of `callback`.
|
|
* @returns {Number} Returns the index at which the value should be inserted
|
|
* into `array`.
|
|
* @example
|
|
*
|
|
* _.sortedIndex([20, 30, 50], 40);
|
|
* // => 2
|
|
*
|
|
* // using "_.pluck" callback shorthand
|
|
* _.sortedIndex([{ 'x': 20 }, { 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x');
|
|
* // => 2
|
|
*
|
|
* var dict = {
|
|
* 'wordToNumber': { 'twenty': 20, 'thirty': 30, 'fourty': 40, 'fifty': 50 }
|
|
* };
|
|
*
|
|
* _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
|
|
* return dict.wordToNumber[word];
|
|
* });
|
|
* // => 2
|
|
*
|
|
* _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
|
|
* return this.wordToNumber[word];
|
|
* }, dict);
|
|
* // => 2
|
|
*/
|
|
function sortedIndex(array, value, callback, thisArg) {
|
|
var low = 0,
|
|
high = array ? array.length : low;
|
|
|
|
// explicitly reference `identity` for better inlining in Firefox
|
|
callback = callback ? createCallback(callback, thisArg, 1) : identity;
|
|
value = callback(value);
|
|
|
|
while (low < high) {
|
|
var mid = (low + high) >>> 1;
|
|
callback(array[mid]) < value
|
|
? low = mid + 1
|
|
: high = mid;
|
|
}
|
|
return low;
|
|
}
|
|
|
|
/**
|
|
* Computes the union of the passed-in arrays using strict equality for
|
|
* comparisons, i.e. `===`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Arrays
|
|
* @param {Array} [array1, array2, ...] Arrays to process.
|
|
* @returns {Array} Returns a new array of unique values, in order, that are
|
|
* present in one or more of the arrays.
|
|
* @example
|
|
*
|
|
* _.union([1, 2, 3], [101, 2, 1, 10], [2, 1]);
|
|
* // => [1, 2, 3, 101, 10]
|
|
*/
|
|
function union() {
|
|
return uniq(concat.apply(arrayRef, arguments));
|
|
}
|
|
|
|
/**
|
|
* Creates a duplicate-value-free version of the `array` using strict equality
|
|
* for comparisons, i.e. `===`. If the `array` is already sorted, passing `true`
|
|
* for `isSorted` will run a faster algorithm. If `callback` is passed, each
|
|
* element of `array` is passed through a callback` before uniqueness is computed.
|
|
* The `callback` is bound to `thisArg` and invoked with three arguments; (value, index, array).
|
|
*
|
|
* If a property name is passed for `callback`, the created "_.pluck" style
|
|
* callback will return the property value of the given element.
|
|
*
|
|
* If an object is passed for `callback`, the created "_.where" style callback
|
|
* will return `true` for elements that have the propeties of the given object,
|
|
* else `false`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @alias unique
|
|
* @category Arrays
|
|
* @param {Array} array The array to process.
|
|
* @param {Boolean} [isSorted=false] A flag to indicate that the `array` is already sorted.
|
|
* @param {Function|Object|String} [callback=identity] The function called per
|
|
* iteration. If a property name or object is passed, it will be used to create
|
|
* a "_.pluck" or "_.where" style callback, respectively.
|
|
* @param {Mixed} [thisArg] The `this` binding of `callback`.
|
|
* @returns {Array} Returns a duplicate-value-free array.
|
|
* @example
|
|
*
|
|
* _.uniq([1, 2, 1, 3, 1]);
|
|
* // => [1, 2, 3]
|
|
*
|
|
* _.uniq([1, 1, 2, 2, 3], true);
|
|
* // => [1, 2, 3]
|
|
*
|
|
* _.uniq([1, 2, 1.5, 3, 2.5], function(num) { return Math.floor(num); });
|
|
* // => [1, 2, 3]
|
|
*
|
|
* _.uniq([1, 2, 1.5, 3, 2.5], function(num) { return this.floor(num); }, Math);
|
|
* // => [1, 2, 3]
|
|
*
|
|
* // using "_.pluck" callback shorthand
|
|
* _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
|
|
* // => [{ 'x': 1 }, { 'x': 2 }]
|
|
*/
|
|
function uniq(array, isSorted, callback, thisArg) {
|
|
var index = -1,
|
|
length = array ? array.length : 0,
|
|
result = [],
|
|
seen = result;
|
|
|
|
// juggle arguments
|
|
if (typeof isSorted == 'function') {
|
|
thisArg = callback;
|
|
callback = isSorted;
|
|
isSorted = false;
|
|
}
|
|
// init value cache for large arrays
|
|
var isLarge = !isSorted && length >= 75;
|
|
if (isLarge) {
|
|
var cache = {};
|
|
}
|
|
if (callback) {
|
|
seen = [];
|
|
callback = createCallback(callback, thisArg);
|
|
}
|
|
while (++index < length) {
|
|
var value = array[index],
|
|
computed = callback ? callback(value, index, array) : value;
|
|
|
|
if (isLarge) {
|
|
var key = computed + '';
|
|
var inited = hasOwnProperty.call(cache, key)
|
|
? !(seen = cache[key])
|
|
: (seen = cache[key] = []);
|
|
}
|
|
if (isSorted
|
|
? !index || seen[seen.length - 1] !== computed
|
|
: inited || indexOf(seen, computed) < 0
|
|
) {
|
|
if (callback || isLarge) {
|
|
seen.push(computed);
|
|
}
|
|
result.push(value);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Creates an array with all occurrences of the passed values removed using
|
|
* strict equality for comparisons, i.e. `===`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Arrays
|
|
* @param {Array} array The array to filter.
|
|
* @param {Mixed} [value1, value2, ...] Values to remove.
|
|
* @returns {Array} Returns a new filtered array.
|
|
* @example
|
|
*
|
|
* _.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
|
|
* // => [2, 3, 4]
|
|
*/
|
|
function without(array) {
|
|
var index = -1,
|
|
length = array ? array.length : 0,
|
|
contains = cachedContains(arguments, 1),
|
|
result = [];
|
|
|
|
while (++index < length) {
|
|
var value = array[index];
|
|
if (!contains(value)) {
|
|
result.push(value);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Groups the elements of each array at their corresponding indexes. Useful for
|
|
* separate data sources that are coordinated through matching array indexes.
|
|
* For a matrix of nested arrays, `_.zip.apply(...)` can transpose the matrix
|
|
* in a similar fashion.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Arrays
|
|
* @param {Array} [array1, array2, ...] Arrays to process.
|
|
* @returns {Array} Returns a new array of grouped elements.
|
|
* @example
|
|
*
|
|
* _.zip(['moe', 'larry'], [30, 40], [true, false]);
|
|
* // => [['moe', 30, true], ['larry', 40, false]]
|
|
*/
|
|
function zip(array) {
|
|
var index = -1,
|
|
length = array ? max(pluck(arguments, 'length')) : 0,
|
|
result = Array(length);
|
|
|
|
while (++index < length) {
|
|
result[index] = pluck(arguments, index);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* Creates a function that is restricted to executing `func` only after it is
|
|
* called `n` times. The `func` is executed with the `this` binding of the
|
|
* created function.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Functions
|
|
* @param {Number} n The number of times the function must be called before
|
|
* it is executed.
|
|
* @param {Function} func The function to restrict.
|
|
* @returns {Function} Returns the new restricted function.
|
|
* @example
|
|
*
|
|
* var renderNotes = _.after(notes.length, render);
|
|
* _.forEach(notes, function(note) {
|
|
* note.asyncSave({ 'success': renderNotes });
|
|
* });
|
|
* // `renderNotes` is run once, after all notes have saved
|
|
*/
|
|
function after(n, func) {
|
|
if (n < 1) {
|
|
return func();
|
|
}
|
|
return function() {
|
|
if (--n < 1) {
|
|
return func.apply(this, arguments);
|
|
}
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Creates a function that, when called, invokes `func` with the `this`
|
|
* binding of `thisArg` and prepends any additional `bind` arguments to those
|
|
* passed to the bound function.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Functions
|
|
* @param {Function} func The function to bind.
|
|
* @param {Mixed} [thisArg] The `this` binding of `func`.
|
|
* @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied.
|
|
* @returns {Function} Returns the new bound function.
|
|
* @example
|
|
*
|
|
* var func = function(greeting) {
|
|
* return greeting + ' ' + this.name;
|
|
* };
|
|
*
|
|
* func = _.bind(func, { 'name': 'moe' }, 'hi');
|
|
* func();
|
|
* // => 'hi moe'
|
|
*/
|
|
function bind(func, thisArg) {
|
|
// use `Function#bind` if it exists and is fast
|
|
// (in V8 `Function#bind` is slower except when partially applied)
|
|
return isBindFast || (nativeBind && arguments.length > 2)
|
|
? nativeBind.call.apply(nativeBind, arguments)
|
|
: createBound(func, thisArg, slice(arguments, 2));
|
|
}
|
|
|
|
/**
|
|
* Binds methods on `object` to `object`, overwriting the existing method.
|
|
* Method names may be specified as individual arguments or as arrays of method
|
|
* names. If no method names are provided, all the function properties of `object`
|
|
* will be bound.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Functions
|
|
* @param {Object} object The object to bind and assign the bound methods to.
|
|
* @param {String} [methodName1, methodName2, ...] Method names on the object to bind.
|
|
* @returns {Object} Returns `object`.
|
|
* @example
|
|
*
|
|
* var view = {
|
|
* 'label': 'docs',
|
|
* 'onClick': function() { alert('clicked ' + this.label); }
|
|
* };
|
|
*
|
|
* _.bindAll(view);
|
|
* jQuery('#docs').on('click', view.onClick);
|
|
* // => alerts 'clicked docs', when the button is clicked
|
|
*/
|
|
function bindAll(object) {
|
|
var funcs = concat.apply(arrayRef, arguments),
|
|
index = funcs.length > 1 ? 0 : (funcs = functions(object), -1),
|
|
length = funcs.length;
|
|
|
|
while (++index < length) {
|
|
var key = funcs[index];
|
|
object[key] = bind(object[key], object);
|
|
}
|
|
return object;
|
|
}
|
|
|
|
/**
|
|
* Creates a function that, when called, invokes the method at `object[key]`
|
|
* and prepends any additional `bindKey` arguments to those passed to the bound
|
|
* function. This method differs from `_.bind` by allowing bound functions to
|
|
* reference methods that will be redefined or don't yet exist.
|
|
* See http://michaux.ca/articles/lazy-function-definition-pattern.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Functions
|
|
* @param {Object} object The object the method belongs to.
|
|
* @param {String} key The key of the method.
|
|
* @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied.
|
|
* @returns {Function} Returns the new bound function.
|
|
* @example
|
|
*
|
|
* var object = {
|
|
* 'name': 'moe',
|
|
* 'greet': function(greeting) {
|
|
* return greeting + ' ' + this.name;
|
|
* }
|
|
* };
|
|
*
|
|
* var func = _.bindKey(object, 'greet', 'hi');
|
|
* func();
|
|
* // => 'hi moe'
|
|
*
|
|
* object.greet = function(greeting) {
|
|
* return greeting + ', ' + this.name + '!';
|
|
* };
|
|
*
|
|
* func();
|
|
* // => 'hi, moe!'
|
|
*/
|
|
function bindKey(object, key) {
|
|
return createBound(object, key, slice(arguments, 2));
|
|
}
|
|
|
|
/**
|
|
* Creates a function that is the composition of the passed functions,
|
|
* where each function consumes the return value of the function that follows.
|
|
* For example, composing the functions `f()`, `g()`, and `h()` produces `f(g(h()))`.
|
|
* Each function is executed with the `this` binding of the composed function.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Functions
|
|
* @param {Function} [func1, func2, ...] Functions to compose.
|
|
* @returns {Function} Returns the new composed function.
|
|
* @example
|
|
*
|
|
* var greet = function(name) { return 'hi ' + name; };
|
|
* var exclaim = function(statement) { return statement + '!'; };
|
|
* var welcome = _.compose(exclaim, greet);
|
|
* welcome('moe');
|
|
* // => 'hi moe!'
|
|
*/
|
|
function compose() {
|
|
var funcs = arguments;
|
|
return function() {
|
|
var args = arguments,
|
|
length = funcs.length;
|
|
|
|
while (length--) {
|
|
args = [funcs[length].apply(this, args)];
|
|
}
|
|
return args[0];
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Creates a function that will delay the execution of `func` until after
|
|
* `wait` milliseconds have elapsed since the last time it was invoked. Pass
|
|
* `true` for `immediate` to cause debounce to invoke `func` on the leading,
|
|
* instead of the trailing, edge of the `wait` timeout. Subsequent calls to
|
|
* the debounced function will return the result of the last `func` call.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Functions
|
|
* @param {Function} func The function to debounce.
|
|
* @param {Number} wait The number of milliseconds to delay.
|
|
* @param {Boolean} immediate A flag to indicate execution is on the leading
|
|
* edge of the timeout.
|
|
* @returns {Function} Returns the new debounced function.
|
|
* @example
|
|
*
|
|
* var lazyLayout = _.debounce(calculateLayout, 300);
|
|
* jQuery(window).on('resize', lazyLayout);
|
|
*/
|
|
function debounce(func, wait, immediate) {
|
|
var args,
|
|
result,
|
|
thisArg,
|
|
timeoutId;
|
|
|
|
function delayed() {
|
|
timeoutId = null;
|
|
if (!immediate) {
|
|
result = func.apply(thisArg, args);
|
|
}
|
|
}
|
|
return function() {
|
|
var isImmediate = immediate && !timeoutId;
|
|
args = arguments;
|
|
thisArg = this;
|
|
|
|
clearTimeout(timeoutId);
|
|
timeoutId = setTimeout(delayed, wait);
|
|
|
|
if (isImmediate) {
|
|
result = func.apply(thisArg, args);
|
|
}
|
|
return result;
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Executes the `func` function after `wait` milliseconds. Additional arguments
|
|
* will be passed to `func` when it is invoked.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Functions
|
|
* @param {Function} func The function to delay.
|
|
* @param {Number} wait The number of milliseconds to delay execution.
|
|
* @param {Mixed} [arg1, arg2, ...] Arguments to invoke the function with.
|
|
* @returns {Number} Returns the `setTimeout` timeout id.
|
|
* @example
|
|
*
|
|
* var log = _.bind(console.log, console);
|
|
* _.delay(log, 1000, 'logged later');
|
|
* // => 'logged later' (Appears after one second.)
|
|
*/
|
|
function delay(func, wait) {
|
|
var args = slice(arguments, 2);
|
|
return setTimeout(function() { func.apply(undefined, args); }, wait);
|
|
}
|
|
|
|
/**
|
|
* Defers executing the `func` function until the current call stack has cleared.
|
|
* Additional arguments will be passed to `func` when it is invoked.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Functions
|
|
* @param {Function} func The function to defer.
|
|
* @param {Mixed} [arg1, arg2, ...] Arguments to invoke the function with.
|
|
* @returns {Number} Returns the `setTimeout` timeout id.
|
|
* @example
|
|
*
|
|
* _.defer(function() { alert('deferred'); });
|
|
* // returns from the function before `alert` is called
|
|
*/
|
|
function defer(func) {
|
|
var args = slice(arguments, 1);
|
|
return setTimeout(function() { func.apply(undefined, args); }, 1);
|
|
}
|
|
// use `setImmediate` if it's available in Node.js
|
|
if (isV8 && freeModule && typeof setImmediate == 'function') {
|
|
defer = bind(setImmediate, window);
|
|
}
|
|
|
|
/**
|
|
* Creates a function that memoizes the result of `func`. If `resolver` is
|
|
* passed, it will be used to determine the cache key for storing the result
|
|
* based on the arguments passed to the memoized function. By default, the first
|
|
* argument passed to the memoized function is used as the cache key. The `func`
|
|
* is executed with the `this` binding of the memoized function.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Functions
|
|
* @param {Function} func The function to have its output memoized.
|
|
* @param {Function} [resolver] A function used to resolve the cache key.
|
|
* @returns {Function} Returns the new memoizing function.
|
|
* @example
|
|
*
|
|
* var fibonacci = _.memoize(function(n) {
|
|
* return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
|
|
* });
|
|
*/
|
|
function memoize(func, resolver) {
|
|
var cache = {};
|
|
return function() {
|
|
var key = (resolver ? resolver.apply(this, arguments) : arguments[0]) + '';
|
|
return hasOwnProperty.call(cache, key)
|
|
? cache[key]
|
|
: (cache[key] = func.apply(this, arguments));
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Creates a function that is restricted to execute `func` once. Repeat calls to
|
|
* the function will return the value of the first call. The `func` is executed
|
|
* with the `this` binding of the created function.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Functions
|
|
* @param {Function} func The function to restrict.
|
|
* @returns {Function} Returns the new restricted function.
|
|
* @example
|
|
*
|
|
* var initialize = _.once(createApplication);
|
|
* initialize();
|
|
* initialize();
|
|
* // `initialize` executes `createApplication` once
|
|
*/
|
|
function once(func) {
|
|
var ran,
|
|
result;
|
|
|
|
return function() {
|
|
if (ran) {
|
|
return result;
|
|
}
|
|
ran = true;
|
|
result = func.apply(this, arguments);
|
|
|
|
// clear the `func` variable so the function may be garbage collected
|
|
func = null;
|
|
return result;
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Creates a function that, when called, invokes `func` with any additional
|
|
* `partial` arguments prepended to those passed to the new function. This
|
|
* method is similar to `_.bind`, except it does **not** alter the `this` binding.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Functions
|
|
* @param {Function} func The function to partially apply arguments to.
|
|
* @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied.
|
|
* @returns {Function} Returns the new partially applied function.
|
|
* @example
|
|
*
|
|
* var greet = function(greeting, name) { return greeting + ' ' + name; };
|
|
* var hi = _.partial(greet, 'hi');
|
|
* hi('moe');
|
|
* // => 'hi moe'
|
|
*/
|
|
function partial(func) {
|
|
return createBound(func, slice(arguments, 1));
|
|
}
|
|
|
|
/**
|
|
* This method is similar to `_.partial`, except that `partial` arguments are
|
|
* appended to those passed to the new function.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Functions
|
|
* @param {Function} func The function to partially apply arguments to.
|
|
* @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied.
|
|
* @returns {Function} Returns the new partially applied function.
|
|
* @example
|
|
*
|
|
* var defaultsDeep = _.partialRight(_.merge, _.defaults);
|
|
*
|
|
* var options = {
|
|
* 'variable': 'data',
|
|
* 'imports': { 'jq': $ }
|
|
* };
|
|
*
|
|
* defaultsDeep(options, _.templateSettings);
|
|
*
|
|
* options.variable
|
|
* // => 'data'
|
|
*
|
|
* options.imports
|
|
* // => { '_': _, 'jq': $ }
|
|
*/
|
|
function partialRight(func) {
|
|
return createBound(func, slice(arguments, 1), null, indicatorObject);
|
|
}
|
|
|
|
/**
|
|
* Creates a function that, when executed, will only call the `func`
|
|
* function at most once per every `wait` milliseconds. If the throttled
|
|
* function is invoked more than once during the `wait` timeout, `func` will
|
|
* also be called on the trailing edge of the timeout. Subsequent calls to the
|
|
* throttled function will return the result of the last `func` call.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Functions
|
|
* @param {Function} func The function to throttle.
|
|
* @param {Number} wait The number of milliseconds to throttle executions to.
|
|
* @returns {Function} Returns the new throttled function.
|
|
* @example
|
|
*
|
|
* var throttled = _.throttle(updatePosition, 100);
|
|
* jQuery(window).on('scroll', throttled);
|
|
*/
|
|
function throttle(func, wait) {
|
|
var args,
|
|
result,
|
|
thisArg,
|
|
timeoutId,
|
|
lastCalled = 0;
|
|
|
|
function trailingCall() {
|
|
lastCalled = new Date;
|
|
timeoutId = null;
|
|
result = func.apply(thisArg, args);
|
|
}
|
|
return function() {
|
|
var now = new Date,
|
|
remaining = wait - (now - lastCalled);
|
|
|
|
args = arguments;
|
|
thisArg = this;
|
|
|
|
if (remaining <= 0) {
|
|
clearTimeout(timeoutId);
|
|
timeoutId = null;
|
|
lastCalled = now;
|
|
result = func.apply(thisArg, args);
|
|
}
|
|
else if (!timeoutId) {
|
|
timeoutId = setTimeout(trailingCall, remaining);
|
|
}
|
|
return result;
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Creates a function that passes `value` to the `wrapper` function as its
|
|
* first argument. Additional arguments passed to the function are appended
|
|
* to those passed to the `wrapper` function. The `wrapper` is executed with
|
|
* the `this` binding of the created function.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Functions
|
|
* @param {Mixed} value The value to wrap.
|
|
* @param {Function} wrapper The wrapper function.
|
|
* @returns {Function} Returns the new function.
|
|
* @example
|
|
*
|
|
* var hello = function(name) { return 'hello ' + name; };
|
|
* hello = _.wrap(hello, function(func) {
|
|
* return 'before, ' + func('moe') + ', after';
|
|
* });
|
|
* hello();
|
|
* // => 'before, hello moe, after'
|
|
*/
|
|
function wrap(value, wrapper) {
|
|
return function() {
|
|
var args = [value];
|
|
push.apply(args, arguments);
|
|
return wrapper.apply(this, args);
|
|
};
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* Converts the characters `&`, `<`, `>`, `"`, and `'` in `string` to their
|
|
* corresponding HTML entities.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Utilities
|
|
* @param {String} string The string to escape.
|
|
* @returns {String} Returns the escaped string.
|
|
* @example
|
|
*
|
|
* _.escape('Moe, Larry & Curly');
|
|
* // => 'Moe, Larry & Curly'
|
|
*/
|
|
function escape(string) {
|
|
return string == null ? '' : (string + '').replace(reUnescapedHtml, escapeHtmlChar);
|
|
}
|
|
|
|
/**
|
|
* This function returns the first argument passed to it.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Utilities
|
|
* @param {Mixed} value Any value.
|
|
* @returns {Mixed} Returns `value`.
|
|
* @example
|
|
*
|
|
* var moe = { 'name': 'moe' };
|
|
* moe === _.identity(moe);
|
|
* // => true
|
|
*/
|
|
function identity(value) {
|
|
return value;
|
|
}
|
|
|
|
/**
|
|
* Adds functions properties of `object` to the `lodash` function and chainable
|
|
* wrapper.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Utilities
|
|
* @param {Object} object The object of function properties to add to `lodash`.
|
|
* @example
|
|
*
|
|
* _.mixin({
|
|
* 'capitalize': function(string) {
|
|
* return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase();
|
|
* }
|
|
* });
|
|
*
|
|
* _.capitalize('moe');
|
|
* // => 'Moe'
|
|
*
|
|
* _('moe').capitalize();
|
|
* // => 'Moe'
|
|
*/
|
|
function mixin(object) {
|
|
forEach(functions(object), function(methodName) {
|
|
var func = lodash[methodName] = object[methodName];
|
|
|
|
lodash.prototype[methodName] = function() {
|
|
var args = [this.__wrapped__];
|
|
push.apply(args, arguments);
|
|
return new lodash(func.apply(lodash, args));
|
|
};
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Reverts the '_' variable to its previous value and returns a reference to
|
|
* the `lodash` function.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Utilities
|
|
* @returns {Function} Returns the `lodash` function.
|
|
* @example
|
|
*
|
|
* var lodash = _.noConflict();
|
|
*/
|
|
function noConflict() {
|
|
window._ = oldDash;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Produces a random number between `min` and `max` (inclusive). If only one
|
|
* argument is passed, a number between `0` and the given number will be returned.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Utilities
|
|
* @param {Number} [min=0] The minimum possible value.
|
|
* @param {Number} [max=1] The maximum possible value.
|
|
* @returns {Number} Returns a random number.
|
|
* @example
|
|
*
|
|
* _.random(0, 5);
|
|
* // => a number between 0 and 5
|
|
*
|
|
* _.random(5);
|
|
* // => also a number between 0 and 5
|
|
*/
|
|
function random(min, max) {
|
|
if (min == null && max == null) {
|
|
max = 1;
|
|
}
|
|
min = +min || 0;
|
|
if (max == null) {
|
|
max = min;
|
|
min = 0;
|
|
}
|
|
return min + floor(nativeRandom() * ((+max || 0) - min + 1));
|
|
}
|
|
|
|
/**
|
|
* Resolves the value of `property` on `object`. If `property` is a function,
|
|
* it will be invoked and its result returned, else the property value is
|
|
* returned. If `object` is falsey, then `null` is returned.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Utilities
|
|
* @param {Object} object The object to inspect.
|
|
* @param {String} property The property to get the value of.
|
|
* @returns {Mixed} Returns the resolved value.
|
|
* @example
|
|
*
|
|
* var object = {
|
|
* 'cheese': 'crumpets',
|
|
* 'stuff': function() {
|
|
* return 'nonsense';
|
|
* }
|
|
* };
|
|
*
|
|
* _.result(object, 'cheese');
|
|
* // => 'crumpets'
|
|
*
|
|
* _.result(object, 'stuff');
|
|
* // => 'nonsense'
|
|
*/
|
|
function result(object, property) {
|
|
var value = object ? object[property] : undefined;
|
|
return isFunction(value) ? object[property]() : value;
|
|
}
|
|
|
|
/**
|
|
* A micro-templating method that handles arbitrary delimiters, preserves
|
|
* whitespace, and correctly escapes quotes within interpolated code.
|
|
*
|
|
* Note: In the development build, `_.template` utilizes sourceURLs for easier
|
|
* debugging. See http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl
|
|
*
|
|
* Note: Lo-Dash may be used in Chrome extensions by either creating a `lodash csp`
|
|
* build and using precompiled templates, or loading Lo-Dash in a sandbox.
|
|
*
|
|
* For more information on precompiling templates see:
|
|
* http://lodash.com/#custom-builds
|
|
*
|
|
* For more information on Chrome extension sandboxes see:
|
|
* http://developer.chrome.com/stable/extensions/sandboxingEval.html
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Utilities
|
|
* @param {String} text The template text.
|
|
* @param {Obect} data The data object used to populate the text.
|
|
* @param {Object} options The options object.
|
|
* escape - The "escape" delimiter regexp.
|
|
* evaluate - The "evaluate" delimiter regexp.
|
|
* interpolate - The "interpolate" delimiter regexp.
|
|
* sourceURL - The sourceURL of the template's compiled source.
|
|
* variable - The data object variable name.
|
|
*
|
|
* @returns {Function|String} Returns a compiled function when no `data` object
|
|
* is given, else it returns the interpolated text.
|
|
* @example
|
|
*
|
|
* // using a compiled template
|
|
* var compiled = _.template('hello <%= name %>');
|
|
* compiled({ 'name': 'moe' });
|
|
* // => 'hello moe'
|
|
*
|
|
* var list = '<% _.forEach(people, function(name) { %><li><%= name %></li><% }); %>';
|
|
* _.template(list, { 'people': ['moe', 'larry'] });
|
|
* // => '<li>moe</li><li>larry</li>'
|
|
*
|
|
* // using the "escape" delimiter to escape HTML in data property values
|
|
* _.template('<b><%- value %></b>', { 'value': '<script>' });
|
|
* // => '<b><script></b>'
|
|
*
|
|
* // using the ES6 delimiter as an alternative to the default "interpolate" delimiter
|
|
* _.template('hello ${ name }', { 'name': 'curly' });
|
|
* // => 'hello curly'
|
|
*
|
|
* // using the internal `print` function in "evaluate" delimiters
|
|
* _.template('<% print("hello " + epithet); %>!', { 'epithet': 'stooge' });
|
|
* // => 'hello stooge!'
|
|
*
|
|
* // using custom template delimiters
|
|
* _.templateSettings = {
|
|
* 'interpolate': /{{([\s\S]+?)}}/g
|
|
* };
|
|
*
|
|
* _.template('hello {{ name }}!', { 'name': 'mustache' });
|
|
* // => 'hello mustache!'
|
|
*
|
|
* // using the `sourceURL` option to specify a custom sourceURL for the template
|
|
* var compiled = _.template('hello <%= name %>', null, { 'sourceURL': '/basic/greeting.jst' });
|
|
* compiled(data);
|
|
* // => find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector
|
|
*
|
|
* // using the `variable` option to ensure a with-statement isn't used in the compiled template
|
|
* var compiled = _.template('hi <%= data.name %>!', null, { 'variable': 'data' });
|
|
* compiled.source;
|
|
* // => function(data) {
|
|
* var __t, __p = '', __e = _.escape;
|
|
* __p += 'hi ' + ((__t = ( data.name )) == null ? '' : __t) + '!';
|
|
* return __p;
|
|
* }
|
|
*
|
|
* // using the `source` property to inline compiled templates for meaningful
|
|
* // line numbers in error messages and a stack trace
|
|
* fs.writeFileSync(path.join(cwd, 'jst.js'), '\
|
|
* var JST = {\
|
|
* "main": ' + _.template(mainText).source + '\
|
|
* };\
|
|
* ');
|
|
*/
|
|
function template(text, data, options) {
|
|
// based on John Resig's `tmpl` implementation
|
|
// http://ejohn.org/blog/javascript-micro-templating/
|
|
// and Laura Doktorova's doT.js
|
|
// https://github.com/olado/doT
|
|
var settings = lodash.templateSettings;
|
|
text || (text = '');
|
|
|
|
// avoid missing dependencies when `iteratorTemplate` is not defined
|
|
options = defaults({}, options, settings);
|
|
|
|
var imports = defaults({}, options.imports, settings.imports),
|
|
importsKeys = keys(imports),
|
|
importsValues = values(imports);
|
|
|
|
var isEvaluating,
|
|
index = 0,
|
|
interpolate = options.interpolate || reNoMatch,
|
|
source = "__p += '";
|
|
|
|
// compile regexp to match each delimiter
|
|
var reDelimiters = RegExp(
|
|
(options.escape || reNoMatch).source + '|' +
|
|
interpolate.source + '|' +
|
|
(interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' +
|
|
(options.evaluate || reNoMatch).source + '|$'
|
|
, 'g');
|
|
|
|
text.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
|
|
interpolateValue || (interpolateValue = esTemplateValue);
|
|
|
|
// escape characters that cannot be included in string literals
|
|
source += text.slice(index, offset).replace(reUnescapedString, escapeStringChar);
|
|
|
|
// replace delimiters with snippets
|
|
if (escapeValue) {
|
|
source += "' +\n__e(" + escapeValue + ") +\n'";
|
|
}
|
|
if (evaluateValue) {
|
|
isEvaluating = true;
|
|
source += "';\n" + evaluateValue + ";\n__p += '";
|
|
}
|
|
if (interpolateValue) {
|
|
source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
|
|
}
|
|
index = offset + match.length;
|
|
|
|
// the JS engine embedded in Adobe products requires returning the `match`
|
|
// string in order to produce the correct `offset` value
|
|
return match;
|
|
});
|
|
|
|
source += "';\n";
|
|
|
|
// if `variable` is not specified and the template contains "evaluate"
|
|
// delimiters, wrap a with-statement around the generated code to add the
|
|
// data object to the top of the scope chain
|
|
var variable = options.variable,
|
|
hasVariable = variable;
|
|
|
|
if (!hasVariable) {
|
|
variable = 'obj';
|
|
source = 'with (' + variable + ') {\n' + source + '\n}\n';
|
|
}
|
|
// cleanup code by stripping empty strings
|
|
source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)
|
|
.replace(reEmptyStringMiddle, '$1')
|
|
.replace(reEmptyStringTrailing, '$1;');
|
|
|
|
// frame code as the function body
|
|
source = 'function(' + variable + ') {\n' +
|
|
(hasVariable ? '' : variable + ' || (' + variable + ' = {});\n') +
|
|
"var __t, __p = '', __e = _.escape" +
|
|
(isEvaluating
|
|
? ', __j = Array.prototype.join;\n' +
|
|
"function print() { __p += __j.call(arguments, '') }\n"
|
|
: ';\n'
|
|
) +
|
|
source +
|
|
'return __p\n}';
|
|
|
|
// Use a sourceURL for easier debugging and wrap in a multi-line comment to
|
|
// avoid issues with Narwhal, IE conditional compilation, and the JS engine
|
|
// embedded in Adobe products.
|
|
// http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl
|
|
var sourceURL = '\n/*\n//@ sourceURL=' + (options.sourceURL || '/lodash/template/source[' + (templateCounter++) + ']') + '\n*/';
|
|
|
|
try {
|
|
var result = Function(importsKeys, 'return ' + source + sourceURL).apply(undefined, importsValues);
|
|
} catch(e) {
|
|
e.source = source;
|
|
throw e;
|
|
}
|
|
if (data) {
|
|
return result(data);
|
|
}
|
|
// provide the compiled function's source via its `toString` method, in
|
|
// supported environments, or the `source` property as a convenience for
|
|
// inlining compiled templates during the build process
|
|
result.source = source;
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Executes the `callback` function `n` times, returning an array of the results
|
|
* of each `callback` execution. The `callback` is bound to `thisArg` and invoked
|
|
* with one argument; (index).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Utilities
|
|
* @param {Number} n The number of times to execute the callback.
|
|
* @param {Function} callback The function called per iteration.
|
|
* @param {Mixed} [thisArg] The `this` binding of `callback`.
|
|
* @returns {Array} Returns a new array of the results of each `callback` execution.
|
|
* @example
|
|
*
|
|
* var diceRolls = _.times(3, _.partial(_.random, 1, 6));
|
|
* // => [3, 6, 4]
|
|
*
|
|
* _.times(3, function(n) { mage.castSpell(n); });
|
|
* // => calls `mage.castSpell(n)` three times, passing `n` of `0`, `1`, and `2` respectively
|
|
*
|
|
* _.times(3, function(n) { this.cast(n); }, mage);
|
|
* // => also calls `mage.castSpell(n)` three times
|
|
*/
|
|
function times(n, callback, thisArg) {
|
|
n = +n || 0;
|
|
var index = -1,
|
|
result = Array(n);
|
|
|
|
while (++index < n) {
|
|
result[index] = callback.call(thisArg, index);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* The opposite of `_.escape`, this method converts the HTML entities
|
|
* `&`, `<`, `>`, `"`, and `'` in `string` to their
|
|
* corresponding characters.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Utilities
|
|
* @param {String} string The string to unescape.
|
|
* @returns {String} Returns the unescaped string.
|
|
* @example
|
|
*
|
|
* _.unescape('Moe, Larry & Curly');
|
|
* // => 'Moe, Larry & Curly'
|
|
*/
|
|
function unescape(string) {
|
|
return string == null ? '' : (string + '').replace(reEscapedHtml, unescapeHtmlChar);
|
|
}
|
|
|
|
/**
|
|
* Generates a unique ID. If `prefix` is passed, the ID will be appended to it.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Utilities
|
|
* @param {String} [prefix] The value to prefix the ID with.
|
|
* @returns {String} Returns the unique ID.
|
|
* @example
|
|
*
|
|
* _.uniqueId('contact_');
|
|
* // => 'contact_104'
|
|
*
|
|
* _.uniqueId();
|
|
* // => '105'
|
|
*/
|
|
function uniqueId(prefix) {
|
|
var id = ++idCounter;
|
|
return (prefix == null ? '' : prefix + '') + id;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* Invokes `interceptor` with the `value` as the first argument, and then
|
|
* returns `value`. The purpose of this method is to "tap into" a method chain,
|
|
* in order to perform operations on intermediate results within the chain.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @category Chaining
|
|
* @param {Mixed} value The value to pass to `interceptor`.
|
|
* @param {Function} interceptor The function to invoke.
|
|
* @returns {Mixed} Returns `value`.
|
|
* @example
|
|
*
|
|
* _([1, 2, 3, 4])
|
|
* .filter(function(num) { return num % 2 == 0; })
|
|
* .tap(alert)
|
|
* .map(function(num) { return num * num; })
|
|
* .value();
|
|
* // => // [2, 4] (alerted)
|
|
* // => [4, 16]
|
|
*/
|
|
function tap(value, interceptor) {
|
|
interceptor(value);
|
|
return value;
|
|
}
|
|
|
|
/**
|
|
* Produces the `toString` result of the wrapped value.
|
|
*
|
|
* @name toString
|
|
* @memberOf _
|
|
* @category Chaining
|
|
* @returns {String} Returns the string result.
|
|
* @example
|
|
*
|
|
* _([1, 2, 3]).toString();
|
|
* // => '1,2,3'
|
|
*/
|
|
function wrapperToString() {
|
|
return this.__wrapped__ + '';
|
|
}
|
|
|
|
/**
|
|
* Extracts the wrapped value.
|
|
*
|
|
* @name valueOf
|
|
* @memberOf _
|
|
* @alias value
|
|
* @category Chaining
|
|
* @returns {Mixed} Returns the wrapped value.
|
|
* @example
|
|
*
|
|
* _([1, 2, 3]).valueOf();
|
|
* // => [1, 2, 3]
|
|
*/
|
|
function wrapperValueOf() {
|
|
return this.__wrapped__;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
// add functions that return wrapped values when chaining
|
|
lodash.after = after;
|
|
lodash.assign = assign;
|
|
lodash.at = at;
|
|
lodash.bind = bind;
|
|
lodash.bindAll = bindAll;
|
|
lodash.bindKey = bindKey;
|
|
lodash.compact = compact;
|
|
lodash.compose = compose;
|
|
lodash.countBy = countBy;
|
|
lodash.debounce = debounce;
|
|
lodash.defaults = defaults;
|
|
lodash.defer = defer;
|
|
lodash.delay = delay;
|
|
lodash.difference = difference;
|
|
lodash.filter = filter;
|
|
lodash.flatten = flatten;
|
|
lodash.forEach = forEach;
|
|
lodash.forIn = forIn;
|
|
lodash.forOwn = forOwn;
|
|
lodash.functions = functions;
|
|
lodash.groupBy = groupBy;
|
|
lodash.initial = initial;
|
|
lodash.intersection = intersection;
|
|
lodash.invert = invert;
|
|
lodash.invoke = invoke;
|
|
lodash.keys = keys;
|
|
lodash.map = map;
|
|
lodash.max = max;
|
|
lodash.memoize = memoize;
|
|
lodash.merge = merge;
|
|
lodash.min = min;
|
|
lodash.object = object;
|
|
lodash.omit = omit;
|
|
lodash.once = once;
|
|
lodash.pairs = pairs;
|
|
lodash.partial = partial;
|
|
lodash.partialRight = partialRight;
|
|
lodash.pick = pick;
|
|
lodash.pluck = pluck;
|
|
lodash.range = range;
|
|
lodash.reject = reject;
|
|
lodash.rest = rest;
|
|
lodash.shuffle = shuffle;
|
|
lodash.sortBy = sortBy;
|
|
lodash.tap = tap;
|
|
lodash.throttle = throttle;
|
|
lodash.times = times;
|
|
lodash.toArray = toArray;
|
|
lodash.union = union;
|
|
lodash.uniq = uniq;
|
|
lodash.values = values;
|
|
lodash.where = where;
|
|
lodash.without = without;
|
|
lodash.wrap = wrap;
|
|
lodash.zip = zip;
|
|
|
|
// add aliases
|
|
lodash.collect = map;
|
|
lodash.drop = rest;
|
|
lodash.each = forEach;
|
|
lodash.extend = assign;
|
|
lodash.methods = functions;
|
|
lodash.select = filter;
|
|
lodash.tail = rest;
|
|
lodash.unique = uniq;
|
|
|
|
// add functions to `lodash.prototype`
|
|
mixin(lodash);
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
// add functions that return unwrapped values when chaining
|
|
lodash.clone = clone;
|
|
lodash.cloneDeep = cloneDeep;
|
|
lodash.contains = contains;
|
|
lodash.escape = escape;
|
|
lodash.every = every;
|
|
lodash.find = find;
|
|
lodash.has = has;
|
|
lodash.identity = identity;
|
|
lodash.indexOf = indexOf;
|
|
lodash.isArguments = isArguments;
|
|
lodash.isArray = isArray;
|
|
lodash.isBoolean = isBoolean;
|
|
lodash.isDate = isDate;
|
|
lodash.isElement = isElement;
|
|
lodash.isEmpty = isEmpty;
|
|
lodash.isEqual = isEqual;
|
|
lodash.isFinite = isFinite;
|
|
lodash.isFunction = isFunction;
|
|
lodash.isNaN = isNaN;
|
|
lodash.isNull = isNull;
|
|
lodash.isNumber = isNumber;
|
|
lodash.isObject = isObject;
|
|
lodash.isPlainObject = isPlainObject;
|
|
lodash.isRegExp = isRegExp;
|
|
lodash.isString = isString;
|
|
lodash.isUndefined = isUndefined;
|
|
lodash.lastIndexOf = lastIndexOf;
|
|
lodash.mixin = mixin;
|
|
lodash.noConflict = noConflict;
|
|
lodash.random = random;
|
|
lodash.reduce = reduce;
|
|
lodash.reduceRight = reduceRight;
|
|
lodash.result = result;
|
|
lodash.size = size;
|
|
lodash.some = some;
|
|
lodash.sortedIndex = sortedIndex;
|
|
lodash.template = template;
|
|
lodash.unescape = unescape;
|
|
lodash.uniqueId = uniqueId;
|
|
|
|
// add aliases
|
|
lodash.all = every;
|
|
lodash.any = some;
|
|
lodash.detect = find;
|
|
lodash.foldl = reduce;
|
|
lodash.foldr = reduceRight;
|
|
lodash.include = contains;
|
|
lodash.inject = reduce;
|
|
|
|
forOwn(lodash, function(func, methodName) {
|
|
if (!lodash.prototype[methodName]) {
|
|
lodash.prototype[methodName] = function() {
|
|
var args = [this.__wrapped__];
|
|
push.apply(args, arguments);
|
|
return func.apply(lodash, args);
|
|
};
|
|
}
|
|
});
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
// add functions capable of returning wrapped and unwrapped values when chaining
|
|
lodash.first = first;
|
|
lodash.last = last;
|
|
|
|
// add aliases
|
|
lodash.take = first;
|
|
lodash.head = first;
|
|
|
|
forOwn(lodash, function(func, methodName) {
|
|
if (!lodash.prototype[methodName]) {
|
|
lodash.prototype[methodName]= function(callback, thisArg) {
|
|
var result = func(this.__wrapped__, callback, thisArg);
|
|
return callback == null || (thisArg && typeof callback != 'function')
|
|
? result
|
|
: new lodash(result);
|
|
};
|
|
}
|
|
});
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* The semantic version number.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @type String
|
|
*/
|
|
lodash.VERSION = '1.0.1';
|
|
|
|
// add "Chaining" functions to the wrapper
|
|
lodash.prototype.toString = wrapperToString;
|
|
lodash.prototype.value = wrapperValueOf;
|
|
lodash.prototype.valueOf = wrapperValueOf;
|
|
|
|
// add `Array` functions that return unwrapped values
|
|
each(['join', 'pop', 'shift'], function(methodName) {
|
|
var func = arrayRef[methodName];
|
|
lodash.prototype[methodName] = function() {
|
|
return func.apply(this.__wrapped__, arguments);
|
|
};
|
|
});
|
|
|
|
// add `Array` functions that return the wrapped value
|
|
each(['push', 'reverse', 'sort', 'unshift'], function(methodName) {
|
|
var func = arrayRef[methodName];
|
|
lodash.prototype[methodName] = function() {
|
|
func.apply(this.__wrapped__, arguments);
|
|
return this;
|
|
};
|
|
});
|
|
|
|
// add `Array` functions that return new wrapped values
|
|
each(['concat', 'slice', 'splice'], function(methodName) {
|
|
var func = arrayRef[methodName];
|
|
lodash.prototype[methodName] = function() {
|
|
return new lodash(func.apply(this.__wrapped__, arguments));
|
|
};
|
|
});
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
// expose Lo-Dash
|
|
// some AMD build optimizers, like r.js, check for specific condition patterns like the following:
|
|
if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
|
|
// Expose Lo-Dash to the global object even when an AMD loader is present in
|
|
// case Lo-Dash was injected by a third-party script and not intended to be
|
|
// loaded as a module. The global assignment can be reverted in the Lo-Dash
|
|
// module via its `noConflict()` method.
|
|
window._ = lodash;
|
|
|
|
// define as an anonymous module so, through path mapping, it can be
|
|
// referenced as the "underscore" module
|
|
define(function() {
|
|
return lodash;
|
|
});
|
|
}
|
|
// check for `exports` after `define` in case a build optimizer adds an `exports` object
|
|
else if (freeExports) {
|
|
// in Node.js or RingoJS v0.8.0+
|
|
if (freeModule) {
|
|
(freeModule.exports = lodash)._ = lodash;
|
|
}
|
|
// in Narwhal or RingoJS v0.7.0-
|
|
else {
|
|
freeExports._ = lodash;
|
|
}
|
|
}
|
|
else {
|
|
// in a browser or Rhino
|
|
window._ = lodash;
|
|
}
|
|
}(this));
|
|
|
|
},{}],76:[function(require,module,exports){
|
|
var Buffer=require("__browserify_Buffer").Buffer;// uuid.js
|
|
//
|
|
// (c) 2010-2012 Robert Kieffer
|
|
// MIT License
|
|
// https://github.com/broofa/node-uuid
|
|
(function() {
|
|
var _global = this;
|
|
|
|
// Unique ID creation requires a high quality random # generator. We feature
|
|
// detect to determine the best RNG source, normalizing to a function that
|
|
// returns 128-bits of randomness, since that's what's usually required
|
|
var _rng;
|
|
|
|
// Node.js crypto-based RNG - http://nodejs.org/docs/v0.6.2/api/crypto.html
|
|
//
|
|
// Moderately fast, high quality
|
|
if (typeof(require) == 'function') {
|
|
try {
|
|
var _rb = require('crypto').randomBytes;
|
|
_rng = _rb && function() {return _rb(16);};
|
|
} catch(e) {}
|
|
}
|
|
|
|
if (!_rng && _global.crypto && crypto.getRandomValues) {
|
|
// WHATWG crypto-based RNG - http://wiki.whatwg.org/wiki/Crypto
|
|
//
|
|
// Moderately fast, high quality
|
|
var _rnds8 = new Uint8Array(16);
|
|
_rng = function whatwgRNG() {
|
|
crypto.getRandomValues(_rnds8);
|
|
return _rnds8;
|
|
};
|
|
}
|
|
|
|
if (!_rng) {
|
|
// Math.random()-based (RNG)
|
|
//
|
|
// If all else fails, use Math.random(). It's fast, but is of unspecified
|
|
// quality.
|
|
var _rnds = new Array(16);
|
|
_rng = function() {
|
|
for (var i = 0, r; i < 16; i++) {
|
|
if ((i & 0x03) === 0) r = Math.random() * 0x100000000;
|
|
_rnds[i] = r >>> ((i & 0x03) << 3) & 0xff;
|
|
}
|
|
|
|
return _rnds;
|
|
};
|
|
}
|
|
|
|
// Buffer class to use
|
|
var BufferClass = typeof(Buffer) == 'function' ? Buffer : Array;
|
|
|
|
// Maps for number <-> hex string conversion
|
|
var _byteToHex = [];
|
|
var _hexToByte = {};
|
|
for (var i = 0; i < 256; i++) {
|
|
_byteToHex[i] = (i + 0x100).toString(16).substr(1);
|
|
_hexToByte[_byteToHex[i]] = i;
|
|
}
|
|
|
|
// **`parse()` - Parse a UUID into it's component bytes**
|
|
function parse(s, buf, offset) {
|
|
var i = (buf && offset) || 0, ii = 0;
|
|
|
|
buf = buf || [];
|
|
s.toLowerCase().replace(/[0-9a-f]{2}/g, function(oct) {
|
|
if (ii < 16) { // Don't overflow!
|
|
buf[i + ii++] = _hexToByte[oct];
|
|
}
|
|
});
|
|
|
|
// Zero out remaining bytes if string was short
|
|
while (ii < 16) {
|
|
buf[i + ii++] = 0;
|
|
}
|
|
|
|
return buf;
|
|
}
|
|
|
|
// **`unparse()` - Convert UUID byte array (ala parse()) into a string**
|
|
function unparse(buf, offset) {
|
|
var i = offset || 0, bth = _byteToHex;
|
|
return bth[buf[i++]] + bth[buf[i++]] +
|
|
bth[buf[i++]] + bth[buf[i++]] + '-' +
|
|
bth[buf[i++]] + bth[buf[i++]] + '-' +
|
|
bth[buf[i++]] + bth[buf[i++]] + '-' +
|
|
bth[buf[i++]] + bth[buf[i++]] + '-' +
|
|
bth[buf[i++]] + bth[buf[i++]] +
|
|
bth[buf[i++]] + bth[buf[i++]] +
|
|
bth[buf[i++]] + bth[buf[i++]];
|
|
}
|
|
|
|
// **`v1()` - Generate time-based UUID**
|
|
//
|
|
// Inspired by https://github.com/LiosK/UUID.js
|
|
// and http://docs.python.org/library/uuid.html
|
|
|
|
// random #'s we need to init node and clockseq
|
|
var _seedBytes = _rng();
|
|
|
|
// Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1)
|
|
var _nodeId = [
|
|
_seedBytes[0] | 0x01,
|
|
_seedBytes[1], _seedBytes[2], _seedBytes[3], _seedBytes[4], _seedBytes[5]
|
|
];
|
|
|
|
// Per 4.2.2, randomize (14 bit) clockseq
|
|
var _clockseq = (_seedBytes[6] << 8 | _seedBytes[7]) & 0x3fff;
|
|
|
|
// Previous uuid creation time
|
|
var _lastMSecs = 0, _lastNSecs = 0;
|
|
|
|
// See https://github.com/broofa/node-uuid for API details
|
|
function v1(options, buf, offset) {
|
|
var i = buf && offset || 0;
|
|
var b = buf || [];
|
|
|
|
options = options || {};
|
|
|
|
var clockseq = options.clockseq != null ? options.clockseq : _clockseq;
|
|
|
|
// UUID timestamps are 100 nano-second units since the Gregorian epoch,
|
|
// (1582-10-15 00:00). JSNumbers aren't precise enough for this, so
|
|
// time is handled internally as 'msecs' (integer milliseconds) and 'nsecs'
|
|
// (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00.
|
|
var msecs = options.msecs != null ? options.msecs : new Date().getTime();
|
|
|
|
// Per 4.2.1.2, use count of uuid's generated during the current clock
|
|
// cycle to simulate higher resolution clock
|
|
var nsecs = options.nsecs != null ? options.nsecs : _lastNSecs + 1;
|
|
|
|
// Time since last uuid creation (in msecs)
|
|
var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000;
|
|
|
|
// Per 4.2.1.2, Bump clockseq on clock regression
|
|
if (dt < 0 && options.clockseq == null) {
|
|
clockseq = clockseq + 1 & 0x3fff;
|
|
}
|
|
|
|
// Reset nsecs if clock regresses (new clockseq) or we've moved onto a new
|
|
// time interval
|
|
if ((dt < 0 || msecs > _lastMSecs) && options.nsecs == null) {
|
|
nsecs = 0;
|
|
}
|
|
|
|
// Per 4.2.1.2 Throw error if too many uuids are requested
|
|
if (nsecs >= 10000) {
|
|
throw new Error('uuid.v1(): Can\'t create more than 10M uuids/sec');
|
|
}
|
|
|
|
_lastMSecs = msecs;
|
|
_lastNSecs = nsecs;
|
|
_clockseq = clockseq;
|
|
|
|
// Per 4.1.4 - Convert from unix epoch to Gregorian epoch
|
|
msecs += 12219292800000;
|
|
|
|
// `time_low`
|
|
var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000;
|
|
b[i++] = tl >>> 24 & 0xff;
|
|
b[i++] = tl >>> 16 & 0xff;
|
|
b[i++] = tl >>> 8 & 0xff;
|
|
b[i++] = tl & 0xff;
|
|
|
|
// `time_mid`
|
|
var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff;
|
|
b[i++] = tmh >>> 8 & 0xff;
|
|
b[i++] = tmh & 0xff;
|
|
|
|
// `time_high_and_version`
|
|
b[i++] = tmh >>> 24 & 0xf | 0x10; // include version
|
|
b[i++] = tmh >>> 16 & 0xff;
|
|
|
|
// `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant)
|
|
b[i++] = clockseq >>> 8 | 0x80;
|
|
|
|
// `clock_seq_low`
|
|
b[i++] = clockseq & 0xff;
|
|
|
|
// `node`
|
|
var node = options.node || _nodeId;
|
|
for (var n = 0; n < 6; n++) {
|
|
b[i + n] = node[n];
|
|
}
|
|
|
|
return buf ? buf : unparse(b);
|
|
}
|
|
|
|
// **`v4()` - Generate random UUID**
|
|
|
|
// See https://github.com/broofa/node-uuid for API details
|
|
function v4(options, buf, offset) {
|
|
// Deprecated - 'format' argument, as supported in v1.2
|
|
var i = buf && offset || 0;
|
|
|
|
if (typeof(options) == 'string') {
|
|
buf = options == 'binary' ? new BufferClass(16) : null;
|
|
options = null;
|
|
}
|
|
options = options || {};
|
|
|
|
var rnds = options.random || (options.rng || _rng)();
|
|
|
|
// Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
|
|
rnds[6] = (rnds[6] & 0x0f) | 0x40;
|
|
rnds[8] = (rnds[8] & 0x3f) | 0x80;
|
|
|
|
// Copy bytes to buffer, if provided
|
|
if (buf) {
|
|
for (var ii = 0; ii < 16; ii++) {
|
|
buf[i + ii] = rnds[ii];
|
|
}
|
|
}
|
|
|
|
return buf || unparse(rnds);
|
|
}
|
|
|
|
// Export public API
|
|
var uuid = v4;
|
|
uuid.v1 = v1;
|
|
uuid.v4 = v4;
|
|
uuid.parse = parse;
|
|
uuid.unparse = unparse;
|
|
uuid.BufferClass = BufferClass;
|
|
|
|
if (_global.define && define.amd) {
|
|
// Publish as AMD module
|
|
define(function() {return uuid;});
|
|
} else if (typeof(module) != 'undefined' && module.exports) {
|
|
// Publish as node.js module
|
|
module.exports = uuid;
|
|
} else {
|
|
// Publish as global (in browsers)
|
|
var _previousRoot = _global.uuid;
|
|
|
|
// **`noConflict()` - (browser only) to reset global 'uuid' var**
|
|
uuid.noConflict = function() {
|
|
_global.uuid = _previousRoot;
|
|
return uuid;
|
|
};
|
|
|
|
_global.uuid = uuid;
|
|
}
|
|
}());
|
|
|
|
},{"__browserify_Buffer":65,"crypto":60}],77:[function(require,module,exports){
|
|
(function(root, factory) {
|
|
if (typeof exports === 'object') {
|
|
// CommonJS
|
|
factory(exports, module);
|
|
} else if (typeof define === 'function' && define.amd) {
|
|
// AMD
|
|
define(['exports', 'module'], factory);
|
|
}
|
|
}(this, function(exports, module) {
|
|
|
|
/**
|
|
* ANONYMOUS `Mechanism` constructor.
|
|
*
|
|
* This class implements the ANONYMOUS SASL mechanism.
|
|
*
|
|
* The ANONYMOUS SASL mechanism provides support for permitting anonymous
|
|
* access to various services
|
|
*
|
|
* References:
|
|
* - [RFC 4505](http://tools.ietf.org/html/rfc4505)
|
|
*
|
|
* @api public
|
|
*/
|
|
function Mechanism() {
|
|
}
|
|
|
|
Mechanism.prototype.name = 'ANONYMOUS';
|
|
Mechanism.prototype.clientFirst = true;
|
|
|
|
/**
|
|
* Encode a response using optional trace information.
|
|
*
|
|
* Options:
|
|
* - `trace` trace information (optional)
|
|
*
|
|
* @param {Object} cred
|
|
* @api public
|
|
*/
|
|
Mechanism.prototype.response = function(cred) {
|
|
return cred.trace || '';
|
|
};
|
|
|
|
/**
|
|
* Decode a challenge issued by the server.
|
|
*
|
|
* @param {String} chal
|
|
* @api public
|
|
*/
|
|
Mechanism.prototype.challenge = function(chal) {
|
|
};
|
|
|
|
exports = module.exports = Mechanism;
|
|
|
|
}));
|
|
|
|
},{}],78:[function(require,module,exports){
|
|
(function(root, factory) {
|
|
if (typeof exports === 'object') {
|
|
// CommonJS
|
|
factory(exports,
|
|
module,
|
|
require('./lib/mechanism'));
|
|
} else if (typeof define === 'function' && define.amd) {
|
|
// AMD
|
|
define(['exports',
|
|
'module',
|
|
'./lib/mechanism'], factory);
|
|
}
|
|
}(this, function(exports, module, Mechanism) {
|
|
|
|
exports = module.exports = Mechanism;
|
|
exports.Mechanism = Mechanism;
|
|
|
|
}));
|
|
|
|
},{"./lib/mechanism":77}],79:[function(require,module,exports){
|
|
(function(root, factory) {
|
|
if (typeof exports === 'object') {
|
|
// CommonJS
|
|
factory(exports, module, require('crypto'));
|
|
} else if (typeof define === 'function' && define.amd) {
|
|
// AMD
|
|
define(['exports', 'module', 'crypto'], factory);
|
|
}
|
|
}(this, function(exports, module, crypto) {
|
|
|
|
/**
|
|
* DIGEST-MD5 `Mechanism` constructor.
|
|
*
|
|
* This class implements the DIGEST-MD5 SASL mechanism.
|
|
*
|
|
* References:
|
|
* - [RFC 2831](http://tools.ietf.org/html/rfc2831)
|
|
*
|
|
* @api public
|
|
*/
|
|
function Mechanism(options) {
|
|
options = options || {};
|
|
this._genNonce = options.genNonce || genNonce(32);
|
|
}
|
|
|
|
Mechanism.prototype.name = 'DIGEST-MD5';
|
|
Mechanism.prototype.clientFirst = false;
|
|
|
|
/**
|
|
* Encode a response using given credential.
|
|
*
|
|
* Options:
|
|
* - `username`
|
|
* - `password`
|
|
* - `host`
|
|
* - `serviceType`
|
|
* - `authzid` authorization identity (optional)
|
|
*
|
|
* @param {Object} cred
|
|
* @api public
|
|
*/
|
|
Mechanism.prototype.response = function(cred) {
|
|
// TODO: Implement support for subsequent authentication. This requires
|
|
// that the client be able to store username, realm, nonce,
|
|
// nonce-count, cnonce, and qop values from prior authentication.
|
|
// The impact of this requirement needs to be investigated.
|
|
//
|
|
// See RFC 2831 (Section 2.2) for further details.
|
|
|
|
// TODO: Implement support for auth-int and auth-conf, as defined in RFC
|
|
// 2831 sections 2.3 Integrity Protection and 2.4 Confidentiality
|
|
// Protection, respectively.
|
|
//
|
|
// Note that supporting this functionality has implications
|
|
// regarding the negotiation of security layers via SASL. Due to
|
|
// the fact that TLS has largely superseded this functionality,
|
|
// implementing it is a low priority.
|
|
|
|
var uri = cred.serviceType + '/' + cred.host;
|
|
if (cred.serviceName && cred.host !== cred.serviceName) {
|
|
uri += '/' + serviceName;
|
|
}
|
|
var realm = cred.realm || this._realm || ''
|
|
, cnonce = this._genNonce()
|
|
, nc = '00000001'
|
|
, qop = 'auth'
|
|
, ha1
|
|
, ha2
|
|
, digest;
|
|
|
|
var str = '';
|
|
str += 'username="' + cred.username + '"';
|
|
if (realm) { str += ',realm="' + realm + '"'; };
|
|
str += ',nonce="' + this._nonce + '"';
|
|
str += ',cnonce="' + cnonce + '"';
|
|
str += ',nc=' + nc;
|
|
str += ',qop=' + qop;
|
|
str += ',digest-uri="' + uri + '"';
|
|
|
|
if (cred.authzid) {
|
|
ha1 = md5(md5(cred.username + ":" + realm + ":" + cred.password, 'binary') + ":" + this._nonce + ":" + cnonce + ":" + cred.authzid);
|
|
} else {
|
|
ha1 = md5(md5(cred.username + ":" + realm + ":" + cred.password, 'binary') + ":" + this._nonce + ":" + cnonce);
|
|
}
|
|
|
|
if (qop == 'auth') {
|
|
ha2 = md5('AUTHENTICATE:' + uri);
|
|
} else if (qop == 'auth-int' || qop == 'auth-conf') {
|
|
ha2 = md5('AUTHENTICATE:' + uri + ':00000000000000000000000000000000');
|
|
}
|
|
|
|
digest = md5(ha1 + ":" + this._nonce + ":" + nc + ":" + cnonce + ":" + qop + ":" + ha2);
|
|
str += ',response=' + digest;
|
|
|
|
if (this._charset == 'utf-8') { str += ',charset=utf-8'; }
|
|
if (cred.authzid) { str += 'authzid="' + cred.authzid + '"'; }
|
|
|
|
return str;
|
|
};
|
|
|
|
/**
|
|
* Decode a challenge issued by the server.
|
|
*
|
|
* @param {String} chal
|
|
* @return {Mechanism} for chaining
|
|
* @api public
|
|
*/
|
|
Mechanism.prototype.challenge = function(chal) {
|
|
var dtives = parse(chal);
|
|
|
|
// TODO: Implement support for multiple realm directives, as allowed by the
|
|
// DIGEST-MD5 specification.
|
|
this._realm = dtives['realm'];
|
|
this._nonce = dtives['nonce'];
|
|
this._qop = (dtives['qop'] || 'auth').split(',');
|
|
this._stale = dtives['stale'];
|
|
this._maxbuf = parseInt(dtives['maxbuf']) || 65536;
|
|
this._charset = dtives['charset'];
|
|
this._algo = dtives['algorithm'];
|
|
this._cipher = dtives['cipher'];
|
|
if (this._cipher) { this._cipher.split(','); }
|
|
return this;
|
|
};
|
|
|
|
|
|
/**
|
|
* Parse challenge.
|
|
*
|
|
* @api private
|
|
*/
|
|
function parse(chal) {
|
|
var dtives = {};
|
|
var tokens = chal.split(/,(?=(?:[^"]|"[^"]*")*$)/);
|
|
for (var i = 0, len = tokens.length; i < len; i++) {
|
|
var dtiv = /(\w+)=["]?([^"]+)["]?$/.exec(tokens[i]);
|
|
if (dtiv) {
|
|
dtives[dtiv[1]] = dtiv[2];
|
|
}
|
|
}
|
|
return dtives;
|
|
}
|
|
|
|
/**
|
|
* Return a unique nonce with the given `len`.
|
|
*
|
|
* genNonce(10)();
|
|
* // => "FDaS435D2z"
|
|
*
|
|
* @param {Number} len
|
|
* @return {Function}
|
|
* @api private
|
|
*/
|
|
function genNonce(len) {
|
|
var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
|
|
, charlen = chars.length;
|
|
|
|
return function() {
|
|
var buf = [];
|
|
for (var i = 0; i < len; ++i) {
|
|
buf.push(chars[Math.random() * charlen | 0]);
|
|
}
|
|
return buf.join('');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Return md5 hash of the given string and optional encoding,
|
|
* defaulting to hex.
|
|
*
|
|
* md5('wahoo');
|
|
* // => "e493298061761236c96b02ea6aa8a2ad"
|
|
*
|
|
* @param {String} str
|
|
* @param {String} encoding
|
|
* @return {String}
|
|
* @api private
|
|
*/
|
|
function md5(str, encoding){
|
|
return crypto
|
|
.createHash('md5')
|
|
.update(str)
|
|
.digest(encoding || 'hex');
|
|
}
|
|
|
|
|
|
exports = module.exports = Mechanism;
|
|
|
|
}));
|
|
|
|
},{"crypto":60}],80:[function(require,module,exports){
|
|
(function(root, factory) {
|
|
if (typeof exports === 'object') {
|
|
// CommonJS
|
|
factory(exports,
|
|
module,
|
|
require('./lib/mechanism'));
|
|
} else if (typeof define === 'function' && define.amd) {
|
|
// AMD
|
|
define(['exports',
|
|
'module',
|
|
'./lib/mechanism'], factory);
|
|
}
|
|
}(this, function(exports, module, Mechanism) {
|
|
|
|
exports = module.exports = Mechanism;
|
|
exports.Mechanism = Mechanism;
|
|
|
|
}));
|
|
|
|
},{"./lib/mechanism":79}],81:[function(require,module,exports){
|
|
(function(root, factory) {
|
|
if (typeof exports === 'object') {
|
|
// CommonJS
|
|
factory(exports, module);
|
|
} else if (typeof define === 'function' && define.amd) {
|
|
// AMD
|
|
define(['exports', 'module'], factory);
|
|
}
|
|
}(this, function(exports, module) {
|
|
|
|
/**
|
|
* EXTERNAL `Mechanism` constructor.
|
|
*
|
|
* This class implements the EXTERNAL SASL mechanism.
|
|
*
|
|
* The EXTERNAL SASL mechanism provides support for authentication using
|
|
* credentials established by external means.
|
|
*
|
|
* References:
|
|
* - [RFC 4422](http://tools.ietf.org/html/rfc4422)
|
|
*
|
|
* @api public
|
|
*/
|
|
function Mechanism() {
|
|
}
|
|
|
|
Mechanism.prototype.name = 'EXTERNAL';
|
|
Mechanism.prototype.clientFirst = true;
|
|
|
|
/**
|
|
* Encode a response using given credential.
|
|
*
|
|
* Options:
|
|
* - `authzid` authorization identity (optional)
|
|
*
|
|
* @param {Object} cred
|
|
* @api public
|
|
*/
|
|
Mechanism.prototype.response = function(cred) {
|
|
return cred.authzid || '';
|
|
};
|
|
|
|
/**
|
|
* Decode a challenge issued by the server.
|
|
*
|
|
* @param {String} chal
|
|
* @api public
|
|
*/
|
|
Mechanism.prototype.challenge = function(chal) {
|
|
};
|
|
|
|
exports = module.exports = Mechanism;
|
|
|
|
}));
|
|
|
|
},{}],82:[function(require,module,exports){
|
|
(function(root, factory) {
|
|
if (typeof exports === 'object') {
|
|
// CommonJS
|
|
factory(exports,
|
|
module,
|
|
require('./lib/mechanism'));
|
|
} else if (typeof define === 'function' && define.amd) {
|
|
// AMD
|
|
define(['exports',
|
|
'module',
|
|
'./lib/mechanism'], factory);
|
|
}
|
|
}(this, function(exports, module, Mechanism) {
|
|
|
|
exports = module.exports = Mechanism;
|
|
exports.Mechanism = Mechanism;
|
|
|
|
}));
|
|
|
|
},{"./lib/mechanism":81}],83:[function(require,module,exports){
|
|
(function(root, factory) {
|
|
if (typeof exports === 'object') {
|
|
// CommonJS
|
|
factory(exports, module);
|
|
} else if (typeof define === 'function' && define.amd) {
|
|
// AMD
|
|
define(['exports', 'module'], factory);
|
|
}
|
|
}(this, function(exports, module) {
|
|
|
|
/**
|
|
* PLAIN `Mechanism` constructor.
|
|
*
|
|
* This class implements the PLAIN SASL mechanism.
|
|
*
|
|
* The PLAIN SASL mechanism provides support for exchanging a clear-text
|
|
* username and password. This mechanism should not be used without adequate
|
|
* security provided by an underlying transport layer.
|
|
*
|
|
* References:
|
|
* - [RFC 4616](http://tools.ietf.org/html/rfc4616)
|
|
*
|
|
* @api public
|
|
*/
|
|
function Mechanism() {
|
|
}
|
|
|
|
Mechanism.prototype.name = 'PLAIN';
|
|
Mechanism.prototype.clientFirst = true;
|
|
|
|
/**
|
|
* Encode a response using given credential.
|
|
*
|
|
* Options:
|
|
* - `username`
|
|
* - `password`
|
|
* - `authzid` authorization identity (optional)
|
|
*
|
|
* @param {Object} cred
|
|
* @api public
|
|
*/
|
|
Mechanism.prototype.response = function(cred) {
|
|
var str = '';
|
|
str += cred.authzid || '';
|
|
str += '\0';
|
|
str += cred.username;
|
|
str += '\0';
|
|
str += cred.password;
|
|
return str;
|
|
};
|
|
|
|
/**
|
|
* Decode a challenge issued by the server.
|
|
*
|
|
* @param {String} chal
|
|
* @return {Mechanism} for chaining
|
|
* @api public
|
|
*/
|
|
Mechanism.prototype.challenge = function(chal) {
|
|
return this;
|
|
};
|
|
|
|
exports = module.exports = Mechanism;
|
|
|
|
}));
|
|
|
|
},{}],84:[function(require,module,exports){
|
|
(function(root, factory) {
|
|
if (typeof exports === 'object') {
|
|
// CommonJS
|
|
factory(exports,
|
|
module,
|
|
require('./lib/mechanism'));
|
|
} else if (typeof define === 'function' && define.amd) {
|
|
// AMD
|
|
define(['exports',
|
|
'module',
|
|
'./lib/mechanism'], factory);
|
|
}
|
|
}(this, function(exports, module, Mechanism) {
|
|
|
|
exports = module.exports = Mechanism;
|
|
exports.Mechanism = Mechanism;
|
|
|
|
}));
|
|
|
|
},{"./lib/mechanism":83}],85:[function(require,module,exports){
|
|
(function(root, factory) {
|
|
if (typeof exports === 'object') {
|
|
// CommonJS
|
|
factory(exports, module, require('crypto'), require('buffer'));
|
|
} else if (typeof define === 'function' && define.amd) {
|
|
// AMD
|
|
define(['exports', 'module', 'crypto', 'buffer'], factory);
|
|
}
|
|
}(this, function(exports, module, crypto, buffer) {
|
|
|
|
var Buffer = buffer.Buffer;
|
|
|
|
/**
|
|
* SCRAM-SHA-1 `Mechanism` constructor.
|
|
*
|
|
* This class implements the SCRAM-SHA-1 SASL mechanism.
|
|
*
|
|
* References:
|
|
* - [RFC 5802](http://tools.ietf.org/html/rfc5802)
|
|
*
|
|
* @api public
|
|
*/
|
|
function Mechanism(options) {
|
|
options = options || {};
|
|
this._genNonce = options.genNonce || genNonce(32);
|
|
this._stage = 0;
|
|
}
|
|
|
|
Mechanism.prototype.name = 'SCRAM-SHA-1';
|
|
Mechanism.prototype.clientFirst = true;
|
|
|
|
/**
|
|
* Encode a response using given credentials.
|
|
*
|
|
* Options:
|
|
* - `username`
|
|
* - `password`
|
|
* - `authzid`
|
|
*
|
|
* @param {object} cred
|
|
* @api public
|
|
*/
|
|
Mechanism.prototype.response = function (cred) {
|
|
return responses[this._stage](this, cred);
|
|
};
|
|
|
|
/**
|
|
* Decode a challenge issued by the server.
|
|
*
|
|
* @param {String} chal
|
|
* @return {Mechanism} for chaining
|
|
* @api public
|
|
*/
|
|
Mechanism.prototype.challenge = function (chal) {
|
|
var values = parse(chal);
|
|
|
|
this._salt = new Buffer(values.s || '', 'base64').toString('binary');
|
|
this._iterationCount = parseInt(values.i, 10);
|
|
this._nonce = values.r;
|
|
this._verifier = values.v;
|
|
this._error = values.e;
|
|
this._challenge = chal;
|
|
|
|
return this;
|
|
};
|
|
|
|
|
|
var responses = {};
|
|
responses[0] = function (mech, cred) {
|
|
mech._cnonce = mech._genNonce();
|
|
|
|
var authzid = '';
|
|
if (cred.authzid) {
|
|
authzid = 'a=' + saslname(cred.authzid);
|
|
}
|
|
|
|
mech._gs2Header = 'n,' + authzid + ',';
|
|
|
|
var nonce = 'r=' + mech._cnonce;
|
|
var username = 'n=' + saslname(cred.username);
|
|
|
|
mech._clientFirstMessageBare = username + ',' + nonce;
|
|
var result = mech._gs2Header + mech._clientFirstMessageBare
|
|
|
|
mech._stage = 1;
|
|
|
|
return result;
|
|
};
|
|
responses[1] = function (mech, cred) {
|
|
var gs2Header = new Buffer(mech._gs2Header).toString('base64');
|
|
|
|
mech._clientFinalMessageWithoutProof = 'c=' + gs2Header + ',r=' + mech._nonce;
|
|
|
|
var saltedPassword = Hi(cred.password, mech._salt, mech._iterationCount);
|
|
var clientKey = HMAC(saltedPassword, 'Client Key');
|
|
var storedKey = H(clientKey);
|
|
var authMessage = mech._clientFirstMessageBare + ',' +
|
|
mech._challenge + ',' +
|
|
mech._clientFinalMessageWithoutProof;
|
|
var clientSignature = HMAC(storedKey, authMessage);
|
|
|
|
var xorstuff = XOR(clientKey, clientSignature);
|
|
|
|
var clientProof = new Buffer(xorstuff, 'binary').toString('base64');
|
|
var serverKey = HMAC(saltedPassword, 'Server Key');
|
|
|
|
mech._serverSignature = HMAC(serverKey, authMessage);
|
|
|
|
var result = mech._clientFinalMessageWithoutProof + ',p=' + clientProof;
|
|
|
|
mech._stage = 2;
|
|
|
|
return result;
|
|
};
|
|
responses[2] = function (mech, cred) {
|
|
// TODO: Signal errors
|
|
return '';
|
|
};
|
|
|
|
/**
|
|
* Create a SHA-1 HMAC.
|
|
*
|
|
* @param {String} key
|
|
* @param {String} msg
|
|
* @api private
|
|
*/
|
|
function HMAC(key, msg) {
|
|
return crypto.createHmac('sha1', key).update(msg).digest('binary');
|
|
}
|
|
|
|
/**
|
|
* Iteratively create an HMAC, with a salt.
|
|
*
|
|
* @param {String} text
|
|
* @param {String} salt
|
|
* @param {Number} iterations
|
|
* @api private
|
|
*/
|
|
function Hi(text, salt, iterations) {
|
|
var ui1 = HMAC(text, salt + '\0\0\0\1');
|
|
ui = ui1;
|
|
for (var i = 0; i < iterations - 1; i++) {
|
|
ui1 = HMAC(text, ui1);
|
|
ui = XOR(ui, ui1);
|
|
}
|
|
return ui;
|
|
}
|
|
|
|
/**
|
|
* Create a SHA-1 hash.
|
|
*
|
|
* @param {String} text
|
|
* @api private
|
|
*/
|
|
function H(text) {
|
|
return crypto.createHash('sha1').update(text).digest('binary');
|
|
}
|
|
|
|
/**
|
|
* String XOR
|
|
*
|
|
* @param {String} a
|
|
* @param {String} b
|
|
* @api private
|
|
*/
|
|
function XOR(a, b) {
|
|
a = new Buffer(a, 'binary');
|
|
b = new Buffer(b, 'binary');
|
|
|
|
var len = Math.min(a.length, b.length);
|
|
result = [];
|
|
for (var i = 0; i < len; i++) {
|
|
result.push(a[i] ^ b[i]);
|
|
}
|
|
result = new Buffer(result, 'binary');
|
|
return result.toString('binary');
|
|
}
|
|
|
|
/**
|
|
* Escape special characters in username values.
|
|
*
|
|
* @param {String} name
|
|
* @api private
|
|
*/
|
|
function saslname(name) {
|
|
var escaped = [];
|
|
var curr = '';
|
|
for (var i = 0; i < name.length; i++) {
|
|
curr = name[i];
|
|
if (curr === ',') {
|
|
escaped.push('=2C');
|
|
} else if (curr === '=') {
|
|
escaped.push('=3D');
|
|
} else {
|
|
escaped.push(curr);
|
|
}
|
|
}
|
|
return escaped.join('');
|
|
}
|
|
|
|
/**
|
|
* Parse challenge.
|
|
*
|
|
* @api private
|
|
*/
|
|
function parse(chal) {
|
|
var dtives = {};
|
|
var tokens = chal.split(/,(?=(?:[^"]|"[^"]*")*$)/);
|
|
for (var i = 0, len = tokens.length; i < len; i++) {
|
|
var dtiv = /(\w+)=["]?([^"]+)["]?$/.exec(tokens[i]);
|
|
if (dtiv) {
|
|
dtives[dtiv[1]] = dtiv[2];
|
|
}
|
|
}
|
|
return dtives;
|
|
}
|
|
|
|
|
|
/**
|
|
* Return a unique nonce with the given `len`.
|
|
*
|
|
* genNonce(10)();
|
|
* // => "FDaS435D2z"
|
|
*
|
|
* @param {Number} len
|
|
* @return {Function}
|
|
* @api private
|
|
*/
|
|
function genNonce(len) {
|
|
var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
|
var charlen = chars.length;
|
|
|
|
return function() {
|
|
var buf = [];
|
|
for (var i = 0; i < len; ++i) {
|
|
buf.push(chars[Math.random() * charlen | 0]);
|
|
}
|
|
return buf.join('');
|
|
}
|
|
}
|
|
|
|
exports = module.exports = Mechanism;
|
|
}));
|
|
|
|
},{"buffer":58,"crypto":60}],86:[function(require,module,exports){
|
|
(function(root, factory) {
|
|
if (typeof exports === 'object') {
|
|
// CommonJS
|
|
factory(exports,
|
|
module,
|
|
require('./lib/mechanism'));
|
|
} else if (typeof define === 'function' && define.amd) {
|
|
// AMD
|
|
define(['exports',
|
|
'module',
|
|
'./lib/mechanism'], factory);
|
|
}
|
|
}(this, function(exports, module, Mechanism) {
|
|
|
|
exports = module.exports = Mechanism;
|
|
exports.Mechanism = Mechanism;
|
|
|
|
}));
|
|
|
|
},{"./lib/mechanism":85}],87:[function(require,module,exports){
|
|
(function(root, factory) {
|
|
if (typeof exports === 'object') {
|
|
// CommonJS
|
|
factory(exports, module);
|
|
} else if (typeof define === 'function' && define.amd) {
|
|
// AMD
|
|
define(['exports', 'module'], factory);
|
|
}
|
|
}(this, function(exports, module) {
|
|
|
|
/**
|
|
* `Factory` constructor.
|
|
*
|
|
* @api public
|
|
*/
|
|
function Factory() {
|
|
this._mechs = [];
|
|
}
|
|
|
|
/**
|
|
* Utilize the given `mech` with optional `name`, overridding the mechanism's
|
|
* default name.
|
|
*
|
|
* Examples:
|
|
*
|
|
* factory.use(FooMechanism);
|
|
*
|
|
* factory.use('XFOO', FooMechanism);
|
|
*
|
|
* @param {String|Mechanism} name
|
|
* @param {Mechanism} mech
|
|
* @return {Factory} for chaining
|
|
* @api public
|
|
*/
|
|
Factory.prototype.use = function(name, mech) {
|
|
if (!mech) {
|
|
mech = name;
|
|
name = mech.prototype.name;
|
|
}
|
|
this._mechs.push({ name: name, mech: mech });
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Create a new mechanism from supported list of `mechs`.
|
|
*
|
|
* If no mechanisms are supported, returns `null`.
|
|
*
|
|
* Examples:
|
|
*
|
|
* var mech = factory.create(['FOO', 'BAR']);
|
|
*
|
|
* @param {Array} mechs
|
|
* @return {Mechanism}
|
|
* @api public
|
|
*/
|
|
Factory.prototype.create = function(mechs) {
|
|
for (var i = 0, len = this._mechs.length; i < len; i++) {
|
|
for (var j = 0, jlen = mechs.length; j < jlen; j++) {
|
|
var entry = this._mechs[i];
|
|
if (entry.name == mechs[j]) {
|
|
return new entry.mech();
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
|
|
exports = module.exports = Factory;
|
|
|
|
}));
|
|
|
|
},{}],88:[function(require,module,exports){
|
|
(function(root, factory) {
|
|
if (typeof exports === 'object') {
|
|
// CommonJS
|
|
factory(exports,
|
|
module,
|
|
require('./lib/factory'));
|
|
} else if (typeof define === 'function' && define.amd) {
|
|
// AMD
|
|
define(['exports',
|
|
'module',
|
|
'./lib/factory'], factory);
|
|
}
|
|
}(this, function(exports, module, Factory) {
|
|
|
|
exports = module.exports = Factory;
|
|
exports.Factory = Factory;
|
|
|
|
}));
|
|
|
|
},{"./lib/factory":87}],89:[function(require,module,exports){
|
|
/*
|
|
WildEmitter.js is a slim little event emitter by @henrikjoreteg largely based
|
|
on @visionmedia's Emitter from UI Kit.
|
|
|
|
Why? I wanted it standalone.
|
|
|
|
I also wanted support for wildcard emitters like this:
|
|
|
|
emitter.on('*', function (eventName, other, event, payloads) {
|
|
|
|
});
|
|
|
|
emitter.on('somenamespace*', function (eventName, payloads) {
|
|
|
|
});
|
|
|
|
Please note that callbacks triggered by wildcard registered events also get
|
|
the event name as the first argument.
|
|
*/
|
|
module.exports = WildEmitter;
|
|
|
|
function WildEmitter() {
|
|
this.callbacks = {};
|
|
}
|
|
|
|
// Listen on the given `event` with `fn`. Store a group name if present.
|
|
WildEmitter.prototype.on = function (event, groupName, fn) {
|
|
var hasGroup = (arguments.length === 3),
|
|
group = hasGroup ? arguments[1] : undefined,
|
|
func = hasGroup ? arguments[2] : arguments[1];
|
|
func._groupName = group;
|
|
(this.callbacks[event] = this.callbacks[event] || []).push(func);
|
|
return this;
|
|
};
|
|
|
|
// Adds an `event` listener that will be invoked a single
|
|
// time then automatically removed.
|
|
WildEmitter.prototype.once = function (event, groupName, fn) {
|
|
var self = this,
|
|
hasGroup = (arguments.length === 3),
|
|
group = hasGroup ? arguments[1] : undefined,
|
|
func = hasGroup ? arguments[2] : arguments[1];
|
|
function on() {
|
|
self.off(event, on);
|
|
func.apply(this, arguments);
|
|
}
|
|
this.on(event, group, on);
|
|
return this;
|
|
};
|
|
|
|
// Unbinds an entire group
|
|
WildEmitter.prototype.releaseGroup = function (groupName) {
|
|
var item, i, len, handlers;
|
|
for (item in this.callbacks) {
|
|
handlers = this.callbacks[item];
|
|
for (i = 0, len = handlers.length; i < len; i++) {
|
|
if (handlers[i]._groupName === groupName) {
|
|
//console.log('removing');
|
|
// remove it and shorten the array we're looping through
|
|
handlers.splice(i, 1);
|
|
i--;
|
|
len--;
|
|
}
|
|
}
|
|
}
|
|
return this;
|
|
};
|
|
|
|
// Remove the given callback for `event` or all
|
|
// registered callbacks.
|
|
WildEmitter.prototype.off = function (event, fn) {
|
|
var callbacks = this.callbacks[event],
|
|
i;
|
|
|
|
if (!callbacks) return this;
|
|
|
|
// remove all handlers
|
|
if (arguments.length === 1) {
|
|
delete this.callbacks[event];
|
|
return this;
|
|
}
|
|
|
|
// remove specific handler
|
|
i = callbacks.indexOf(fn);
|
|
callbacks.splice(i, 1);
|
|
return this;
|
|
};
|
|
|
|
// Emit `event` with the given args.
|
|
// also calls any `*` handlers
|
|
WildEmitter.prototype.emit = function (event) {
|
|
var args = [].slice.call(arguments, 1),
|
|
callbacks = this.callbacks[event],
|
|
specialCallbacks = this.getWildcardCallbacks(event),
|
|
i,
|
|
len,
|
|
item;
|
|
|
|
if (callbacks) {
|
|
for (i = 0, len = callbacks.length; i < len; ++i) {
|
|
if (callbacks[i]) {
|
|
callbacks[i].apply(this, args);
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (specialCallbacks) {
|
|
for (i = 0, len = specialCallbacks.length; i < len; ++i) {
|
|
if (specialCallbacks[i]) {
|
|
specialCallbacks[i].apply(this, [event].concat(args));
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
// Helper for for finding special wildcard event handlers that match the event
|
|
WildEmitter.prototype.getWildcardCallbacks = function (eventName) {
|
|
var item,
|
|
split,
|
|
result = [];
|
|
|
|
for (item in this.callbacks) {
|
|
split = item.split('*');
|
|
if (item === '*' || (split.length === 2 && eventName.slice(0, split[1].length) === split[1])) {
|
|
result = result.concat(this.callbacks[item]);
|
|
}
|
|
}
|
|
return result;
|
|
};
|
|
|
|
},{}],90:[function(require,module,exports){
|
|
var global=self;/**
|
|
* @license
|
|
* Lo-Dash 1.3.1 (Custom Build) lodash.com/license
|
|
* Build: `lodash include="each,unique,extend"`
|
|
* Underscore.js 1.4.4 underscorejs.org/LICENSE
|
|
*/
|
|
;(function(G){function H(a,d,b){b=(b||0)-1;for(var c=a.length;++b<c;)if(a[b]===d)return b;return-1}function pa(a,d){var b=typeof d;a=a.k;if("boolean"==b||null==d)return a[d];"number"!=b&&"string"!=b&&(b="object");var c="number"==b?d:Z+d;a=a[b]||(a[b]={});return"object"==b?a[c]&&-1<H(a[c],d)?0:-1:a[c]?0:-1}function qa(a){var d=this.k,b=typeof a;if("boolean"==b||null==a)d[a]=!0;else{"number"!=b&&"string"!=b&&(b="object");var c="number"==b?a:Z+a,e=d[b]||(d[b]={});if("object"==b){if((e[c]||(e[c]=[])).push(a)==
|
|
this.b.length)d[b]=!1}else e[c]=!0}}function P(){return Q.pop()||{a:"",b:null,c:"",k:null,"false":!1,d:"",e:"",f:"","null":!1,number:null,object:null,push:null,g:null,string:null,h:"","true":!1,undefined:!1,i:!1,j:!1}}function $(a){return typeof a.toString!="function"&&typeof(a+"")=="string"}function y(a){a.length=0;z.length<aa&&z.push(a)}function I(a){var d=a.k;d&&I(d);a.b=a.k=a.object=a.number=a.string=null;Q.length<aa&&Q.push(a)}function f(){}function J(){var a=P();a.g=R;a.b=a.c=a.f=a.h="";a.e=
|
|
"r";a.i=!0;a.j=!!K;for(var d,b=0;d=arguments[b];b++)for(var c in d)a[c]=d[c];b=a.a;a.d=/^[^,]+/.exec(b)[0];d=Function;b="return function("+b+"){";c="var m,r="+a.d+",C="+a.e+";if(!r)return C;"+a.h+";";a.b?(c+="var s=r.length;m=-1;if("+a.b+"){",h.unindexedChars&&(c+="if(q(r)){r=r.split('')}"),c+="while(++m<s){"+a.f+";}}else{"):h.nonEnumArgs&&(c+="var s=r.length;m=-1;if(s&&n(r)){while(++m<s){m+='';"+a.f+";}}else{");h.enumPrototypes&&(c+="var E=typeof r=='function';");h.enumErrorProps&&(c+="var D=r===j||r instanceof Error;");
|
|
var e=[];h.enumPrototypes&&e.push('!(E&&m=="prototype")');h.enumErrorProps&&e.push('!(D&&(m=="message"||m=="name"))');if(a.i&&a.j)c+="var A=-1,B=z[typeof r]&&t(r),s=B?B.length:0;while(++A<s){m=B[A];",e.length&&(c+="if("+e.join("&&")+"){"),c+=a.f+";",e.length&&(c+="}"),c+="}";else if(c+="for(m in r){",a.i&&e.push("l.call(r, m)"),e.length&&(c+="if("+e.join("&&")+"){"),c+=a.f+";",e.length&&(c+="}"),c+="}",h.nonEnumShadows){c+="if(r!==y){var h=r.constructor,p=r===(h&&h.prototype),e=r===H?G:r===j?i:J.call(r),v=w[e];";
|
|
for(k=0;7>k;k++)c+="m='"+a.g[k]+"';if((!(p&&v[m])&&l.call(r,m))",a.i||(c+="||(!v[m]&&r[m]!==y[m])"),c+="){"+a.f+"}";c+="}"}if(a.b||h.nonEnumArgs)c+="}";c+=a.c+";return C";d=d("i,j,l,n,o,q,t,u,y,z,w,G,H,J",b+c+"}");I(a);return d(ba,S,q,v,T,ca,K,f,A,B,l,L,ra,t)}function v(a){return t.call(a)==U}function w(a,d,b,c,e,r){var M=b===da;if(typeof b=="function"&&!M){b=f.createCallback(b,c,2);var n=b(a,d);if(typeof n!="undefined")return!!n}if(a===d)return 0!==a||1/a==1/d;var m=typeof a,g=typeof d;if(a===a&&
|
|
(!a||"function"!=m&&"object"!=m)&&(!d||"function"!=g&&"object"!=g))return!1;if(null==a||null==d)return a===d;g=t.call(a);m=t.call(d);g==U&&(g=C);m==U&&(m=C);if(g!=m)return!1;switch(g){case ea:case fa:return+a==+d;case ga:return a!=+a?d!=+d:0==a?1/a==1/d:a==+d;case ha:case L:return a==String(d)}m=g==V;if(!m){if(q.call(a,"__wrapped__")||q.call(d,"__wrapped__"))return w(a.__wrapped__||a,d.__wrapped__||d,b,c,e,r);if(g!=C||!h.nodeClass&&($(a)||$(d)))return!1;var g=!h.argsObject&&v(a)?Object:a.constructor,
|
|
u=!h.argsObject&&v(d)?Object:d.constructor;if(g!=u&&(!D(g)||!(g instanceof g&&D(u)&&u instanceof u)))return!1}u=!e;e||(e=z.pop()||[]);r||(r=z.pop()||[]);for(g=e.length;g--;)if(e[g]==a)return r[g]==d;var l=0,n=!0;e.push(a);r.push(d);if(m){g=a.length;l=d.length;n=l==a.length;if(!n&&!M)return n;for(;l--;)if(m=g,u=d[l],M)for(;m--&&!(n=w(a[m],u,b,c,e,r)););else if(!(n=w(a[l],u,b,c,e,r)))break;return n}W(d,function(d,f,g){if(q.call(g,f))return l++,n=q.call(a,f)&&w(a[f],d,b,c,e,r)});n&&!M&&W(a,function(a,
|
|
b,c){if(q.call(c,b))return n=-1<--l});u&&(y(e),y(r));return n}function D(a){return typeof a=="function"}function ia(a){return!(!a||!B[typeof a])}function ca(a){return typeof a=="string"||t.call(a)==L}function ja(a,d,b){if(d&&typeof b=="undefined"&&T(a)){b=-1;for(var c=a.length;++b<c&&false!==d(a[b],b,a););}else sa(a,d,b);return a}function ka(a,d,b){if(typeof b=="number"){var c=a?a.length:0;b=0>b?ta(0,c+b):b||0}else if(b)return b=la(a,d),a[b]===d?b:-1;return a?H(a,d,b):-1}function la(a,d,b,c){var e=0,r=
|
|
a?a.length:e;b=b?f.createCallback(b,c,1):X;for(d=b(d);e<r;)c=e+r>>>1,b(a[c])<d?e=c+1:r=c;return e}function X(a){return a}var z=[],Q=[],da={},Z=+new Date+"",aa=40,E=(E=/\bthis\b/)&&E.test(function(){return this})&&E,R="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),U="[object Arguments]",V="[object Array]",ea="[object Boolean]",fa="[object Date]",ba="[object Error]",ga="[object Number]",C="[object Object]",ha="[object RegExp]",L="[object String]",
|
|
B={"boolean":!1,"function":!0,object:!0,number:!1,string:!1,undefined:!1},N=B[typeof exports]&&exports,ma=B[typeof module]&&module&&module.exports==N&&module,s=B[typeof global]&&global;if(s&&(s.global===s||s.window===s))G=s;var S=Error.prototype,A=Object.prototype,ra=String.prototype,s=RegExp("^"+String(A.valueOf).replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/valueOf|for [^\]]+/g,".+?")+"$"),ua=Function.prototype.toString,q=A.hasOwnProperty,Y=A.propertyIsEnumerable,t=A.toString,F=s.test(F=t.bind)&&
|
|
F,p=s.test(p=Object.create)&&p,x=s.test(x=Array.isArray)&&x,O=s.test(O=Object.keys)&&O,ta=Math.max,p=s.test(G.attachEvent),va=F&&!/\n|true/.test(F+p),l={};l[V]=l[fa]=l[ga]={constructor:!0,toLocaleString:!0,toString:!0,valueOf:!0};l[ea]=l[L]={constructor:!0,toString:!0,valueOf:!0};l[ba]=l["[object Function]"]=l[ha]={constructor:!0,toString:!0};l[C]={constructor:!0};(function(){for(var a=R.length;a--;){var d=R[a],b;for(b in l)q.call(l,b)&&!q.call(l[b],d)&&(l[b][d]=!1)}})();var h=f.support={};(function(){var a=
|
|
function(){this.x=1},d=[];a.prototype={valueOf:1,y:1};for(var b in new a)d.push(b);for(b in arguments);h.argsObject=arguments.constructor==Object&&!(arguments instanceof Array);h.argsClass=v(arguments);h.enumErrorProps=Y.call(S,"message")||Y.call(S,"name");h.enumPrototypes=Y.call(a,"prototype");h.fastBind=F&&!va;h.nonEnumArgs=0!=b;h.nonEnumShadows=!/valueOf/.test(d);h.unindexedChars="xx"!="x"[0]+Object("x")[0];try{h.nodeClass=!(t.call(document)==C&&!({toString:0}+""))}catch(c){h.nodeClass=!0}})(1);var na={a:"x,F,k",
|
|
h:"var a=arguments,b=0,c=typeof k=='number'?2:a.length;while(++b<c){r=a[b];if(r&&z[typeof r]){",f:"if(typeof C[m]=='undefined')C[m]=r[m]",c:"}}"},p={a:"f,d,I",h:"d=d&&typeof I=='undefined'?d:u.createCallback(d,I)",b:"typeof s=='number'",f:"if(d(r[m],m,f)===false)return C"},s={h:"if(!z[typeof r])return C;"+p.h,b:!1};h.argsClass||(v=function(a){return a?q.call(a,"callee"):!1});var T=x||function(a){return a?typeof a=="object"&&t.call(a)==V:!1},oa=J({a:"x",e:"[]",h:"if(!(z[typeof x]))return C",f:"C.push(m)"}),
|
|
K=!O?oa:function(a){return!ia(a)?[]:h.enumPrototypes&&typeof a=="function"||h.nonEnumArgs&&a.length&&v(a)?oa(a):O(a)},sa=J(p),x=J(na,{h:na.h.replace(";",";if(c>3&&typeof a[c-2]=='function'){var d=u.createCallback(a[--c-1],a[c--],2)}else if(c>2&&typeof a[c-1]=='function'){d=a[--c]}"),f:"C[m]=d?d(C[m],r[m]):r[m]"}),W=J(p,s,{i:!1});D(/x/)&&(D=function(a){return typeof a=="function"&&"[object Function]"==t.call(a)});p=function(a){return function(d,b,c,e){typeof b!="boolean"&&null!=b&&(e=c,c=!(e&&e[b]===
|
|
d)?b:void 0,b=!1);null!=c&&(c=f.createCallback(c,e));return a(d,b,c,e)}}(function(a,d,b){var c=-1,e;e=(e=f.indexOf)===ka?H:e;var r=a?a.length:0,h=[],n=!d&&75<=r&&e===H,m=b||n?z.pop()||[]:h;if(n){var g;g=m;var l=-1,s=g.length,p=P();p["false"]=p["null"]=p["true"]=p.undefined=!1;var q=P();q.b=g;q.k=p;for(q.push=qa;++l<s;)q.push(g[l]);(g=false===p.object?(I(q),null):q)?(e=pa,m=g):(n=!1,m=b?m:(y(m),h))}for(;++c<r;)if(g=a[c],l=b?b(g,c,a):g,d?!c||m[m.length-1]!==l:0>e(m,l))(b||n)&&m.push(l),h.push(g);n?(y(m.b),
|
|
I(m)):b&&y(m);return h});f.assign=x;f.createCallback=function(a,d,b){if(null==a)return X;var c=typeof a;if("function"!=c){if("object"!=c)return function(b){return b[a]};var e=K(a);return function(b){for(var c=e.length,d=!1;c--&&(d=w(b[e[c]],a[e[c]],da)););return d}}return typeof d=="undefined"||E&&!E.test(ua.call(a))?a:1===b?function(b){return a.call(d,b)}:2===b?function(b,c){return a.call(d,b,c)}:4===b?function(b,c,e,f){return a.call(d,b,c,e,f)}:function(b,c,e){return a.call(d,b,c,e)}};f.forEach=
|
|
ja;f.forIn=W;f.keys=K;f.uniq=p;f.each=ja;f.extend=x;f.unique=p;f.identity=X;f.indexOf=ka;f.isArguments=v;f.isArray=T;f.isEqual=w;f.isFunction=D;f.isObject=ia;f.isString=ca;f.sortedIndex=la;f.VERSION="1.3.1";typeof define=="function"&&typeof define.amd=="object"&&define.amd?(G._=f, define(function(){return f})):N&&!N.nodeType?ma?(ma.exports=f)._=f:N._=f:G._=f})(this);
|
|
},{}]},{},[1])(1)
|
|
});
|
|
; |