-1) {
searchResult = "";
} else {
searchResult = this.highlight(searchResult, searchResult);
}
}
return searchResult;
}
},
/**
* Process the given string into an array of tokens where each token is
* either a search criteria or an operator (AND or OR). Also makes each
* search criteria token lowercase, so that searches will be case-
* insensitive.
*
* @param {String} queryString The string to tokenize.
*
* @return {String} The tokenized string
*/
processQueryString: {
value: function(queryString) {
if (!queryString) {
return;
}
queryString = queryString + "";
queryString = queryString.replace(/\&\&/g, " AND ").replace(/\|\|/g, " OR ");
this.debug(" Normalized query string, " + queryString);
// Split on spaces
var queryArray = queryString.split(/ +/);
// Create an array of tokens out of the query string where each token is
// either a search criteria or an operator (AND or OR).
var queryTokens = [];
var currentString = "";
for (var i in queryArray) {
var currentItem = queryArray[i].trim();
if (currentItem.length <= 0) {
break;
} else if ((currentItem === "AND") || (currentItem === "OR")) {
queryTokens.push(currentString);
queryTokens.push(currentItem);
currentString = "";
} else if (currentString) {
/* toLowerCase introduces a bug in search where camel case fields loose their capitals, then cant be matched with fields in the map reduce results */
currentString = currentString + " " + currentItem; //.toLowerCase();
} else {
currentString = currentItem; //.toLowerCase();
}
}
queryTokens.push(currentString);
this.debug(" Tokenized query string, ", queryTokens);
return queryTokens;
}
},
getDisplayableFieldForActivitiesEtc: {
value: function() {
return this.model.fields.where({
label: "utterance"
})[0].get("mask");
}
},
/**
* Clone the current Datum and return the clone. The clone is put in the current
* Session, regardless of the origin Datum's Session. //TODO it doesn tlook liek this is the case below:
*
* @return The clone of the current Datum.
*/
cloneDeprecated: {
value: function() {
// Create a new Datum based on the current Datum
var datum = new Datum({
audioVideo: new AudioVideos(this.get("audioVideo").toJSON(), {
parse: true
}),
comments: new Comments(this.get("comments").toJSON(), {
parse: true
}),
dateEntered: this.get("dateEntered"),
dateModified: this.get("dateModified"),
fields: new DatumFields(this.fields.toJSON(), {
parse: true
}),
datumStates: new DatumStates(this.get("datumStates").toJSON(), {
parse: true
}),
datumTags: new DatumTags(this.get("datumTags").toJSON(), {
parse: true
}),
dbname: this.dbname,
session: this.get("session")
});
return datum;
}
},
/**
* This function is used to get the most prominent datumstate (now called
* ValidationStatus) eg "CheckedWithSeberina" or "Deleted" or "ToBeChecked"
*
* @returns {String} a string which is the first item in the
* validationSatuts field
*/
getValidationStatus: {
value: function() {
var validationStatus = "";
var stati = this.fields.where({
"label": "validationStatus"
});
if (stati.length > 0) {
stati = stati[0].get("mask").split(" ");
if (stati.length > 0) {
validationStatus = stati[0];
}
}
/* Handle upgrade from previous corpora look in datum states too */
if (validationStatus === "") {
stati = this.get("datumStates").where({
selected: "selected"
});
if (stati.length > 0) {
validationStatus = stati[0].get("state");
}
}
this.updateDatumState(validationStatus);
return validationStatus;
}
},
/**
* This function is used to colour a datum background to make
* visually salient the validation status of the datum.
*
* @param status
* This is an optional string which is used to find the
* colour for a particular DatumState. If the string is
* not provided it gets the first element from the
* validation status field.
* @returns {String} This is the colour using Bootstrap (warning is
* Orange, success Green etc.)
*/
getValidationStatusColor: {
value: function(status) {
if (!status) {
status = this.getValidationStatus();
}
/* TODO once the new ValidationStatus pattern is in the corpus proper, dont hard code the colors */
if (status.toLowerCase().indexOf("deleted") > -1) {
return "danger";
}
if (status.toLowerCase().indexOf("tobechecked") > -1) {
return "warning";
}
if (status.toLowerCase().indexOf("checked") > -1) {
return "success";
}
}
},
/**
* This function is used to set the primary status of the datum,
* eg. put Deleted as the first item in the validation status.
*
* @param selectedValue
* This is a string which is the validation status
* you want the datum to be
*/
updateDatumState: {
value: function(selectedValue) {
if (!selectedValue) {
return;
}
this.debug("Asking to change the datum state to " + selectedValue);
/* make sure all the corpus states are availible in this datum */
var thisdatumStates = this.get("datumStates");
window.app.corpus.get("datumStates").each(function(datumstate) {
var obj = datumstate.toJSON();
obj.selected = "";
thisdatumStates.addIfNew(obj);
});
try {
$.each(this.get("datumStates").where({
selected: "selected"
}), function() {
if (this.get("state") !== selectedValue) {
this.set("selected", "");
}
});
this.get("datumStates").where({
state: selectedValue
})[0].set("selected", "selected");
} catch (e) {
this.debug("problem getting color of datum state, probaly none are selected.", e);
}
/* prepend this state to the new validationStates as of v1.46.2 */
var n = this.fields.where({
label: "validationStatus"
})[0];
if (n === [] || !n) {
n = new DatumField({
label: "validationStatus",
shouldBeEncrypted: "",
showToUserTypes: "all",
userchooseable: "disabled",
help: "Any number of status of validity (replaces DatumStates). For example: ToBeCheckedWithSeberina, CheckedWithRicardo, Deleted etc..."
});
this.fields.add(n);
}
var validationStatus = n.get("mask") || "";
validationStatus = selectedValue + " " + validationStatus;
var uniqueStati = _.unique(validationStatus.trim().split(" "));
n.set("mask", uniqueStati.join(" "));
// this.save();
//TODO save it
}
},
/**
* Make the model marked as Deleted, mapreduce function will
* ignore the deleted models so that it does not show in the app,
* but deleted model remains in the database until the admin empties
* the trash.
*
* Also remove it from the view so the user cant see it.
*
*/
putInTrash: {
value: function() {
this.set("trashed", "deleted" + Date.now());
this.updateDatumState("Deleted");
this.saveAndInterConnectInApp(function() {
/* This actually removes it from the database */
//thisdatum.destroy();
if (window.appView) {
window.appView.datumsEditView.showMostRecentDatum();
}
});
}
},
/**
* The LaTeXiT function automatically mark-ups an example in LaTeX code
* (\exg. \"a) and then copies it on the export modal so that when the user
* switches over to their LaTeX file they only need to paste it in.
*
* We did a poll on Facebook among EGGers, and other linguists we know and
* found that Linguex was very popular, and GB4E, so we did the export in
* GB4E.
*/
/* jshint ignore:start */
laTeXiT: {
value: function(showInExportModal) {
this.debug(showInExportModal);
//corpus's most frequent fields
var frequentFields;
if (this.application && this.application.corpus && this.application.corpus.frequentFields) {
frequentFields = this.application.corpus.frequentFields;
} else {
frequentFields = this.fields.map(function(field) {
return field.id
});
}
//this datum/datalist's datumfields and their names
var fields = this.fields.map(function(field) {
return field.value;
});
var fieldLabels = this.fields.map(function(field) {
return field.id;
});
//setting up for IGT case...
var judgementIndex = -1;
var judgement = "";
var utteranceIndex = -1;
var utterance = "";
var morphemesIndex = -1;
var morphemes = "";
var glossIndex = -1;
var gloss = "";
var translationIndex = -1;
var translation = "";
var result = "\n\\begin{exe} \n \\ex \[";
//IGT case:
if (this.datumIsInterlinearGlossText()) {
/* get the key pieces of the IGT and delete them from the fields and fieldLabels arrays*/
judgementIndex = fieldLabels.indexOf("judgement");
if (judgementIndex >= 0) {
judgement = fields[judgementIndex];
fieldLabels.splice(judgementIndex, 1);
fields.splice(judgementIndex, 1);
}
utteranceIndex = fieldLabels.indexOf("utterance");
if (utteranceIndex >= 0) {
utterance = fields[utteranceIndex];
fieldLabels.splice(utteranceIndex, 1);
fields.splice(utteranceIndex, 1);
}
morphemesIndex = fieldLabels.indexOf("morphemes");
if (morphemesIndex >= 0) {
morphemes = fields[morphemesIndex];
fieldLabels.splice(morphemesIndex, 1);
fields.splice(morphemesIndex, 1);
}
glossIndex = fieldLabels.indexOf("gloss");
if (glossIndex >= 0) {
gloss = fields[glossIndex];
fieldLabels.splice(glossIndex, 1);
fields.splice(glossIndex, 1);
}
translationIndex = fieldLabels.indexOf("translation");
if (translationIndex >= 0) {
translation = fields[translationIndex];
fieldLabels.splice(translationIndex, 1);
fields.splice(translationIndex, 1);
}
//print the main IGT, escaping special latex chars
/* ignore unnecessary escapement */
result = result + this.escapeLatexChars(judgement) + "\]\{" + this.escapeLatexChars(utterance) +
"\n \\gll " + this.escapeLatexChars(morphemes) + "\\\\" +
"\n " + this.escapeLatexChars(gloss) + "\\\\" +
"\n \\trans " + this.escapeLatexChars(translation) + "\}" +
"\n\\label\{\}";
}
//remove any empty fields from our arrays
for (var i = fields.length - 1; i >= 0; i--) {
if (!fields[i]) {
fields.splice(i, 1);
fieldLabels.splice(i, 1);
}
}
/*throughout this next section, print frequent fields and infrequent ones differently
frequent fields get latex'd as items in a description and infrequent ones are the same,
but commented out.*/
if (fields && (fields.length > 0)) {
var numInfrequent = 0;
for (var field in fields) {
if (frequentFields.indexOf(fieldLabels[field]) >= 0) {
break;
}
numInfrequent++;
}
if (numInfrequent !== fieldLabels.length) {
result = result + "\n \\begin\{description\}";
} else {
result = result + "\n% \\begin\{description\}";
}
for (field in fields) {
if (fields[field] && (frequentFields.indexOf(fieldLabels[field]) >= 0)) {
result = result + "\n \\item\[\\sc\{" + this.escapeLatexChars(fieldLabels[field]) + "\}\] " + this.escapeLatexChars(fields[field]);
} else if (fields[field]) {
/* If as a field that is designed for LaTex dont excape the LaTeX characters */
if (fieldLabels[field].toLowerCase().indexOf("latex") > -1) {
result = result + "\n " + fields[field];
} else {
result = result + "\n% \\item\[\\sc\{" + this.escapeLatexChars(fieldLabels[field]) + "\}\] " + this.escapeLatexChars(fields[field]);
}
}
}
if (numInfrequent !== fieldLabels.length) {
result = result + "\n \\end\{description\}";
} else {
result = result + "\n% \\end\{description\}";
}
}
result = result + "\n\\end{exe}\n\n";
return result;
}
},
/* jshint ignore:end */
latexitDataList: {
value: function(showInExportModal) {
//this version prints new data as well as previously shown latex'd data (best for datalists)
var result = this.laTeXiT(showInExportModal);
if (showInExportModal) {
$("#export-type-description").html(" as LaTeX (GB4E)");
$("#export-text-area").val($("#export-text-area").val() + result);
}
return result;
}
},
latexitDatum: {
value: function(showInExportModal) {
//this version prints new data and deletes previously shown latex'd data (best for datums)
var result = this.laTeXiT(showInExportModal);
if (showInExportModal) {
$("#export-type-description").html(" as LaTeX (GB4E)");
var latexDocument =
"\\documentclass[12pt]{article} \n" +
"\\usepackage{fullpage} \n" +
"\\usepackage{tipa} \n" +
"\\usepackage{qtree} \n" +
"\\usepackage{gb4e} \n" +
"\\begin{document} \n" + result +
"\\end{document}";
$("#export-text-area").val(latexDocument);
}
return result;
}
},
escapeLatexChars: {
value: function(input) {
var result = input;
//curly braces need to be escaped TO and escaped FROM, so we're using a placeholder
result = result.replace(/\\/g, "\\textbackslashCURLYBRACES");
result = result.replace(/\^/g, "\\textasciicircumCURLYBRACES");
result = result.replace(/\~/g, "\\textasciitildeCURLYBRACES");
result = result.replace(/#/g, "\\#");
result = result.replace(/\$/g, "\\$");
result = result.replace(/%/g, "\\%");
result = result.replace(/&/g, "\\&");
result = result.replace(/_/g, "\\_");
result = result.replace(/{/g, "\\{");
result = result.replace(/}/g, "\\}");
result = result.replace(//g, "\\textgreater");
result = result.replace(/CURLYBRACES/g, "{}");
return result;
}
},
datumIsInterlinearGlossText: {
value: function(fieldLabels) {
if (!fieldLabels) {
fieldLabels = this.fields.map(function(field) {
return field.id;
});
}
var utteranceOrMorphemes = false;
var gloss = false;
var trans = false;
for (var fieldLabel in fieldLabels) {
if (fieldLabels[fieldLabel] === "utterance" || fieldLabels[fieldLabel] === "morphemes") {
utteranceOrMorphemes = true;
}
if (fieldLabels[fieldLabel] === "gloss") {
gloss = true;
}
if (fieldLabels[fieldLabel] === "translation") {
trans = true;
}
}
if (gloss || utteranceOrMorphemes || trans) {
return true;
} else {
return false;
}
}
},
/**
* This function simply takes the utterance gloss and translation and puts
* them out as plain text so the user can do as they wish.
*/
exportAsPlainText: {
value: function(showInExportModal) {
// var header = _.pluck(this.fields.toJSON(), "label") || [];
var fields = this.fields.map(function(field) {
return field.value;
});
var result = fields.join("\n");
if (showInExportModal) {
$("#export-type-description").html(" as text (Word)");
$("#export-text-area").val(
$("#export-text-area").val() + result
);
}
return result;
}
},
/**
* This takes as an argument the order of fields and then creates a row of csv.
*/
exportAsCSV: {
value: function(showInExportModal, orderedFields, printheaderonly) {
var asFlatObject = this.accessAsObject,
header = orderedFields || [],
columns = [];
if (orderedFields) {
columns = orderedFields.map(function(fieldid) {
return asFlatObject[fieldid] || "";
});
} else {
for (var fieldlabel in asFlatObject) {
header.push(fieldlabel);
columns.push(asFlatObject[fieldlabel]);
}
}
if (printheaderonly) {
columns = header;
}
var result = columns.map(function(cell) {
return "\"" + cell.replace(/"/g, "\\\"") + "\"";
}).join(",") + "\n";
// if (orderedFields === null) {
// orderedFields = ["judgement","utterance","morphemes","gloss","translation"];
// }
// judgement = this.columns.where({label: "judgement"})[0].get("mask");
// morphemes = this.columns.where({label: "morphemes"})[0].get("mask");
// utterance= this.columns.where({label: "utterance"})[0].get("mask");
// gloss = this.columns.where({label: "gloss"})[0].get("mask");
// translation= this.columns.where({label: "translation"})[0].get("mask");
// var resultarray = [judgement,utterance,morphemes,gloss,translation];
// var result = '"' + resultarray.join('","') + '"\n';
if (showInExportModal) {
$("#export-type-description").html(" as CSV (Excel, Filemaker Pro)");
$("#export-text-area").val(
$("#export-text-area").val() + result);
}
return result;
}
},
/**
* Encrypts the datum if it is confidential
*
* @returns {Boolean}
*/
encrypt: {
value: function() {
this.set("confidential", true);
this.fields.each(function(dIndex) {
dIndex.set("encrypted", "checked");
});
//TODO scrub version history to get rid of all unencrypted versions.
this.saveAndInterConnectInApp(window.app.router.renderDashboardOrNot, window.app.router.renderDashboardOrNot);
}
},
/**
* Decrypts the datum if it was encrypted
*/
decrypt: {
value: function() {
this.set("confidential", false);
this.fields.each(function(dIndex) {
dIndex.set("encrypted", "");
});
}
},
/**
* Accepts two functions to call back when save is successful or
* fails. If the fail callback is not overridden it will alert
* failure to the user.
*
* - Adds the datum to the top of the default data list in the corpus if it is in the right corpus
* - Adds the datum to the datums container if it wasnt there already
* - Adds an activity to the logged in user with diff in what the user changed.
*
* @param successcallback
* @param failurecallback
*/
saveAndInterConnectInApp: {
value: function(successcallback, failurecallback) {
this.debug("Saving a Datum");
var self = this;
var newModel = true;
if (this.id) {
newModel = false;
} else {
this.set("dateEntered", JSON.stringify(new Date()));
}
//protect against users moving datums from one corpus to another on purpose or accidentially
if (window.app.corpus.dbname !== this.dbname) {
if (typeof failurecallback === "function") {
failurecallback();
} else {
self.bug("Datum save error. I cant save this datum in this corpus, it belongs to another corpus. ");
}
return;
}
//If it was decrypted, this will save the changes before we go into encryptedMode
this.fields.each(function(dIndex) {
//Anything can be done here, it is the set function which does all the work.
dIndex.set("value", dIndex.get("mask"));
});
// Store the current Session, the current corpus, and the current date
// in the Datum
this.set({
"dbname": window.app.corpus.dbname,
"dateModified": JSON.stringify(new Date()),
"timestamp": Date.now(),
"jsonType": "Datum"
});
if (!this.get("session")) {
this.set("session", window.app.get("currentSession"));
self.debug("Setting the session on this datum to the current one.");
} else {
self.debug("Not setting the session on this datum.");
}
window.app.corpus.set("dateOfLastDatumModifiedToCheckForOldSession", JSON.stringify(new Date()));
var oldrev = this.get("_rev");
/*
* For some reason the corpus is getting an extra state that no one defined in it.
* this gets rid of it when we save. (if it gets in to a datum)
*/
try {
var ds = this.get("datumStates").models;
for (var s in ds) {
if (ds[s].get("state") === undefined) {
this.get("datumStates").remove(ds[s]);
}
}
} catch (e) {
self.debug("Removing empty states work around failed some thing was wrong.", e);
}
self.save(null, {
success: function(model, response) {
self.debug("Datum save success");
var utterance = model.fields.where({
label: "utterance"
})[0].get("mask");
var differences = "#diff/oldrev/" + oldrev + "/newrev/" + response._rev;
//TODO add privacy for datum goals in corpus
// if(window.app.corpus.get("keepDatumDetailsPrivate")){
// utterance = "";
// differences = "";
// }
if (window.appView) {
window.appView.toastUser("Sucessfully saved datum: " + utterance, "alert-success", "Saved!");
window.appView.addSavedDoc(model.id);
}
var verb = "modified";
var verbicon = "icon-pencil";
if (newModel) {
verb = "added";
verbicon = "icon-plus";
}
window.app.addActivity({
verb: "" + verb + " ",
verbicon: verbicon,
directobject: "" + utterance + " ",
directobjecticon: "icon-list",
indirectobject: "in " + window.app.corpus.get("title") + "",
teamOrPersonal: "team",
context: " via Offline App."
});
window.app.addActivity({
verb: "" + verb + " ",
verbicon: verbicon,
directobject: "" + utterance + " ",
directobjecticon: "icon-list",
indirectobject: "in " + window.app.corpus.get("title") + "",
teamOrPersonal: "personal",
context: " via Offline App."
});
// /*
// * If the current data list is the default
// * list, render the datum there since is the "Active" copy
// * that will eventually overwrite the default in the
// * corpus if the user saves the current data list
// */
// var defaultIndex = window.app.corpus.datalists.length - 1;
// if(window.appView.currentEditDataListView.model.id === window.app.corpus.datalists.models[defaultIndex].id){
// //Put it into the current data list views
// window.appView.currentPaginatedDataListDatumsView.collection.remove(model);//take it out of where it was,
// window.appView.currentPaginatedDataListDatumsView.collection.unshift(model); //and put it on the top. this is only in the default data list
// //Put it into the ids of the current data list
// var positionInCurrentDataList = window.app.get("currentDataList").get("datumIds").indexOf(model.id);
// if(positionInCurrentDataList !== -1){
// window.app.get("currentDataList").get("datumIds").splice(positionInCurrentDataList, 1);
// }
// window.app.get("currentDataList").get("datumIds").unshift(model.id);
// window.appView.addUnsavedDoc(window.app.get("currentDataList").id);
// }else{
// /*
// * Make sure the datum is at the top of the default data list which is in the corpus,
// * this is in case the default data list is not being displayed
// */
// var positionInDefaultDataList = window.app.corpus.datalists.models[defaultIndex].get("datumIds").indexOf(model.id);
// if(positionInDefaultDataList !== -1 ){
// //We only reorder the default data list datum to be in the order of the most recent modified, other data lists can stay in the order teh usr designed them.
// window.app.corpus.datalists.models[defaultIndex].get("datumIds").splice(positionInDefaultDataList, 1);
// }
// window.app.corpus.datalists.models[defaultIndex].get("datumIds").unshift(model.id);
// window.app.corpus.datalists.models[defaultIndex].needsSave = true;
// window.appView.addUnsavedDoc(window.app.corpus.id);
// }
/*
* Also, see if this datum matches the search datalist, and add it to the top of the search list
*/
if ($("#search_box").val() !== "") {
//TODO check this
var datumJson = model.fields.toJSON();
var datumAsDBResponseRow = {};
for (var x in datumJson) {
datumAsDBResponseRow[datumJson[x].label] = datumJson[x].mask;
}
var queryTokens = self.processQueryString($("#search_box").val());
var thisDatumIsIn = self.matchesSingleCriteria(datumAsDBResponseRow, queryTokens[0]);
for (var j = 1; j < queryTokens.length; j += 2) {
if (queryTokens[j] === "AND") {
// Short circuit: if it's already false then it continues to be false
if (!thisDatumIsIn) {
break;
}
// Do an intersection
thisDatumIsIn = thisDatumIsIn && model.matchesSingleCriteria(datumAsDBResponseRow, queryTokens[j + 1]);
} else {
// Do a union
thisDatumIsIn = thisDatumIsIn || model.matchesSingleCriteria(datumAsDBResponseRow, queryTokens[j + 1]);
}
}
if (thisDatumIsIn) {
// Insert the datum at the top of the search datums collection view
window.appView.searchEditView.searchPaginatedDataListDatumsView.collection.remove(model); //take it out of where it was,
window.appView.searchEditView.searchPaginatedDataListDatumsView.collection.unshift(model);
//Do the same to the datumids in the search data list itself
var positioninsearchresults = window.appView.searchEditView.searchDataListView.model.get("datumIds").indexOf(model.id);
if (positioninsearchresults !== -1) {
window.appView.searchEditView.searchDataListView.model.get("datumIds").splice(positioninsearchresults, 1);
}
window.appView.searchEditView.searchDataListView.model.get("datumIds").unshift(model.id);
}
} //end of if search is open and running for Alan
//dont need to save the user every time when we change a datum.
// window.app.get("authentication").saveAndInterConnectInApp();
if (typeof successcallback === "function") {
successcallback();
}
},
error: function(e, f, g) {
self.debug("Datum save error", e, f, g);
if (typeof failurecallback === "function") {
failurecallback();
} else {
self.bug("Datum save error: " + f.reason);
}
}
});
}
},
/**
* Accepts two functions success will be called if sucessfull,
* otherwise it will attempt to render the current datum views. If
* the datum isn't in the current corpus it will call the fail
* callback or it will alert a bug to the user. Override the fail
* callback if you don't want the alert.
*
* @param successcallback
* @param failurecallback
* @deprecated
*/
setAsCurrentDatum: {
value: function() {
this.warn("Using deprected method setAsCurrentDatum.");
// if( window.app.corpus.dbname !== this.dbname ){
// if (typeof failurecallback === "function") {
// failurecallback();
// }else{
// self.bug("This is a bug, cannot load the datum you asked for, it is not in this corpus.");
// }
// return;
// }else{
// if (window.appView.datumsEditView.datumsView.collection.models[0].id !== this.id ) {
// window.appView.datumsEditView.datumsView.prependDatum(this);
// //TODO might not need to do it on the Read one since it is the same model?
// }
// if (typeof successcallback === "function") {
// successcallback();
// }
// }
}
},
/* highlight returns text with all instances of stringToHighlight enclosed
* in a span. Note that stringToHighlight is treated as a regexp.
*/
highlight: {
value: function(text, stringToHighlight, className) {
className = className || "highlight";
var re = new RegExp("(" + stringToHighlight + ")", "gi");
return text.replace(re, "$1");
}
},
toJSON: {
value: function(includeEvenEmptyAttributes, removeEmptyAttributes) {
this.debug("Customizing toJSON ", includeEvenEmptyAttributes, removeEmptyAttributes);
var json = FieldDBObject.prototype.toJSON.apply(this, arguments);
if (!json) {
this.warn("Not returning json right now.");
return;
}
this.debug("saving fields as the deprecated datumFields");
json.datumFields = json.fields;
delete json.fields;
this.debug(json);
return json;
}
}
});
exports.Datum = Datum;
},{"./../Collection":2,"./../FieldDBObject":3,"./../audio_video/AudioVideo":10,"./../audio_video/AudioVideos":12,"./../comment/Comments":16,"./../corpus/corpus.json":25,"./../image/Images":47,"./DatumField":32,"./DatumFields":33,"./DatumStates":35,"./DatumTags":37,"./Session":40}],32:[function(require,module,exports){
var FieldDBObject = require("./../FieldDBObject").FieldDBObject;
var Confidential = require("./../confidentiality_encryption/Confidential").Confidential;
/**
* @class The datum fields are the fields in the datum and session models.
* They can be freely added and should show up in the datum view
* according to frequency.
* @name DatumField
* @property size The size of the datum field refers to the width of the
* text area. Some of them, such as the judgment one will be very
* short, while others context can be infinitely long.
* @property label The label that is associated with the field, such as
* Transcription, Morphemes, etc.
* @property value This is what the user will enter when entering data into
* the data fields.
* @property mask This allows users to mask fields for confidentiality.
* @property shouldBeEncrypted This is whether the field is masked or not.
* @property help This is a pop up that tells other users how to use the
* field the user has created.
* @extends FieldDBObject
* @constructs
*/
var DatumField = function DatumField(options) {
if (!this._fieldDBtype) {
this._fieldDBtype = "DatumField";
}
this.debug("Constructing DatumField ", options);
// Let encryptedValue and value from serialization be set
if (options && options.encryptedValue) {
options._encryptedValue = options.encryptedValue;
}
if (options && options.value) {
options._value = options.value;
}
FieldDBObject.apply(this, arguments);
};
DatumField.prototype = Object.create(FieldDBObject.prototype, /** @lends DatumField.prototype */ {
constructor: {
value: DatumField
},
defaults: {
get: function() {
return {
id: Date.now(),
labelFieldLinguists: "",
labelPsychoLinguists: "",
labelExperimenters: "",
labelNonLinguists: "",
labelTranslators: "",
labelComputationalLinguist: "",
type: "",
shouldBeEncrypted: false,
showToUserTypes: "all",
defaultfield: false,
value: "",
mask: "",
encrypted: "",
json: {},
help: "Put your team's data entry conventions here (if any)...",
helpLinguists: "Put your team's data entry conventions here (if any)...",
helpNonLinguists: "Put your team's data entry conventions here (if any)...",
helpTranslators: "Put your team's data entry conventions here (if any)...",
ComputationalLinguists: "Put your team's data entry conventions here (if any)...",
helpDevelopers: "Put your team's data entry conventions here (if any)..."
};
},
set: function() {}
},
// Internal models: used by the parse function
internalModels: {
value: {} // There are no nested models
},
id: {
get: function() {
return this._id || FieldDBObject.DEFAULT_STRING;
},
set: function(value) {
if (value === this._id) {
return;
}
if (!value) {
delete this._id;
return;
}
if (value.trim) {
value = value.trim();
}
var originalValue = value + "";
value = this.sanitizeStringForPrimaryKey(value); //TODO dont do this on all objects
if (value === null) {
this.bug("Invalid id, not using " + originalValue + " id remains as " + this._id);
return;
}
this._id = value;
}
},
label: {
get: function() {
this.debug("label is deprecated, instead automatically contextualize a label for appropriate user eg labelFieldLinguists, labelNonLinguists, labelTranslators, labelComputationalLinguist");
return this._labelNonLinguists || this._labelFieldLinguists || this.id || FieldDBObject.DEFAULT_STRING;
},
set: function(value) {
this.debug("label is deprecated, instead automatically contextualize a label for appropriate user eg labelFieldLinguists, labelNonLinguists, labelTranslators, labelComputationalLinguist");
if (!this._labelFieldLinguists) {
if (value && value.length > 2) {
this._labelFieldLinguists = value[0].toUpperCase() + value.substring(1, value.length);
} else {
this._labelFieldLinguists = value;
}
}
if (!this._labelNonLinguists) {
if (value && value.length > 2) {
this._labelNonLinguists = value[0].toUpperCase() + value.substring(1, value.length);
} else {
this._labelNonLinguists = value;
}
}
if (!this._id) {
this.id = value;
}
}
},
userchooseable: {
get: function() {
this.debug("userchooseable is deprecated, instead use defaultfield");
return this.defaultfield;
},
set: function(value) {
this.debug("userchooseable is deprecated, instead use defaultfield");
if (value === "disabled") {
value = true;
}
if (!value) {
value = false;
}
this.defaultfield = value;
}
},
labelFieldLinguists: {
get: function() {
return this._labelFieldLinguists || this.label;
},
set: function(value) {
if (value === this._labelFieldLinguists) {
return;
}
if (!value) {
delete this._labelFieldLinguists;
return;
}
this._labelFieldLinguists = value.trim();
}
},
labelPsychoLinguists: {
get: function() {
return this._labelPsychoLinguists || this.labelFieldLinguists;
},
set: function(value) {
if (value === this._labelPsychoLinguists) {
return;
}
if (!value) {
delete this._labelPsychoLinguists;
return;
}
this._labelPsychoLinguists = value.trim();
}
},
labelExperimenters: {
get: function() {
return this._labelExperimenters || this.labelNonLinguists;
},
set: function(value) {
if (value === this._labelExperimenters) {
return;
}
if (!value) {
delete this._labelExperimenters;
return;
}
this._labelExperimenters = value.trim();
}
},
labelNonLinguists: {
get: function() {
return this._labelNonLinguists || this.label;
},
set: function(value) {
if (value === this._labelNonLinguists) {
return;
}
if (!value) {
delete this._labelNonLinguists;
return;
}
this._labelNonLinguists = value.trim();
}
},
labelTranslators: {
get: function() {
return this._labelTranslators || this.labelNonLinguists;
},
set: function(value) {
if (value === this._labelTranslators) {
return;
}
if (!value) {
delete this._labelTranslators;
return;
}
this._labelTranslators = value.trim();
}
},
labelComputationalLinguist: {
get: function() {
return this._labelComputationalLinguist || this.label;
},
set: function(value) {
if (value === this._labelComputationalLinguist) {
return;
}
if (!value) {
delete this._labelComputationalLinguist;
return;
}
this._labelComputationalLinguist = value.trim();
}
},
type: {
get: function() {
return this._type || FieldDBObject.DEFAULT_STRING;
},
set: function(value) {
if (value === this._type) {
return;
}
if (!value) {
delete this._type;
return;
}
this._type = value.trim();
}
},
shouldBeEncrypted: {
get: function() {
return this._shouldBeEncrypted || FieldDBObject.DEFAULT_FALSE;
},
set: function(value) {
this.verbose("Setting shouldBeEncrypted " + value, this);
if (value === this._shouldBeEncrypted) {
return;
}
if (value === "checked") {
value = true;
}
value = !!value;
this.verbose("Setting shouldBeEncrypted " + value, this);
if (this._shouldBeEncrypted === true && value === false) {
this.warn("This field's shouldBeEncrypted cannot be undone. Only a corpus administrator can change shouldBeEncrypted to false if it has been true before.");
return;
}
this._shouldBeEncrypted = value;
}
},
encrypted: {
get: function() {
return this._encrypted || FieldDBObject.DEFAULT_FALSE;
},
set: function(value) {
if (value === this._encrypted) {
return;
}
if (!value) {
delete this._encrypted;
return;
}
if (value === "checked") {
value = true;
}
this._encrypted = !!value;
}
},
showToUserTypes: {
get: function() {
return this._showToUserTypes || "all";
},
set: function(value) {
if (value === this._showToUserTypes) {
return;
}
if (!value) {
delete this._showToUserTypes;
return;
}
this._showToUserTypes = value.trim();
}
},
defaultfield: {
get: function() {
return this._defaultfield || FieldDBObject.DEFAULT_FALSE;
},
set: function(value) {
if (value === this._defaultfield) {
return;
}
if (!value) {
delete this._defaultfield;
return;
}
this._defaultfield = !!value;
}
},
repairMissingEncryption: {
value: true
},
value: {
configurable: true,
get: function() {
this.debug("looking up the value of this field", this._value);
if (this._value === undefined || this._value === null || this._value === "") {
return FieldDBObject.DEFAULT_STRING;
}
// If there was a value before, there are extra precautions
if (!this._shouldBeEncrypted) {
return this._value;
} else {
if (!this.encrypted) {
return this._value;
} else {
if (!this.decryptedMode) {
if (this._encryptedValue) {
this.warn("User is not able to view the " + this.mask + " value of " + this.label + ", it is encrypted and the user isn't in decryptedMode."); //" mask: "+ this._mask +" value: " +this._value);
}
return this.mask || FieldDBObject.DEFAULT_STRING;
} else {
if (!this._encryptedValue || this._encryptedValue.indexOf("confidential:") !== 0) {
this.warn("The value was supposed to be encrypted but was not encrypted. This should not happen, it might only happen if an app was editing the data and didn't have the encryption implemented. Not overwritting the value.");
if (this.repairMissingEncryption && this.confidential) {
var encryptedValue = this.confidential.encrypt(this._value);
this.warn(" Encrypting the value " + this._value);
this._encryptedValue = encryptedValue;
this._mask = this.createMask(this._value);
this._value = this._mask;
} else {
return this._value;
}
}
if (this._encryptedValue.indexOf("confidential:") === 0) {
// All conditions are satisified, decrypt the value and give it to the user
if (!this.confidential) {
this.warn("This field's encrypter hasnt been set. It cannot be decrypted yet.");
return this.mask;
}
var decryptedValue = this.confidential.decrypt(this._encryptedValue);
if (!decryptedValue) {
this.warn("Encryption key is the wrong key, showing the user the mask instead.");
this.decryptedMode = false;
return this.mask;
}
if (this.type && this.type.indexOf("number") > -1) {
var tryAsNumber = Number(decryptedValue);
if (!isNaN(tryAsNumber)) {
decryptedValue = tryAsNumber;
}
}
this.debug("decryptedValue " + decryptedValue);
return decryptedValue;
}
}
}
}
this.bug("The value wasn't returned, this should never happen and is a bug in the logic.");
},
set: function(value) {
if (value === this._value) {
return;
}
if (typeof value.trim === "function") {
value = value.trim();
}
if (value === undefined || value === null || value === "" && !this._value) {
return;
}
if (!value && this._value) {
var fieldCanBeEmptied = !this._shouldBeEncrypted || (this._shouldBeEncrypted && this.decryptedMode);
if (fieldCanBeEmptied) {
this._value = "";
this._mask = "";
this._encryptedValue = "";
return;
} else {
if (this._value) {
this.warn("The value " + this._value + " of " + this.id + " was requested to be removed by the user, but they are not able to edit the field currently. No changes were made ");
}
return;
}
}
var encryptedValue;
if (!this._shouldBeEncrypted) {
this._encryptedValue = value;
this._mask = value;
this._value = this._mask;
return;
} else {
if (!this.encrypted) {
this._encryptedValue = value;
this._mask = value;
this._value = this._mask;
return;
} else {
if (!this._value) {
// If there was no value before, set the new value
if (!this.confidential) {
if (typeof value.indexOf === "function" && value.indexOf("confidential:") === 0 && !this._encryptedValue) {
this._encryptedValue = value;
this._value = this.mask;
this.debug("This is probably a new field initialization from old data (the value has \"confidential:\" in it, and yet the encryptedValue isn't set");
} else {
this.warn("This field's encrypter hasnt been set. It cannot be edited yet.");
}
return;
}
encryptedValue = this.confidential.encrypt(value);
this._encryptedValue = encryptedValue;
this._mask = this.createMask(value);
this._value = this._mask;
} else {
// If there was a value before, there are extra precautions
if (!this.decryptedMode) {
if (this._encryptedValue) {
this.warn("User is not able to change the value " + this.mask + " of " + this.label + ", it is encrypted and the user isn't in decryptedMode.");
}
return;
} else {
if (!this._encryptedValue || this._encryptedValue.indexOf("confidential:") !== 0) {
this.warn("The value was changed, and it was supposed to be encrypted but was not encrypted. This should not happen, it might only happen if an app was editing the data and didn't have the encryption implemented.");
if (this.repairMissingEncryption && this.confidential) {
encryptedValue = this.confidential.encrypt(value);
this._encryptedValue = encryptedValue;
this._mask = this.createMask(value);
this._value = this._mask;
this.warn(" Overwritting the value.");
} else {
this.warn(" Not overwritting the value.");
return;
}
}
// All conditions are satisified, accept the new value.
if (!this.confidential) {
this.warn("This field's encrypter hasnt been set. It cannot be edited yet.");
return;
}
encryptedValue = this.confidential.encrypt(value);
this._encryptedValue = encryptedValue;
this._mask = this.createMask(value);
this._value = this._mask;
}
}
}
}
}
},
mask: {
get: function() {
return this._mask || FieldDBObject.DEFAULT_STRING;
},
set: function(value) {
if (value === this._mask) {
return;
}
if (!value) {
delete this._mask;
return;
}
this.debug("Setting datum field mask " + value);
if (typeof value.trim === "function") {
value = value.trim();
}
this._mask = value;
}
},
encryptedValue: {
get: function() {
return this._encryptedValue || FieldDBObject.DEFAULT_STRING;
},
set: function(value) {
if (!value || value === this._encryptedValue) {
return;
}
if (this._encryptedValue) {
this.warn(this.id + " cannot be changed directly, instead you must be in decryptedMode ");
}
this.debug(" not setting " + value);
}
},
json: {
get: function() {
return this._json || FieldDBObject.DEFAULT_OBJECT;
},
set: function(value) {
if (value === this._json) {
return;
}
if (!value) {
delete this._json;
return;
}
if (value && this._shouldBeEncrypted && !this.decryptedMode) {
this.debug("encrypt json also");
}
this._json = value;
}
},
help: {
configurable: true,
get: function() {
return this._help || this._helpNonLinguists || "Put your team's data entry conventions here (if any)...";
},
set: function(value) {
if (value === this._help) {
return;
}
if (!value) {
delete this._help;
return;
}
this._help = value.trim();
if (!this._helpNonLinguists) {
this.helpNonLinguists = this._help;
}
}
},
helpLinguists: {
get: function() {
return this._helpLinguists || this.help;
},
set: function(value) {
if (value === this._helpLinguists) {
return;
}
if (!value) {
delete this._helpLinguists;
return;
}
this._helpLinguists = value.trim();
}
},
helpNonLinguists: {
get: function() {
return this._helpNonLinguists || this.help;
},
set: function(value) {
if (value === this._helpNonLinguists) {
return;
}
if (!value) {
delete this._helpNonLinguists;
return;
}
this._helpNonLinguists = value.trim();
}
},
helpTranslators: {
get: function() {
return this._helpTranslators || this.help;
},
set: function(value) {
if (value === this._helpTranslators) {
return;
}
if (!value) {
delete this._helpTranslators;
return;
}
this._helpTranslators = value.trim();
}
},
helpComputationalLinguists: {
get: function() {
return this._helpComputationalLinguists || this.help;
},
set: function(value) {
if (value === this._helpComputationalLinguists) {
return;
}
if (!value) {
delete this._helpComputationalLinguists;
return;
}
this._helpComputationalLinguists = value.trim();
}
},
helpDevelopers: {
get: function() {
return this._helpDevelopers || this.help;
},
set: function(value) {
if (value === this._helpDevelopers) {
return;
}
if (!value) {
delete this._helpDevelopers;
return;
}
this._helpDevelopers = value.trim();
}
},
/**
* Called before set and save, checks the attributes that the
* user is attempting to set or save. If the user is trying to
* set a mask on an encrypted datum field that should be encrypted, the only time they can do this is if the data is
* in tempEncryptedVisible, with decryptedMode on.
*
* @param attributes
*/
validate: {
value: function(attributes) {
this.tood("Vaidating is commented out ", attributes);
// if(attributes.mask){
// if(attributes.shouldBeEncrypted !== "checked" ){
// //user can modify the mask, no problem.
// }else if(attributes.encrypted !== "checked" ){
// //user can modify the mask, no problem.
// }else if( attributes.encrypted === "checked" &&
//// attributes.tempEncryptedVisible === "checked" &&
// attributes.shouldBeEncrypted === "checked" &&
// this.corpus.confidential.decryptedMode ){
// //user can modify the mask, no problem.
// }else if( attributes.mask !== this.mask ){
// return "The datum is presently encrypted, the mask cannot be set by anything other than the model itself.";
// }
// }
// if( attributes.value ){
//
// if(this.value && this.value.indexOf("confidential") === 0){
// return "Cannot modify the value of a confidential datum field directly";
// }
//
// if(attributes.shouldBeEncrypted !== "checked" ){
// //user can modify the value, no problem.
// }else if(attributes.encrypted !== "checked" ){
// //user can modify the value, no problem.
// }else if( attributes.encrypted === "checked" &&
//// attributes.tempEncryptedVisible === "checked" &&
// attributes.shouldBeEncrypted === "checked" &&
// this.corpus.confidential.decryptedMode ){
// //the user/app can modify the value, no problem.
// }else if( attributes.value !== this.value ){
// return "The value cannot be set by anything other than the model itself, from a mask.";
// }
// }
}
},
/**
* In the case of the datumfield, if the datum
* field is not encrypted, then the mask and value are essentially the same.
* If however the datum is supposed to be encrypted, the value needs to
* start with confidential, and the mask should be xxxx representign
* words/morphemes which are allowed to be shown.
* http://stackoverflow.com/questions/11315844/what-is-the-correct-way-in-backbone-js-to-listen-and-modify-a-model-property
*
* @param key
* @param value
* @param options
* @returns null
*/
upgrade: {
value: function(attributes, options) {
options = options || {};
// do any other custom property changes here
/*
* Copy the mask, value and shouldBeEncrypted and encrypted from the object if it is not being set.
*/
if (attributes.mask === undefined && this.mask) {
attributes.mask = this.mask;
}
if (attributes.value === undefined && this.value) {
attributes.value = this.value;
}
if (attributes.shouldBeEncrypted === undefined && this.shouldBeEncrypted) {
attributes.shouldBeEncrypted = this.shouldBeEncrypted;
}
if (attributes.encrypted === undefined && this.encrypted) {
attributes.encrypted = this.encrypted;
}
if ((attributes.mask && attributes.mask !== "")) {
if (attributes.shouldBeEncrypted !== "checked") {
//Don't do anything special, this field doesnt get encrypted when the data is confidential
attributes.value = attributes.mask;
} else if (attributes.encrypted !== "checked") {
//Don't do anything special, this datum isn't confidential
attributes.value = attributes.mask;
/*
* A, B, C, D: If we are supposed to be encrypted, and we are encrypted, but we want to let the user see the data to change it.
*
*/
} else if (this.corpus.confidential.decryptedMode) {
/*
* A: If it wasn't encrypted, encrypt the value, and leave the mask as the original value for now,
* can happen when the user clicks on the lock button for the first time.
*/
if (attributes.mask.indexOf("confidential:") !== 0) {
// attributes.mask = attributes.mask;//leave mask open
//save the mask encrpyted as the new value, this is triggered when the user modifies the data
attributes.value = this.corpus.confidential.encrypt(attributes.mask);
/*
* B: A strange case which is used by the Datum Save function, to trigger the mask into the xxx version of the current value that it will be saved in the data base with xxx.
*/
} else if (attributes.mask.indexOf("confidential:") === 0) {
attributes.mask = this.mask(this.corpus.confidential.decrypt(this.value));
attributes.value = this.value; //don't let the user modify the value.
}
/*
* C & D: this should never be called since the value is supposed to come from the mask only.
*/
/*
* C: If the value wasn't encrypted, encrypt the value, and leave the mask as the original value since we are in decryptedMode
*/
if (attributes.value && attributes.value.indexOf("confidential") !== 0) {
// attributes.mask = attributes.mask;//leave mask open
attributes.value = this.corpus.confidential.encrypt(attributes.mask);
/*
* D: If the value was encrypted, there is some sort of bug, leave the value as it was, decrypt it and put it in to the mask since we are in decryptedMode
*/
} else if (attributes.value && attributes.value.indexOf("confidential") === 0) {
// If it was encrypted, turn the mask into the decrypted version of the current value so the user can see it.
//this might get called at the same time as the first mask if above
attributes.mask = this.corpus.confidential.decrypt(this.value);
attributes.value = this.value; //don't let the user modify the value.
}
/*
* E, F, G, H: If we are supposed to be encrypted and we are encrypted, but we are not in decrypted mode.
*/
} else {
//Don't let the user take off encryption if they are not in decryptedMode
if (this.encrypted === "checked") {
if (true && attributes.encrypted !== "checked" && !this.corpus.confidential.decryptedMode) {
attributes.encrypted = "checked";
}
}
/*
* E: A strange case which is used by the Datum Save function, to trigger the mask into the xxx version of the current value that it will be saved in the data base with xxx.
* (Same as B above)
*/
if (attributes.mask && attributes.mask.indexOf("confidential") === 0) {
attributes.mask = this.mask(this.corpus.confidential.decrypt(this.value));
attributes.value = this.value; //don't let the user modify the value.
/*
* F: If the value is encrypted, then the mask is probably set, don't let the user change anything since they shouldn't be able to see the data anyway.s
*/
} else {
//Don't let user change value of confidential or mask: see validate function
attributes.mask = this.mask;
attributes.value = this.value;
}
/*
* G: If the data is not encrypted, encrypt it and mask it in the mask. This might be called the first time a user clicks on the lock to first encrypts the value.
* (Similar to C above, except that we mask the mask)
*/
if (attributes.value && attributes.value.indexOf("confidential") !== 0) {
attributes.mask = this.mask(this.value); //use value to make mask
attributes.value = this.corpus.confidential.encrypt(this.value);
/*
* H: If the value is encrypted, then the mask is probably set, don't let the user change anything since they shouldn't be able to see the data anyway.s
*/
} else {
//Don't let user change value of confidential or mask: see validate function
attributes.mask = this.mask;
attributes.value = this.value;
}
}
} else {
// alert("The datum field has no mask, there is a bug somewhere.");
// attributes.value ="";
// attributes.mask = "";
}
return attributes;
}
},
createMask: {
value: function(stringToMask) {
stringToMask = stringToMask || "";
stringToMask = stringToMask + "";
return stringToMask.replace(/[^_=., -]/g, "x");
}
},
saveAndInterConnectInApp: {
value: function(callback) {
if (typeof callback === "function") {
callback();
}
}
},
confidential: {
get: function() {
return this.confidentialEncrypter;
},
set: function(value) {
if (value === this.confidentialEncrypter) {
return;
}
if (typeof value.encrypt !== "function" && value.secretkey) {
value = new Confidential(value);
}
this.confidentialEncrypter = value;
}
},
toJSON: {
value: function(includeEvenEmptyAttributes, removeEmptyAttributes) {
this.debug("Customizing toJSON ", includeEvenEmptyAttributes, removeEmptyAttributes);
includeEvenEmptyAttributes = true;
var json = FieldDBObject.prototype.toJSON.apply(this, arguments);
delete json.dateCreated;
delete json.dateModified;
delete json.comments;
delete json.dbname;
// TODO eventually dont include the label and hint but now include it for backward compaitibilty
json.label = this.id;
json.hint = this.hint || "";
json.value = this.value || "";
json.mask = this.mask || "";
json.id = this.id;
delete json._id;
json.fieldDBtype = this.fieldDBtype;
delete json._type;
this.debug(json);
return json;
}
}
});
exports.DatumField = DatumField;
},{"./../FieldDBObject":3,"./../confidentiality_encryption/Confidential":17}],33:[function(require,module,exports){
var Collection = require("./../Collection").Collection;
var DatumField = require("./../datum/DatumField").DatumField;
/**
* @class Collection of Datum Field
* @name DatumFields
* @description The DatumFields is a minimal customization of the Collection
* to add an internal model of DatumField.
*
* @extends Collection
* @constructs
*/
var DatumFields = function DatumFields(options) {
if (!this._fieldDBtype) {
this._fieldDBtype = "DatumFields";
}
this.debug("Constructing DatumFields length: ", options);
Collection.apply(this, arguments);
};
DatumFields.prototype = Object.create(Collection.prototype, /** @lends DatumFields.prototype */ {
constructor: {
value: DatumFields
},
/**
* The primary key < v2 was "label" but we changed to use "id" so that
* "label" could be used only for a human friendly (and customizable)
* label while the id must remain unchanged for glossing and other automation.
* @type {Object}
*/
primaryKey: {
value: "id"
},
INTERNAL_MODELS: {
value: {
item: DatumField
}
},
capitalizeFirstCharacterOfPrimaryKeys: {
value: false
},
/**
* Docs/items in a DatumFields are reorderable by default
* @type {Boolean}
*/
docsAreReorderable: {
get: function() {
if (this._docsAreReorderable !== null && this._docsAreReorderable !== undefined) {
return this._docsAreReorderable;
}
return true;
},
set: function(value) {
if (value === null || value === undefined) {
delete this._docsAreReorderable;
return;
}
this._docsAreReorderable = value;
}
},
/**
* Docs/items in a DatumFields are reorderable by default
* @type {Boolean}
*/
showDocPosition: {
get: function() {
if (this._showDocPosition !== null && this._showDocPosition !== undefined) {
return this._showDocPosition;
}
return true;
},
set: function(value) {
if (value === null || value === undefined) {
delete this._showDocPosition;
return;
}
this._showDocPosition = value;
}
},
cloneStructure: {
value: function(includeEvenEmptyAttributes) {
if (includeEvenEmptyAttributes) {
this.todo("includeEvenEmptyAttributes is not implemented: " + includeEvenEmptyAttributes);
}
var json = Collection.prototype.toJSON.apply(this, arguments);
json.map = json.map(function(field){
field.value = "";
field.mask = "";
field.encryptedValue= "";
return field;
});
return json;
}
}
});
exports.DatumFields = DatumFields;
},{"./../Collection":2,"./../datum/DatumField":32}],34:[function(require,module,exports){
var FieldDBObject = require("./../FieldDBObject").FieldDBObject;
var UserMask = require("./../user/UserMask").UserMask;
/**
* @class The datum state lets the fieldlinguists assign their own state
* categories to data (ie check with consultant, check with x,
* checked, checked and wrong, hidden, deleted), whatever state they
* decide. They an make each state have a color so that the team can
* see quickly if there is something that needs to be done with that
* data. We also added an optional field, Consultant that they can use
* to say who they want to check with in case they have mulitple
* consultants and the consultants have different grammaticality
* judgements. When users change the state of the datum, we will add
* a note in the datum"s comments field so that the history of its
* state is kept in an annotated format.
*
* @name DatumState
*
* @extends FieldDBObject
* @constructs
*/
var DatumState = function DatumState(options) {
if (!this._fieldDBtype) {
this._fieldDBtype = "DatumState";
}
this.debug("Constructing DatumState ", options);
FieldDBObject.apply(this, arguments);
};
DatumState.prototype = Object.create(FieldDBObject.prototype, /** @lends DatumState.prototype */ {
constructor: {
value: DatumState
},
defaults: {
value: {
state: "Checked",
color: "",
consultant: UserMask, //TODO comment out htis line when we confirm that state is working
showInSearchResults: "checked",
selected: ""
}
},
// Internal models: used by the parse function
INTERNAL_MODELS: {
value: {
consultant: UserMask
}
},
validationStatus: {
get: function() {
if (!this._validationStatus && this.state) {
this.warn("state is deprecated, use validationStatus instead.");
this._validationStatus = this.state;
}
return this._validationStatus || FieldDBObject.DEFAULT_STRING;
},
set: function(value) {
if (value === this._validationStatus) {
return;
}
if (!value) {
delete this._validationStatus;
return;
}
this._validationStatus = value.trim();
}
}
});
exports.DatumState = DatumState;
},{"./../FieldDBObject":3,"./../user/UserMask":65}],35:[function(require,module,exports){
var DatumTags = require("./DatumTags").DatumTags;
var DatumState = require("./DatumState").DatumState;
/**
* @class DatumStates of Datum validation states
* @name DatumStates
* @description The DatumStates is a minimal customization of the DatumTags
* to add an internal model of DatumState.
*
* @extends DatumTags
* @constructs
*/
var DatumStates = function DatumStates(options) {
if (!this._fieldDBtype) {
this._fieldDBtype = "DatumStates";
}
this.debug("Constructing DatumStates length: ", options);
DatumTags.apply(this, arguments);
};
DatumStates.prototype = Object.create(DatumTags.prototype, /** @lends DatumStates.prototype */ {
constructor: {
value: DatumStates
},
/**
* The primary key < v2 was "label" but we changed to use "id" so that
* "label" could be used only for a human friendly (and customizable)
* label while the id must remain unchanged for glossing and other automation.
* @type {Object}
*/
primaryKey: {
value: "validationStatus"
},
INTERNAL_MODELS: {
value: {
item: DatumState
}
}
});
exports.DatumStates = DatumStates;
},{"./DatumState":34,"./DatumTags":37}],36:[function(require,module,exports){
var FieldDBObject = require("./../FieldDBObject").FieldDBObject;
/**
* @class The DatumTag allows the user to label data with grammatical tags
* i.e. passive, causative. This is useful for searches.
*
* @name DatumTag
* @description The initialize function brings up a field in which the user
* can enter tags.@class FieldDBObject of Datum validation states
* @extends FieldDBObject
* @constructs
*/
var DatumTag = function DatumTag(options) {
if (!this._fieldDBtype) {
this._fieldDBtype = "DatumTag";
}
this.debug("Constructing DatumTag ", options);
FieldDBObject.apply(this, arguments);
};
DatumTag.prototype = Object.create(FieldDBObject.prototype, /** @lends DatumTag.prototype */ {
constructor: {
value: DatumTag
}
});
exports.DatumTag = DatumTag;
},{"./../FieldDBObject":3}],37:[function(require,module,exports){
var Collection = require("./../Collection").Collection;
var DatumTag = require("./DatumTag").DatumTag;
/**
* @class Collection of Datum validation states
* @name DatumTags
* @description The DatumTags is a minimal customization of the Collection
* to add an internal model of DatumTag.
*
* @extends Collection
* @constructs
*/
var DatumTags = function DatumTags(options) {
if (!this._fieldDBtype) {
this._fieldDBtype = "DatumTags";
}
this.debug("Constructing DatumTags ", options);
Collection.apply(this, arguments);
};
DatumTags.prototype = Object.create(Collection.prototype, /** @lends DatumTags.prototype */ {
constructor: {
value: DatumTags
},
/**
* The primary key < v2 was "label" but we changed to use "id" so that
* "label" could be used only for a human friendly (and customizable)
* label while the id must remain unchanged for glossing and other automation.
* @type {Object}
*/
primaryKey: {
value: "tag"
},
INTERNAL_MODELS: {
value: {
item: DatumTag
}
}
});
exports.DatumTags = DatumTags;
},{"./../Collection":2,"./DatumTag":36}],38:[function(require,module,exports){
var Collection = require("./../Collection").Collection;
var FieldDBObject = require("./../FieldDBObject").FieldDBObject;
/**
* @class Collection of CouchDB docs
* @name DocumentCollection
* @description The DocumentCollection is a minimal customization of the Collection
* to add an internal model of Document and prevent the primary key from being sanitized
*
* @extends Collection
* @constructs
*/
var DocumentCollection = function DocumentCollection(options) {
if (!this._fieldDBtype) {
this._fieldDBtype = "DocumentCollection";
}
this.debug("Constructing DocumentCollection ", options);
Collection.apply(this, arguments);
};
DocumentCollection.prototype = Object.create(Collection.prototype, /** @lends DocumentCollection.prototype */ {
constructor: {
value: DocumentCollection
},
INTERNAL_MODELS: {
value: {
item: FieldDBObject
}
},
sanitizeStringForPrimaryKey: {
value: function(value) {
return value;
}
}
});
exports.DocumentCollection = DocumentCollection;
},{"./../Collection":2,"./../FieldDBObject":3}],39:[function(require,module,exports){
var Stimulus = require("./Stimulus").Stimulus,
Q = require("q");
/**
* @class The Response is a minimal customization of a Stimulus which allows the user to add additional information
* which can be used for experiments.
*
* @name Response
* @extends Stimulus
* @constructs
*/
var Response = function Response(options) {
if (!this._fieldDBtype) {
this._fieldDBtype = "Response";
}
this.debug("Constructing Response ", options);
Stimulus.apply(this, arguments);
};
Response.prototype = Object.create(Stimulus.prototype, /** @lends Response.prototype */ {
constructor: {
value: Response
},
jsonType: {
get: function() {
return this.fieldDBtype;
}
},
collection: {
get: function() {
return this.fieldDBtype;
}
},
// responses: {
// value: null,
// configurable: true
// },
pauseAudioWhenConfirmingResponse: {
value: null,
configurable: true
},
addResponse: {
value: function(responseEvent, stimulusId) {
if (!responseEvent) {
throw new Error("Cannot add response without the x y information found in the touch/click responseEvent");
}
var reactionTimeEnd = Date.now();
var audioDuration = this.application.audioPlayer.getDuration(this.audioFile) || 0;
if (audioDuration) {
audioDuration = audioDuration * 1000;
} else {
this.warn("The audio has no duration.. This is strange.");
}
if (this.pauseAudioWhenConfirmingResponse) {
this.pauseAudio();
}
var self = this;
var continueToNextStimulus = Q.defer();
if (this.confirmResponseChoiceMessage) {
this.contextualizer.currentLocale = this.application.interfaceLocale;
var confirmChoicePrompt = this.contextualizer.localize(this.confirmResponseChoiceMessage);
var options = {
iconSrc: self.ownerComponent.iconSrc,
message: confirmChoicePrompt
};
this.confirm(options.message).then(function() {
continueToNextStimulus.resolve();
}, function() {
continueToNextStimulus.reject(new Error("The x prevented the cancel?"));
}).fail(function(error) {
console.error(error.stack, self);
});
} else {
continueToNextStimulus.resolve();
}
continueToNextStimulus.promise.then(function() {
// self.ownerComponent.templateObjects.reinforcement.next();
self.stopAudio();
self.ownerComponent.nextStimulus();
}, function(reason) {
self.warn("Not continuing to next stimulus", reason);
if (this.pauseAudioWhenConfirmingResponse) {
self.playAudio();
}
}).fail(function(error) {
console.error(error.stack, self);
});
var choice = "";
if (stimulusId) {
choice = this[stimulusId].substring(this[stimulusId].lastIndexOf("/") + 1).replace(/\..+$/, "").replace(/\d+_/, "");
if (choice === this.target.orthographic) {
choice = this.target;
} else {
this.distractors.map(function(distractor) {
if (choice === distractor.orthographic) {
choice = distractor;
}
});
}
}
var response = {
"reactionTimeAudioOffset": reactionTimeEnd - this.reactionTimeStart - audioDuration,
"reactionTimeAudioOnset": reactionTimeEnd - this.reactionTimeStart,
"x": responseEvent.x,
"y": responseEvent.y,
"pageX": responseEvent.pageX,
"pageY": responseEvent.pageY,
// "prime": {
// phonemic: this.prime.phonemic,
// orthographic: this.prime.orthographic,
// imageFile: this.prime.imageFile
// },
"choice": choice,
// "target": this.target,
"score": this.scoreResponse(this.target, choice)
};
this.responses.push(response);
self.warn("Recorded response", JSON.stringify(response));
}
},
addOralResponse: {
value: function(choice, dontAutoAdvance) {
var reactionTimeEnd = Date.now();
var audioDuration = this.application.audioPlayer.getDuration(this.audioFile) || 0;
if (audioDuration) {
audioDuration = audioDuration * 1000;
} else {
this.warn("The audio has no duration.. This is strange.");
}
if (this.pauseAudioWhenConfirmingResponse) {
this.pauseAudio();
}
var self = this;
var continueToNextStimulus = Q.defer();
if (this.confirmResponseChoiceMessage) {
this.contextualizer.currentLocale = this.application.interfaceLocale;
var confirmChoicePrompt = this.contextualizer.localize(this.confirmResponseChoiceMessage);
var options = {
iconSrc: self.ownerComponent.iconSrc,
message: confirmChoicePrompt
};
this.confirm(options.message).then(function() {
continueToNextStimulus.resolve();
}, function() {
continueToNextStimulus.reject(new Error("The x prevented the cancel?"));
}).fail(function(error) {
console.error(error.stack, self);
});
} else {
if (!dontAutoAdvance) {
continueToNextStimulus.resolve();
}
}
continueToNextStimulus.promise.then(function() {
// self.ownerComponent.templateObjects.reinforcement.next();
self.stopAudio();
self.ownerComponent.nextStimulus();
}, function(reason) {
self.warn("Not continuing to next stimulus", reason);
if (this.pauseAudioWhenConfirmingResponse) {
self.playAudio();
}
}).fail(function(error) {
console.error(error.stack, self);
});
var response = {
"reactionTimeAudioOffset": reactionTimeEnd - this.reactionTimeStart - audioDuration,
"reactionTimeAudioOnset": reactionTimeEnd - this.reactionTimeStart,
"x": 0,
"y": 0,
"pageX": 0,
"pageY": 0,
"choice": choice,
"score": choice.score
};
this.responses = this.responses || [];
this.responses.push(response);
self.warn("Recorded response", JSON.stringify(response));
}
},
scoreResponse: {
value: function(expectedResponse, actualResponse) {
if (!actualResponse.orthographic) {
return "error";
}
if (actualResponse.orthographic === expectedResponse.orthographic) {
return 1;
} else {
return 0;
}
}
},
addNonResponse: {
value: function(responseEvent) {
if (!responseEvent) {
throw "Cannot add response without the x y information found in the touch/click responseEvent";
}
var reactionTimeEnd = Date.now();
var response = {
"reactionTimeAudioOffset": reactionTimeEnd - this.reactionTimeStart,
"reactionTimeAudioOnset": reactionTimeEnd - this.reactionTimeStart,
"x": responseEvent.x,
"y": responseEvent.y,
"pageX": responseEvent.pageX,
"pageY": responseEvent.pageY,
"chosenVisualStimulus": "none",
"responseScore": -1
};
this.responses = this.responses || [];
this.nonResponses.push(response);
this.warn("Recorded non-response, the user is confused or not playing the game.", JSON.stringify(response));
}
},
/**
* TODO try using a media controller later montage/ui/controller/media-controller
* @type {Object}
*/
playAudio: {
value: function(delay) {
this.application.audioPlayer.play(this.audioFile, delay);
}
},
pauseAudio: {
value: function() {
this.application.audioPlayer.pause(this.audioFile);
}
},
stopAudio: {
value: function() {
this.application.audioPlayer.stop(this.audioFile);
}
},
load: {
value: function(details) {
for (var d in details) {
if (details.hasOwnProperty(d)) {
this[d] = details[d];
}
}
if (this.responses === null) {
this.responses = [];
}
if (this.nonResponses === null) {
this.nonResponses = [];
}
this.nonResponses = [];
this.experimenterId = this.application.experiment.experimenter.id;
this.participantId = this.application.experiment.participant.id;
// Not playing audio by default, child must call it.
// this.playAudio(2000);
}
}
});
exports.Response = Response;
},{"./Stimulus":41,"q":248}],40:[function(require,module,exports){
var Confidential = require("./../confidentiality_encryption/Confidential").Confidential;
var DatumFields = require("./DatumFields").DatumFields;
var DataList = require("./../data_list/DataList").DataList;
var FieldDBObject = require("./../FieldDBObject").FieldDBObject;
var DEFAULT_CORPUS_MODEL = require("./../corpus/corpus.json");
/**
* @class The Session widget is the place where information which is generally
* shared by many datum (due to being part of an elicitiation session)
* @property {Number} sessionID The session ID is an automatically generated
* number which will uniquely identify the session.
* @property {String} user The user is the person inputting the data for
* that session.
* @property {String} team The team is the team that the user belongs to.
* @property {String} consultant The consultant is the native speaker of the
* language under investigation that has verified the data in the
* session.
* @property {String} language The language is the language under
* investigation in the particular session.
* @property {String} languageFamily The language family is an attribute
* which users can use to group languages.
* @property {String} dialect The dialect specifies the dialect of the
* language under investigation.
* @property {String} date The date is the date that the data was elicited.
* @property {String} goal The goal is the particular linguistic goal that
* the researcher was pursuing during that session.
*
* new DatumField({
label : "user",
shouldBeEncrypted: "",
userchooseable: "disabled"
}),
new DatumField({
label : "consultants",
shouldBeEncrypted: "",
userchooseable: "disabled"
}),
new DatumField({
label : "language",
shouldBeEncrypted: "",
userchooseable: "disabled",
help: "This is the langauge (or language family) if you would like to use it."
}),
new DatumField({
label : "dialect",
shouldBeEncrypted: "",
userchooseable: "disabled",
help: "You can use this field to be as precise as you would like about the dialect of this session."
}),
new DatumField({
label : "dateElicited",
shouldBeEncrypted: "",
userchooseable: "disabled",
help: "This is the date in which the session took place."
}),
new DatumField({
label : "dateSEntered",
shouldBeEncrypted: "",
userchooseable: "disabled",
help: "This is the date in which the session was entered."
}),
new DatumField({
label : "goal",
shouldBeEncrypted: "",
userchooseable: "disabled",
help: "This describes the goals of the session."
}),
*
*
*
* @description The initialize function brings up a page in which the user
* can fill out the details corresponding to the session. These
* details will be linked to each datum submitted in the
* session.
* @name Session
* @extends FieldDBObject
* @constructs
*/
var Session = function Session(options) {
if (!this._fieldDBtype) {
this._fieldDBtype = "Session";
}
// this.debugMode = true;
this.debug("Constructing Session: ", options);
options = options || {};
if (!options || (!options._rev && !options.fields)) {
//If its a new session with out a revision and without fields use the defaults
options.fields = this.defaults.fields;
}
// Dont Initialize the datalist to avoid each datum causing each session to run queries on the server needlessly. and docs to ensure its ready incase we want to use them.
if (options.docIds || options.docs) {
this.initializeDatalist();
}
this.debug(" -> ", options.datalist);
FieldDBObject.apply(this, arguments);
this.debug(" after construction: ", this._datalist);
};
Session.prototype = Object.create(FieldDBObject.prototype, /** @lends Session.prototype */ {
constructor: {
value: Session
},
dateAndGoalSnippet: {
get: function() {
var goal = this.goal;
if (goal.length > 31) {
goal = goal.substr(0, 30) + "...";
}
var dateElicited = this.dateElicited;
if (dateElicited.length > 16) {
dateElicited = dateElicited.substr(0, 15) + "...";
}
return dateElicited + " : " + goal;
},
set: function() {
this.debug("cant set the snippet.");
}
},
title: {
get: function() {
return this.goal;
},
set: function(value) {
this.warn("title is syntactic sugar for goal, if it was used this will make it overwrite the goal field");
return this.goal = value;
}
},
goal: {
configurable: true,
get: function() {
if (this.fields && this.fields.goal) {
return this.fields.goal.value;
} else {
return FieldDBObject.DEFAULT_STRING;
}
},
set: function(value) {
if (this.fields && this.fields.goal) {
// this.fields.debugMode = true;
} else {
this.fields = this.defaults.fields;
}
if (!value || (value.indexOf && value.indexOf("Change this session") > -1)) {
value = "Practice collecting linguistic utterances or words";
}
this.fields.goal.value = value;
}
},
date: {
get: function() {
return this.dateElicited;
},
set: function(value) {
this.warn("date is syntactic sugar for dateElicited");
return this.dateElicited = value;
}
},
dateElicited: {
configurable: true,
get: function() {
if (this.fields && this.fields.dateElicited) {
if (this.fields.dateElicited.value && this.fields.dateElicited.value.indexOf && this.fields.dateElicited.value.indexOf("Change this to a tim") > -1) {
this.fields.dateElicited.value = "Probably prior to " + new Date(this.dateCreated);
}
if (!this.fields.dateElicited.value && this.dateCreated) {
this.fields.dateElicited.value = new Date(this.dateCreated) + "";
}
return this.fields.dateElicited.value;
} else {
return FieldDBObject.DEFAULT_STRING;
}
},
set: function(value) {
if (this.fields) {
// this.fields.debugMode = true;
} else {
this.fields = this.defaults.fields;
}
if (value && value.indexOf && value.indexOf("Change this to a tim") > -1) {
value = "Probably prior to " + new Date(this.dateCreated);
}
this.fields.dateElicited.value = value;
}
},
// The couchdb-connector is capable of mapping the url scheme
// proposed by the authors of Backbone to documents in your database,
// so that you don't have to change existing apps when you switch the sync-strategy
api: {
value: "sessions"
},
// Internal models: used by the parse function
INTERNAL_MODELS: {
value: {
fields: DatumFields,
confidential: Confidential,
docs: FieldDBObject.DEFAULT_COLLECTION,
docIds: FieldDBObject.DEFAULT_COLLECTION,
datalist: DataList
}
},
sessionFields: {
get: function() {
return this.fields;
},
set: function(value) {
this.warn("sessionFields are depreacted, use fields instead " + this.id);
return this.fields = value;
}
},
fields: {
get: function() {
this.debug("getting fields " + this.id);
return this._fields;
},
set: function(value) {
if (value && !value.confidential && this.confidential) {
value.confidential = this.confidential;
}
this.ensureSetViaAppropriateType("fields", value);
}
},
defaults: {
get: function() {
var doc = {
fields: DEFAULT_CORPUS_MODEL.sessionFields
};
return JSON.parse(JSON.stringify(doc));
},
set: function() {}
},
confidentiality: {
get: function() {
if (this.fields) {
return this.fields.confidentiality.value;
} else {
return;
}
},
set: function(value) {
if (!this.fields) {
this.fields = this.defaults.fields;
}
// this.warn("Cannot change the public/private of " + this.collection + " (it must be anonymous). " + value);
this.fields.confidentiality.value = value;
}
},
participants: {
configurable: true,
get: function() {
if (this.fields && this.fields.participants && this.fields.participants.json && this.fields.participants.json.users) {
return this.fields.participants.json.users;
} else {
return;
}
},
set: function(value) {
if (!this.fields) {
this.fields = this.defaults.fields;
}
if (typeof value === "string") {
if (value.indexOf(",") > -1) {
value = value.split();
} else {
value = [value];
}
value = value.map(function(username) {
username = username.trim();
return {
username: username,
name: username,
gravatar: ""
};
});
}
if (Object.prototype.toString.call(value) === "[object Array]") {
var self = this;
value.map(function(usermask) {
self.fields.participants.json.users.unshift(usermask);
});
} else {
this.fields.participants.json.users.unshift(value);
}
}
},
consultants: {
get: function() {
var dataEntryPeople = [];
if (this.fields && this.fields.participants && this.fields.participants.json && this.fields.participants.json.users) {
this.fields.participants.json.users.map(function(usermask) {
if (usermask.role && usermask.role.indexOf("speaker") > -1) {
dataEntryPeople.push(usermask);
}
});
if (dataEntryPeople.length === 0) {
dataEntryPeople = this.fields.participants.json.users;
}
}
return dataEntryPeople;
},
set: function(value) {
if (!this.fields) {
this.fields = this.defaults.fields;
}
// if (Object.prototype.toString.call(value) === "[object Array]") {
// var self = this;
// value.map(function(usermask) {
// self.consultants = usermask;
// });
// return;
// }
if (typeof value === "string") {
if (value.indexOf(",") > -1) {
value = value.split(",");
} else {
value = [value];
}
value = value.map(function(username) {
username = username.trim();
return {
username: username,
name: username,
gravatar: ""
};
});
}
if (Object.prototype.toString.call(value) !== "[object Array]") {
value = [value];
}
var self = this;
value = value.map(function(userMask) {
if (userMask.role) {
userMask.role = "speaker," + userMask.role;
} else {
userMask.role = "speaker";
}
self.fields.participants.json.users.unshift(userMask);
return userMask;
});
this.debug("adding consultant", value);
}
},
user: {
get: function() {
var dataEntryPeople = [];
if (this.fields && this.fields.participants && this.fields.participants.json && this.fields.participants.json.users) {
this.fields.participants.json.users.map(function(usermask) {
if (usermask.role && usermask.role.indexOf("dataEntry") > -1) {
dataEntryPeople.push(usermask);
}
});
if (dataEntryPeople.length === 0) {
dataEntryPeople = this.fields.participants.json.users;
}
}
return dataEntryPeople[0];
},
set: function(value) {
if (!this.fields) {
this.fields = this.defaults.fields;
}
if (typeof value === "string") {
if (value.indexOf(",") > -1) {
value = value.split(",");
} else {
value = [value];
}
value = value.map(function(username) {
username = username.trim();
return {
username: username,
name: username,
gravatar: ""
};
});
}
if (Object.prototype.toString.call(value) !== "[object Array]") {
value = [value];
}
var self = this;
value = value.map(function(userMask) {
if (userMask.role) {
userMask.role = "dataEntry," + userMask.role;
} else {
userMask.role = "dataEntry";
}
self.fields.participants.json.users.unshift(userMask);
return userMask;
});
this.debug("adding user", value);
}
},
encryptByCorpus: {
value: true
},
confidential: {
get: function() {
return this.confidentialEncrypter;
},
set: function(value) {
this.ensureSetViaAppropriateType("confidential", value, "confidentialEncrypter");
if (this._fields && this.confidentialEncrypter) {
// this.debug("setting session fields confidential in the Session.confidential set function.");
this._fields.confidential = this.confidentialEncrypter;
}
}
},
languages: {
get: function() {
if (this.fields) {
return this.fields.languages.value;
} else {
return;
}
},
set: function(value) {
var stringvalue;
var objectvalue;
if (typeof value === "string") {
this.debug("User set the languages with a string");
if (this.fields.languages && this.fields.languages && this.fields.languages.json) {
this.confirm("Do you want to set the languages from " + JSON.stringify(this.fields.languages.json) + " to " + value);
}
stringvalue = value;
objectvalue = {
value: value,
label: "languages",
json: {
languages: value.split(",")
}
};
objectvalue.json.languages = objectvalue.json.languages.map(function(languageName) {
return {
iso: languageName.toLowerCase().trim(),
name: languageName.trim(),
nativeName: languageName.trim()
};
});
} else {
objectvalue = value;
}
if (!this.fields) {
this.fields = this.defaults.fields;
}
if (stringvalue) {
this.fields.languages.value = stringvalue;
}
this.debug("setting language ", objectvalue);
for (var property in objectvalue) {
if (!objectvalue.hasOwnProperty(property)) {
continue;
}
this.debug("looking at " + property);
this.fields.languages[property] = objectvalue[property];
}
}
},
dialects: {
get: function() {
return this.languages;
},
set: function(value) {
return this.languages = value;
}
},
docIds: {
get: function() {
if (this._datalist && this._datalist.docIds) {
return this._datalist.docIds;
}
// return FieldDBObject.DEFAULT_COLLECTION;
},
set: function(value) {
if (!this._datalist) {
this.initializeDatalist();
}
this._datalist.docIds = value;
}
},
docs: {
get: function() {
if (this._datalist && this._datalist._docs) {
return this._datalist._docs;
}
},
set: function(value) {
if (!value || value.length === 0) {
this.warn("cant clear the docs of a session like this.", value);
return;
}
if (!this.whenReindexedFromApi) {
this.initializeDatalist();
}
var self = this,
docPrimaryKey;
this.whenReindexedFromApi.fail(function(error) {
console.log(error.stack);
}).done(function() {
self.warn(" making sure " + value.length + " items are in the list of data.");
value.map(function(tempDoc) {
docPrimaryKey = tempDoc[self._datalist.primaryKey];
if (!docPrimaryKey) {
self.warn("This doc has no primary key, trying to add it anyway.", tempDoc);
self._datalist._docs.add(tempDoc);
} else {
if (!self._datalist._docs[docPrimaryKey]) {
self.warn("Adding " + tempDoc + " to the list. ");
self._datalist._docs.add(tempDoc);
}
}
});
});
}
},
utterances: {
get: function() {
return this.docs;
},
set: function(value) {
return this.docs = value;
}
},
transcriptions: {
get: function() {
return this.docs;
},
set: function(value) {
return this.docs = value;
}
},
items: {
get: function() {
return this.docs;
},
set: function(value) {
return this.docs = value;
}
},
datum: {
get: function() {
return this.docs;
},
set: function(value) {
return this.docs = value;
}
},
data: {
get: function() {
return this.docs;
},
set: function(value) {
return this.docs = value;
}
},
records: {
get: function() {
return this.docs;
},
set: function(value) {
return this.docs = value;
}
},
entries: {
get: function() {
return this.docs;
},
set: function(value) {
return this.docs = value;
}
},
examples: {
get: function() {
return this.docs;
},
set: function(value) {
return this.docs = value;
}
},
cards: {
get: function() {
return this.docs;
},
set: function(value) {
return this.docs = value;
}
},
add: {
value: function(value) {
if (!value) {
return;
}
this.debug("Adding to the " + this.id + " session", value);
if (this._datalist && this._datalist.docs && typeof this._datalist.docs.add === "function") {
return this._datalist.docs.add(value);
}
if (!this.whenReindexedFromApi) {
this.initializeDatalist();
}
var self = this;
this.whenReindexedFromApi.fail(function(error) {
console.log(error.stack);
}).done(function() {
self._datalist.docs.add(value);
});
}
},
length: {
get: function() {
if (this._datalist) {
return this._datalist.length || 0;
}
return 0;
},
set: function(value) {
this.warn("Cant set the lenght of a session. It's automatically determined by the number of items in its data list.", value);
}
},
initializeDatalist: {
value: function(datalistJson) {
this.debug(" initializeDatalist ", this._datalist);
if (this._datalist && this._datalist.whenReindexedFromApi) {
if (datalistJson) {
this.todo("the caller asked for a speciific data list to be created, ignoring it. ");
}
this.debug("Datalist is already ready.");
return;
}
if (!datalistJson) {
datalistJson = {
title: {
default: "All data in " + this.goal
},
dbname: this.dbname,
docs: [],
debugMode: true
};
}
this._datalist = new DataList(datalistJson);
if (this.id) {
this._datalist.api = "_design/pages/_list/as_data_list/list_of_data_by_session?key=%22" + this.id + "%22";
}
this.debug("Asking the datalist to check for changes in the database.");
if (typeof this._datalist.reindexFromApi !== "function") {
this.warn("This datalist isnt real, throwing error... ", this, this._datalist);
throw new Error("this DataList isnt real.");
}
this._datalist.reindexFromApi();
}
},
whenReindexedFromApi: {
get: function() {
if (this._datalist && this._datalist.whenReindexedFromApi) {
return this._datalist.whenReindexedFromApi;
}
},
set: function() {}
},
datalist: {
get: function() {
this.debug("Getting datalist " + this.id, this._datalist);
// if (!this._datalist || !(this._datalist instanceof DataList) || typeof this._datalist.reindexFromApi !== "function") {
// this.initializeDatalist();
// }
return this._datalist;
},
set: function(value) {
this.debug("Cant set the datalist on a session", this._datalist, value);
// this.ensureSetViaAppropriateType("datalist", value);
}
},
/**
* Accepts two functions to call back when save is successful or
* fails. If the fail callback is not overridden it will alert
* failure to the user.
*
* - Adds the session to the corpus if it is in the right corpus, and wasnt already there
* - Adds the session to the user if it wasn't already there
* - Adds an activity to the logged in user with diff in what the user changed.
*
* @param successcallback
* @param failurecallback
*/
saveAndInterConnectInApp: {
value: function(successcallback, failurecallback) {
var self = this;
var newModel = true;
if (this.id) {
newModel = false;
} else {
this.set("dateCreated", JSON.stringify(new Date()));
}
this.debug("Saving the Session");
//protect against users moving sessions from one corpus to another on purpose or accidentially
if (self.application.corpus.dbname !== this.dbname) {
if (typeof failurecallback === "function") {
failurecallback();
} else {
this.bug("Session save error. I cant save this session in this corpus, it belongs to another corpus. ");
}
return;
}
var oldrev = this.get("_rev");
this.set("dateModified", JSON.stringify(new Date()));
this.set("timestamp", Date.now());
self.save(null, {
success: function(model, response) {
self.debug("Session save success");
var goal = model.get("sessionFields").where({
label: "goal"
})[0].get("mask");
var differences = "#diff/oldrev/" + oldrev + "/newrev/" + response._rev;
//TODO add privacy for session goals in corpus
// if(self.application.corpus.get("keepSessionDetailsPrivate")){
// goal = "";
// differences = "";
// }
if (self.application) {
self.application.toastUser("Sucessfully saved session: " + goal, "alert-success", "Saved!");
self.application.addSavedDoc(model.id);
}
var verb = "modified";
var verbicon = "icon-pencil";
if (newModel) {
verb = "added";
verbicon = "icon-plus";
}
self.application.addActivity({
verb: "" + verb + " ",
verbicon: verbicon,
directobjecticon: "icon-calendar",
directobject: "" + goal + " ",
indirectobject: "in " + self.application.corpus.get("title") + "",
teamOrPersonal: "team",
context: " via Offline App."
});
self.application.addActivity({
verb: "" + verb + " ",
verbicon: verbicon,
directobjecticon: "icon-calendar",
directobject: "" + goal + " ",
indirectobject: "in " + self.application.corpus.get("title") + "",
teamOrPersonal: "personal",
context: " via Offline App."
});
/*
* make sure the session is visible in this corpus
*/
var previousversionincorpus = self.application.corpus.sessions.get(model.id);
if (previousversionincorpus === undefined) {
self.application.corpus.sessions.unshift(model);
} else {
self.application.corpus.sessions.remove(previousversionincorpus);
self.application.corpus.sessions.unshift(model);
}
self.application.get("authentication").get("userPrivate").get("mostRecentIds").sessionid = model.id;
//make sure the session is in the history of the user
if (self.application.get("authentication").get("userPrivate").get("sessionHistory").indexOf(model.id) === -1) {
self.application.get("authentication").get("userPrivate").get("sessionHistory").unshift(model.id);
}
// self.application.addUnsavedDoc(self.application.get("authentication").get("userPrivate").id);
self.application.get("authentication").saveAndInterConnectInApp();
if (typeof successcallback === "function") {
successcallback();
}
},
error: function(e, f, g) {
self.debug("Session save error", e, f, g);
if (typeof failurecallback === "function") {
failurecallback();
} else {
self.bug("Session save error: " + f.reason);
}
}
});
}
},
/**
* Accepts two functions success will be called if sucessfull,
* otherwise it will attempt to render the current session views. If
* the session isn't in the current corpus it will call the fail
* callback or it will alert a bug to the user. Override the fail
* callback if you don't want the alert.
*
* @param successcallback
* @param failurecallback
*/
setAsCurrentSession: {
value: function(successcallback, failurecallback) {
var self = this;
if (self.application.corpus.dbname !== this.dbname) {
if (typeof failurecallback === "function") {
failurecallback();
} else {
self.bug("This is a bug, cannot load the session you asked for, it is not in this corpus.");
}
return;
}
if (self.application.get("currentSession").id !== this.id) {
self.application.set("currentSession", this); //This results in a non-identical session in the currentsession with the one live in the corpus sessions collection.
// self.application.set("currentSession", app.corpus.sessions.get(this.id)); //this is a bad idea too, use above instead
}
self.application.get("authentication").get("userPrivate").get("mostRecentIds").sessionid = this.id;
self.application.get("authentication").saveAndInterConnectInApp(); //saving users is cheep
if (self.application) {
self.application.setUpAndAssociateViewsAndModelsWithCurrentSession(function() {
if (typeof successcallback === "function") {
successcallback();
} else {
self.application.currentSessionReadView.format = "leftSide";
self.application.currentSessionReadView.render();
self.application.toastUser("Sucessfully connected all views up to session: " + this.id, "alert-success", "Connected!");
// self.application.renderEditableSessionViews("leftSide");
// self.application.renderReadonlySessionViews("leftSide");
}
});
} else {
if (typeof successcallback === "function") {
successcallback();
}
}
}
},
toJSON: {
value: function(includeEvenEmptyAttributes, removeEmptyAttributes) {
this.debug("Customizing toJSON ", includeEvenEmptyAttributes, removeEmptyAttributes);
var attributesNotToJsonify = ["_docs", "_docIds", "_datalist", "docs", "docIds", "datalist", "whenReindexedFromApi"];
var json = FieldDBObject.prototype.toJSON.apply(this, [includeEvenEmptyAttributes, removeEmptyAttributes, attributesNotToJsonify]);
// Dont keep docids in a session, this would cause the datum to have sessions iwth data lists, of themselves. which is very heavy. instead sessions docs alwasy come from a reindinxing operation on the db, and only if the session is not just a stub.
// delete json._datalist;
// if (this._datalist && this._datalist.docIds && this._datalist.docIds.length > 0) {
// json.docIds = this.docIds;
// }
this.debug(json);
return json;
}
}
});
exports.Session = Session;
},{"./../FieldDBObject":3,"./../confidentiality_encryption/Confidential":17,"./../corpus/corpus.json":25,"./../data_list/DataList":28,"./DatumFields":33}],41:[function(require,module,exports){
var Datum = require("./Datum").Datum;
/**
* @class The Stimulus is a minimal customization of a Datum which allows the user to add additional information
* which can be used for experiments.
*
* @name Stimulus
* @extends Datum
* @constructs
*/
var Stimulus = function Stimulus(options) {
if (!this._fieldDBtype) {
this._fieldDBtype = "Stimulus";
}
this.debug("Constructing Stimulus ", options);
Datum.apply(this, arguments);
};
Stimulus.prototype = Object.create(Datum.prototype, /** @lends Stimulus.prototype */ {
constructor: {
value: Stimulus
},
prime: {
get: function() {
// if (this._prime) {
return this._prime;
// }
// return {
// "imageFile": "x.png",
// "utterance": "χχ",
// "orthography": "xx",
// "audioFile": "prime.mp3"
// };
},
set: function(value) {
this._prime = value;
}
},
target: {
get: function() {
// if (this._target) {
return this._target;
// }
// return {
// "imageFile": "x.png",
// "utterance": "χχ",
// "orthography": "x",
// "audioFile": "target.mp3"
// };
},
set: function(value) {
this._target = value;
}
},
distractors: {
get: function() {
// if (this._distractors) {
return this._distractors;
// }
// return [{
// "imageFile": "placeholder.jpg",
// "utterance": "ʁχχ",
// "orthography": "rxx",
// "audioFile": "distractor.mp3"
// }];
},
set: function(value) {
this._distractors = value;
}
},
layout: {
get: function() {
// if (this._layout) {
return this._layout;
// }
// return {
// randomize: false,
// visualChoiceA: this.target,
// visualChoiceB: this.distractors[0]
// };
},
set: function(value) {
this._layout = value;
}
}
});
exports.Stimulus = Stimulus;
},{"./Datum":31}],42:[function(require,module,exports){
/**
* @class The export class helps export a set of selected data into csv, xml
* and LaTex file.
* @name Export
*
* @property {Collection} datalist This is the data selected for export.
* @property {String} dataListName This is the name of the data set which
* appears as a filename when exported.
* @property {Array} fields The fields array contains titles of the fields.
* @property {Event} event The export event (e.g. click "LatexIt").
*
* @description The initialize serves to bind export to e.g. LaTexIt event.
*
*
* @extends Backbone.Model
* @constructs
*/
var Export = /** @lends Export.prototype */ {
initialize: function() {},
exportCSV: function() {},
exportXML: function() {},
exportLaTex: function() {},
};
exports.Export = Export;
},{}],43:[function(require,module,exports){
(function (global){
/* globals window, URL */
/**
* FieldDB
* A open ended database for evolving data collection projects
*
* @module FieldDB
* @tutorial tests/FieldDBTest.js
* @requires Export
* @requires FieldDBObject
* @requires CORS
* @requires UserMask
*/
(function(exports) {
"use strict";
var FieldDB = {};
var Activities = require("./activity/Activities").Activities;
FieldDB.Activities = Activities;
FieldDB["Activities"] = Activities;
var Activity = require("./activity/Activity").Activity;
FieldDB.Activity = Activity;
FieldDB["Activity"] = Activity;
var App = require("./app/App").App;
FieldDB.App = App;
FieldDB["App"] = App;
var AudioVideo = require("./audio_video/AudioVideo").AudioVideo;
FieldDB.AudioVideo = AudioVideo;
FieldDB["AudioVideo"] = AudioVideo;
var AudioVideoRecorder = require("./audio_video/AudioVideoRecorder").AudioVideoRecorder;
FieldDB.AudioVideoRecorder = AudioVideoRecorder;
FieldDB["AudioVideoRecorder"] = AudioVideoRecorder;
var AudioVideos = require("./audio_video/AudioVideos").AudioVideos;
FieldDB.AudioVideos = AudioVideos;
FieldDB["AudioVideos"] = AudioVideos;
var Authentication = require("./authentication/Authentication").Authentication;
FieldDB.Authentication = Authentication;
FieldDB["Authentication"] = Authentication;
var CORS = require("./CORS").CORS;
FieldDB.CORS = CORS;
FieldDB["CORS"] = CORS;
var Collection = require("./Collection").Collection;
FieldDB.Collection = Collection;
FieldDB["Collection"] = Collection;
var Comment = require("./comment/Comment").Comment;
FieldDB.Comment = Comment;
FieldDB["Comment"] = Comment;
var Comments = require("./comment/Comments").Comments;
FieldDB.Comments = Comments;
FieldDB["Comments"] = Comments;
var Confidential = require("./confidentiality_encryption/Confidential").Confidential;
FieldDB.Confidential = Confidential;
FieldDB["Confidential"] = Confidential;
var Connection = require("./corpus/Connection").Connection;
FieldDB.Connection = Connection;
FieldDB["Connection"] = Connection;
var Consultant = require("./user/Consultant").Consultant;
FieldDB.Consultant = Consultant;
FieldDB["Consultant"] = Consultant;
var ContextualizableObject = require("./locales/ContextualizableObject").ContextualizableObject;
FieldDB.ContextualizableObject = ContextualizableObject;
FieldDB["ContextualizableObject"] = ContextualizableObject;
var Contextualizer = require("./locales/Contextualizer").Contextualizer;
FieldDB.Contextualizer = Contextualizer;
FieldDB["Contextualizer"] = Contextualizer;
var Corpora = require("./corpus/Corpora").Corpora;
FieldDB.Corpora = Corpora;
FieldDB["Corpora"] = Corpora;
var Corpus = require("./corpus/Corpus").Corpus;
FieldDB.Corpus = Corpus;
FieldDB["Corpus"] = Corpus;
var CorpusMask = require("./corpus/CorpusMask").CorpusMask;
FieldDB.CorpusMask = CorpusMask;
FieldDB["CorpusMask"] = CorpusMask;
var DataList = require("./data_list/DataList").DataList;
FieldDB.DataList = DataList;
FieldDB["DataList"] = DataList;
var Database = require("./corpus/Database").Database;
FieldDB.Database = Database;
FieldDB["Database"] = Database;
var Datum = require("./datum/Datum").Datum;
FieldDB.Datum = Datum;
FieldDB["Datum"] = Datum;
var DatumField = require("./datum/DatumField").DatumField;
FieldDB.DatumField = DatumField;
FieldDB["DatumField"] = DatumField;
var DatumFields = require("./datum/DatumFields").DatumFields;
FieldDB.DatumFields = DatumFields;
FieldDB["DatumFields"] = DatumFields;
var ExperimentDataList = require("./data_list/ExperimentDataList").ExperimentDataList;
FieldDB.ExperimentDataList = ExperimentDataList;
FieldDB["ExperimentDataList"] = ExperimentDataList;
var Export = require("./export/Export");
FieldDB.Export = Export;
FieldDB["Export"] = Export;
var FieldDBConnection = require("./corpus/Database").FieldDBConnection;
FieldDB.FieldDBConnection = FieldDBConnection;
FieldDB["FieldDBConnection"] = FieldDBConnection;
var FieldDBImage = require("./image/Image").Image;
FieldDB.Image = FieldDBImage;
FieldDB["Image"] = FieldDBImage;
var FieldDBObject = require("./FieldDBObject").FieldDBObject;
FieldDB.FieldDBObject = FieldDBObject;
FieldDB["FieldDBObject"] = FieldDBObject;
var FieldDatabase = require("./corpus/Corpus").FieldDatabase;
FieldDB.FieldDatabase = FieldDatabase;
FieldDB["FieldDatabase"] = FieldDatabase;
var HotKeys = require("./hotkey/HotKeys").HotKeys;
FieldDB.HotKeys = HotKeys;
FieldDB["HotKeys"] = HotKeys;
var Images = require("./image/Images").Images;
FieldDB.Images = Images;
FieldDB["Images"] = Images;
var Import = require("./import/Import").Import;
FieldDB.Import = Import;
FieldDB["Import"] = Import;
var Participant = require("./user/Participant").Participant;
FieldDB.Participant = Participant;
FieldDB["Participant"] = Participant;
var Permission = require("./permission/Permission").Permission;
FieldDB.Permission = Permission;
FieldDB["Permission"] = Permission;
var Permissions = require("./permission/Permissions").Permissions;
FieldDB.Permissions = Permissions;
FieldDB["Permissions"] = Permissions;
var PsycholinguisticsApp = require("./app/PsycholinguisticsApp").PsycholinguisticsApp;
FieldDB.PsycholinguisticsApp = PsycholinguisticsApp;
FieldDB["PsycholinguisticsApp"] = PsycholinguisticsApp;
var PsycholinguisticsDatabase = require("./corpus/PsycholinguisticsDatabase").PsycholinguisticsDatabase;
FieldDB.PsycholinguisticsDatabase = PsycholinguisticsDatabase;
FieldDB["PsycholinguisticsDatabase"] = PsycholinguisticsDatabase;
var Response = require("./datum/Response").Response;
FieldDB.Response = Response;
FieldDB["Response"] = Response;
var Router = require("./Router").Router;
FieldDB.Router = Router;
FieldDB["Router"] = Router;
var Search = require("./search/Search").Search;
FieldDB.Search = Search;
FieldDB["Search"] = Search;
var Session = require("./datum/Session").Session;
FieldDB.Session = Session;
FieldDB["Session"] = Session;
var Speaker = require("./user/Speaker").Speaker;
FieldDB.Speaker = Speaker;
FieldDB["Speaker"] = Speaker;
var Stimulus = require("./datum/Stimulus").Stimulus;
FieldDB.Stimulus = Stimulus;
FieldDB["Stimulus"] = Stimulus;
var SubExperimentDataList = require("./data_list/SubExperimentDataList").SubExperimentDataList;
FieldDB.SubExperimentDataList = SubExperimentDataList;
FieldDB["SubExperimentDataList"] = SubExperimentDataList;
var Team = require("./user/Team").Team;
FieldDB.Team = Team;
FieldDB["Team"] = Team;
var UnicodeSymbol = require("./unicode/UnicodeSymbol").UnicodeSymbol;
FieldDB.UnicodeSymbol = UnicodeSymbol;
FieldDB["UnicodeSymbol"] = UnicodeSymbol;
var UnicodeSymbols = require("./unicode/UnicodeSymbols").UnicodeSymbols;
FieldDB.UnicodeSymbols = UnicodeSymbols;
FieldDB["UnicodeSymbols"] = UnicodeSymbols;
var User = require("./user/User").User;
FieldDB.User = User;
FieldDB["User"] = User;
var UserMask = require("./user/UserMask").UserMask;
FieldDB.UserMask = UserMask;
FieldDB["UserMask"] = UserMask;
var UserPreference = require("./user/UserPreference").UserPreference;
FieldDB.UserPreference = UserPreference;
FieldDB["UserPreference"] = UserPreference;
var Users = require("./user/Users").Users;
FieldDB.Users = Users;
FieldDB["Users"] = Users;
var Q = require("q");
FieldDB.Q = Q;
FieldDB["Q"] = Q;
CORS.bug = FieldDBObject.prototype.bug;
FieldDB.Document = FieldDB.FieldDBObject;
FieldDB["Document"] = FieldDB.FieldDBObject;
exports.FieldDB = FieldDB;
global.FieldDB = FieldDB;
setTimeout(function() {
var brandname = "FieldDB";
if (FieldDB && FieldDB["FieldDBObject"] && FieldDB["FieldDBObject"].application && FieldDB["FieldDBObject"].application.brand) {
brandname = FieldDB["FieldDBObject"].application.brand.replace(/\W/g, "_");
try {
window[brandname] = FieldDB;
// Inject browser URL as the URL parser.
Connection.URLParser = URL;
} catch (e) {
console.warn("Couldnt attach the FieldDB library as " + brandname, e);
// Inject nodejs URL as the URL parser.
Connection.URLParser = require("url");
}
}
console.log("-----------------------------------------------------");
console.log("-----------------------------------------------------");
console.log("-----------------------------------------------------");
console.log(" ___ _ _ _ ");
console.log(" | _ \\_____ __ _____ _ _ | | | |______ _ _( )___");
console.log(" | _/ _ \\ V V / -_| '_| | |_| (_-/ -_| '_|/(_-<");
console.log(" |_| \\___/\\_/\\_/\\___|_| \\___//__\\___|_| /__/");
console.log(" ___ _ _ _ ");
console.log(" |_ _|_ _| |_ ___ _ _ __ _ __| |_(___ _____ ");
console.log(" | || ' | _/ -_| '_/ _` / _| _| \\ V / -_)");
console.log(" |___|_||_\\__\\___|_| \\__,_\\__|\\__|_|\\_/\\___|");
console.log(" ___ _ ");
console.log(" / __|___ _ _ ______| |___ ");
console.log(" | (__/ _ | ' \\(_-/ _ | / -_)");
console.log(" \\___\\__.|_||_|__\\__.|_\\___|");
console.log(" ");
console.log("-----Power User's Interactive Console loaded " +
new FieldDB["FieldDBObject"]().version);
console.log("-----------------------------------------------------");
console.log("-----for available models/functionality, type--------");
console.log(" " + brandname + ".");
console.log("-----------------------------------------------------");
console.log("-----------------------------------------------------");
console.log("-----------------------------------------------------");
console.log("-----------------------------------------------------");
}, 1000);
}(typeof exports === "object" && exports || this));
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"./CORS":1,"./Collection":2,"./FieldDBObject":3,"./Router":4,"./activity/Activities":5,"./activity/Activity":6,"./app/App":7,"./app/PsycholinguisticsApp":8,"./audio_video/AudioVideo":10,"./audio_video/AudioVideoRecorder":11,"./audio_video/AudioVideos":12,"./authentication/Authentication":14,"./comment/Comment":15,"./comment/Comments":16,"./confidentiality_encryption/Confidential":17,"./corpus/Connection":19,"./corpus/Corpora":20,"./corpus/Corpus":21,"./corpus/CorpusMask":22,"./corpus/Database":23,"./corpus/PsycholinguisticsDatabase":24,"./data_list/DataList":28,"./data_list/ExperimentDataList":29,"./data_list/SubExperimentDataList":30,"./datum/Datum":31,"./datum/DatumField":32,"./datum/DatumFields":33,"./datum/Response":39,"./datum/Session":40,"./datum/Stimulus":41,"./export/Export":42,"./hotkey/HotKeys":45,"./image/Image":46,"./image/Images":47,"./import/Import":48,"./locales/ContextualizableObject":49,"./locales/Contextualizer":50,"./permission/Permission":55,"./permission/Permissions":56,"./search/Search":57,"./unicode/UnicodeSymbol":58,"./unicode/UnicodeSymbols":59,"./user/Consultant":60,"./user/Participant":61,"./user/Speaker":62,"./user/Team":63,"./user/User":64,"./user/UserMask":65,"./user/UserPreference":66,"./user/Users":67,"q":248,"url":243}],44:[function(require,module,exports){
var FieldDBObject = require("./../FieldDBObject").FieldDBObject;
/**
* @class A HotKey is a keyboard shortcut that uses one key (or a
* combination thereof) which allows users to execute a command
* without using a mouse, a menu, etc.
*
* @name HotKey
* @extends FieldDBObject
* @constructs
*/
var HotKey = function HotKey(options) {
if (!this._fieldDBtype) {
this._fieldDBtype = "HotKey";
}
this.debug("Constructing HotKey", options);
FieldDBObject.apply(this, arguments);
};
HotKey.prototype = Object.create(FieldDBObject.prototype, /** @lends HotKey.prototype */ {
constructor: {
value: HotKey
},
defaults: {
value: {
firstKey: "",
secondKey: "",
functiontocall: function() {},
description: ""
}
},
keySequence: {
get: function() {
var value = this.firstKey + "+" + this.secondKey;
this.debug("Getting keySequence " + value);
return value;
}
}
});
exports.HotKey = HotKey;
},{"./../FieldDBObject":3}],45:[function(require,module,exports){
var Collection = require("./../Collection").Collection;
var HotKey = require("./HotKey").HotKey;
/**
* @class HotKeys is a set of HotKey. A user will be able to have multiple shortcuts.
* There will be defaults, but users will also be able to select their own HotKeys.
*
* IPA This will allow users to easily switch to type in IPA
* fullscreen This will expand the view
* nextDatum This will allow users to skip to the next datum entry field
* previousDatum This will allow users to go back to the previous datum entry field
* sync This will allow users to easily sync to the server
*
* @name HotKeys
*
* @extends Collection
* @constructs
*/
var HotKeys = function HotKeys(options) {
if (!this._fieldDBtype) {
this._fieldDBtype = "HotKeys";
}
if (options && options.firstkey === "" && options.secondKey === "" && options.description === "") {
options = null;
this.debug("Upgrading pre v2 hotkeys");
}
this.debug("Constructing HotKeys ", options);
Collection.apply(this, arguments);
};
HotKeys.prototype = Object.create(Collection.prototype, /** @lends HotKeys.prototype */ {
constructor: {
value: HotKeys
},
primaryKey: {
value: "keySequence"
},
INTERNAL_MODELS: {
value: {
item: HotKey
}
}
});
exports.HotKeys = HotKeys;
},{"./../Collection":2,"./HotKey":44}],46:[function(require,module,exports){
var AudioVideo = require("./../audio_video/AudioVideo").AudioVideo;
/**
* @class The Image is a type of AudioVideo with any additional fields or
* metadata that a team might use to visually ground their data.
*
* @name Image
* @extends AudioVideo
* @constructs
*/
var Image = function Image(options) {
if (!this._fieldDBtype) {
this._fieldDBtype = "Image";
}
this.debug("Constructing Image length: ", options);
AudioVideo.apply(this, arguments);
};
Image.prototype = Object.create(AudioVideo.prototype, /** @lends Image.prototype */ {
constructor: {
value: Image
},
api: {
value: "images"
}
});
exports.Image = Image;
},{"./../audio_video/AudioVideo":10}],47:[function(require,module,exports){
var Collection = require("./../Collection").Collection;
var Image = require("./Image").Image;
/**
* @class Images of Datum validation states
* @name Images
* @description The Images is a minimal customization of the Collection
* to add an internal model of Image.
*
* @extends Collection
* @constructs
*/
var Images = function Images(options) {
if (!this._fieldDBtype) {
this._fieldDBtype = "Images";
}
this.debug("Constructing Images length: ", options);
Collection.apply(this, arguments);
};
Images.prototype = Object.create(Collection.prototype, /** @lends Images.prototype */ {
constructor: {
value: Images
},
primaryKey: {
value: "URL"
},
INTERNAL_MODELS: {
value: {
item: Image
}
}
});
exports.Images = Images;
},{"./../Collection":2,"./Image":46}],48:[function(require,module,exports){
/* globals window, escape, $, FileReader, FormData, atob, unescape, Blob */
var FieldDBImage = require("./../image/Image").Image;
var AudioVideo = require("./../audio_video/AudioVideo").AudioVideo;
var AudioVideos = require("./../audio_video/AudioVideos").AudioVideos;
var Collection = require("./../Collection").Collection;
var CORS = require("./../CORS").CORS;
var Corpus = require("./../corpus/Corpus").Corpus;
// var DataList = require("./../data_list/DataList").DataList;
var Participant = require("./../user/Participant").Participant;
var Datum = require("./../datum/Datum").Datum;
var DatumField = require("./../datum/DatumField").DatumField;
var DatumFields = require("./../datum/DatumFields").DatumFields;
var FieldDBObject = require("./../FieldDBObject").FieldDBObject;
// var FileReader = {};
var Session = require("./../datum/Session").Session;
var TextGrid = require("textgrid").TextGrid;
var X2JS = {};
var Q = require("q");
var _ = require("underscore");
/**
* @class The import class helps import csv, xml and raw text data into a corpus, or create a new corpus.
*
* @property {FileList} files These are the file(s) that were dragged in.
* @property {String} dbname This is the corpusid wherej the data should be imported
* @property {DatumFields} fields The fields array contains titles of the data columns.
* @property {DataList} datalist The datalist imported, to hold the data before it is saved.
* @property {Event} event The drag/drop event.
*
* @description The initialize serves to bind import to all drag and drop events.
*
* @extends FieldDBObject
* @tutorial tests/CorpusTest.js
*/
//http://stackoverflow.com/questions/4998908/convert-data-uri-to-file-then-append-to-formdata
var dataURItoBlob = function(dataURI) {
// convert base64/URLEncoded data component to raw binary data held in a string
var byteString;
if (dataURI.split(",")[0].indexOf("base64") >= 0) {
byteString = atob(dataURI.split(",")[1]);
} else {
byteString = unescape(dataURI.split(",")[1]);
}
// separate out the mime component
var mimeString = dataURI.split(",")[0].split(":")[1].split(";")[0];
// write the bytes of the string to a typed array
var ia = new Uint8Array(byteString.length);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
return new Blob([ia], {
type: mimeString
});
};
var getUnique = function(arrayObj) {
var u = {},
a = [];
for (var i = 0, l = arrayObj.length; i < l; ++i) {
if (u.hasOwnProperty(arrayObj[i])) {
continue;
}
if (arrayObj[i]) {
a.push(arrayObj[i]);
u[arrayObj[i]] = 1;
}
}
return a;
};
var Import = function Import(options) {
if (!this._fieldDBtype) {
this._fieldDBtype = "Import";
}
this.debug(" new import ", options);
FieldDBObject.apply(this, arguments);
options = options || {};
var sessionOptions = options.session || {};
sessionOptions.datalist = options.datalist || {
title: {
default: "Imported Data"
},
docs: {
id: "tempdatalist",
collection: [],
primaryKey: "tempId"
},
// confidential: self.corpus.confidential,
// debugMode: true
};
this.session = sessionOptions;
this.session.goal = "Goal from file import";
};
Import.prototype = Object.create(FieldDBObject.prototype, /** @lends Import.prototype */ {
constructor: {
value: Import
},
fillWithDefaults: {
value: function() {
if (!this.datumFields) {
this.datumFields = this.corpus.datumFields.clone();
}
}
},
defaults: {
get: function() {
return {
status: "",
showImportFirstStep: true,
showImportSecondStep: false,
showImportThirdStep: false,
progress: {
total: 0,
completed: 0
},
datalist: {},
session: {},
dbname: "",
files: [],
asFieldMatrix: [],
asCSV: []
};
},
set: function() {}
},
INTERNAL_MODELS: {
value: {
progress: {},
// datalist: DataList,
datumFields: DatumFields,
session: Session,
corpus: Corpus
}
},
showImportSecondStep: {
get: function() {
if (this.dontShowSecondStep) {
return false;
}
return this.asCSV && this.asCSV.length > 0;
},
set: function() {}
},
showImportThirdStep: {
get: function() {
return this.datalist && this.datalist.docs && this.datalist.docs.length > 0;
},
set: function() {}
},
addFileUri: {
value: function(options) {
var deferred = Q.defer(),
self = this;
if (!options) {
throw new Error("Options must be specified {}");
}
if (!options.uri) {
throw new Error("Uri must be specified in the options in order to import it" + JSON.stringify(options));
}
Q.nextTick(function() {
self.readUri(options)
.then(function() {
return self.preprocess.apply(self, arguments);
})
.then(function() {
return self.import.apply(self, arguments);
})
.then(function(result) {
self.debug("Import is finished");
if (options && typeof options.next === "function" /* enable use as middleware */ ) {
options.next();
}
self.debug("result.datum", result.datum);
self.files.add(result.datum);
deferred.resolve(result);
})
.fail(function(reason) {
console.error(reason.stack);
deferred.reject(reason);
});
});
return deferred.promise;
}
},
readUri: {
value: function(options) {
var deferred = Q.defer(),
self = this;
Q.nextTick(function() {
if (!options) {
throw new Error("Options must be specified {}");
}
var pipeline = function(optionsWithADatum) {
if (optionsWithADatum.readOptions) {
optionsWithADatum.readOptions.readFileFunction(function(err, data) {
if (err) {
deferred.reject(err);
} else {
optionsWithADatum.rawText = data;
deferred.resolve(optionsWithADatum);
}
});
} else {
self.debug("TODO reading url in browser");
CORS.makeCORSRequest({
type: "GET",
dataType: "json",
uri: optionsWithADatum.uri
}).then(function(data) {
self.debug(data);
optionsWithADatum.rawText = data;
deferred.resolve(optionsWithADatum);
},
function(reason) {
self.debug(reason);
deferred.reject(reason);
}).fail(
function(error) {
console.error(error.stack, self);
deferred.reject(error);
});
}
};
self.corpus.find(options.uri)
.then(function(similarData) {
if (similarData.length === 1) {
options.datum = similarData[0];
pipeline(options);
} else {
// self.debug("readUri corpus", self);
self.corpus.newDatumAsync().then(function(datum) {
options.datum = datum;
pipeline(options);
});
}
})
.fail(function(reason) {
deferred.reject(reason);
});
});
return deferred.promise;
}
},
convertTableIntoDataList: {
value: function(options) {
this.warn("convertTableIntoDataList is deprecated, use convertMatrixIntoDataList");
return this.convertMatrixIntoDataList(options);
}
},
convertMatrixIntoDataList: {
value: function() {
var self = this,
deferred = Q.defer();
if (this.importType === "participants" && (!this.corpus || !this.corpus.confidential || !this.corpus.confidential.secretkey)) {
Q.nextTick(function() {
deferred.reject({
userFriendlyErrors: ["Cannot create encrypted participants at this time", "Corpus's encrypter isn't available right now, maybe the app is still loading?"]
});
});
return deferred.promise;
}
if (!this.asFieldMatrix || this.asFieldMatrix.length === 0) {
Q.nextTick(function() {
deferred.reject({
userFriendlyErrors: ["There was nothing to import. Are you sure you ran step 1?"]
});
});
return deferred.promise;
}
Q.nextTick(function() {
deferred.resolve(self.datalist);
});
try {
if (!self.progress) {
self.progress = {
total: 0,
completed: 0
};
}
self.progress.total = self.asFieldMatrix.length;
var filename = " typing/copy paste into text area";
var descript = "This is the data list which results from the import of the text typed/pasted in the import text area.";
try {
filename = self.files.map(function(file) {
return file.name;
}).join(", ");
descript = "This is the data list which results from the import of these file(s). " + self.fileDetails;
} catch (e) {
self.todo("turn the copy pasted text into a File to upload");
}
// self.render();
self.session.consultants = [];
/* put metadata in the session goals */
if (self.metadataLines) {
self.session.goal = self.metadataLines.join("\n") + "\n" + self.session.goal;
}
self.render("session");
self.datalist.description = descript;
if (!self.extractedHeaderObjects) {
self.warn("There was no extracted header.");
if (self.asFieldMatrix && self.asFieldMatrix.length > 0 && self.asFieldMatrix[0].concat) {
self.warn("Using the first row as the extracted header.");
self.extractedHeaderObjects = self.asFieldMatrix[0].concat([]);
// self.extractedHeaderObjects = JSON.parse(JSON.stringify(self.asFieldMatrix[0]));
// self.extractedHeaderObjects = self.asFieldMatrix.shift();
self.extractedHeaderObjects = self.extractedHeaderObjects.map(function(object) {
if (object === "" || object === undefined || object === null) {
return;
}
if (object && !object.id && object.value !== undefined && object.value !== null) {
object.id = object.value;
object.value = "";
}
return object;
});
} else {
return deferred.promise;
}
}
var fieldLabelFromExtractedHeader,
correspondingDatumField,
columnIndex;
try {
var getColumnHeadings = function(obj) {
if (obj && obj.id && obj.id !== "columnplaceholder") {
return "";
}
return obj.id;
};
// this.debugMode = true;
for (columnIndex = 0; columnIndex < self.extractedHeaderObjects.length; columnIndex++) {
fieldLabelFromExtractedHeader = self.extractedHeaderObjects[columnIndex].id || self.extractedHeaderObjects[columnIndex];
correspondingDatumField = self.normalizeImportFieldWithExistingCorpusFields(fieldLabelFromExtractedHeader);
if (correspondingDatumField && correspondingDatumField.id) {
var fields = self.extractedHeaderObjects.map(getColumnHeadings);
if (fields.indexOf(correspondingDatumField.id) >= 0) {
self.bug("You seem to have some column labels '" + correspondingDatumField.id + "' that are duplicated" +
" (the same label on two columns). This will result in a strange " +
"import where only the second of the two will be used in the import. " +
"Is this really what you want?.");
}
}
self.debug(columnIndex + " correspondingDatumField", correspondingDatumField);
self.debug("setting extractedHeaderObjects was once problematic", self.extractedHeaderObjects[columnIndex], correspondingDatumField);
self.extractedHeaderObjects[columnIndex] = correspondingDatumField;
}
// this.debugMode = false;
} catch (e) {
this.warn(e);
this.warn(e.stack);
throw new Error(" problem in extractedHeaderObjects ");
}
if (self.debugMode) {
// self.debug(" these are the extracted header cells ", self.extractedHeaderObjects.map(function(field) {
// return field.id;
// }));
}
if (self.debugMode) {
self.debug("JSON.stringify(self.extractedHeaderObjects, null, 2)");
self.extractedHeaderObjects.map(function(headerField) {
self.debug("headerField", headerField);
});
}
/*
* Cycle through all the rows in table and create a datum with the matching fields.
*/
var testForEmptyness,
cellIndex,
cell;
self.asFieldMatrix.map(function(row) {
self.progress.completed = self.progress.completed + 1;
if (!row || row.length < 1) {
self.debug("Skipping empty row");
return;
}
self.debug("Working on row ", row);
var docToSave;
self.debug("Cloning fields ", self.extractedHeaderObjects.length);
var fields = self.extractedHeaderObjects.map(function(headerField) {
return headerField.toJSON();
});
self.debug("Cloned fields ", fields.length);
self.debug("fields[0] equals extractedHeaderObjects[0]", fields[0] === self.extractedHeaderObjects[0]);
if (self.importType === "participants") {
docToSave = new Participant({
fields: fields
});
self.debug("Creating a participant.", row);
} else if (self.importType === "audioVideo") {
docToSave = new AudioVideo();
docToSave.description = self.rawText; //TODO look into the textgrid import
self.debug("Creating a audioVideo.", docToSave.description);
} else {
docToSave = new Datum({
fields: fields
});
self.debug("Creating a datum.", row);
}
docToSave.confidential = self.corpus.confidential;
// docToSave.decryptedMode = true;
// return;
testForEmptyness = "";
for (cellIndex = 0; cellIndex < row.length; cellIndex++) {
cell = row[cellIndex];
self.debug("working on cell ", cell);
if (!cell || cellIndex > self.extractedHeaderObjects.length || self.extractedHeaderObjects[cellIndex].id === "columnplaceholder") {
self.debug("Skipping column " + cellIndex + " :", cell);
continue;
}
if (self.importType === "audioVideo") {
self.debug("this is an audioVideo but we arent doing anything with the self.importFields");
} else {
for (var attrib in cell) {
if (cell.hasOwnProperty(attrib)) {
docToSave.fields._collection[cellIndex][attrib] = cell[attrib];
}
}
/* user can edit the matrix and it will show in the data list */
row[cellIndex] = docToSave.fields._collection[cellIndex];
}
testForEmptyness += cell.value;
}
//if the table row has more than 2 non-white space characters, enter it as data
if (testForEmptyness.replace(/[ \t\n]/g, "").length >= 2) {
if (self.debugMode) {
// self.debug("new doc", docToSave.fields.map(function(field) {
// return field.value
// }));
}
// docToSave.tempId = docToSave.id = FieldDBObject.uuidGenerator();
if (docToSave) {
docToSave.tempId = FieldDBObject.uuidGenerator();
docToSave.dbname = self.corpus.dbname;
self.datalist.add(docToSave);
}
} else {
self.debug("Didn't add row with only blank cells:" + testForEmptyness + ": ");
}
});
self.debug("Finished building the data list");
self.showImportThirdStep = true;
self.render();
self.progress.total = self.progress.completed = self.datalist.length;
// /*
// * after building an array of datumobjects, turn them into backbone objects
// */
// var eachFileDetails = function(fileDetails) {
// var details = JSON.parse(JSON.stringify(fileDetails));
// delete details.textgrid;
// audioFileDescriptionsKeyedByFilename[fileDetails.fileBaseName + ".mp3"] = details;
// };
// var forEachRow = function(index, value) {
// if (index === "" || index === undefined) {
// //do nothing
// }
// /* TODO removing old tag code for */
// // else if (index === "datumTags") {
// // var tags = value.split(" ");
// // for(g in tags){
// // var t = new DatumTag({
// // "tag" : tags[g]
// // });
// // d.get("datumTags").add(t);
// // }
// // }
// /* turn the CheckedWithConsultant and ToBeCheckedWithConsultantinto columns into a status, with that string as the person */
// else if (index.toLowerCase().indexOf("checkedwithconsultant") > -1) {
// var consultants = [];
// if (value.indexOf(",") > -1) {
// consultants = value.split(",");
// } else if (value.indexOf(";") > -1) {
// consultants = value.split(";");
// } else {
// consultants = value.split(" ");
// }
// var validationStati = [];
// for (var g in consultants) {
// var consultantusername = consultants[g].toLowerCase();
// self.consultants.push(consultantusername);
// if (!consultantusername) {
// continue;
// }
// var validationType = "CheckedWith";
// var validationColor = "success";
// if (index.toLowerCase().indexOf("ToBeChecked") > -1) {
// validationType = "ToBeCheckedWith";
// validationColor = "warning";
// }
// var validationString = validationType + consultants[g].replace(/[- _.]/g, "");
// validationStati.push(validationString);
// var n = fields.where({
// label: "validationStatus"
// })[0];
// /* add to any exisitng validation states */
// var validationStatus = n.get("mask") || "";
// validationStatus = validationStatus + " ";
// validationStatus = validationStatus + validationStati.join(" ");
// var uniqueStati = _.unique(validationStatus.trim().split(" "));
// n.set("mask", uniqueStati.join(" "));
// // ROUGH DRAFT of adding CONSULTANTS logic TODO do self in the angular app, dont bother with the backbone app
// // /* get the initials from the data */
// // var consultantCode = consultants[g].replace(/[a-z -]/g,"");
// // if(consultantusername.length === 2){
// // consultantCode = consultantusername;
// // }
// // if(consultantCode.length < 2){
// // consultantCode = consultantCode+"C";
// // }
// // var c = new Consultant("username", consultantCode);
// // /* use the value in the cell for the checked with state, but don't keep the spaces */
// // var validationType = "CheckedWith";
// // if(index.toLowerCase().indexOf("ToBeChecked") > -1){
// // validationType = "ToBeCheckedWith";
// // }
// // /*
// // * This function uses the consultant code to create a new validation status
// // */
// // var onceWeGetTheConsultant = function(){
// // var validationString = validationType+consultants[g].replace(/ /g,"");
// // validationStati.push(validationString);
// // var n = fields.where({label: "validationStatus"})[0];
// // if(n !== undefined){
// // /* add to any exisitng validation states */
// // var validationStatus = n.get("mask") || "";
// // validationStatus = validationStatus + " ";
// // validationStatus = validationStatus + validationStati.join(" ");
// // var uniqueStati = _.unique(validationStatus.trim().split(" "));
// // n.set("mask", uniqueStati.join(" "));
// // }
// // };
// // /*
// // * This function creates a consultant code and then calls
// // * onceWeGetTheConsultant to create a new validation status
// // */
// // var callIfItsANewConsultant = function(){
// // var dialect = "";
// // var language = "";
// // try{
// // dialect = fields.where({label: "dialect"})[0] || "";
// // language = fields.where({label: "language"})[0] || "";
// // }catch(e){
// // self.debug("Couldn't get self consultant's dialect or language");
// // }
// // c = new Consultant({filledWithDefaults: true});
// // c.set("username", Date.now());
// // if(dialect)
// // c.set("dialect", dialect);
// // if(dialect)
// // c.set("language", language);
// //
// // onceWeGetTheConsultant();
// // };
// // c.fetch({
// // success : function(model, response, options) {
// // onceWeGetTheConsultant();
// // },
// // error : function(model, xhr, options) {
// // callIfItsANewConsultant();
// // }
// // });
// }
// } else if (index === "validationStatus") {
// var eachValidationStatus = fields.where({
// label: index
// })[0];
// if (eachValidationStatus !== undefined) {
// /* add to any exisitng validation states */
// var selfValidationStatus = eachValidationStatus.get("mask") || "";
// selfValidationStatus = selfValidationStatus + " ";
// selfValidationStatus = selfValidationStatus + value;
// var selfUniqueStati = _.unique(selfValidationStatus.trim().split(" "));
// eachValidationStatus.set("mask", selfUniqueStati.join(" "));
// }
// } else if (index === "audioFileName") {
// if (!audioVideo) {
// audioVideo = new AudioVideo();
// }
// audioVideo.set("filename", value);
// audioVideo.set("orginalFilename", audioFileDescriptionsKeyedByFilename[value] ? audioFileDescriptionsKeyedByFilename[value].name : "");
// audioVideo.set("URL", self.audioUrl + "/" + window.app.get("corpus").dbname + "/" + value);
// audioVideo.set("description", audioFileDescriptionsKeyedByFilename[value] ? audioFileDescriptionsKeyedByFilename[value].description : "");
// audioVideo.set("details", audioFileDescriptionsKeyedByFilename[value]);
// } else if (index === "startTime") {
// if (!audioVideo) {
// audioVideo = new AudioVideo();
// }
// audioVideo.set("startTime", value);
// } else if (index === "endTime") {
// if (!audioVideo) {
// audioVideo = new AudioVideo();
// }
// audioVideo.set("endTime", value);
// } else {
// var knownlowercasefields = "utterance,gloss,morphemes,translation".split();
// if (knownlowercasefields.indexOf(index.toLowerCase()) > -1) {
// index = index.toLowerCase();
// }
// var igtField = fields.where({
// label: index
// })[0];
// if (igtField !== undefined) {
// igtField.set("mask", value);
// }
// }
// };
// for (var a in array) {
// var d = new Datum({
// filledWithDefaults: true,
// dbname: self.dbname
// });
// //copy the corpus"s datum fields and empty them.
// var datumfields = self.importFields.clone();
// for (var x in datumfields) {
// datumfields[x].mask = "";
// datumfields[x].value = "";
// }
// var fields = new DatumFields(datumfields);
// var audioVideo = null;
// var audioFileDescriptionsKeyedByFilename = {};
// if (self.files && self.files.map) {
// self.files.map(eachFileDetails);
// }
// $.each(array[a], forEachRow);
// d.set("datumFields", fields);
// if (audioVideo) {
// d.audioVideo.add(audioVideo);
// if (self.debugMode) {
// self.debug(JSON.stringify(audioVideo.toJSON()) + JSON.stringify(fields.toJSON()));
// }
// }
// // var states = window.app.get("corpus").get("datumStates").clone();
// // d.set("datumStates", states);
// d.set("session", self.get("session"));
// //these are temp datums, dont save them until the user saves the data list
// self.importPaginatedDataListDatumsView.collection.add(d);
// // self.dataListView.model.get("datumIds").push(d.id); the datum has no id, cannot put in datumIds
// d.lookForSimilarDatum();
// self.get("files").push(d);
// }
// self.set("consultants", _.unique(self.consultants).join(","));
// self.importPaginatedDataListDatumsView.renderUpdatedPaginationControl();
// $(".approve-save").removeAttr("disabled");
// $(".approve-save").removeClass("disabled");
} catch (e) {
self.warn("There was a problem while converting the matrix into a data list.", e);
self.warn(e.stack);
deferred.reject("There was a problem while converting the matrix into a data list.");
}
return deferred.promise;
}
},
// savedcount : 0,
// savedindex : [],
// savefailedcount : 0,
// savefailedindex : [],
// nextsavedatum : 0,
preprocess: {
value: function(options) {
var deferred = Q.defer(),
self = this;
this.verbose("In the preprocess", this);
Q.nextTick(function() {
self.debug("Preprocessing ");
try {
var failFunction = function(reason) {
if (options && typeof options.next === "function" /* enable use as middleware */ ) {
options.next();
}
deferred.reject(reason);
};
var successFunction = function(optionsWithResults) {
self.debug("Preprocesing success");
if (optionsWithResults && typeof optionsWithResults.next === "function" /* enable use as middleware */ ) {
optionsWithResults.next();
}
deferred.resolve(optionsWithResults);
};
options.datum.datumFields.orthography.value = options.rawText;
options.datum.datumFields.utterance.value = options.rawText;
options.datum.id = options.uri;
self.debug("running write for preprocessed");
if (options.preprocessOptions && options.preprocessOptions.writePreprocessedFileFunction) {
options.preprocessedUrl = options.uri.substring(0, options.uri.lastIndexOf(".")) + "_preprocessed.json";
var preprocessResult = JSON.stringify(options.datum.toJSON(), null, 2);
deferred.resolve(options);
options.preprocessOptions.writePreprocessedFileFunction(options.preprocessedUrl,
preprocessResult,
function(err, data) {
self.debug("Wrote " + options.preprocessedUrl, data);
if (err) {
failFunction(err);
} else {
successFunction(options);
}
});
} else {
successFunction(options);
}
} catch (e) {
deferred.reject(e);
}
});
return deferred.promise;
}
},
importFields: {
get: function() {
if (!this._importFields || this._importFields.length === 0) {
if (this.importType === "participants") {
if (this.corpus && this.corpus.participantFields) {
this._importFields = new DatumFields(this.corpus.participantFields.clone());
} else {
this._importFields = new DatumFields(this.corpus.defaults_psycholinguistics.participantFields);
}
} else if (this.corpus && this.corpus.datumFields) {
this._importFields = new DatumFields(this.corpus.datumFields.clone());
}
}
if (!this._importFields) {
this._importFields = new DatumFields();
}
return this._importFields;
},
set: function(fields) {
this._importFields = fields;
}
},
/**
* This function looks for the field's details from the import fields, if they exist it returns those values.
*
* If the field isnt in the importFields, it looks for fields which this field should map to (eg, if the field is codepermanent it can be mapped to anonymouscode)
* @param {String/Object} field A datumField to look for, or the label/id of a datum field to look for.
* @return {DatumField} A datum field with details filled in from the corresponding field in the corpus, or from a template.
*/
normalizeImportFieldWithExistingCorpusFields: {
value: function(field) {
var correspondingDatumField;
if (this.corpus && this.corpus.normalizeFieldWithExistingCorpusFields) {
correspondingDatumField = this.corpus.normalizeFieldWithExistingCorpusFields(field, this.importFields);
}
this.debug("correspondingDatumField ", correspondingDatumField);
if (correspondingDatumField) {
return correspondingDatumField;
} else {
return new DatumField({
id: "columnplaceholder",
value: ""
});
}
}
},
/**
* Executes the final import if the options indicate that it should be executed, by default it only produces a dry run.
*
* @type {Object}
*/
import: {
value: function(options) {
var deferred = Q.defer(),
self = this;
this.todo("TODO test the import");
if (options && typeof options.next === "function" /* enable use as middleware */ ) {
options.next();
}
var savePromises = [];
var docsToSave = [];
if (this.datalist.docs && this.datalist.docs._collection) {
docsToSave = this.datalist.docs._collection;
} else {
this.warn("There were no docs prepared for import, this is odd.");
}
docsToSave.map(function(builtDoc) {
if (self.importType === "audioVideo") {
self.debug("not doing any save for an audio video import");
} else {
self.bug("test the save on the new docs from import");
if (self.importType === "participant") {
builtDoc.id = builtDoc.anonymousCode || Date.now();
}
builtDoc.session = self.session;
self.debug(" saving", builtDoc.id);
self.progress.total++;
// self.datalist.docs.add(builtDoc);
var promise = builtDoc.save();
promise.then(function(success) {
self.debug(success);
self.progress.completed++;
}, function(error) {
self.debug(error);
self.progress.completed++;
}).fail(function(error) {
console.error(error.stack, self);
deferred.reject(error);
});
savePromises.push(promise);
}
});
Q.allSettled(savePromises).then(function(results) {
self.debug(results);
deferred.resolve(results);
self.progress.completed++;
self.render();
return options;
}, function(results) {
self.debug(results);
deferred.resolve(results);
self.progress.completed++;
self.render();
return options;
}).fail(function(error) {
console.error(error.stack, self);
deferred.reject(error);
});
return deferred.promise;
}
},
fileDetails: {
get: function() {
return this._fileDetails || FieldDBObject.DEFAULT_STRING;
},
set: function(value) {
this._fileDetails = value;
}
},
/**
* Holds meta data about the imported data list and references to the datum ids
*
* @type {Object}
*/
datalist: {
get: function() {
if (!this.session || !this.session.datalist) {
return;
// this.debug("creating a default data list");
// this.session.datalist = new DataList();
// console.log("this.session.datalist", this.session.datalist);
}
return this.session.datalist;
},
set: function(value) {
if (this._session && value === this._session.datalist) {
return this;
}
if (!value || !value || !value.docs || !value.docs.primaryKey || value.docs.primaryKey !== "tempId") {
this.warn(" not setting the datalist, its missing some stuff ", value);
return this;
}
this.debug(" setting the _session.datalist", value.docs.primaryKey);
delete this._session._datalist;
this._session.initializeDatalist(value);
return this;
}
},
session: {
get: function() {
if (!this._session) {
this.debug("There's no session!");
return;
}
this.debug("getting the _session", this._session);
return this._session;
},
set: function(value) {
if (value === this._session) {
return;
}
if (!value || !value.datalist || !value.datalist.docs) {
this.warn(" not setting the session on import, its missing some stuff ", value);
return;
}
value.datalist.docs.primaryKey = "tempId";
var datalist = value.datalist;
this.debug(" setting the _session", value);
if (!(value instanceof Session)) {
value = new Session(value);
}
this.debug(" setting the _session's datalist", datalist);
this._session = value;
// this._session.initializeDatalist(datalist);
this.datalist = datalist;
return;
}
},
/**
* Holds the files themselves while the import is in process
*
* @type {Object}
*/
files: {
get: function() {
this.debug("Getting Datum collection");
if (!this._files) {
this._files = new Collection({
id: "importfiles",
inverted: false,
primaryKey: "fileName"
});
}
this.debug("Returning a collection");
return this._files;
},
set: function(value) {
if (value === this._files) {
return;
}
this._files = value;
}
},
/**
* Saves the import's state to file to be resumed or reviewed later
*
* @type {Object}
*/
pause: {
value: function(options) {
if (options && typeof options.next === "function" /* enable use as middleware */ ) {
options.next();
}
return this;
}
},
/**
* Resumes a previous import from a json object, or a uri containing json
*
* @type {Object}
*/
resume: {
value: function(options) {
if (options && typeof options.next === "function" /* enable use as middleware */ ) {
options.next();
}
return this;
}
},
id: {
get: function() {
if (this.datalist) {
return this.datalist.id;
}
},
set: function(value) {
if (this.datalist) {
this.datalist.id = value;
}
}
},
url: {
value: "/datalists"
},
corpus: {
get: function() {
if (!this._corpus) {
// throw new Error("Import\"s corpus is undefined");
// this.warn("Import\"s corpus is undefined");
return;
}
return this._corpus;
},
set: function(value) {
if (value === this._corpus) {
return;
}
this._corpus = value;
}
},
asFieldMatrix: {
get: function() {
return this._asFieldMatrix;
},
set: function(value) {
this._asFieldMatrix = value;
}
},
asCSV: {
get: function() {
return this.asFieldMatrix;
},
set: function(value) {
var tryAsNumber,
tryAsDate;
value = value.map(function(row) {
return row.map(function(cell) {
if (cell === undefined || cell === null) {
cell = {
value: ""
};
}
if (typeof cell !== "object") {
cell = {
value: cell
};
}
if (cell && cell.value && typeof cell.value.trim === "function") {
cell.value = cell.value.trim();
}
if (cell.value !== "") {
tryAsNumber = Number(cell.value);
if (!isNaN(tryAsNumber)) {
cell.value = tryAsNumber;
cell.type = "number";
} else {
tryAsDate = new Date(cell.value);
if (!isNaN(tryAsDate.getDate() && tryAsDate.getYear() > 70)) {
// cell.value = tryAsDate;
cell.type = "date";
cell.json = {
"date": tryAsDate,
"timestamp": {
// "start": tryAsDate,
"end": tryAsDate.getTime(),
// "accuracy": null
}
};
}
}
}
return cell;
});
});
this.asFieldMatrix = value;
}
},
/**
* This function tries to guess if you have \n or \r as line endings
* and then tries to determine if you have "surounding your text".
*
* CSV is a common export format for Filemaker, Microsoft Excel and
* OpenOffice Spreadsheets, and could be a good format to export
* from these sources and import into FieldDB.
*
* @param text to be imported
*/
importCSV: {
value: function(text, callback) {
if (!text) {
return;
}
var rows = text.split("\n");
if (rows.length < 3) {
var macrows = text.split("\r");
if (macrows.length > rows.length) {
rows = macrows;
this.status = this.status + " Detected a \r line ending.";
}
}
var firstrow = rows[0];
var hasQuotes = false;
//If it looks like it already has quotes:
if (rows[0].split("", "").length > 2 && rows[5].split("", "").length > 2) {
hasQuotes = true;
this.status = this.status + " Detected text was already surrounded in quotes.";
}
for (var l in rows) {
if (hasQuotes) {
rows[l] = rows[l].trim().replace(/^"/, "").replace(/"$/, "").split("", "");
// var withoutQuotes = [];
// _.each(rows[l],function(d){
// withoutQuotes.push(d.replace(/"/g,""));
// });
// rows[l] = withoutQuotes;
} else {
rows[l] = this.parseLineCSV(rows[l]);
/* This was a fix for alan's data but it breaks other data. */
// var rowWithoutQuotes = rows[l].replace(/"/g,"");
// rows[l] = this.parseLineCSV(rowWithoutQuotes);
}
}
/* get the first line and set it to be the header by default */
var header = [];
if (rows.length > 1) {
firstrow = firstrow;
if (hasQuotes) {
header = firstrow.trim().replace(/^"/, "").replace(/"$/, "").split("", "");
} else {
header = this.parseLineCSV(firstrow);
}
} else if (rows.length === 1) {
header = rows[0].map(function() {
return "";
});
}
this.extractedHeaderObjects = header;
this.asCSV = rows;
if (typeof callback === "function") {
callback();
}
}
},
/**
* http://purbayubudi.wordpress.com/2008/11/09/csv-parser-using-javascript/
* -- CSV PARSER --
* author : Purbayu, 30Sep2008
* email : purbayubudi@gmail.com
*
* description :
* This jscript code describes how to load csv file and parse it into fields.
* Additionally, a function to display html table as result is added.
*
* disclamer:
* To use this code freely, you must put author's name in it.
*/
parseLineCSV: {
value: function(lineCSV) {
// parse csv line by line into array
var CSV = [];
var csvCharacter = ",";
this.debug(lineCSV, typeof lineCSV);
var matches = lineCSV.split(csvCharacter);
if (matches.length < 2) {
csvCharacter = ";";
}
// Insert space before character ",". This is to anticipate
// "split" in IE
// try this:
//
// var a=",,,a,,b,,c,,,,d";
// a=a.split(/\,/g);
// document.write(a.length);
//
// You will see unexpected result!
//
lineCSV = lineCSV.replace(new RegExp(csvCharacter, "g"), " " + csvCharacter);
lineCSV = lineCSV.split(new RegExp(csvCharacter, "g"));
// This is continuing of "split" issue in IE
// remove all trailing space in each field
var i,
j;
for (i = 0; i < lineCSV.length; i++) {
lineCSV[i] = lineCSV[i].replace(/\s*$/g, "");
}
lineCSV[lineCSV.length - 1] = lineCSV[lineCSV.length - 1]
.replace(/^\s*|\s*$/g, "");
var fstart = -1;
for (i = 0; i < lineCSV.length; i++) {
if (lineCSV[i].match(/"$/)) {
if (fstart >= 0) {
for (j = fstart + 1; j <= i; j++) {
lineCSV[fstart] = lineCSV[fstart] + csvCharacter + lineCSV[j];
lineCSV[j] = "-DELETED-";
}
fstart = -1;
}
}
fstart = (lineCSV[i].match(/^"/)) ? i : fstart;
}
j = 0;
for (i = 0; i < lineCSV.length; i++) {
if (lineCSV[i] !== "-DELETED-") {
CSV[j] = lineCSV[i];
CSV[j] = CSV[j].replace(/^\s*|\s*$/g, ""); // remove leading & trailing
// space
CSV[j] = CSV[j].replace(/^"|"$/g, ""); // remove " on the beginning
// and end
CSV[j] = CSV[j].replace(/""/g, "\""); // replace "" with "
j++;
}
}
return CSV;
}
},
importXML: {
value: function() {
throw new Error("The app thinks this might be a XML file, but we haven't implemented this kind of import yet. You can vote for it in our bug tracker.");
}
},
importElanXML: {
value: function(text, callback) {
if (!text) {
return;
}
this.todo("import xml parsers to turn xml import back on");
if (true) {
return;
}
//alert("The app thinks this might be a XML file, but we haven't implemented this kind of import yet. You can vote for it in our bug tracker.");
var xmlParser = new X2JS();
window.text = text;
var jsonObj = xmlParser.xml_str2json(text);
this.debug(jsonObj);
//add the header to the session
// HEADER can be put in the session and in the datalist
var annotationDetails = JSON.stringify(jsonObj.ANNOTATION_DOCUMENT.HEADER).replace(/,/g, "\n").replace(/[\[\]{}]/g, "").replace(/:/g, " : ").replace(/"/g, "").replace(/\n/g, "").replace(/file : /g, "file:").replace(/ : \//g, ":/").trim();
//TODO turn these into session fields
this.status = this.status + "\n" + annotationDetails;
var header = [];
var tierinfo = [];
// TIER has tiers of each, create datum it says who the informant is and who the data entry person is. can turn the objects in the tier into a datum
//for tier, add rows containing
// _ANNOTATOR
tierinfo.push("_ANNOTATOR");
// _DEFAULT_LOCALE
tierinfo.push("_DEFAULT_LOCALE");
// _LINGUISTIC_TYPE_REF
tierinfo.push("_LINGUISTIC_TYPE_REF");
// _PARTICIPANT
tierinfo.push("_PARTICIPANT");
// _TIER_ID
tierinfo.push("_TIER_ID");
// __cnt
tierinfo.push("__cnt");
var annotationinfo = [];
// ANNOTATION.ALIGNABLE_ANNOTATION.ANNOTATION_VALUE.__cnt
// annotationinfo.push({"FieldDBDatumFieldName" : "ANNOTATION.ALIGNABLE_ANNOTATION.ANNOTATION_VALUE", "elanALIGNABLE_ANNOTATION": "ANNOTATION_VALUE"});
// ANNOTATION.ALIGNABLE_ANNOTATION._ANNOTATION_ID
annotationinfo.push({
"FieldDBDatumFieldName": "ANNOTATION.ALIGNABLE_ANNOTATION._ANNOTATION_ID",
"elanALIGNABLE_ANNOTATION": "_ANNOTATION_ID"
});
// ANNOTATION.ALIGNABLE_ANNOTATION._TIME_SLOT_REF1
annotationinfo.push({
"FieldDBDatumFieldName": "ANNOTATION.ALIGNABLE_ANNOTATION._TIME_SLOT_REF1",
"elanALIGNABLE_ANNOTATION": "_TIME_SLOT_REF1"
});
// ANNOTATION.ALIGNABLE_ANNOTATION._TIME_SLOT_REF2
annotationinfo.push({
"FieldDBDatumFieldName": "ANNOTATION.ALIGNABLE_ANNOTATION._TIME_SLOT_REF2",
"elanALIGNABLE_ANNOTATION": "_TIME_SLOT_REF2"
});
//
var refannotationinfo = [];
// ANNOTATION.REF_ANNOTATION.ANNOTATION_VALUE
refannotationinfo.push({
"FieldDBDatumFieldName": "ANNOTATION.REF_ANNOTATION.ANNOTATION_VALUE",
"elanREF_ANNOTATION": "ANNOTATION_VALUE"
});
// ANNOTATION.REF_ANNOTATION._ANNOTATION_ID
refannotationinfo.push({
"FieldDBDatumFieldName": "ANNOTATION.REF_ANNOTATION._ANNOTATION_ID",
"elanREF_ANNOTATION": "_ANNOTATION_ID"
});
// ANNOTATION.REF_ANNOTATION._ANNOTATION_REF
refannotationinfo.push({
"FieldDBDatumFieldName": "ANNOTATION.REF_ANNOTATION._ANNOTATION_REF",
"elanREF_ANNOTATION": "_ANNOTATION_REF"
});
header.push("_ANNOTATOR");
header.push("_DEFAULT_LOCALE");
header.push("_LINGUISTIC_TYPE_REF");
header.push("_PARTICIPANT");
header.push("_TIER_ID");
header.push("__cnt");
header.push("ANNOTATION.ALIGNABLE_ANNOTATION.ANNOTATION_VALUE");
header.push("ANNOTATION.ALIGNABLE_ANNOTATION._ANNOTATION_ID");
header.push("ANNOTATION.ALIGNABLE_ANNOTATION._TIME_SLOT_REF1");
header.push("ANNOTATION.ALIGNABLE_ANNOTATION._TIME_SLOT_REF2");
header.push("ANNOTATION.REF_ANNOTATION.ANNOTATION_VALUE");
header.push("ANNOTATION.REF_ANNOTATION._ANNOTATION_ID");
header.push("ANNOTATION.REF_ANNOTATION._ANNOTATION_REF");
//similar to toolbox
var matrix = [];
var TIER = jsonObj.ANNOTATION_DOCUMENT.TIER;
var l,
annotation,
cell;
//there are normally 8ish tiers, with different participants
for (l in TIER) {
//in those tiers are various amounts of annotations per participant
for (annotation in TIER[l].ANNOTATION) {
matrix[annotation] = [];
for (cell in tierinfo) {
matrix[annotation][tierinfo[cell]] = jsonObj.ANNOTATION_DOCUMENT.TIER[l][tierinfo[cell]];
}
try {
matrix[annotation]["ANNOTATION.ALIGNABLE_ANNOTATION.ANNOTATION_VALUE.__cnt"] = TIER[l].ANNOTATION[annotation].ALIGNABLE_ANNOTATION.ANNOTATION_VALUE.__cnt;
for (cell in annotationinfo) {
matrix[annotation][annotationinfo[cell].FieldDBDatumFieldName] = TIER[l].ANNOTATION[annotation].ALIGNABLE_ANNOTATION[annotationinfo[cell].elanALIGNABLE_ANNOTATION];
}
} catch (e) {
this.debug("TIER " + l + " doesnt seem to have a ALIGNABLE_ANNOTATION object. We don't really knwo waht the elan file format is, or why some lines ahve ALIGNABLE_ANNOTATION and some dont. So we are just skipping them for this datum.");
}
try {
for (cell in refannotationinfo) {
matrix[annotation][refannotationinfo[cell].FieldDBDatumFieldName] = TIER[l].ANNOTATION[annotation].REF_ANNOTATION[refannotationinfo[cell].elanREF_ANNOTATION];
}
} catch (e) {
this.debug("TIER " + l + " doesnt seem to have a REF_ANNOTATION object. We don't really knwo waht the elan file format is, or why some lines ahve REF_ANNOTATION and some dont. So we are just skipping them for this datum.");
}
}
}
var rows = [];
for (var d in matrix) {
var cells = [];
//loop through all the column headings, find the data for that header and put it into a row of cells
for (var h in header) {
cell = matrix[d][header[h]];
if (cell) {
cells.push(cell);
} else {
//fill the cell with a blank if that datum didn't have a header
cells.push("");
}
}
rows.push(cells);
}
if (rows === []) {
rows.push("");
}
this.extractedHeaderObjects = header;
this.asCSV = rows;
if (typeof callback === "function") {
callback();
}
}
},
/**
* This function accepts text which uses \t tabs between columns. If
* you have your data in ELAN or in Microsoft Excel or OpenOffice
* spreadsheets, this will most likely be a good format to export
* your data, and import into FieldDB. This function is triggered if
* your file has more than 100 tabs in it, FieldDB guesses that it
* should try this function.
*
* @param text to be imported
*/
importTabbed: {
value: function(text, callback) {
if (!text) {
return;
}
var rows = text.split("\n"),
l;
if (rows.length < 3) {
rows = text.split("\r");
this.status = this.status + " Detected a \n line ending.";
}
for (l in rows) {
rows[l] = rows[l].split("\t");
}
this.asCSV = rows;
if (typeof callback === "function") {
callback();
}
}
},
metadataLines: [],
/**
* This function takes in a text block, splits it on lines and then
* takes the first word with a \firstword as the data type/column
* heading and then walks through the file looking for lines that
* start with \ge and creates a new datum each time it finds \ge
* This works for verb lexicons but would be \ref if an interlinear
* gloss. TODO figure out how Toolbox knows when one data entry
* stops and another starts. It doesn't appear to be double spaces...
*
* @param text
* @param callback
*/
importToolbox: {
value: function(text, callback) {
if (!text) {
return;
}
var lines = text.split("\n");
var macLineEndings = false;
if (lines.length < 3) {
lines = text.split("\r");
macLineEndings = true;
this.status = this.status + " Detected a \r line ending.";
}
var matrix = [];
var currentDatum = -1;
var header = [];
var columnhead = "";
var firstToolboxField = "";
/* Looks for the first line of the toolbox data */
while (!firstToolboxField && lines.length > 0) {
var potentialToolBoxFieldMatches = lines[0].match(/^\\[a-zA-Z]+\b/);
if (potentialToolBoxFieldMatches && potentialToolBoxFieldMatches.length > 0) {
firstToolboxField = potentialToolBoxFieldMatches[0];
} else {
/* remove the line, and put it into the metadata lines */
this.metadataLines.push(lines.shift());
}
}
for (var l in lines) {
//Its a new row
if (lines[l].indexOf(firstToolboxField) === 0) {
currentDatum += 1;
matrix[currentDatum] = {};
matrix[currentDatum][firstToolboxField.replace(/\\/g, "")] = lines[l].replace(firstToolboxField, "").trim();
header.push(firstToolboxField.replace(/\\/g, ""));
} else {
if (currentDatum >= 0) {
//If the line starts with \ its a column
if (lines[l].match(/^\\/)) {
var pieces = lines[l].split(/ +/);
columnhead = pieces[0].replace("\\", "");
matrix[currentDatum][columnhead] = lines[l].replace(pieces[0], "");
header.push(columnhead);
} else {
//add it to the current column head in the current datum, its just another line.
if (lines[1].trim() !== "") {
matrix[currentDatum][columnhead] += lines[l];
}
}
}
}
}
//only keep the unique headers
header = getUnique(header);
var rows = [];
for (var d in matrix) {
var cells = [];
//loop through all the column headings, find the data for that header and put it into a row of cells
for (var h in header) {
var cell = matrix[d][header[h]];
if (cell) {
cells.push(cell);
} else {
//fill the cell with a blank if that datum didn't have a header
cells.push("");
}
}
rows.push(cells);
}
if (rows === []) {
rows.push("");
}
this.extractedHeaderObjects = header;
this.asCSV = rows;
if (typeof callback === "function") {
callback();
}
}
},
importMorphChallengeSegmentation: {
value: function(text, self, callback) {
var rows = text.trim().split("\n");
if (rows.length < 3) {
rows = text.split("\r");
self.status = self.status + " Detected a \n line ending.";
}
var row,
original,
twoPieces,
word,
alternates,
morphemes,
gloss,
source,
l,
filename = self.files[0].name;
var header = ["orthography", "utterance", "morphemes", "gloss", "alternatesAnalyses", "alternates", "original", "source"];
var convertFlatIGTtoObject = function(alternateParse) {
morphemes = alternateParse.trim().split(" ");
// self.debug("working on alternateParse", morphemes);
return morphemes.map(function(morpheme) {
return {
morphemes: morpheme.split(":")[0],
gloss: morpheme.split(":")[1]
};
});
};
var extractMorphemesFromIGT = function(alternate) {
return alternate.morphemes.replace("+", "");
};
var extractGlossFromIGT = function(alternate) {
return alternate.gloss.replace("+", "");
};
for (l in rows) {
row = original = rows[l] + "";
source = filename + ":line:" + l;
twoPieces = row.split(/\t/);
word = twoPieces[0];
if (!twoPieces || !twoPieces[1]) {
continue;
}
alternates = twoPieces[1].split(",");
alternates = alternates.map(convertFlatIGTtoObject);
morphemes = alternates[0].map(extractMorphemesFromIGT).join("-");
gloss = alternates[0].map(extractGlossFromIGT).join("-");
alternates.shift();
// get alternative morpheme analyses so they show in the app.
var alternateMorphemes = [];
for (var alternateIndex = 0; alternateIndex < alternates; alternateIndex++) {
alternateMorphemes.push(alternates[alternateIndex].map(extractMorphemesFromIGT).join("-"));
}
rows[l] = [word, word, morphemes, gloss, twoPieces[1], alternateMorphemes.join(","), original + "", source];
}
self.extractedHeaderObjects = header;
self.asCSV = rows;
if (typeof callback === "function") {
callback();
}
}
},
uploadFiles: {
value: function(files) {
var deferred = Q.defer(),
self = this;
self.error = "";
self.status = "";
Q.nextTick(function() {
var uploadUrl = new AudioVideo().BASE_SPEECH_URL + "/upload/extract/utterances";
// var data = {
// files: files,
// token: self.token,
// dbname: self.dbname,
// username: self.username,
// returnTextGrid: self.returnTextGrid
// };
//
var data = new FormData();
// for (var ?fileIndex = 0; fileIndex > files.length; fileIndex++) {
// data.append("file" + fileIndex, files[fileIndex]);
// }
// data.files = files;
self.todo("use the files passed instead of jquery ", files);
// http://stackoverflow.com/questions/24626177/how-to-create-an-image-file-from-a-dataurl
if (files.indexOf("data") === 0) {
// data.append("data", files); //test new split
// var base64 = files.split("base64,")[1];
var blob = dataURItoBlob(files);
// blob.name = "file_" + Date.now() + "." + blob.type.split("/")[1];
// blob.lastModfied = Date.now();
// blob.lastModifiedDate = new Date(blob.lastModfied);
// fd.append("canvasImage", blob);
//http://www.nczonline.net/blog/2012/06/05/working-with-files-in-javascript-part-5-blobs/
// var reconstructedFile = new File("file_" + Date.now() + ".mp3", blob, "audio/mpeg");
//http://stackoverflow.com/questions/8390855/how-to-instantiate-a-file-object-in-javascript
files = [blob];
}
self.rawText = "";
$.each(files, function(i, file) {
data.append(i, file);
if (file.name) {
self.rawText = self.rawText + " " + file.name;
}
});
if (self.rawText && self.rawText.trim()) {
// window.alert("rendering import");
self.rawText = self.rawText.trim();
self.render();
}
if (!self.dbname && self.parent && self.parent.dbname) {
self.dbname = self.parent.dbname;
}
// data.append("files", files);
data.append("token", self.uploadtoken || "uploadingfromspreadsheet");
data.append("pouchname", self.dbname);
data.append("dbname", self.dbname);
data.append("username", self.application.authentication.user.username);
data.append("returnTextGrid", self.returnTextGrid || true);
self.audioVideo = null;
// this.model.audioVideo.reset();
$.ajax({
url: uploadUrl,
type: "post",
// dataType: 'json',
cache: false,
// withCredentials: false,
contentType: false,
processData: false,
data: data,
success: function(results) {
if (results && results.status === 200) {
self.uploadDetails = results;
self.files = results.files;
self.status = "File(s) uploaded and utterances were extracted.";
var messages = [];
self.rawText = "";
/* Check for any textgrids which failed */
for (var fileIndex = 0; fileIndex < results.files.length; fileIndex++) {
if (results.files[fileIndex].textGridStatus >= 400) {
self.debug(results.files[fileIndex]);
var instructions = results.files[fileIndex].textGridInfo;
if (results.files[fileIndex].textGridStatus >= 500) {
instructions = " Please report this error.";
}
messages.push("Generating the textgrid for " + results.files[fileIndex].fileBaseName + " seems to have failed. " + instructions);
results.files[fileIndex].filename = results.files[fileIndex].name;
if (results.files[fileIndex].type && (results.files[fileIndex].type.indexOf("audio") > -1 || results.files[fileIndex].type.indexOf("video") > -1)) {
results.files[fileIndex].filename = results.files[fileIndex].fileBaseName + ".mp3";
}
results.files[fileIndex].URL = new AudioVideo().BASE_SPEECH_URL + "/" + self.corpus.dbname + "/" + results.files[fileIndex].filename;
results.files[fileIndex].description = results.files[fileIndex].description || "File from import";
self.addAudioVideoFile(results.files[fileIndex]);
} else {
self.downloadTextGrid(results.files[fileIndex]);
}
}
if (messages.length > 0) {
self.status = messages.join(", ");
deferred.resolve(self.status);
// $(self.el).find(".status").html(self.get("status"));
// if(window && window.appView && typeof window.appView.toastUser === "function") window.appView.toastUser(messages.join(", "), "alert-danger", "Import:");
}
} else {
self.debug(results);
var message = "Upload might have failed to complete processing on your file(s). Please report this error.";
self.status = message + ": " + JSON.stringify(results);
deferred.reject(message);
// if(window && window.appView && typeof window.appView.toastUser === "function") window.appView.toastUser(message, "alert-danger", "Import:");
}
// $(self.el).find(".status").html(self.get("status"));
},
error: function(response) {
var reason = {};
if (response && response.responseJSON) {
reason = response.responseJSON;
} else {
var message = "Error contacting the server. ";
if (response.status >= 500) {
message = message + " Please report this error.";
} else if (response.status === 413) {
message = message + " Your file is too big for upload, please try using FFMpeg to convert it to an mp3 for upload (you can still use your original video/audio in the app when the utterance chunking is done on an mp3.) ";
} else {
message = message + " Are you offline? If you are online and you still recieve this error, please report it to us: ";
}
reason = {
status: response.status,
userFriendlyErrors: [message + response.status]
};
}
self.debug(reason);
if (reason && reason.userFriendlyErrors) {
self.status = "";
self.error = "Upload error: " + reason.userFriendlyErrors.join(" ");
self.bug(self.error);
// if(window && window.appView && typeof window.appView.toastUser === "function") window.appView.toastUser(reason.userFriendlyErrors.join(" "), "alert-danger", "Import:");
// $(self.el).find(".status").html(self.get("status"));
}
deferred.reject(self.error);
}
});
self.status = "Contacting server...";
// $(this.el).find(".status").html(this.model.get("status"));
});
return deferred.promise;
}
},
downloadTextGrid: {
value: function(fileDetails) {
var self = this;
var textridUrl = new AudioVideo().BASE_SPEECH_URL + "/" + this.corpus.dbname + "/" + fileDetails.fileBaseName + ".TextGrid";
CORS.makeCORSRequest({
url: textridUrl,
type: "GET",
withCredentials: false
}).then(function(results) {
if (results) {
fileDetails.textgrid = results;
var syllables = "unknown";
if (fileDetails.syllablesAndUtterances && fileDetails.syllablesAndUtterances.syllableCount) {
syllables = fileDetails.syllablesAndUtterances.syllableCount;
}
var pauses = "unknown";
if (fileDetails.syllablesAndUtterances && fileDetails.syllablesAndUtterances.pauseCount) {
pauses = parseInt(fileDetails.syllablesAndUtterances.pauseCount, 10);
}
var utteranceCount = 1;
if (pauses > 0) {
utteranceCount = pauses + 2;
}
var message = " Downloaded Praat TextGrid which contained a count of roughly " + syllables + " syllables and auto detected utterances for " + fileDetails.fileBaseName + " The utterances were not automatically transcribed for you, you can either save the textgrid and transcribe them using Praat, or continue to import them and transcribe them after.";
fileDetails.description = message;
self.status = self.status + "
" + message;
self.fileDetails = self.status + message;
if (window && window.appView && typeof window.appView.toastUser === "function") {
window.appView.toastUser(message, "alert-info", "Import:");
}
self.rawText = self.rawText.trim() + "\n\n\nFile name = " + fileDetails.fileBaseName + ".mp3\n" + results;
if (!self.parent) {
self.importTextGrid(self.rawText, null);
} else {
self.debug("Not showing second import step, this looks like its audio import only.");
}
fileDetails.filename = fileDetails.fileBaseName + ".mp3";
fileDetails.URL = new AudioVideo().BASE_SPEECH_URL + "/" + self.corpus.dbname + "/" + fileDetails.fileBaseName + ".mp3";
self.addAudioVideoFile(fileDetails);
self.rawText = self.rawText.trim();
} else {
self.debug(results);
fileDetails.textgrid = "Error result was empty. " + results;
}
}, function(response) {
var reason = {};
if (response && response.responseJSON) {
reason = response.responseJSON;
} else {
var message = "Error contacting the server. ";
if (response.status >= 500) {
message = message + " Please report this error.";
} else {
message = message + " Are you offline? If you are online and you still recieve this error, please report it to us: ";
}
reason = {
status: response.status,
userFriendlyErrors: [message + response.status]
};
}
self.debug(reason);
if (reason && reason.userFriendlyErrors) {
self.status = fileDetails.fileBaseName + "import error: " + reason.userFriendlyErrors.join(" ");
if (window && window.appView && typeof window.appView.toastUser === "function") {
window.appView.toastUser(reason.userFriendlyErrors.join(" "), "alert-danger", "Import:");
}
}
}).fail(function(error) {
console.error(error.stack, self);
});
}
},
addAudioVideoFile: {
value: function(details) {
if (!details) {
this.warn("No details were provided to add be added to any file collection.");
return;
}
var fileCollection = "relatedData";
if (details.type.indexOf("image") > -1) {
fileCollection = "images";
details = new FieldDBImage(details);
} else if (details.type.indexOf("audio") > -1 || details.type.indexOf("video") > -1) {
fileCollection = "audioVideo";
}
if (!this[fileCollection]) {
this[fileCollection] = new AudioVideos();
}
this[fileCollection].add(details);
if (this.parent) {
if (typeof this.parent.markAsNeedsToBeSaved === "function") {
this.parent.markAsNeedsToBeSaved();
}
if (typeof this.parent.addFile === "function") {
this.parent.addFile(details);
} else if (this.parent.audioVideo && typeof this.parent.audioVideo.push === "function") {
this.parent.audioVideo.push(details);
} else {
this.bug("There was a problem attaching this file. Please report this.");
}
this.render();
// this.asCSV = [];
}
}
},
importTextGrid: {
value: function(text, callback) {
if (!text) {
return;
}
// alert("The app thinks this might be a Praat TextGrid file, but we haven't implemented this kind of import yet. You can vote for it in our bug tracker.");
var textgrid = TextGrid.textgridToIGT(text);
var audioFileName = "copypastedtextgrid_unknownaudio";
if (this.files && this.files[0] && this.files[0].name) {
audioFileName = this.files[0].name;
}
audioFileName = audioFileName.replace(/\.textgrid/i, "");
if (!textgrid || !textgrid.intervalsByXmin) {
if (typeof callback === "function") {
callback();
}
}
var matrix = [],
h,
itemIndex,
intervalIndex,
row,
interval;
var header = [];
var consultants = [];
if (textgrid.isIGTNestedOrAlignedOrBySpeaker.probablyAligned) {
for (itemIndex in textgrid.intervalsByXmin) {
if (!textgrid.intervalsByXmin.hasOwnProperty(itemIndex)) {
continue;
}
if (textgrid.intervalsByXmin[itemIndex]) {
row = {};
for (intervalIndex = 0; intervalIndex < textgrid.intervalsByXmin[itemIndex].length; intervalIndex++) {
interval = textgrid.intervalsByXmin[itemIndex][intervalIndex];
row.startTime = row.startTime ? row.startTime : interval.xmin;
row.endTime = row.endTime ? row.endTime : interval.xmax;
row.utterance = row.utterance ? row.utterance : interval.text.trim();
row.modality = "spoken";
row.tier = interval.tierName;
row.speakers = interval.speaker;
row.audioFileName = interval.fileName || audioFileName;
row.CheckedWithConsultant = interval.speaker;
consultants.push(row.speakers);
row[interval.tierName] = interval.text;
header.push(interval.tierName);
}
matrix.push(row);
}
}
} else {
for (itemIndex in textgrid.intervalsByXmin) {
if (!textgrid.intervalsByXmin.hasOwnProperty(itemIndex)) {
continue;
}
if (textgrid.intervalsByXmin[itemIndex]) {
for (intervalIndex = 0; intervalIndex < textgrid.intervalsByXmin[itemIndex].length; intervalIndex++) {
row = {};
interval = textgrid.intervalsByXmin[itemIndex][intervalIndex];
row.startTime = row.startTime ? row.startTime : interval.xmin;
row.endTime = row.endTime ? row.endTime : interval.xmax;
row.utterance = row.utterance ? row.utterance : interval.text.trim();
row.modality = "spoken";
row.tier = interval.tierName;
row.speakers = interval.speaker;
row.audioFileName = interval.fileName || audioFileName;
row.CheckedWithConsultant = interval.speaker;
consultants.push(row.speakers);
row[interval.tierName] = interval.text;
header.push(interval.tierName);
matrix.push(row);
}
}
}
}
header = getUnique(header);
consultants = getUnique(consultants);
if (consultants.length > 0) {
this.consultants = consultants.join(",");
} else {
this.consultants = "Unknown";
}
header = header.concat(["utterance", "tier", "speakers", "CheckedWithConsultant", "startTime", "endTime", "modality", "audioFileName"]);
var rows = [];
for (var d in matrix) {
var cells = [];
//loop through all the column headings, find the data for that header and put it into a row of cells
for (h in header) {
var cell = matrix[d][header[h]];
if (cell) {
cells.push(cell);
} else {
//fill the cell with a blank if that datum didn't have a that column
cells.push("");
}
}
//if the datum has any text, add it to the table
if (cells.length >= 8 && cells.slice(0, cells.length - 8).join("").replace(/[0-9.]/g, "").length > 0 && cells[cells.length - 8] !== "silent") {
// cells.push(audioFileName);
rows.push(cells);
} else {
this.debug("This row has only the default columns, not text or anything interesting.", cells);
}
}
if (rows === []) {
rows.push("");
}
// header.push("audioFileName");
this.extractedHeaderObjects = header;
this.asCSV = rows;
if (typeof callback === "function") {
callback();
}
}
},
importLatex: {
value: function() {
throw new Error("The app thinks this might be a LaTeX file, but we haven't implemented this kind of import yet. You can vote for it in our bug tracker.");
// if (typeof callback === "function") {
// callback();
// }
}
},
/**
* This function accepts text using double (or triple etc) spaces to indicate
* separate datum. Each line in the block is treated as a column in
* the table.
*
* If you have your data in Microsoft word or OpenOffice or plain
* text, then this will be the easiest format for you to import your
* data in.
*
* @param text
*/
importTextIGT: {
value: function(text, callback) {
if (!text) {
return;
}
var rows = text.split(/\n\n+/),
l;
var macLineEndings = false;
if (rows.length < 3) {
var macrows = text.split("\r\r");
if (macrows.length > rows.length) {
this.status = this.status + " Detected a MAC line ending.";
macLineEndings = true;
rows = macrows;
}
}
for (l in rows) {
if (macLineEndings) {
rows[l] = rows[l].replace(/ +/g, " ").split("\r");
} else {
rows[l] = rows[l].replace(/ +/g, " ").split("\n");
}
}
this.asCSV = rows;
this.extractedHeaderObjects = rows[0];
if (typeof callback === "function") {
callback();
}
}
},
/**
* This function accepts text using double (or triple etc) spaces to indicate
* separate datum. Each line in the block is treated as a column in
* the table.
*
* If you have your data in Microsoft word or OpenOffice or plain
* text, then this will be the easiest format for you to import your
* data in.
*
* @param text
*/
importRawText: {
value: function(text) {
if (this.ignoreLineBreaksInRawText) {
text.replace(/\n+/g, " ").replace(/\r+/g, " ");
}
this.datalist.add(new Datum({
fields: [{
id: "orthography",
value: text
}]
}));
this.debug("added a datum to the collection");
}
},
/**
* Reads the import's array of files using a supplied readOptions or using
* the readFileIntoRawText function which uses the browsers FileReader API.
* It can read only part of a file if start and stop are passed in the options.
*
* @param Object options Options can be specified to pass start and stop bytes
* for the files to be read.
*
* @return Promise Returns a promise which will have an array of results
* for each file which was requested to be read
*/
readFiles: {
value: function(options) {
var deferred = Q.defer(),
self = this,
promisses = [];
options = options || {};
this.progress = {
total: 0,
completed: 0
};
Q.nextTick(function() {
var fileDetails = [];
var files = self.files;
var filesToUpload = [];
self.progress.total = files.length;
for (var i = 0, file; file = files[i]; i++) {
var details = [escape(file.name), file.type || "n/a", "-", file.size, "bytes, last modified:", file.lastModifiedDate ? file.lastModifiedDate.toLocaleDateString() : "n/a"].join(" ");
self.status = self.status + "; " + details;
fileDetails.push(JSON.parse(JSON.stringify(file)));
if (file.type && (file.type.indexOf("audio") > -1 || file.type.indexOf("video") > -1 || file.type.indexOf("image") > -1)) {
filesToUpload.push(file);
} else if (options.readOptions) {
promisses.push(options.readOptions.readFileFunction.apply(self, [{
file: file.name,
start: options.start,
stop: options.stop
}]));
} else {
promisses.push(self.readFileIntoRawText({
file: file,
start: options.start,
stop: options.stop
}));
}
}
if (filesToUpload.length > 0) {
promisses.push(self.uploadFiles(self.files));
}
self.fileDetails = fileDetails;
Q.allSettled(promisses).then(function(results) {
deferred.resolve(results.map(function(result) {
self.progress.completed += 1;
return result.value;
}));
}, function(results) {
self.error = "Error processing files";
deferred.reject(results);
}).fail(function(error) {
console.error(error.stack, self);
self.warn("There was an error when importing these options ", error, options);
deferred.reject(error);
});
});
return deferred.promise;
}
},
/**
* Reads a file using the FileReader API, can read only part of a file if start and stop are passed in the options.
* @param Object options Options can be specified to pass start and stop bytes for the file to be read.
* @return Promise Returns a promise which will have an array of results for each file which was requested to be read
*/
readFileIntoRawText: {
value: function(options) {
var deferred = Q.defer(),
self = this;
this.debug("readFileIntoRawText", options);
Q.nextTick(function() {
if (!options) {
options = {
error: "Options must be defined for readFileIntoRawText"
};
deferred.reject(options);
return;
}
if (!options.file) {
options.error = "Options: file must be defined for readFileIntoRawText";
deferred.reject(options);
return;
}
options.start = options.start ? parseInt(options.start, 10) : 0;
options.stop = options.stop ? parseInt(options.stop, 10) : options.file.size - 1;
var reader = new FileReader();
// If we use onloadend, we need to check the readyState.
reader.onloadend = function(evt) {
if (evt.target.readyState === FileReader.DONE) { // DONE === 2
options.rawText = evt.target.result;
self.rawText = self.rawText + options.rawText;
// self.showImportSecondStep = true;
deferred.resolve(options);
}
};
var blob = "";
if (options.file.slice) {
blob = options.file.slice(options.start, options.stop + 1);
} else if (options.file.mozSlice) {
blob = options.file.mozSlice(options.start, options.stop + 1);
} else if (options.file.webkitSlice) {
blob = options.file.webkitSlice(options.start, options.stop + 1);
}
// reader.readAsBinaryString(blob);
// reader.readAsText(blob, "UTF-8");
reader.readAsText(blob);
});
return deferred.promise;
}
},
/**
* This function attempts to guess the format of the file/textarea, and calls the appropriate import handler.
*/
guessFormatAndPreviewImport: {
value: function(fileIndex) {
if (!fileIndex) {
fileIndex = 0;
}
var importTypeConfidenceMeasures = {
handout: {
confidence: 0,
id: "handout",
importFunction: this.importTextIGT
},
csv: {
confidence: 0,
id: "csv",
importFunction: this.importCSV
},
tabbed: {
confidence: 0,
id: "tabbed",
importFunction: this.importTabbed
},
xml: {
confidence: 0,
id: "xml",
importFunction: this.importXML
},
toolbox: {
confidence: 0,
id: "toolbox",
importFunction: this.importToolbox
},
elanXML: {
confidence: 0,
id: "elanXML",
importFunction: this.importElanXML
},
praatTextgrid: {
confidence: 0,
id: "praatTextgrid",
importFunction: this.importTextGrid
},
latex: {
confidence: 0,
id: "latex",
importFunction: this.importLatex
}
};
//if the user is just typing, try raw text
if (this.files && this.files[fileIndex]) {
var fileExtension = this.files[fileIndex].name.split(".").pop().toLowerCase();
if (fileExtension === "csv") {
importTypeConfidenceMeasures.csv.confidence++;
} else if (fileExtension === "txt") {
//If there are more than 20 tabs in the file, try tabbed.
if (this.rawText.split("\t").length > 20) {
importTypeConfidenceMeasures.tabbed.confidence++;
} else {
importTypeConfidenceMeasures.handout.confidence++;
}
} else if (fileExtension === "eaf") {
importTypeConfidenceMeasures.elanXML.confidence++;
} else if (fileExtension === "xml") {
importTypeConfidenceMeasures.xml.confidence++;
} else if (fileExtension === "sf") {
importTypeConfidenceMeasures.toolbox.confidence++;
} else if (fileExtension === "tex") {
importTypeConfidenceMeasures.latex.confidence++;
} else if (fileExtension === "textgrid") {
importTypeConfidenceMeasures.praatTextgrid.confidence++;
} else if (fileExtension === "mov") {
importTypeConfidenceMeasures.praatTextgrid.confidence++;
} else if (fileExtension === "wav") {
importTypeConfidenceMeasures.praatTextgrid.confidence++;
} else if (fileExtension === "mp3") {
importTypeConfidenceMeasures.praatTextgrid.confidence++;
}
} else {
if (this.rawText && this.rawText.length) {
var textLength = this.rawText.length;
if (this.rawText.indexOf("\\gll") > -1 || this.rawText.indexOf("\\begin{") > -1 || this.rawText.indexOf("\\ex") > -1) {
importTypeConfidenceMeasures.latex.confidence = 100;
} else if (this.rawText.indexOf("mpi.nl/tools/elan/EAF") > -1) {
importTypeConfidenceMeasures.elanXML.confidence = 100;
} else if (this.rawText.indexOf(" -1) {
importTypeConfidenceMeasures.xml.confidence = 100;
} else {
importTypeConfidenceMeasures.csv.confidence = this.rawText.split(",").length / textLength;
importTypeConfidenceMeasures.tabbed.confidence = this.rawText.split("\t").length / textLength;
importTypeConfidenceMeasures.handout.confidence = this.rawText.split(/\n\n+/).length / textLength;
importTypeConfidenceMeasures.toolbox.confidence = this.rawText.split(/\n\\/).length / textLength;
importTypeConfidenceMeasures.praatTextgrid.confidence = this.rawText.split("intervals").length / textLength;
}
}
}
this.importTypeConfidenceMeasures = importTypeConfidenceMeasures;
var mostLikelyImport = _.max(importTypeConfidenceMeasures, function(obj) {
return obj.confidence;
});
this.importTypeConfidenceMeasures.mostLikely = mostLikelyImport;
this.status = "";
mostLikelyImport.importFunction.apply(this, [this.rawText, null]); //no callback
}
},
readBlob: {
value: function(file, callback, opt_startByte, opt_stopByte) {
this.warn("Read blob is deprecated", file, callback, opt_startByte, opt_stopByte);
}
}
});
exports.Import = Import;
},{"./../CORS":1,"./../Collection":2,"./../FieldDBObject":3,"./../audio_video/AudioVideo":10,"./../audio_video/AudioVideos":12,"./../corpus/Corpus":21,"./../datum/Datum":31,"./../datum/DatumField":32,"./../datum/DatumFields":33,"./../datum/Session":40,"./../image/Image":46,"./../user/Participant":61,"q":248,"textgrid":250,"underscore":251}],49:[function(require,module,exports){
var FieldDBObject = require("./../FieldDBObject").FieldDBObject,
Q = require("q");
/**
* @class The ContextualizableObject allows the user to label data with grammatical tags
* i.e. passive, causative. This is useful for searches.
*
* @name ContextualizableObject
* @description The initialize function brings up a field in which the user
* can enter tags.@class Object of Datum validation states
* @extends Object
* @constructs
*/
var ContextualizableObject = function ContextualizableObject(json) {
// if (!this._fieldDBtype) {
// this._fieldDBtype = "Activities";
// }
// this.debugMode = true;
this.debug("Constructing ContextualizableObject ", json);
if (json && typeof json === "string") {
if (ContextualizableObject.compatibleWithSimpleStrings) {
// Dont localize this, return what you received to be backward compatible
// http://stackoverflow.com/questions/1978049/what-values-can-a-constructor-return-to-avoid-returning-this
/* jshint ignore:start */
return new String(json);
/* jshint ignore:end */
// Can also throw the string and catch it and use the original value...
// throw json;
}
var stringAsKey = "locale_" + json.replace(/[^a-zA-Z0-9-]/g, "_");
var value = json;
json = {
default: stringAsKey
};
this.originalString = value;
this.data = this.data || {};
this.data[stringAsKey] = {
"message": value
};
this.add(stringAsKey, value);
// if (this.contextualizer && this.contextualizer.contextualize(for_context) === for_context) {
// this.contextualizer.updateContextualization(for_context, locale_string)
// this.debug("added to contextualizer "+ this.contextualizer.contextualize(for_context));
// }
}
for (var member in json) {
if (!json.hasOwnProperty(member) || member === "contextualizer") {
continue;
}
this.add(member, json[member]);
}
Object.apply(this, arguments);
};
var forcedebug = false;
ContextualizableObject.compatibleWithSimpleStrings = true;
ContextualizableObject.prototype = Object.create(Object.prototype, /** @lends ContextualizableObject.prototype */ {
constructor: {
value: ContextualizableObject
},
fieldDBtype: {
value: "ContextualizableObject"
},
contextualizer: {
get: function() {
return FieldDBObject.prototype.contextualizer;
}
},
debug: {
value: function(message, message2, message3, message4) {
if (FieldDBObject.application && FieldDBObject.application.contextualizer) {
// console.log("using FieldDBObject.application.contextualizer.debug " + FieldDBObject.application.contextualizer.debugMode);
return FieldDBObject.application.contextualizer.debug;
} else {
if (forcedebug) {
console.log(this.fieldDBtype.toUpperCase() + "-DEBUG FORCED: " + message);
if (message2) {
console.log(message2);
}
if (message3) {
console.log(message3);
}
if (message4) {
console.log(message4);
}
}
}
}
},
todo: {
value: function() {
return FieldDBObject.prototype.todo.apply(this, arguments);
}
},
contextualize: {
value: function(locale_string) {
this.debug("requesting contextualization of " + locale_string);
var contextualizedString;
if (this.contextualizer) {
contextualizedString = this.contextualizer.contextualize(locale_string);
}
if (!contextualizedString || contextualizedString === locale_string) {
if (this.data && this.data[locale_string]) {
contextualizedString = this.data[locale_string].message;
} else {
contextualizedString = locale_string;
}
}
this.debug("::" + contextualizedString + "::");
return contextualizedString;
}
},
updateContextualization: {
value: function(for_context, locale_string) {
this.debug("updateContextualization" + for_context);
var updatePromiseOrSyncrhonousConfirmed,
self = this;
if (this.contextualizer) {
this.debug(this.contextualizer.data);
updatePromiseOrSyncrhonousConfirmed = this.contextualizer.updateContextualization(for_context, locale_string);
if (updatePromiseOrSyncrhonousConfirmed !== true) {
self.todo("Test async updatePromiseOrSyncrhonousConfirmed");
Q.nextTick(function() {
if (self.contextualizer) {
var updated = self.contextualizer.contextualize(for_context);
if ((!updated || updated === for_context) && self.data) {
self.data[for_context] = self.data[for_context] || {
message: ""
};
self.data[for_context].message = locale_string;
}
} else {
console.warn("This is strange, i lost my contextualizer...", self);
}
});
}
}
// this.data = this.data || {};
// this.data[for_context] = {
// message: locale_string
// };
if (this._default === for_context) {
this.originalString = locale_string;
}
return updatePromiseOrSyncrhonousConfirmed;
}
},
add: {
value: function(for_context, locale_string) {
var underscoreNotation = "_" + for_context;
this[underscoreNotation] = locale_string;
this.__defineGetter__(for_context, function() {
this.debug("overidding getter");
return this.contextualize(this[underscoreNotation]);
});
this.__defineSetter__(for_context, function(value) {
this.debug("overidding setter " + underscoreNotation, value);
this.updateContextualization(this[underscoreNotation], value);
});
this.debug("adding string to ContextualizableObject's own data " + for_context);
//if there is no contextualizer, add this to the local data
this.data = this.data || {};
this.data[for_context] = {
"message": locale_string
};
if (for_context.indexOf("locale_") === 0 || for_context.indexOf("localized_") === 0) {
this.debug("intializing the data in this ContextualizableObject");
this.debug(" for_context " + for_context);
this.debug(" locale_string " + locale_string);
// If the contextualizer doesnt have a value for this string, add it to the contextualizations... (this could introduce a lot of data into the localizations)
if (this.contextualizer) {
this.debug(" adding to contextualizer: " + for_context + " as " + locale_string);
this.contextualizer.updateContextualization(for_context, locale_string);
this.debug("added to contextualizer " + this.contextualizer.contextualize(for_context));
}
}
this.debug("data", this.data);
}
},
toJSON: {
value: function(includeEvenEmptyAttributes, removeEmptyAttributes) {
var json = {},
aproperty,
underscorelessProperty;
// this.debugMode = true;
if (!ContextualizableObject.compatibleWithSimpleStrings && this.originalString) {
return this.originalString;
} else {
this.debug("Original string is not defined, returning an object. ", ContextualizableObject.compatibleWithSimpleStrings, this.originalString);
}
for (aproperty in this) {
if (this.hasOwnProperty(aproperty) && typeof this[aproperty] !== "function" && aproperty !== "contextualizer" && aproperty.indexOf("_") === 0) {
underscorelessProperty = aproperty.replace(/^_/, "");
if (!removeEmptyAttributes || (removeEmptyAttributes && !this.isEmpty(aproperty))) {
if (this[aproperty] && typeof this[aproperty].toJSON === "function") {
json[underscorelessProperty] = this[aproperty].toJSON(includeEvenEmptyAttributes, removeEmptyAttributes);
} else {
json[underscorelessProperty] = this[aproperty];
}
}
}
}
/* if the caller requests a complete object include the default for all defauls by calling get on them */
if (includeEvenEmptyAttributes && this.INTERNAL_MODELS) {
for (aproperty in this.INTERNAL_MODELS) {
if (!json[aproperty] && this.INTERNAL_MODELS) {
if (this.INTERNAL_MODELS[aproperty] && typeof this.INTERNAL_MODELS[aproperty] === "function" && typeof new this.INTERNAL_MODELS[aproperty]().toJSON === "function") {
json[aproperty] = new this.INTERNAL_MODELS[aproperty]().toJSON(includeEvenEmptyAttributes, removeEmptyAttributes);
} else {
json[aproperty] = this.INTERNAL_MODELS[aproperty];
}
}
}
}
// Preseve the original string in this mini-contextualizer if it was originally a string
if (json.default && this.originalString) {
json[json.default] = this.originalString;
delete json.originalString;
}
return json;
}
}
});
exports.ContextualizableObject = ContextualizableObject;
},{"./../FieldDBObject":3,"q":248}],50:[function(require,module,exports){
(function (global){
/* globals window, localStorage, navigator */
var FieldDBObject = require("./../FieldDBObject").FieldDBObject;
var ELanguages = require("./ELanguages").ELanguages;
var CORS = require("./../CORS").CORS;
var Q = require("q");
var english_texts = require("./en/messages.json");
var spanish_texts = require("./es/messages.json");
var elanguages = require("./elanguages.json");
/**
* @class The contextualizer can resolves strings depending on context and locale of the user
* @name Contextualizer
*
* @property {ELanguage} defaultLocale The language/context to use if a translation/contextualization is missing.
* @property {ELanguage} currentLocale The current locale to use (often the browsers default locale, or a corpus" default locale).
*
* @extends FieldDBObject
* @constructs
*/
var Contextualizer = function Contextualizer(options) {
if (!this._fieldDBtype) {
this._fieldDBtype = "Contextualizer";
}
this.debug("Constructing Contextualizer ", options);
// this.debugMode = true;
var localArguments = arguments;
if (!options) {
options = {};
localArguments = [options];
}
if (!options.defaultLocale || !options.defaultLocale.iso) {
options.defaultLocale = {
iso: "en"
};
}
// if (!options.currentLocale || !options.currentLocale.iso) {
// options.currentLocale = {
// iso: "en"
// };
// }
if (!options.currentContext) {
options.currentContext = "default";
}
if (!options.elanguages) {
options.elanguages = elanguages;
}
FieldDBObject.apply(this, localArguments);
if (!options || options.alwaysConfirmOkay === undefined) {
this.debug("By default it will be okay for users to modify global locale strings. IF they are saved this will affect other users.");
this.alwaysConfirmOkay = true;
}
if (this.userOverridenLocalePreference) {
this.currentLocale = this.userOverridenLocalePreference;
} else {
try {
if (navigator.languages[0].indexOf(this.currentLocale.iso) === -1) {
this.currentLocale = navigator.languages[0];
}
} catch (e) {
this.debug("not using hte browser's language", e);
}
}
return this;
};
Contextualizer.prototype = Object.create(FieldDBObject.prototype, /** @lends Contextualizer.prototype */ {
constructor: {
value: Contextualizer
},
INTERNAL_MODELS: {
value: {
elanguages: ELanguages
}
},
_require: {
value: (typeof global !== "undefined") ? global.require : (typeof window !== "undefined") ? window.require : null
},
data: {
get: function() {
return this._data;
},
set: function(value) {
this._data = value;
}
},
currentLocale: {
get: function() {
if (this._currentLocale) {
return this._currentLocale;
}
if (this._mostAvailableLanguage) {
return this._mostAvailableLanguage;
}
return this.defaultLocale;
},
set: function(value) {
if (value === this._currentLocale) {
return;
}
if (value && value.toLowerCase && typeof value === "string") {
value = value.toLowerCase().replace(/[^a-z-]/g, "");
if (this.elanguages && this.elanguages[value]) {
value = this.elanguages[value];
} else {
value = {
iso: value
};
}
}
this.debug("SETTING LOCALE FROM " + this._currentLocale + " to ", value, this.data);
this._currentLocale = value;
}
},
userOverridenLocalePreference: {
get: function() {
var userOverridenLocalePreference;
try {
userOverridenLocalePreference = JSON.parse(localStorage.getItem("_userOverridenLocalePreference"));
} catch (e) {
this.debug("Localstorage is not available, using the object there will be no persistance across loads", e, this._userOverridenLocalePreference);
userOverridenLocalePreference = this._userOverridenLocalePreference;
}
if (!userOverridenLocalePreference) {
return;
}
return userOverridenLocalePreference;
},
set: function(value) {
if (value) {
try {
localStorage.setItem("_userOverridenLocalePreference", JSON.stringify(value));
} catch (e) {
this._userOverridenLocalePreference = value;
this.debug("Localstorage is not available, using the object there will be no persistance across loads", e, this._userOverridenLocalePreference);
}
} else {
try {
localStorage.removeItem("_userOverridenLocalePreference");
} catch (e) {
this.debug("Localstorage is not available, using the object there will be no persistance across loads", e, this._userOverridenLocalePreference);
delete this._userOverridenLocalePreference;
}
}
}
},
availableLanguages: {
get: function() {
this.data = this.data || {};
if (this._availableLanguages && this.data[this._availableLanguages._collection[0].iso] && this._availableLanguages._collection[0].length === this.data[this._availableLanguages._collection[0].iso].length) {
return this._availableLanguages;
}
var availLanguages = new ELanguages(),
bestAvailabilityCount = 0;
for (var code in this.data) {
if (this.data.hasOwnProperty(code)) {
this.elanguages[code].length = this.data[code].length;
if (this.elanguages[code].length > bestAvailabilityCount) {
availLanguages.unshift(this.elanguages[code]);
bestAvailabilityCount = this.elanguages[code].length;
} else {
availLanguages.push(this.elanguages[code]);
}
}
}
if (bestAvailabilityCount === 0 || availLanguages.length === 0) {
this.todo("Ensuring that at least english is an available language, not sure if this is a good idea.");
availLanguages.unshift(this.elanguages.en);
} else {
availLanguages._collection.map(function(language) {
language.percentageOfAvailability = Math.round(language.length / bestAvailabilityCount * 100);
return language;
});
}
this.todo("test whether setting the currentLocale to the most complete locale has adverse affects.");
this._mostAvailableLanguage = availLanguages._collection[0];
this._availableLanguages = availLanguages;
return availLanguages;
}
},
defaults: {
get: function() {
return {
en: JSON.parse(JSON.stringify(english_texts)),
es: JSON.parse(JSON.stringify(spanish_texts))
};
}
},
loadDefaults: {
value: function() {
if (this.defaults.en) {
this.addMessagesToContextualizedStrings("en", this.defaults.en);
} else {
this.debug("English Locales did not load.");
}
if (this.defaults.es) {
this.addMessagesToContextualizedStrings("es", this.defaults.es);
} else {
this.debug("English Locales did not load.");
}
return this;
}
},
localize: {
value: function(message, optionalLocaleForThisCall) {
return this.contextualize(message, optionalLocaleForThisCall);
}
},
contextualize: {
value: function(message, optionalLocaleForThisCall) {
if (!optionalLocaleForThisCall) {
optionalLocaleForThisCall = this.currentLocale.iso;
}
if (optionalLocaleForThisCall && optionalLocaleForThisCall.iso) {
optionalLocaleForThisCall = optionalLocaleForThisCall.iso;
}
this.debug("Resolving localization in " + optionalLocaleForThisCall);
var result = message,
aproperty;
// Use the current context if the caller is requesting localization of an object
if (typeof message === "object") {
var foundAContext = false;
for (aproperty in message) {
if (!message.hasOwnProperty(aproperty)) {
continue;
}
if (aproperty.indexOf(this.currentContext) > -1 || ((this.currentContext === "child" || this.currentContext === "game") && aproperty.indexOf("gamified") > -1)) {
result = message[aproperty];
foundAContext = true;
this.debug("Using " + aproperty + " for this contxtualization.");
break;
}
}
if (!foundAContext && message.default) {
this.debug("Using default for this contxtualization. ", message);
result = message.default;
}
}
if (!this.data) {
this.warn("No localizations available, resolving the key itself: ", result);
return result;
}
var keepTrying = true;
if (this.data[optionalLocaleForThisCall] && this.data[optionalLocaleForThisCall][result] && this.data[optionalLocaleForThisCall][result].message !== undefined) {
result = this.data[optionalLocaleForThisCall][result].message;
this.debug("Resolving requested contextualization using requested language: ", result);
keepTrying = false;
} else if (this.data[this.defaultLocale.iso] && this.data[this.defaultLocale.iso][result] && this.data[this.defaultLocale.iso][result].message !== undefined) {
result = this.data[this.defaultLocale.iso][result].message;
this.debug("Resolving requested contextualization using default language: ", result);
keepTrying = false;
} else {
if (typeof message === "object") {
if (message[result] && this.data[optionalLocaleForThisCall] && this.data[optionalLocaleForThisCall][message[result]] && this.data[optionalLocaleForThisCall][message[result]].message !== undefined && this.data[optionalLocaleForThisCall][message[result]].message) {
result = this.data[optionalLocaleForThisCall][message[result]].message;
this.debug("Resolving localization using requested contextualization: ", message[result]);
keepTrying = false;
} else if (message.default && this.data[optionalLocaleForThisCall] && this.data[optionalLocaleForThisCall][message.default] && this.data[optionalLocaleForThisCall][message.default].message !== undefined && this.data[optionalLocaleForThisCall][message.default].message) {
result = this.data[optionalLocaleForThisCall][message.default].message;
this.debug("Resolving localization using default contextualization: ", message.default);
keepTrying = false;
} else if (message.default && this.data[this.defaultLocale.iso] && this.data[this.defaultLocale.iso][message.default] && this.data[this.defaultLocale.iso][message.default].message !== undefined && this.data[this.defaultLocale.iso][message.default].message) {
result = this.data[this.defaultLocale.iso][message.default].message;
this.debug("Resolving localization using default contextualization and default locale: ", message.default);
keepTrying = false;
}
}
if (keepTrying && this.data[this.defaultLocale.iso] && this.data[this.defaultLocale.iso][result] && this.data[this.defaultLocale.iso][result].message !== undefined && this.data[this.defaultLocale.iso][result].message) {
result = this.data[this.defaultLocale.iso][result].message;
this.debug("Resolving localization using default: ", result);
}
}
if (keepTrying && !this.requestedCorpusSpecificLocalizations && FieldDBObject && FieldDBObject.application && FieldDBObject.application.corpus && FieldDBObject.application.corpus.loaded) {
FieldDBObject.application.corpus.getCorpusSpecificLocalizations();
this.requestedCorpusSpecificLocalizations = true;
}
result = result.replace(/^locale_/, "");
return result;
}
},
/**
*
* @param {String} key A locale to save the message to
* @param {String} value a message which should replace the existing localization
* @return {Promise} A promise for whether or not the update was confirmed and executed
*/
updateContextualization: {
value: function(key, value) {
var deferred = Q.defer(),
self = this,
previousMessage = "",
verb = "create ";
this.whenReadys = this.whenReadys || [];
this.todo("Test async updateContextualization");
this.whenReadys.push(deferred.promise);
this.data[this.currentLocale.iso] = this.data[this.currentLocale.iso] || {};
if (this.data[this.currentLocale.iso][key] && this.data[this.currentLocale.iso][key].message === value) {
Q.nextTick(function() {
deferred.resolve(value);
});
return deferred.promise; //no change
}
if (this.data[this.currentLocale.iso][key]) {
previousMessage = this.data[this.currentLocale.iso][key].message;
verb = "update ";
}
var addTheUsersMessage = function(addkey, addvalue) {
self.debug("Adding the user's message. ", addkey, addvalue);
self.data[self.currentLocale.iso][addkey] = self.data[self.currentLocale.iso][addkey] || {};
self.data[self.currentLocale.iso][addkey].message = addvalue;
if (!self.fossil) {
self.fossil = self.toJSON();
}
self.unsaved = true;
var newLocaleItem = {};
newLocaleItem[key] = {
message: addvalue
};
self.addMessagesToContextualizedStrings(self.currentLocale.iso, newLocaleItem);
Q.nextTick(function() {
deferred.resolve(addvalue);
});
};
if (!this.testingAsyncConfirm && this.alwaysConfirmOkay /* run synchonosuly whenever possible */ ) {
self.debug(" Running synchonosuly. ", key, value);
addTheUsersMessage(key, value);
return deferred.promise;
}
self.debug(" Running asynchonosuly. ", key, value);
this.confirm("Do you also want to " + verb + key + " for other users? \n" + previousMessage + " -> " + value)
.then(function(response) {
self.debug("Recieved confirmation ,", response);
addTheUsersMessage(key, value);
},
function(reason) {
self.debug("Not updating , user clicked cancel", reason);
deferred.reject(reason);
})
.fail(
function(error) {
console.error(error.stack, self);
deferred.reject(error);
});
return deferred.promise;
}
},
audio: {
value: function(key) {
this.debug("Resolving localization in " + this.currentLocale.iso);
var result = {};
if (!this.data) {
this.warn("No localizations available, resolving empty audio details");
return result;
}
if (this.data[this.currentLocale.iso] && this.data[this.currentLocale.iso][key] && this.data[this.currentLocale.iso][key].audio !== undefined && this.data[this.currentLocale.iso][key].audio) {
result = this.data[this.currentLocale.iso][key].audio;
this.debug("Resolving localization audio using requested language: ", result);
} else {
if (this.data[this.defaultLocale.iso] && this.data[this.defaultLocale.iso][key] && this.data[this.defaultLocale.iso][key].audio !== undefined && this.data[this.defaultLocale.iso][key].audio) {
result = this.data[this.defaultLocale.iso][key].audio;
this.warn("Resolving localization audio using default: ", result);
}
}
return result;
}
},
addUrls: {
value: function(files, baseUrl) {
var promises = [],
f;
for (f = 0; f < files.length; f++) {
promises.push(this.addUrl(files[f], baseUrl));
}
return Q.all(promises);
}
},
addUrl: {
value: function(file, baseUrl) {
var deferred = Q.defer(),
localeCode,
self = this;
if (!baseUrl && FieldDBObject && FieldDBObject.application && FieldDBObject.application.corpus && FieldDBObject.application.corpus.url) {
this.debug("using corpus as base url");
baseUrl = FieldDBObject.application.corpus.url;
}
if (file.indexOf("/messages.json" > -1)) {
localeCode = file.replace("/messages.json", "");
if (localeCode.indexOf("/") > -1) {
localeCode = localeCode.substring(localeCode.lastIndexOf("/"));
}
localeCode = localeCode.replace(/[^a-zA-Z-]/g, "").toLowerCase();
if (!localeCode || localeCode.length < 2) {
localeCode = "default";
}
} else {
localeCode = "en";
}
CORS.makeCORSRequest({
method: "GET",
url: baseUrl + "/" + file,
dataType: "json"
}).then(function(localeMessages) {
self.originalDocs = self.originalDocs || [];
self.originalDocs.push(file);
self.addMessagesToContextualizedStrings(localeCode, localeMessages)
.then(deferred.resolve,
deferred.reject)
.fail(function(error) {
console.error(error.stack, self);
deferred.reject(error);
});
}, function(error) {
self.warn("There werent any locales at this url" + baseUrl + " :( Maybe this database has no custom locale messages.", error);
}).fail(function(error) {
console.error(error.stack, self);
deferred.reject(error);
});
return deferred.promise;
}
},
addMessagesToContextualizedStrings: {
value: function(localeCode, localeData) {
var deferred = Q.defer(),
self = this;
if (!localeData) {
Q.nextTick(function() {
deferred.reject("The locales data was empty!");
});
return deferred.promise;
}
if (!localeCode && localeData._id) {
localeCode = localeData._id.replace("/messages.json", "");
if (localeCode.indexOf("/") > -1) {
localeCode = localeCode.substring(localeCode.lastIndexOf("/"));
}
localeCode = localeCode.replace(/[^a-zA-Z-]/g, "").toLowerCase();
if (!localeCode || localeCode.length < 2) {
localeCode = "default";
}
}
self.originalDocs = self.originalDocs || [];
self.originalDocs.push(localeData);
self.data = self.data || {};
for (var message in localeData) {
if (localeData.hasOwnProperty(message) && message.indexOf("_") !== 0) {
self.data[localeCode] = self.data[localeCode] || {
length: 0
};
self.data[localeCode][message] = localeData[message];
self.data[localeCode].length++;
}
}
Q.nextTick(function() {
deferred.resolve(self.data);
});
return deferred.promise;
}
},
save: {
value: function() {
var promises = [];
for (var locale in this.data) {
if (!this.data.hasOwnProperty(locale)) {
continue;
}
this.debug("Requsting save of " + locale);
var doc = new FieldDBObject(this.data[locale]);
doc.dbname = this.dbname;
this.debug("Will save locale save of ", doc);
var userHasModifiedContexualizations = !!this.fossil;
if (this.email) {
this.debug(" via Git ", doc);
promises.push(doc.saveToGit({
email: this.email,
message: "Updated locale messages"
}, userHasModifiedContexualizations));
} else {
doc.id = locale + "/messages.json";
// doc.debugMode = true;
this.debug(" via REST ", doc);
promises.push(doc.save(null, userHasModifiedContexualizations));
}
}
return Q.allSettled(promises);
}
}
});
exports.Contextualizer = Contextualizer;
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"./../CORS":1,"./../FieldDBObject":3,"./ELanguages":51,"./elanguages.json":52,"./en/messages.json":53,"./es/messages.json":54,"q":248}],51:[function(require,module,exports){
var Collection = require("./../Collection").Collection;
var FieldDBObject = require("./../FieldDBObject").FieldDBObject;
/**
* @class Collection of Datum validation states
* @name ELanguages
* @description The ELanguages is a minimal customization of the Collection
* to add a primary key of iso.
*
* @extends Collection
* @constructs
*/
var ELanguages = function ELanguages(options) {
if (!this._fieldDBtype) {
this._fieldDBtype = "ELanguages";
}
this.debug("Constructing ELanguages ", options);
Collection.apply(this, arguments);
};
ELanguages.prototype = Object.create(Collection.prototype, /** @lends ELanguages.prototype */ {
constructor: {
value: ELanguages
},
primaryKey: {
value: "iso"
},
INTERNAL_MODELS: {
value: {
item: FieldDBObject /* TODO use normal object? */
}
},
sanitizeStringForPrimaryKey: {
value: function(value) {
return value;
}
}
});
exports.ELanguages = ELanguages;
},{"./../Collection":2,"./../FieldDBObject":3}],52:[function(require,module,exports){
module.exports=[{
"iso": "Non applicable",
"name": "NA",
"nativeName": "Non applicable"
}, {
"iso": "ab",
"name": "Abkhaz",
"nativeName": "аҧсуа"
}, {
"iso": "aa",
"name": "Afar",
"nativeName": "Afaraf"
}, {
"iso": "af",
"name": "Afrikaans",
"nativeName": "Afrikaans"
}, {
"iso": "ak",
"name": "Akan",
"nativeName": "Akan"
}, {
"iso": "sq",
"name": "Albanian",
"nativeName": "Shqip"
}, {
"iso": "am",
"name": "Amharic",
"nativeName": "አማርኛ"
}, {
"iso": "ar",
"name": "Arabic",
"nativeName": "العربية"
}, {
"iso": "an",
"name": "Aragonese",
"nativeName": "Aragonés"
}, {
"iso": "hy",
"name": "Armenian",
"nativeName": "Հայերեն"
}, {
"iso": "as",
"name": "Assamese",
"nativeName": "অসমীয়া"
}, {
"iso": "av",
"name": "Avaric",
"nativeName": "авар мацӀ, магӀарул мацӀ"
}, {
"iso": "ae",
"name": "Avestan",
"nativeName": "avesta"
}, {
"iso": "ay",
"name": "Aymara",
"nativeName": "aymar aru"
}, {
"iso": "az",
"name": "Azerbaijani",
"nativeName": "azərbaycan dili"
}, {
"iso": "bm",
"name": "Bambara",
"nativeName": "bamanankan"
}, {
"iso": "ba",
"name": "Bashkir",
"nativeName": "башҡорт теле"
}, {
"iso": "eu",
"name": "Basque",
"nativeName": "euskara"
}, {
"iso": "be",
"name": "Belarusian",
"nativeName": "Беларуская"
}, {
"iso": "bn",
"name": "Bengali",
"nativeName": "বাংলা"
}, {
"iso": "bh",
"name": "Bihari",
"nativeName": "भोजपुरी"
}, {
"iso": "bi",
"name": "Bislama",
"nativeName": "Bislama"
}, {
"iso": "bs",
"name": "Bosnian",
"nativeName": "bosanski jezik"
}, {
"iso": "br",
"name": "Breton",
"nativeName": "brezhoneg"
}, {
"iso": "bg",
"name": "Bulgarian",
"nativeName": "български език"
}, {
"iso": "my",
"name": "Burmese",
"nativeName": "ဗမာစာ"
}, {
"iso": "ca",
"name": "Catalan; Valencian",
"nativeName": "Català"
}, {
"iso": "ch",
"name": "Chamorro",
"nativeName": "Chamoru"
}, {
"iso": "ce",
"name": "Chechen",
"nativeName": "нохчийн мотт"
}, {
"iso": "ny",
"name": "Chichewa; Chewa; Nyanja",
"nativeName": "chiCheŵa, chinyanja"
}, {
"iso": "zh",
"name": "Chinese",
"nativeName": "中文"
}, {
"iso": "cv",
"name": "Chuvash",
"nativeName": "чӑваш чӗлхи"
}, {
"iso": "kw",
"name": "Cornish",
"nativeName": "Kernewek"
}, {
"iso": "co",
"name": "Corsican",
"nativeName": "corsu"
}, {
"iso": "cr",
"name": "Cree",
"nativeName": "ᓀᐦᐃᔭᐍᐏᐣ"
}, {
"iso": "hr",
"name": "Croatian",
"nativeName": "hrvatski"
}, {
"iso": "cs",
"name": "Czech",
"nativeName": "česky"
}, {
"iso": "da",
"name": "Danish",
"nativeName": "dansk"
}, {
"iso": "dv",
"name": "Divehi; Dhivehi; Maldivian;",
"nativeName": "ދިވެހި"
}, {
"iso": "nl",
"name": "Dutch",
"nativeName": "Nederlands, Vlaams"
}, {
"iso": "en",
"name": "English",
"nativeName": "English",
"selected": true
}, {
"iso": "eo",
"name": "Esperanto",
"nativeName": "Esperanto"
}, {
"iso": "et",
"name": "Estonian",
"nativeName": "eesti"
}, {
"iso": "ee",
"name": "Ewe",
"nativeName": "Eʋegbe"
}, {
"iso": "fo",
"name": "Faroese",
"nativeName": "føroyskt"
}, {
"iso": "fj",
"name": "Fijian",
"nativeName": "vosa Vakaviti"
}, {
"iso": "fi",
"name": "Finnish",
"nativeName": "suomi"
}, {
"iso": "fr",
"name": "French",
"nativeName": "français"
}, {
"iso": "ff",
"name": "Fula; Fulah; Pulaar; Pular",
"nativeName": "Fulfulde, Pulaar, Pular"
}, {
"iso": "gl",
"name": "Galician",
"nativeName": "Galego"
}, {
"iso": "ka",
"name": "Georgian",
"nativeName": "ქართული"
}, {
"iso": "de",
"name": "German",
"nativeName": "Deutsch"
}, {
"iso": "el",
"name": "Greek, Modern",
"nativeName": "Ελληνικά"
}, {
"iso": "gn",
"name": "Guaraní",
"nativeName": "Avañeẽ"
}, {
"iso": "gu",
"name": "Gujarati",
"nativeName": "ગુજરાતી"
}, {
"iso": "ht",
"name": "Haitian; Haitian Creole",
"nativeName": "Kreyòl ayisyen"
}, {
"iso": "ha",
"name": "Hausa",
"nativeName": "Hausa, هَوُسَ"
}, {
"iso": "he",
"name": "Hebrew (modern)",
"nativeName": "עברית"
}, {
"iso": "hz",
"name": "Herero",
"nativeName": "Otjiherero"
}, {
"iso": "hi",
"name": "Hindi",
"nativeName": "हिन्दी, हिंदी"
}, {
"iso": "ho",
"name": "Hiri Motu",
"nativeName": "Hiri Motu"
}, {
"iso": "hu",
"name": "Hungarian",
"nativeName": "Magyar"
}, {
"iso": "ia",
"name": "Interlingua",
"nativeName": "Interlingua"
}, {
"iso": "id",
"name": "Indonesian",
"nativeName": "Bahasa Indonesia"
}, {
"iso": "ie",
"name": "Interlingue",
"nativeName": "Occidental"
}, {
"iso": "ga",
"name": "Irish",
"nativeName": "Gaeilge"
}, {
"iso": "ig",
"name": "Igbo",
"nativeName": "Asụsụ Igbo"
}, {
"iso": "ik",
"name": "Inupiaq",
"nativeName": "Iñupiaq, Iñupiatun"
}, {
"iso": "io",
"name": "Ido",
"nativeName": "Ido"
}, {
"iso": "is",
"name": "Icelandic",
"nativeName": "Íslenska"
}, {
"iso": "it",
"name": "Italian",
"nativeName": "Italiano"
}, {
"iso": "iu",
"name": "Inuktitut",
"nativeName": "ᐃᓄᒃᑎᑐᑦ"
}, {
"iso": "ja",
"name": "Japanese",
"nativeName": "日本語"
}, {
"iso": "jv",
"name": "Javanese",
"nativeName": "basa Jawa"
}, {
"iso": "kl",
"name": "Kalaallisut, Greenlandic",
"nativeName": "kalaallisut"
}, {
"iso": "kn",
"name": "Kannada",
"nativeName": "ಕನ್ನಡ"
}, {
"iso": "kr",
"name": "Kanuri",
"nativeName": "Kanuri"
}, {
"iso": "ks",
"name": "Kashmiri",
"nativeName": "कश्मीरी, كشميري"
}, {
"iso": "kk",
"name": "Kazakh",
"nativeName": "Қазақ тілі"
}, {
"iso": "km",
"name": "Khmer",
"nativeName": "ភាសាខ្មែរ"
}, {
"iso": "ki",
"name": "Kikuyu, Gikuyu",
"nativeName": "Gĩkũyũ"
}, {
"iso": "rw",
"name": "Kinyarwanda",
"nativeName": "Ikinyarwanda"
}, {
"iso": "ky",
"name": "Kirghiz, Kyrgyz",
"nativeName": "кыргыз тили"
}, {
"iso": "kv",
"name": "Komi",
"nativeName": "коми кыв"
}, {
"iso": "kg",
"name": "Kongo",
"nativeName": "KiKongo"
}, {
"iso": "ko",
"name": "Korean",
"nativeName": "한국어"
}, {
"iso": "ku",
"name": "Kurdish",
"nativeName": "Kurdî, كوردی"
}, {
"iso": "kj",
"name": "Kwanyama, Kuanyama",
"nativeName": "Kuanyama"
}, {
"iso": "la",
"name": "Latin",
"nativeName": "latine"
}, {
"iso": "lb",
"name": "Luxembourgish, Letzeburgesch",
"nativeName": "Lëtzebuergesch"
}, {
"iso": "lg",
"name": "Luganda",
"nativeName": "Luganda"
}, {
"iso": "li",
"name": "Limburgish, Limburgan, Limburger",
"nativeName": "Limburgs"
}, {
"iso": "ln",
"name": "Lingala",
"nativeName": "Lingála"
}, {
"iso": "lo",
"name": "Lao",
"nativeName": "ພາສາລາວ"
}, {
"iso": "lt",
"name": "Lithuanian",
"nativeName": "lietuvių kalba"
}, {
"iso": "lu",
"name": "Luba-Katanga",
"nativeName": ""
}, {
"iso": "lv",
"name": "Latvian",
"nativeName": "latviešu valoda"
}, {
"iso": "gv",
"name": "Manx",
"nativeName": "Gaelg, Gailck"
}, {
"iso": "mk",
"name": "Macedonian",
"nativeName": "македонски јазик"
}, {
"iso": "mg",
"name": "Malagasy",
"nativeName": "Malagasy fiteny"
}, {
"iso": "ms",
"name": "Malay",
"nativeName": "bahasa Melayu"
}, {
"iso": "ml",
"name": "Malayalam",
"nativeName": "മലയാളം"
}, {
"iso": "mt",
"name": "Maltese",
"nativeName": "Malti"
}, {
"iso": "mi",
"name": "Māori",
"nativeName": "te reo Māori"
}, {
"iso": "mr",
"name": "Marathi (Marāṭhī)",
"nativeName": "मराठी"
}, {
"iso": "mh",
"name": "Marshallese",
"nativeName": "Kajin M̧ajeļ"
}, {
"iso": "mn",
"name": "Mongolian",
"nativeName": "монгол"
}, {
"iso": "na",
"name": "Nauru",
"nativeName": "Ekakairũ Naoero"
}, {
"iso": "nv",
"name": "Navajo, Navaho",
"nativeName": "Diné bizaad, Dinékʼehǰí"
}, {
"iso": "nb",
"name": "Norwegian Bokmål",
"nativeName": "Norsk bokmål"
}, {
"iso": "nd",
"name": "North Ndebele",
"nativeName": "isiNdebele"
}, {
"iso": "ne",
"name": "Nepali",
"nativeName": "नेपाली"
}, {
"iso": "ng",
"name": "Ndonga",
"nativeName": "Owambo"
}, {
"iso": "nn",
"name": "Norwegian Nynorsk",
"nativeName": "Norsk nynorsk"
}, {
"iso": "no",
"name": "Norwegian",
"nativeName": "Norsk"
}, {
"iso": "ii",
"name": "Nuosu",
"nativeName": "ꆈꌠ꒿ Nuosuhxop"
}, {
"iso": "nr",
"name": "South Ndebele",
"nativeName": "isiNdebele"
}, {
"iso": "oc",
"name": "Occitan",
"nativeName": "Occitan"
}, {
"iso": "oj",
"name": "Ojibwe, Ojibwa",
"nativeName": "ᐊᓂᔑᓈᐯᒧᐎᓐ"
}, {
"iso": "cu",
"name": "Old Church Slavonic",
"alternateNames": "Old Church Slavonic, Church Slavic, Church Slavonic, Old Bulgarian, Old Slavonic",
"nativeName": "ѩзыкъ словѣньскъ"
}, {
"iso": "om",
"name": "Oromo",
"nativeName": "Afaan Oromoo"
}, {
"iso": "or",
"name": "Oriya",
"nativeName": "ଓଡ଼ିଆ"
}, {
"iso": "os",
"name": "Ossetian, Ossetic",
"nativeName": "ирон æвзаг"
}, {
"iso": "pa",
"name": "Panjabi, Punjabi",
"nativeName": "ਪੰਜਾਬੀ, پنجابی"
}, {
"iso": "pi",
"name": "Pāli",
"nativeName": "पाऴि"
}, {
"iso": "fa",
"name": "Persian",
"nativeName": "فارسی"
}, {
"iso": "pl",
"name": "Polish",
"nativeName": "polski"
}, {
"iso": "ps",
"name": "Pashto, Pushto",
"nativeName": "پښتو"
}, {
"iso": "pt",
"name": "Portuguese",
"nativeName": "Português"
}, {
"iso": "qu",
"name": "Quechua",
"nativeName": "Runa Simi, Kichwa"
}, {
"iso": "rm",
"name": "Romansh",
"nativeName": "rumantsch grischun"
}, {
"iso": "rn",
"name": "Kirundi",
"nativeName": "kiRundi"
}, {
"iso": "ro",
"name": "Romanian, Moldavian, Moldovan",
"nativeName": "română"
}, {
"iso": "ru",
"name": "Russian",
"nativeName": "русский язык"
}, {
"iso": "sa",
"name": "Sanskrit (Saṁskṛta)",
"nativeName": "संस्कृतम्"
}, {
"iso": "sc",
"name": "Sardinian",
"nativeName": "sardu"
}, {
"iso": "sd",
"name": "Sindhi",
"nativeName": "सिन्धी, سنڌي، سندھی"
}, {
"iso": "se",
"name": "Northern Sami",
"nativeName": "Davvisámegiella"
}, {
"iso": "sm",
"name": "Samoan",
"nativeName": "gagana faa Samoa"
}, {
"iso": "sg",
"name": "Sango",
"nativeName": "yângâ tî sängö"
}, {
"iso": "sr",
"name": "Serbian",
"nativeName": "српски језик"
}, {
"iso": "gd",
"name": "Scottish Gaelic; Gaelic",
"nativeName": "Gàidhlig"
}, {
"iso": "sn",
"name": "Shona",
"nativeName": "chiShona"
}, {
"iso": "si",
"name": "Sinhala, Sinhalese",
"nativeName": "සිංහල"
}, {
"iso": "sk",
"name": "Slovak",
"nativeName": "slovenčina"
}, {
"iso": "sl",
"name": "Slovene",
"nativeName": "slovenščina"
}, {
"iso": "so",
"name": "Somali",
"nativeName": "Soomaaliga, af Soomaali"
}, {
"iso": "st",
"name": "Southern Sotho",
"nativeName": "Sesotho"
}, {
"iso": "es",
"name": "Spanish; Castilian",
"nativeName": "español, castellano"
}, {
"iso": "su",
"name": "Sundanese",
"nativeName": "Basa Sunda"
}, {
"iso": "sw",
"name": "Swahili",
"nativeName": "Kiswahili"
}, {
"iso": "ss",
"name": "Swati",
"nativeName": "SiSwati"
}, {
"iso": "sv",
"name": "Swedish",
"nativeName": "svenska"
}, {
"iso": "ta",
"name": "Tamil",
"nativeName": "தமிழ்"
}, {
"iso": "te",
"name": "Telugu",
"nativeName": "తెలుగు"
}, {
"iso": "tg",
"name": "Tajik",
"nativeName": "тоҷикӣ, toğikī, تاجیکی"
}, {
"iso": "th",
"name": "Thai",
"nativeName": "ไทย"
}, {
"iso": "ti",
"name": "Tigrinya",
"nativeName": "ትግርኛ"
}, {
"iso": "bo",
"name": "Tibetan Standard",
"alternateNames": "Tibetan Standard, Tibetan, Central",
"nativeName": "བོད་ཡིག"
}, {
"iso": "tk",
"name": "Turkmen",
"nativeName": "Türkmen, Түркмен"
}, {
"iso": "tl",
"name": "Tagalog",
"alternateNames": "Wikang Tagalog, ᜏᜒᜃᜅ᜔ ᜆᜄᜎᜓᜄ᜔",
"nativeName": "Wikang Tagalog"
}, {
"iso": "tn",
"name": "Tswana",
"nativeName": "Setswana"
}, {
"iso": "to",
"name": "Tonga (Tonga Islands)",
"nativeName": "faka Tonga"
}, {
"iso": "tr",
"name": "Turkish",
"nativeName": "Türkçe"
}, {
"iso": "ts",
"name": "Tsonga",
"nativeName": "Xitsonga"
}, {
"iso": "tt",
"name": "Tatar",
"nativeName": "татарча, tatarça, تاتارچا"
}, {
"iso": "tw",
"name": "Twi",
"nativeName": "Twi"
}, {
"iso": "ty",
"name": "Tahitian",
"nativeName": "Reo Tahiti"
}, {
"iso": "ug",
"name": "Uighur, Uyghur",
"nativeName": "Uyƣurqə, ئۇيغۇرچە"
}, {
"iso": "uk",
"name": "Ukrainian",
"nativeName": "українська"
}, {
"iso": "ur",
"name": "Urdu",
"nativeName": "اردو"
}, {
"iso": "uz",
"name": "Uzbek",
"nativeName": "zbek, Ўзбек, أۇزبېك"
}, {
"iso": "ve",
"name": "Venda",
"nativeName": "Tshivenḓa"
}, {
"iso": "vi",
"name": "Vietnamese",
"nativeName": "Tiếng Việt"
}, {
"iso": "vo",
"name": "Volapük",
"nativeName": "Volapük"
}, {
"iso": "wa",
"name": "Walloon",
"nativeName": "Walon"
}, {
"iso": "cy",
"name": "Welsh",
"nativeName": "Cymraeg"
}, {
"iso": "wo",
"name": "Wolof",
"nativeName": "Wollof"
}, {
"iso": "fy",
"name": "Western Frisian",
"nativeName": "Frysk"
}, {
"iso": "xh",
"name": "Xhosa",
"nativeName": "isiXhosa"
}, {
"iso": "yi",
"name": "Yiddish",
"nativeName": "ייִדיש"
}, {
"iso": "yo",
"name": "Yoruba",
"nativeName": "Yorùbá"
}, {
"iso": "za",
"name": "Zhuang, Chuang",
"nativeName": "Saɯ cueŋƅ, Saw cuengh"
}]
},{}],53:[function(require,module,exports){
module.exports={
"application_title" : {
"message" : "LingSync beta",
"description" : "The title of the application, displayed in the web store."
},
"application_description" : {
"message" : "An on/offline fieldlinguistics database app which adapts to its user's I-Language.",
"description" : "The description of the application, displayed in the web store."
},
"locale_Close_and_login_as_LingLlama" : {
"message" : "Login as LingLlama",
"description" : "button"
},
"locale_Close_and_login_as_LingLlama_Tooltip" : {
"message" : "You can log in as LingLlama to explore the app pre-populated with data. There are also comments left by users to explain what widgets are for and how you can use them. If you're new to the app this is a great place to start after watching the videos. ",
"description" : "tooltip"
},
"locale_Username" : {
"message" : "Username:"
},
"locale_Password" : {
"message" : "Password:"
},
"locale_Sync_my_data_to_this_computer" : {
"message" : "Sync my data to this device"
},
"locale_Welcome_to_FieldDB" : {
"message" : "Welcome to LingSync!"
},
"locale_An_offline_online_fieldlinguistics_database" : {
"message" : "This app is part of a free, open source project developed collectively by field linguists and software developers to make a modular, user-friendly app which can be used to collect, search and share data, both online and offline."
},
"locale_Welcome_Beta_Testers" : {
"message" : "Welcome Beta Testers! Please sit back with a cup of tea and watch this play list before you begin testing the app. Leave us notes, bugs, comments, suggestions etc in the Contact Us/Bug Report form in the User Menu. Your feedback helps us prioritize what to fix/implement next!
"
},
"locale_Welcome_Screen" : {
"message" : "Curious what this is? You can watch this play list to find out.. You can find help and more info in the top right menu of the Corpus Dashboard.
"
},
"locale_Create_a_new_user" : {
"message" : "Register"
},
"locale_What_is_your_username_going_to_be" : {
"message" : "What is your username going to be?"
},
"locale_Confirm_Password" : {
"message" : "Confirm Password:"
},
"locale_Sign_in_with_password" : {
"message" : "Register"
},
"locale_Warning" : {
"message" : "Warning!"
},
"locale_Instructions_to_show_on_dashboard" : {
"comment" : "Welcome! This is your Corpus dashboard. On the left side, there are Corpus and Elicitation Session quick-views, both of which you can make full screen by clicking the icon on the top right corner. Full screen shows you details of the Corpus and Elicitation Session. If this is your first time seeing this message, you should change your corpus title and description by clicking . You can hover over any icon to see what the icon does. You should also change your session goals and date for your first elicitation session.
For more help text, videos and userguide, click the on the top right corner of the app. To more information about what a 'Corpus' is, click . It will show the corpus settings, which contains explanations of each component of a 'Corpus.'
This is the first draft of these instructions. Please help us make this better. Contact us
",
"message" : "Welcome! This is your Corpus dashboard. If this is your first time seeing this message, please do the following:
Corpus On the left side, there is Corpus quick-view. Edit your corpus title and description by clicking . To see what Corpus consists of, click .
Elicitation Session Below the Corpus quick-view, there is Elicitation Session quick-view. Edit the goal and date for your first elicitation session by clicking . Click to see more details of Elicitation Session.
You can hover over any icon to see what the icon does. For more help text, videos and userguide, click the on the top right corner of the app.
This is the first draft of these instructions. Please help us make this better. Contact us
"
},
"locale_elicitation_sessions_explanation" : {
"message" : "Like in the real world, an Elicitation Session can have a variety of forms. For example: a 1 hour session with a language consultant, a 3 hour field methods class with several speakers, an extended conversation or narrative, or data from a file import.
You can describe various aspects of an Elicitation Session such as date, goal/topic, consultant(s), etc. by clicking the icon in Dashboard view. For additional options, click on the icon beside the session name in the list below.
Any description you enter will be displayed in the list of Elicitation Sessions below to help you identify them. This information will also be automatically copied into every Datum that is associated with the Session, so that you can search for individual Datum by date, consultant, dialect, etc.
"
},
"locale_datalists_explanation" : {
"message" : "A Datalist is a collection of Datum that you put together for some reason. Some examples are: making a handout, sharing data with someone, exporting into another program, or simply keeping track of similar Datum for your research.
Creating a Datalist is like making a bookmark to a set of custom search results. First, do a search for whatever you want the Datalist to be about. Then, if you don't want some of the results to be included in the Datalist, click the icon by any Datum to remove it. Finally, edit the title and description, and click the save button to create the Datalist.
You can see your Datalists on the left side of your dashboard (click plus/minus to expand/minimize) or in the list below (double-click on a title to view details).
To see all your data, do a search with nothing in the search bar. If you have over 200 Datum in your corpus, this can be pretty slow, so you may prefer to search for a subset. In general, a Datalist with more than 100 Datum will take a few seconds to load.
In the Datalist view, the Datum will appear in the colour of their current state (i.e. Checked with a consultant, To be checked, Deleted etc). You can make new states in the Datum State Settings on this page.
"
},
"locale_permissions_explanation" : {
"message" : "Permissions are where you give other people access to your corpus.
To add another team member, you need to know their username. Click the icon at the top right and then come back to Permissions and click the 'See current team members' button. You can then add users by typing in their username by the appropriate group.
- Admins can add other people to any group but not do anything with the data unless they are also writers/readers.
- Writers can enter new data, add comments, change Datum State from 'to be checked to 'checked' etc, but not see data that is already entered.
- Readers can see data that is already entered in the app but not edit or comment on it.
If you want someone to be able to both enter data and see existing data, add them as both a writer and a reader.
If you want to make your corpus public and findable on Google as recommended by EMLED data management best practices, type 'Public' in the 'Public or Private' field below.
You can, and should, encrypt any Datum containing sensitive information by clicking the button at the bottom of the Datum. Encrypted Datums are shown as 'xxx xx xx xx' to all users, including on the web. If you want to see the contents of a confidential Datum, click on the and enter your password. This will make the Datum visible for 10 minutes.
"
},
"locale_datum_fields_explanation" : {
"message" : "Datum Fields are fields where you can add information about your Datum. There fields are automatically detected when you import data, so if you have data already, you should import it to save you time configuring your corpus.
By default, the app comes with 4 fields which it uses to create inter-linearized glosses (the pretty view which you are used to seeing in books and handouts). You can add any number of fields (we have tested using over 400 fields).
In the Datum Edit view, the fields that are used most frequently in your corpus will automatically appear when you open a Datum, and you can click on to see the rare fields.
The fields in your corpus (shown below) are automatically available in search. You can choose to encrypt particular fields (e.g. utterance). If you mark a Datum as confidential, the encrypted fields will be encrypted in the database and masked from the user as 'xxx xx xxxxx'. For example, you may choose to not encrypt a lambda calculus field or a grammatical notes field, as these are usually purely a linguistic formalism and may not transmit any personal information which your consultants would like to keep confidential.
Each Datum Field has a help convention, which is the text you see below. Use this to help everyone remember what information goes in which field. Anyone who can enter data in your corpus can see these help conventions by clicking the next to the Datum Field label in the Datum Edit view.
You can edit the help text by clicking icon at the top right. These help conventions are also exported as a README.txt when you export your data, as recommended by EMELD data management best practices.
"
},
"locale_conversation_fields_explanation" : {
"message" : "Conversation Fields are fields which where you can add information about your Conversation. As defaults the conversation comes with 2 fields (audio and speakers), and each turn of the conversation (each Datum within it) comes with the usual 4 default datum fields. You can add any number of fields here if they are relevant to the WHOLE conversation (ex: location, context, world knowledge, sociolinguistic variables). The conversation fields in your corpus (shown below) are automatically available in the search. You can choose to encrypt particular fields (e.g. utterance). If you mark a Conversation as confidential, the encrypted fields will be encrypted in the database and masked from the user as 'xxx xx xxxxx'. For example, you may choose to not encrypt a 'location' field, but instead choose to encrypt a 'world knowledge' field as it may contain sensitive personal information which consultants would not want public. Each Conversation field can have a help convention, which is the text you see below. Your team members can see these help/conventions by clicking the next to the Conversation field label in the Conversation Edit view. These help conventions are also exported as a README.txt when you export your data, as recommended by EMELD data management best practices.
"
},
"locale_datum_states_explanation" : {
"message" : "Datum States are used to keep track of whether the data is valid or invalid, for example, 'Checked' with a consultant, 'To be checked', 'Deleted' etc.
Datum States can be as detailed as you choose. You can create your own Datum States for your own corpus to help you manage your team's data validation workflow (e.g. 'To be checked with Sophie,' 'Checked with Gladys'). You can assign colours to your Datum States, which will appear as the background colour of the Datum in any Datalist.
If you flag a Datum as Deleted it won't show up in search results anymore, but a Datum in a corpus is never really deleted. It remains in the database complete with its change history so that you can review it at a later date. (In future we might add a button to allow users to 'empty the trash' and mass-delete old Datum from the system.)
"
},
"locale_advanced_search_explanation" : {
"message" : "Search errs on the side of including more results, rather than missing anything.
For example, you can type 'nay' and search will find the morphemes 'onay', 'naya' etc.
Search automatically creates a temporary list of data. If you enter new matching data, it will be added automatically this can be a handy way to see the data you have entered recently, as you enter data.. If you want to keep the list of data, click Save and a new DataList will be created.
For now, search is offline, running on your device, but we would eventually like to have a more advanced search that works online, sorts results better, and could let you search for minimal pairs using features.
"
},
"locale_New_User" : {
"message" : "New User"
},
"locale_Activity_Feed_Your" : {
"message" : "Your Activity Feed"
},
"locale_Activity_Feed_Team" : {
"message" : "Corpus Team Activity Feed"
},
"locale_Refresh_Activities" : {
"message" : "Refresh activity feed to bring it up-to-date."
},
"locale_Need_save" : {
"message" : " Need save:"
},
"locale_60_unsaved" : {
"message" : "60% unsaved."
},
"locale_Recent_Changes" : {
"message" : "Recent Changes:"
},
"locale_Need_sync" : {
"message" : "Need sync:"
},
"locale_Differences_with_the_central_server" : {
"message" : "Differences with the central server:"
},
"locale_to_beta_testers" : {
"message" : "These messages are here to communicate to users what the app is doing. We will gradually reduce the number of messages as the app becomes more stable. You can close these messages by clicking on their x.
"
},
"locale_We_need_to_make_sure_its_you" : {
"message" : "We need to make sure it's you..."
},
"locale_Yep_its_me" : {
"message" : "Yep, it's me"
},
"locale_Log_Out" : {
"message" : "Log Out"
},
"locale_Log_In" : {
"message" : "Log In"
},
"locale_User_Settings" : {
"message" : "User Settings"
},
"locale_Keyboard_Shortcuts" : {
"message" : "Keyboard Shortcuts"
},
"locale_Corpus_Settings" : {
"message" : "Corpus Settings"
},
"locale_Terminal_Power_Users" : {
"message" : "Power Users Backend"
},
"locale_New_Datum" : {
"message" : "New Datum"
},
"locale_New_menu" : {
"message" : "New"
},
"locale_New_Conversation" : {
"message" : "New Conversation"
},
"locale_New_Data_List" : {
"message" : "New Data List"
},
"locale_New_Session" : {
"message" : "New Session"
},
"locale_New_Corpus" : {
"message" : "New Corpus"
},
"locale_Data_menu" : {
"message" : "Data"
},
"locale_Import_Data" : {
"message" : "Import Data"
},
"locale_Export_Data" : {
"message" : "Export Data"
},
"locale_All_Data" : {
"message" : "All Data"
},
"locale_All_Speakers" : {
"message" : "All (Native/Heritage) Speakers"
},
"locale_All_Language_Consultants" : {
"message" : "All Language Consultants"
},
"locale_All_Participants" : {
"message" : "All Participants"
},
"locale_All_Users" : {
"message" : "All Users"
},
"locale_All_Elicitation_Sessions" : {
"message" : "All Elicitation Sessions"
},
"locale_All_Datalists" : {
"message" : "All Datalists"
},
"locale_Save" : {
"message" : "Save"
},
"locale_Title" : {
"message" : "Title:"
},
"locale_Description" : {
"message" : "Description:"
},
"locale_Copyright" : {
"message" : "Corpus Copyright:"
},
"locale_License" : {
"message" : "Corpus License:"
},
"locale_License_explanation" : {
"message" : "If you make a portion of your corpus available to other people, EMELD recommends that you document clearly your terms of use, and apply a license to enforce them. For easy to understand standard licenses, you can consult Creative Commons. Creative Commons licenses are applied to most web/community owned/created data, be it Wikipedia or other popular content sharing websites and mobile apps."
},
"locale_Terms_of_use" : {
"message" : "Corpus Terms of Use:"
},
"locale_Terms_explanation" : {
"message" : "When you decide to make a portion of your corpus public, EMELD recommend that you cleary state your Terms of Use with your corpus. You can modify the sample of “Terms of Use” in the textbox below according to the policy of your project (be sure to discuss with other project members and affected parties before deciding on your terms of use). Please also try to choose a license which makes sense with your Terms of Use. For your reference, see also the terms of use for other corpora such as: Mura, PARADISEC, Survey of California and Other Indian Languages "
},
"locale_Sessions_associated" : {
"message" : "Elicitation Sessions associated with this corpus"
},
"locale_Datalists_associated" : {
"message" : "Datalists associated with this corpus"
},
"locale_Permissions_associated" : {
"message" : "Permissions associated with this corpus"
},
"locale_Datum_field_settings" : {
"message" : "Datum Field Settings"
},
"locale_Conversation_field_settings" : {
"message" : "Conversation Field Settings"
},
"locale_Encrypt_if_confidential" : {
"message" : "Encrypt if confidential:"
},
"locale_Help_Text" : {
"message" : "Help Text:"
},
"locale_Add" : {
"message" : "Add"
},
"locale_Datum_state_settings" : {
"message" : "Datum State Settings"
},
"locale_Green" : {
"message" : "Green"
},
"locale_Orange" : {
"message" : "Orange"
},
"locale_Red" : {
"message" : "Red"
},
"locale_Blue" : {
"message" : "Blue"
},
"locale_Teal" : {
"message" : "Teal"
},
"locale_Black" : {
"message" : "Black"
},
"locale_Default" : {
"message" : "Default"
},
"locale_Elicitation_Session" : {
"message" : "Elicitation Session"
},
"locale_Export" : {
"message" : "Export"
},
"locale_Actions" : {
"message" : "Actions"
},
"locale_Navigation" : {
"message" : "Navigation"
},
"locale_Datum_Status_Checked" : {
"message" : "Mark Datum status as checked/verified with language consultant"
},
"locale_Next_Datum" : {
"message" : "Next Datum"
},
"locale_Previous_Datum" : {
"message" : "Previous Datum"
},
"locale_Data_Entry_Area" : {
"message" : "Data Entry Area (1-200 datum)"
},
"locale_Search" : {
"message" : "Type your search query, or hit enter to see all data"
},
"locale_View_Profile_Tooltip" : {
"message" : "Click to view user's page"
},
"locale_View_Public_Profile_Tooltip" : {
"message" : "View/edit your public user's page"
},
"locale_Edit_User_Profile_Tooltip" : {
"message" : "Click to edit your user profile"
},
"locale_Public_Profile_Instructions" : {
"message" : "This is your public user's page. You can edit it to change/remove information. This is what your team members can see when they click on your gravatar. All of this information (including your gravatar) can be different from the information in your private profile."
},
"locale_Private_Profile_Instructions" : {
"message" : "This is your private profile."
},
"locale_Edit_Public_User_Profile" : {
"message" : "Edit my public user's page"
},
"locale_Close" : {
"message" : "Close"
},
"locale_New_Corpus_Instructions" : {
"message" : "Edit the fields below to create a new corpus, or push ESC to enter more data in the current corpus"
},
"locale_New_Corpus_Warning" : {
"message" : " The New Corpus functionality still needs more testing, this message will disappear when New Corpus is not experimental."
},
"locale_Cancel" : {
"message" : "Cancel"
},
"locale_Next" : {
"message" : "Next"
},
"locale_Show" : {
"message" : "Show"
},
"locale_per_page" : {
"message" : "per page"
},
"locale_New_Session_Instructions" : {
"message" : "Edit the fields below to create a new elicitation session, or push ESC to enter more data in the current session.
"
},
"locale_Consultants" : {
"message" : "Consultant(s):"
},
"locale_Goal" : {
"message" : "Goal:"
},
"locale_When" : {
"message" : "When:"
},
"locale_Save_And_Import" : {
"message" : "Save and Finish Importing"
},
"locale_Import" : {
"message" : "Import"
},
"locale_percent_completed" : {
"message" : "% completed."
},
"locale_Import_Instructions" : {
"comment" : " - Type, or Drag and drop a file/text (csv, txt, tabbed, xml, text, eaf, sf) to the area indicated below.
- (Edit/type in the text area to correct information as needed.)
- Associate your corpus's existing default data fields with the appropriate columns by either dragging the colored datum fields, or by typing in the column header input box .
- Type in any other column headings that you want to keep in your data, the app will automatically add these to the corpus' default datum fields. This means that you can search through them to locate your data. Each row in the table will be come a 'datum' in your corpus database.
- Click on the Attempt Import button at any time to see what your data will look like in a interlinear glossed data list.
- Review the interlinear glossed data list which appears on the left to see if the import looks good.
- (Continue to edit the table cells as needed, click Attempt Import and review data list as many times as you would like until the import looks correct).
- When satisfied with the data list, click Save and your data will be imported into your corpus. A new elicitation session will be created using the date modified of the file you imported (if you want, you can edit this session later to add a more accurate goal discussing why the file was originally created), a new data list will also be created which contains all these data since it is likely that you grouped this data together into a file for a reason in the first place. You can find the resulting new default datum fields, session, and data list in your Corpus Settings page.
- (Click on the home button to do something else while it imports your data in the background.)
",
"message" : "Everyone's data is different. You might know some fellow users who might be able to help you import yours: "
},
"locale_Import_First_Step" : {
"message" : "Step 1: Drag & drop, copy-paste or type your data into the text area, or select audio/video file(s) from your computer. Yes, you can edit the data inside the text area.
"
},
"locale_Import_Second_Step" : {
"message" : "Step 2: Drag and drop or type the field names in column headers. Edit data in the table as needed.
"
},
"locale_Import_Third_Step" : {
"message" : "Step 3: The imported data will look like this. Edit in the table or the text area above as needed. Edit the datalist title and description, and the eliciation session section before finishing import.
"
},
"locale_Drag_Fields_Instructions" : {
"message" : "Drag (or type) the coloured datum fields to the column headings which match. Type in any additional column headings which you would like to keep as datum fields. The columns will become default datum fields in your corpus database and will also become fields that you can search through to locate your data. Each row will become a 'datum' in your corpus database.
"
},
"locale_Add_Extra_Columns" : {
"message" : "Insert Extra Columns"
},
"locale_Attempt_Import" : {
"message" : "Preview Import"
},
"locale_LaTeX_Code" : {
"message" : "LaTeX Code:"
},
"locale_Unicode_Instructions" : {
"message" : "By default this is also a keyboard shortcut to type this character in a datum field. To customize the shortcut:"
},
"locale_Remove_Unicode" : {
"message" : "Remove Unicode"
},
"locale_Unicode" : {
"message" : "Unicode"
},
"locale_Drag_and_Drop" : {
"message" : "Drag and Drop"
},
"locale_AND" : {
"message" : "AND"
},
"locale_OR" : {
"message" : "OR"
},
"locale_Advanced_Search" : {
"message" : "Advanced Search"
},
"locale_Advanced_Search_Tooltip" : {
"message" : "Advanced Search allows you to use your corpus-wide datum fields or session details to search for datum, using either AND or OR with substring match."
},
"locale_User_Profile" : {
"message" : "User Profile"
},
"locale_Private_Profile" : {
"message" : "User Profile"
},
"locale_Public_Profile" : {
"message" : "Public Profile"
},
"locale_Email" : {
"message" : "Email:"
},
"locale_Research_Interests" : {
"message" : "Research Interests:"
},
"locale_Affiliation" : {
"message" : "Affiliation:"
},
"locale_Corpora" : {
"message" : "Corpora:"
},
"locale_Gravatar" : {
"message" : "Gravatar"
},
"locale_Gravatar_URL" : {
"message" : "Gravatar URL:"
},
"locale_Firstname" : {
"message" : "First name:"
},
"locale_Lastname" : {
"message" : "Last name:"
},
"locale_Skin" : {
"message" : "Skin:"
},
"locale_Background_on_Random" : {
"message" : "Background on Random"
},
"locale_Transparent_Dashboard" : {
"message" : "Transparent Dashboard"
},
"locale_Change_Background" : {
"message" : "Change Background"
},
"locale_Number_Datum" : {
"message" : "Number of Datum to appear at a time:"
},
"locale_Help_Text_Placeholder" : {
"message" : "Put a help text or your team data entry conventions for this field here (optional)."
},
"locale_Add_Placeholder" : {
"message" : "Add...."
},
"locale_Datalist_Description" : {
"message" : "You can use Datalists to create handouts or to prepare for sessions with consultants, or to share with collaborators."
},
"locale_Add_Tag" : {
"message" : "New Tag..."
},
"locale_Drag_and_Drop_Placeholder" : {
"message" : "Drag and drop, copy-paste or type your data here."
},
"locale_Paste_Type_Unicode_Symbol_Placeholder" : {
"message" : "Paste/type unicode symbol"
},
"locale_TIPA_shortcut" : {
"message" : "TIPA/keyboard shortcut"
},
"locale_Show_Activities" : {
"message" : "Show Activities"
},
"locale_Hide_Activities" : {
"message" : "Hide Activities"
},
"locale_Show_Dashboard" : {
"message" : "Show dashboard with data entry form"
},
"locale_Save_on_this_Computer" : {
"message" : "Save on this device."
},
"locale_Sync_and_Share" : {
"message" : "Sync and share with team"
},
"locale_Show_Readonly" : {
"message" : "Show read only"
},
"locale_Show_Fullscreen" : {
"message" : "Show full screen"
},
"locale_Add_New_Datum_Field_Tooltip" : {
"message" : "Add new datum field"
},
"locale_Add_New_Conversation_Field_Tooltip" : {
"message" : "Add new conversation field"
},
"locale_Add_New_Datum_State_Tooltip" : {
"message" : "Add new datum state"
},
"locale_Show_in_Dashboard" : {
"message" : "Show in dashboard"
},
"locale_Edit_corpus" : {
"message" : "Edit Corpus"
},
"locale_Show_corpus_settings" : {
"message" : "Show Corpus Settings"
},
"locale_Drag_and_Drop_Audio_Tooltip" : {
"message" : "Drag and drop audio over the audio player to attach an audio file. Drag and drop option for YouTube videos coming soon."
},
"locale_Play_Audio" : {
"message" : "Play audio"
},
"locale_Play_Audio_checked" : {
"message" : "Play audio of checked items"
},
"locale_Remove_checked_from_datalist_tooltip" : {
"message" : "Remove checked datum from this data list (they will still be in the corpus). "
},
"locale_Plain_Text_Export_Tooltip" : {
"message" : "Export as plain text/Copy to clipboard"
},
"locale_Plain_Text_Export_Tooltip_checked" : {
"message" : "Export as plain text/Copy checked items to clipboard"
},
"locale_Duplicate" : {
"message" : "Duplicate datum to create a minimal pair"
},
"locale_Encrypt" : {
"message" : "Make this datum confidential"
},
"locale_Encrypt_checked" : {
"message" : "Make checked items confidential"
},
"locale_Decrypt_checked" : {
"message" : "Remove confidentiality from checked items (Warning: this will save them as decrypted in the database). If you just want to unmask them so you can edit edit them, click on the eye instead."
},
"locale_Decrypt" : {
"message" : "Remove confidentiality from this datum (Warning: this will save it as decrypted in the database). If you just want to unmask it so you can edit edit it, click on the eye instead."
},
"locale_Show_confidential_items_Tooltip" : {
"message" : "Unmask confidential/encrypted data so that it can be edited and read for the next 10 minutes."
},
"locale_Hide_confidential_items_Tooltip" : {
"message" : "Return to masked view of confidential/encrypted data"
},
"locale_Edit_Datalist" : {
"message" : "Edit Data List"
},
"locale_Export_checked_as_LaTeX" : {
"message" : "Export checked as LaTeX"
},
"locale_Export_checked_as_CSV" : {
"message" : "Export checked as CSV"
},
"locale_Hide_Datalist" : {
"message" : "Hide datalist"
},
"locale_Show_Datalist" : {
"message" : "Show datalist"
},
"locale_Edit_Datum" : {
"message" : "Edit Datum"
},
"locale_See_Fields" : {
"message" : "Hide/Show infrequent fields"
},
"locale_Add_Tags_Tooltip" : {
"message" : "Add a tag to this datum. Tags can be used to categorize datum, count how many datum of each tag you have, and search datum."
},
"locale_Edit_Session" : {
"message" : "Edit Session"
},
"locale_Show_Unicode_Palette" : {
"message" : "Show Unicode Palette"
},
"locale_Hide_Unicode_Palette" : {
"message" : "Hide Unicode Palette"
},
"locale_Add_new_symbol" : {
"message" : "Add new symbol"
},
"locale_Public_or_Private" : {
"message" : "Public or Private:"
},
"locale_Insert_New_Datum" : {
"message" : "Insert a new datum on top of the dashboard center"
},
"locale_LaTeX" : {
"message" : "Export datum as LaTeX"
},
"locale_CSV_Tooltip" : {
"message" : "Export datum as CSV"
},
"locale_of" : {
"message" : "of"
},
"locale_pages_shown" : {
"message" : "pages shown"
},
"locale_More" : {
"message" : "More"
}
}
},{}],54:[function(require,module,exports){
module.exports={
"application_title" : {
"message" : "iCampo beta"
},
"application_description" : {
"message" : "Un aplicacion de colección de datos linguisticos."
},
"locale_Close_and_login_as_LingLlama" : {
"message" : "Entrar como LingLlama",
"description" : "button"
},
"locale_Close_and_login_as_LingLlama_Tooltip" : {
"message" : "TODO translate You can log in as LingLlama to explore the app pre-populated with data. There are also comments left by users to explain what widgets are for and how you can use them. If you're new to FieldDB this is a great place to start after watching the videos.",
"description" : "tooltip"
},
"locale_Username" : {
"message" : "Usuario:"
},
"locale_Password" : {
"message" : "Contraseña:"
},
"locale_Sync_my_data_to_this_computer" : {
"message" : "Sincronisa mis datos con esta computadora"
},
"locale_Welcome_to_FieldDB" : {
"message" : "¡Bienvenido a iCampo! beta"
},
"locale_An_offline_online_fieldlinguistics_database" : {
"message" : "Un aplicacion de coleccion de datos linguisticos...gratis y OpenSource"
},
"locale_Welcome_Beta_Testers" : {
"message" : "¡Bienvenidos! Por favor vea estos tutoriales antes de empezar de probar iCampo. Dejanos notas, comentarios, sugerencias en la forma abajo."
},
"locale_Create_a_new_user" : {
"message" : "Crear un nuevo usuario"
},
"locale_What_is_your_username_going_to_be" : {
"message" : "¿Que quieres por su usuario?"
},
"locale_Confirm_Password" : {
"message" : "Confirme su contraseña:"
},
"locale_Sign_in_with_password" : {
"message" : "Registrar"
},
"locale_Warning" : {
"message" : "¡Aviso!"
},
"locale_Instructions_to_show_on_dashboard" : {
"message" : "TODO translate instructions"
},
"locale_elicitation_sessions_explanation" : {
"message" : "TODO translate An Elicitation Session is very similar to an elicitation session in the real world. This could be a 1-hour Session with one language consultant, or a 3-hour field methods class, or data from a file import. Generally an elicitation session happens on a specific day, or across a few days, you can write a date or text in the 'dateElicited' field. Often we have a goal set out when we meet for an elicitation Session, if you want, you can put this into the 'Goal' field of the Sessions and it will appear in the Session quick links below. An Elicitation Session has many fields which you can edit by clicking on the icons in the app to see the details. These fields are information which is common to all datum elicited that day for example, the dialect, perhaps the language consultants present the date etc. The Session fields are copied into the Datum that were elicited during that Session, this makes it possible to search for Datum containing a particular dialect and/or speaker etc.
"
},
"locale_datalists_explanation" : {
"message" : "TODO translate A Datalist is a collection of Datum that you put together for a reason, it could be to prepare a handout, to share some of your data with someone, to export into another program or simply to keep track of similar Datum for your research. You could think of Datalists as curated search results that the app remembers for you. Datalists have titles and descriptions, their titles appear as links below. You can click on the links to see the details of the Datalist. In the Datalist view, the Datum will appear in the colour of their current state (i.e. Checked with a consultant, To be checked, Deleted etc). You can make new states in the Datum State Settings on this page. You can create new Datalists by doing a search for what you want to be in the Datalist. You can refine the Datalist items by clicking on to remove Datum in the Datalist view. The Datalist view is normally on the left side of your dashboard, you can see it by double clicking on a Datalist in the list below. If you want to see all your data click on the 'All Data' link below, this will load all your data into a Datalist view. If you have over 200 Datum in your corpus, this can be pretty slow. If you have a large corpus you may prefer searching for a subset of your data rather than skimming all of it at once. In general, any Datalist with more than 100 Datum takes a few seconds to load and display all the Datum it contains.
"
},
"locale_permissions_explanation" : {
"message" : "TODO translate Permissions are where you give your team members access to your corpus. Add users to the 'Admin' group if you want to let them add other team members. Add users to the 'Writers' group if you want to let them add comments, enter new data, change Datum State from 'to be checked to 'checked' etc. For example, if you would like to allow your language consultant to enter or check data, you can put them in the 'writers' group. Add users to the 'Readers' group if you want them to be able to see your data, but not modify it. For example, you might want to share your data with other researchers outside of your team, but you might not want them to leave comments or modify , or mass-export the data. If you want to make your corpus public and findable on Google as recommended by EMLED data management best practices, click the Public checkbox. Don't worry, if your corpus contains confidential or personal information you can, and should, encrypt the Datum containing sensitive information using the buttons. Data which are encrypted are shown as 'xxx xx xx xx' to all users, including on the web. If you want to see the contents of the confidential datum you have to click on the , it will prompt you for your password to make sure you are really you. This will make confidential data visible for 10 minutes.
"
},
"locale_datum_fields_explanation" : {
"message" : "TODO translate Datum Fields are fields which where you can add information about your Datum. There fields are automatically detected when you import data, so if you have data already, you should import it to save you time configuring your corpus. As defaults the app comes with 4 fields which it uses to create inter-linear-glossed text views (i.e. pretty view which you are used to seeing in books and handouts). You can add any number of fields (we have tested using over 400 fields). In the Datum Edit view, the fields that are used most frequently in your corpus will automatically appear when you open a Datum, and you can click on to see the rare fields. The fields in your corpus (shown below) are automatically available in the search. You can choose to encrypt particular fields (e.g. utterance). If you mark a Datum as confidential, the encrypted fields will be encrypted in the database and masked from the user as 'xxx xx xxxxx'. For example, you may choose to not encrypt a lambda calculus field, or a grammatical notes field, as these are usually purely a linguistic formalism and may not transmit any personal information which your consultants would like to keep confidential. Each Datum Fields can have a help convention, which is the text you see below. Your team members can see these help/conventions by clicking the next to the Datum Field label in the Datum Edit view. These help conventions are also exported as a README.txt when you export your data, as recommended by EMELD data management best practices.
"
},
"locale_datum_states_explanation" : {
"message" : "TODO translate Datum States are used to keep track of whether the data is valid or invalid, for example, 'Checked' with a consultant, 'To be checked', 'Deleted' etc. Datum States can be as detailed as you choose. You can create your own Datum States for your own corpus to help you manage your team's data validation workflow (e.g. 'To be checked with Sophie,' 'Checked with Gradys'). You can assign colours to your Datum States, these colours will appear in your data list. You can flag a Datum as Deleted and it won't show up in search results. A Datum in a corpus is never really deleted, it remains in the database complete with its change history so that you can review it at a later date. (In future we might add a button to allow users to 'empty the trash' and mass-delete old Datum from the system.)
"
},
"locale_advanced_search_explanation" : {
"message" : "TODO translate There are two ways to access Search, you can type in your query in the search box which is always present on the top left of the screen, or you can click on the button next to it to get to the Advanced Search. Search is very important to field linguists, this is why we made the Search very powerful, and we are planning on making it more powerful in the future. You can type any string of characters in the Datum or Session Fields below. The search will look through the datum of your corpus, and find datum which contain that substring, this means you can type 'nay' and you will get morphemes 'onay' 'naya' etc. While this is not ideal for finding allomorphs, it works pretty well. Right now the search is happening on your computer, offline. In the future we will be adding a 'lexicon webservice' which will work on indexing your morphemes glosses etc to make search faster, but also smarter by build a more linguistically informed indexes of your data so that you can use linguistic constructs to search for your data as you do naturally when you search with your eyes, rather than with a database. We also have planned a 'Dream' module for phonological search that essentially uses a feature geometry ontology to let you search for minimal pairs. A search automatically creates a temporary Datalist, which appears below the Session quick view on the left side of the screen. You can choose to rename and save this Datalist if created a collection of data that you wanted. You can also leave this search data list open, if you enter new datum which matched your search query that appears in the top left corner, they will automatically appear in the search data list too. This can be handy for you to see datum around a certain phenomena while you are entering new data. If your search query is hard to formulate to get all the examples you need, you can search for nothing (leave all fields blank) and it will return all your data as a new Datalist. In general we have decided to implement search such that it errs on the side of high recall, i.e. that it finds all relevant examples, but also returns some garbage, rather than high precision, i.e. that it finds only exact examples, but misses some relevant ones. Currently the search results are not sorted by relevancy to the query. Once we have a proper 'lexicon webservice' we will have more measures of relevancy and will be able to return results and their relevancy scores.
"
},
"locale_New_User" : {
"message" : "Usuario Nuevo"
},
"locale_Activity_Feed_Your" : {
"message" : "TODO translate Your Canal de Actividad"
},
"locale_Activity_Feed_Team" : {
"message" : "TODO translate Corpus Team Canal de Actividad"
},
"locale_Refresh_Activities" : {
"message" : "TODO translate"
},
"locale_View_Profile_Tooltip" : {
"message" : "TODO translate Click to view user's page"
},
"locale_View_Public_Profile_Tooltip" : {
"message" : "TODO translate View/edit your public user's page"
},
"locale_Edit_User_Profile_Tooltip" : {
"message" : "TODO translate Click to edit your user profile"
},
"locale_Public_Profile_Instructions" : {
"message" : " TODO translateThis is your public profile, you can edit it to change/remove information. This is what people can see when they click on your gravatar."
},
"locale_Private_Profile_Instructions" : {
"message" : "TODO translate This is your private profile, only you members on your team can see it."
},
"locale_Edit_Public_User_Profile" : {
"message" : "TODO translate Edit My Public Profile"
},
"locale_Need_save" : {
"message" : "Se ocupa guadar:"
},
"locale_60_unsaved" : {
"message" : "60% sin guardar."
},
"locale_Recent_Changes" : {
"message" : "Cambios Recientes:"
},
"locale_Need_sync" : {
"message" : "Se ocupa sincronisar:"
},
"locale_Differences_with_the_central_server" : {
"message" : "Diferencias con el servidor central:"
},
"locale_to_beta_testers" : {
"message" : "Estos mensajes son para comunicar con los provadores que hace la aplicación. Los mensajes se desapareserán cuando la aplicación esta mas estable. Puedes cerrar los mensajes con el x.
"
},
"locale_We_need_to_make_sure_its_you" : {
"message" : "Ocupamos asegurar que es ustéd..."
},
"locale_Yep_its_me" : {
"message" : "¡Si, soy yo!"
},
"locale_Log_Out" : {
"message" : "Salir"
},
"locale_Log_In" : {
"message" : "Entrar"
},
"locale_User_Profile" : {
"message" : "Perfil de Usuario"
},
"locale_Private_Profile" : {
"message" : "TODO translate Perfil Privada"
},
"locale_Public_Profile" : {
"message" : "TODO translate Perfil Publico"
},
"locale_User_Settings" : {
"message" : "Configuración de Usuario"
},
"locale_Keyboard_Shortcuts" : {
"message" : "Funciones rápidas de teclado"
},
"locale_Corpus_Settings" : {
"message" : "Configuración de Corpus"
},
"locale_Terminal_Power_Users" : {
"message" : "Terminal"
},
"locale_New_Datum" : {
"message" : "Dato Nuevo"
},
"locale_New_menu" : {
"message" : "Nuevo"
},
"locale_New_Data_List" : {
"message" : "Lista de Datos Nuevo"
},
"locale_New_Session" : {
"message" : "Sesión Nuevo"
},
"locale_New_Corpus" : {
"message" : "Corpus Nuevo"
},
"locale_Data_menu" : {
"message" : "Datos"
},
"locale_Import_Data" : {
"message" : "Importe de Datos"
},
"locale_Export_Data" : {
"message" : "Exporte de Datos"
},
"locale_Save" : {
"message" : "Guadar"
},
"locale_Title" : {
"message" : "Título:"
},
"locale_Description" : {
"message" : "Descripción:"
},
"locale_Sessions_associated" : {
"message" : "Sesiónes de Elicitación asociados con el corpus"
},
"locale_Datalists_associated" : {
"message" : "Listas de datos asociados con el corpus"
},
"locale_Permissions_associated" : {
"message" : "Permisos asociados con el corpus"
},
"locale_Datum_field_settings" : {
"message" : "Configuración de los detailles de datos"
},
"locale_Encrypt_if_confidential" : {
"message" : "Encripta si es confidencial:"
},
"locale_Help_Text" : {
"message" : "Texto de Ayuda:"
},
"locale_Add" : {
"message" : "Añadir"
},
"locale_Datum_state_settings" : {
"message" : "Configuración de Estado de Datos"
},
"locale_Green" : {
"message" : "Verde"
},
"locale_Orange" : {
"message" : "Naranjado"
},
"locale_Red" : {
"message" : "Rojo"
},
"locale_Blue" : {
"message" : "Azul"
},
"locale_Teal" : {
"message" : "Verde Azulado"
},
"locale_Black" : {
"message" : "Negro"
},
"locale_Default" : {
"message" : "Gris"
},
"locale_Elicitation_Session" : {
"message" : "Sesión de Elicitación"
},
"locale_Export" : {
"message" : "Exportar"
},
"locale_Actions" : {
"message" : "Acciónes"
},
"locale_Navigation" : {
"message" : "Navegación"
},
"locale_Datum_Status_Checked" : {
"message" : "TODO translate Mark Datum status as checked/verified with language consultant"
},
"locale_Next_Datum" : {
"message" : "Próximo Dato"
},
"locale_Previous_Datum" : {
"message" : "Último Dato"
},
"locale_Data_Entry_Area" : {
"message" : "TODO translate Data Entry Area (1-5 datum)"
},
"locale_Search" : {
"message" : "Búzqueda"
},
"locale_Close" : {
"message" : "Cerrar"
},
"locale_New_Corpus_Instructions" : {
"message" : "Edite la forma abajo para crear un nuevo corpus, o presione ESC para entrar más datos en el corpus presente."
},
"locale_New_Corpus_Warning" : {
"message" : "La funcionalidad del corpus nuevo aún necesita más pruebas, este mensaje desaparecerá cuando Corpus Nuevo no es experimental."
},
"locale_Cancel" : {
"message" : "Cancel"
},
"locale_Next" : {
"message" : "Próximo"
},
"locale_Show" : {
"message" : "Mostrar"
},
"locale_per_page" : {
"message" : "por pagina"
},
"locale_New_Session_Instructions" : {
"message" : " Edite los forma abajo para crear una sesión, o presionar ESC para entrar más datos en la sesión presente. p> "
},
"locale_Consultants" : {
"message" : "Consultor(es):"
},
"locale_Goal" : {
"message" : "Objectivo:"
},
"locale_When" : {
"message" : "Fecha:"
},
"locale_Save_And_Import" : {
"message" : "Guardar y Terminar de Importar"
},
"locale_Import" : {
"message" : "Importar"
},
"locale_percent_completed" : {
"message" : "% completo."
},
"locale_Import_Instructions" : {
"message" : "
- Jalar y Soltar un archivo (csv, txt, tabed, xml, text) a la zona abajo..
- (Modificar su información como necesario.)
- Jalar o escribe los detailles de datos arriba de los columnos que coinciden. Las columnas se convertirán en filas de su pagina de datos. .
- Precionar el botón Intenta Importar.
- Revisa la lista de datos y averigua que su importe se ve bien.
- Modifica la tabla como necesario, oprime Intentar Importar cuando la lista esta listo, puede hacer este paso las veces que quiere.
- Cuando esta sastifecho con la lista de datos, oprime Guadar y su lista de datos serían importados a su corpus y un nuevo lista de datos será creado.
"
},
"locale_Drag_Fields_Instructions" : {
"message" : "TODO translate Drag (or type) the colored datum fields to the column headings which match, type in any additional column headings which you would like to keep as datum fields. The columns will become searchable fields in your database."
},
"locale_Add_Extra_Columns" : {
"message" : " Agrega Columnas Extras"
},
"locale_Attempt_Import" : {
"message" : "Intenta Importar"
},
"locale_LaTeX_Code" : {
"message" : "Codigo de LaTeX:"
},
"locale_Unicode_Instructions" : {
"message" : "Esto es un función rápida de teclado para entrar esta letra en un fila de datos. Para cambiar el función:"
},
"locale_Remove_Unicode" : {
"message" : "Quite Unicode"
},
"locale_Unicode" : {
"message" : "Unicode"
},
"locale_Drag_and_Drop" : {
"message" : "Jalar y Soltar"
},
"locale_AND" : {
"message" : "Y"
},
"locale_OR" : {
"message" : "O"
},
"locale_Advanced_Search" : {
"message" : "Búsqueda Advanzada"
},
"locale_Advanced_Search_Tooltip" : {
"message" : "Búsqueda Advanzada allows you to use your corpus-wide datum fields or session details to search for datum, using either AND or OR with substring match."
},
"locale_Email" : {
"message" : "Correo Electronico:"
},
"locale_Research_Interests" : {
"message" : "Intereses de Investigación"
},
"locale_Affiliation" : {
"message" : "Afiliación"
},
"locale_Corpora" : {
"message" : "Corpora"
},
"locale_Gravatar" : {
"message" : "Gravatar"
},
"locale_Gravatar_URL" : {
"message" : "Gravatar URL"
},
"locale_Firstname" : {
"message" : "Primer nombre:"
},
"locale_Lastname" : {
"message" : "Apellido:"
},
"locale_Skin" : {
"message" : "Foro:"
},
"locale_Background_on_Random" : {
"message" : "Aleatorio de Foro"
},
"locale_Transparent_Dashboard" : {
"message" : "Tablero Transparente"
},
"locale_Change_Background" : {
"message" : "Cambiar Foro"
},
"locale_Number_Datum" : {
"message" : "Numbero de Datos a la vez:"
},
"locale_Add_Placeholder" : {
"message" : "Añadir...."
},
"locale_Datalist_Description" : {
"message" : "Se puede usar las lista de datos para preparar para sesiones con consultantes o compartir con colaboradores."
},
"locale_Add_Tag" : {
"message" : "Etiqueta Nueva..."
},
"locale_locale_Help_Text" : {
"message" : "TODO this should be merged with locale_Help_Text? Se puede incluir text de ayuda aqui (opcional)"
},
"locale_Drag_and_Drop_Placeholder" : {
"message" : "Jale y Suelta achivos o textos aqui!"
},
"locale_Paste_Type_Unicode_Symbol_Placeholder" : {
"message" : "Tecla o pega símbulo de unicode"
},
"locale_TIPA_shortcut" : {
"message" : "Función rapida de teclado"
},
"locale_Show_Activities" : {
"message" : "Mostrar actividades"
},
"locale_Hide_Activities" : {
"message" : "Esconder actividades"
},
"locale_Show_Dashboard" : {
"message" : "Mostrar Tablero"
},
"locale_Save_on_this_Computer" : {
"message" : "Guardar en la computadora"
},
"locale_Sync_and_Share" : {
"message" : "Sincronizar y compartir con el equipo"
},
"locale_Show_Readonly" : {
"message" : "Mostrar en forma para leer "
},
"locale_Show_Fullscreen" : {
"message" : "Mostrar en pantalla completa "
},
"locale_Add_New_Datum_Field_Tooltip" : {
"message" : "Añadir un nuevo detaille de dato"
},
"locale_Add_New_Datum_State_Tooltip" : {
"message" : "Añadir un estado de dato"
},
"locale_Show_in_Dashboard" : {
"message" : "Mostrar en Tablero"
},
"locale_Edit_corpus" : {
"message" : "Edita Corpus"
},
"locale_Show_corpus_settings" : {
"message" : "Mostrar Configuración de Corpus"
},
"locale_Drag_and_Drop_Audio_Tooltip" : {
"message" : "TODO translate Drag and drop audio over the audio player to attach an audio file. You can also drag and drop a YouTube video URL to attach a YouTube video instead."
},
"locale_Play_Audio" : {
"message" : "Tocar audio"
},
"locale_Plain_Text_Export_Tooltip" : {
"message" : "TODO translate Export as plain text/Copy to clipboard"
},
"locale_Plain_Text_Export_Tooltip_checked" : {
"message" : "TODO translate Export as plain text/Copy checked items to clipboard"
},
"locale_Duplicate" : {
"message" : "Duplicar Dato por hacer un contraste minimál"
},
"locale_Encrypt" : {
"message" : "Encriptar/Decriptar"
},
"locale_Encrypt_checked" : {
"message" : "TODO translate Make checked items confidential"
},
"locale_Decrypt_checked" : {
"message" : "TODO translate Remove confidentiality from checked items (Warning: this will save them as decrypted in the database). If you want them to stay confidential and just want to edit them, click on the eye instead."
},
"locale_Decrypt" : {
"message" : "TODO translate Remove confidentiality from this datum (Warning: this will save it as decrypted in the database). If you want it to stay confidential and just want to edit it, click on the eye instead."
},
"locale_Show_confidential_items_Tooltip" : {
"message" : "TODO translate Unmask confidential/encrypted items so that they can be edited and read for the next 10 minutes."
},
"locale_Hide_confidential_items_Tooltip" : {
"message" : "TODO translate Return to masked view of confidential/encrypted datum"
},
"locale_Edit_Datalist" : {
"message" : "Editar lista de datos"
},
"locale_Export_checked_as_LaTeX" : {
"message" : "Exportar lista de datos seleccionados en formato LaTeX"
},
"locale_Export_checked_as_CSV" : {
"message" : "Exportar lista de datos seleccionados en formato CSV"
},
"locale_Hide_Datalist" : {
"message" : "Esconder lista de datos"
},
"locale_Show_Datalist" : {
"message" : "Mostrar lista de datos"
},
"locale_Edit_Datum" : {
"message" : "Editar Datos"
},
"locale_See_Fields" : {
"message" : "TODO translate Hide/Show infrequent fields"
},
"locale_Add_Tags_Tooltip" : {
"message" : "Añadir etiquetas"
},
"locale_Edit_Session" : {
"message" : "Editar Sesión"
},
"locale_Show_Unicode_Palette" : {
"message" : "Mostrar los Unicodes"
},
"locale_Hide_Unicode_Palette" : {
"message" : "Esconder los Unicodes"
},
"locale_Add_new_symbol" : {
"message" : "Añadir un símbulo nuevo"
},
"locale_Public_or_Private" : {
"message" : "Publico o Privado:"
},
"locale_Play_Audio_checked" : {
"message" : "Tocar audio de los seleccionados"
},
"locale_Remove_checked_from_datalist_tooltip" : {
"message" : "TODO translate los seleccionados"
},
"locale_Insert_New_Datum" : {
"message" : "Insertar un nuevo dato arriba"
},
"locale_LaTeX" : {
"message" : "Exportar dato en formato LaTeX"
},
"locale_CSV_Tooltip" : {
"message" : "Exportar dato en formato CSV "
},
"locale_of" : {
"message" : "de"
},
"locale_pages_shown" : {
"message" : "pagínas mostradas"
},
"locale_More" : {
"message" : "Más"
}
}
},{}],55:[function(require,module,exports){
var FieldDBObject = require("./../FieldDBObject").FieldDBObject;
var Users = require("./../user/Users").Users;
/**
* @class Permission
* @name Permission
*
* @description The permission class specifies which user (User, Consultant or Bot)
* can do what action to what component in a given corpus.
* The specification needs three arguments: User, Verb, Object
*
*
* @property {UserGeneric} user This is userid or username
* @property {String} verb Verb is the action permitted:
* admin: corpus admin. admin can handle permission of other users
* read: can read
* addNew: can add/create new datum etc.
* edit: can edit/change the content of datum etc., including delete datum which is basically just changing datum states
* comment: can comment on datum etc.
* export: can export datum etc.
* @property {String} directObject Object is sub-component of the corpus to which
* the action is directed:
* corpus: corpus and corpus details (description etc.)
* datum: datums in the corpus including their states
* session: sessions in the corpus
* datalist: datalists in the corpus
*
* @extends FieldDBObject
*/
var Permission = function Permission(options) {
if (!this._fieldDBtype) {
this._fieldDBtype = "Permission";
}
this.debug("Constructing Permission ", options);
FieldDBObject.apply(this, arguments);
};
Permission.prototype = Object.create(FieldDBObject.prototype, /** @lends Permission.prototype */ {
constructor: {
value: Permission
},
// Internal models: used by the parse function
INTERNAL_MODELS: {
value: {
users: Users
}
},
length: {
get: function() {
if (this.users && this.users.length) {
return this.users.length;
}
return 0;
}
},
map: {
get: function() {
if (this.users && typeof this.users.map === "function") {
var self = this;
return function(callback) {
return this.users.map.apply(self.users, [callback]);
};
} else {
return undefined;
}
}
}
});
exports.Permission = Permission;
},{"./../FieldDBObject":3,"./../user/Users":67}],56:[function(require,module,exports){
var Collection = require("./../Collection").Collection;
var Permission = require("./Permission").Permission;
var Users = require("./../user/Users").Users;
var CORS = require("./../CORS").CORS;
var Q = require("q");
/**
* @class Permissions
* @name Permissions
*
* @description A collection of open ended permissions which can be applied to any object
* (usually a corpus, but could be a datalist, or datum, or datumField). A permission
* can be thought of roughly as a phrase:
*
*
* User [{username: "lingllama", gravatar: "123"}]
* has permission ["admin","write","read","comment","export","import",etc]
* to "corpus"/"datalist"/"datum"/"datumField"
*
*
*
* @property {Permission} admins Users who can perform admin operations on the corpus/datalist/datum/datumField.
* @property {Permission} exporters Users who can export the items in a corpus/datalist/datum/datumField.
* @property {Permission} writers Users who can modify the items in a corpus/datalist/datum/datumField.
* @property {Permission} commenters Users who can comment on the items in a corpus/datalist/datum/datumField.
* @property {Permission} readers Users who can read the items in a corpus/datalist/datum/datumField.
*
* @property {Object} viewAsBasePermissionSystem This is just syntactic sugar which points to the actual
* permission system. The actual permission system should be used by apps who want provide a power user or
* fine grained and open ended control over the permissions, or whose users want to understand
* the fine graned control at a lower level.
* - Kind of like Unix permissions.
* @property {Object} viewAsDataBasePermissionSystem This is syntactic sugar which makes
* the permission system look like there is an implicative relationship betwween roles.
* - Kind of like PhP/MySQL systems.
* @property {Object} viewAsGroupedPermissionSystem This is syntactic sugar which shows users in
* only one category (readOnly, writeOnly, read/write, admins) it also makes
* the permission system look like there is an implicative relationship betwween roles, but with some hint that
* there are some rare roles (such as write only) for crowdsourcing/non-standard data entry contexts.
* - Kind of like PhP/MySQL systems.
* @property {Object} viewAsEmailingTeamPermissionSystem This might be the way that
* some computational linguistics teams will understand the permission system best,
* but the words `collaborator` and `contributor` are so similar that thus far no one
* has used these terms (that we know of).
* - Kind of like GitHub.
*
* @extends Collection
* @tutorial tests/permission/PermissionTest.js
*/
var Permissions = function Permissions(options) {
if (!this._fieldDBtype) {
this._fieldDBtype = "Permissions";
}
this.debug("Constructing Permissions ", options);
this.cacheTimeLength = 1000;
Collection.apply(this, arguments);
};
Permissions.prototype = Object.create(Collection.prototype, /** @lends Permissions.prototype */ {
constructor: {
value: Permissions
},
INTERNAL_MODELS: {
value: {
item: Permission,
usersNotOnTeam: Users,
allUsers: Users
}
},
/*** Syntactic sugar for research teams how have been collaborating via email
sharing (To, BCC, CC) and/or Dropbox and/or github ***/
/**
* Syntactic sugar for users who have reader+commenter+writer permissions.
*
* This is a common permission in version control systems
* where the user can do everything, including categorize data, assign data cleaning
* to team members, edit information about the database but cannot perform
* except admin functions such as adding other users to the database.
*
* This should be the default permission for most users on the corpus, as the corpus
* is version controlled any action can be undone if users use their power too much,
* they can be downgraded to a collaborator or read only role.
*
* Email collaboration analog: This is for users who would be in a
* To or CC category for emails,
*
* Dropbox analog: This is for users who would be invited to join a shared
* folder on Dropbox.
*
* @type {Permission}
*/
contributors: {
get: function() {
return this.readerCommenterWriters;
},
set: function() {
this.warn("contributors cannot be set. it is only syntactic sugar. If you want to modify roles, see the addUser and removeUser functions");
}
},
/**
* Syntactic sugar for users who have reader+commenter permissions.
*
* This is a common permission used by research teams where an external reviewer,
* or a second language consultant can review and coment on the data,
* but cannot modify the data itself.
*
* Email collaboration analog: This is for users who would be in a BCC category
* for emails (they can read the paper, but they arent supposed to send back a
* version which they modified for the team to accept),
*
* Dropbox analog: This is for uswers who would be given a URL to a folder in Dropbox
* (but cannot download the files and modify them with the others)
*
* @type {Permission}
*/
collaborators: {
get: function() {
return this.readerCommenterOnlys;
},
set: function() {
this.warn("collaborators cannot be set. it is only syntactic sugar. If you want to modify roles, see the addUser and removeUser functions");
}
},
/**
* Syntactic sugar for users who have reader+writer+admin permissions.
*
* This is a common permission used by most data base management systems meaning the user can do anything.
*
* Email collaboration analog: The person who initiates the email thread
*
* Dropbox analog: The person who creates the folder in dropbox and adds others to it.
*
* @type {Permission}
*/
owners: {
get: function() {
return this.admins;
},
set: function(value) {
this.admins = value;
}
},
/*** Gropued permissions (useful to show permissions in an app) ***/
giveMeUsersWithTheseRolesAndNotTheseRoles: {
value: function(wantTheseRoles, dontWantTheseRoles) {
if (!wantTheseRoles || !dontWantTheseRoles) {
this.bug("Invalid request for users, you must supply the roles you want, and the roles you dont want.");
return new Users();
}
if (Object.prototype.toString.call(wantTheseRoles) !== "[object Array]" || Object.prototype.toString.call(dontWantTheseRoles) !== "[object Array]") {
this.bug("Invalid request for users, you must supply an array of the roles you want, and the roles you dont want.");
return new Users();
}
// this.debugMode = true;
var empty = new Users(),
permissionType,
permissionTypeIndex,
self = this,
groupLabel = wantTheseRoles.join(" ") + " onlys",
usersWhoAreOnlyInThisPermissionType = [];
/* accept requests for the plural or singular of the permission type */
wantTheseRoles = wantTheseRoles.map(function(role) {
return (role + "s").replace(/ss$/, "s");
});
dontWantTheseRoles = dontWantTheseRoles.map(function(role) {
return (role + "s").replace(/ss+$/, "s");
});
// Add users who have the wanted roles
permissionType = wantTheseRoles.pop();
if (this[permissionType]) {
usersWhoAreOnlyInThisPermissionType = new Users(this[permissionType].users.toJSON());
} else {
usersWhoAreOnlyInThisPermissionType = new Users();
}
var howToRemoveSomeoneWhoIsntInAllRoles = function(user) {
self.debug(" Checking on " + user.username);
if (self[permissionType].users.indexOf(user.username) === -1) {
self.debug(" - removing " + user.username + " from " + groupLabel + " because they are not in " + permissionType);
usersWhoAreOnlyInThisPermissionType.remove(user.username);
}
};
var showUsernames = function(user) {
return user.username;
};
for (permissionTypeIndex = wantTheseRoles.length - 1; permissionTypeIndex >= 0; permissionTypeIndex--) {
permissionType = wantTheseRoles[permissionTypeIndex];
self.debug("Making sure " + usersWhoAreOnlyInThisPermissionType.map(showUsernames) + " are " + permissionType);
if (!self[permissionType]) {
continue;
}
if (!self[permissionType]) {
this.warn(" This team doesn't have a " + permissionType + " so this means the " + groupLabel + " is empty.");
return empty;
} else {
// self.debug(" who are ", self[permissionType].users.map(function(user) {
// return user.username;
// }));
}
// If the user isn't in this permisisonType also, remove it
for (var userIndex = usersWhoAreOnlyInThisPermissionType._collection.length - 1; userIndex >= 0; userIndex--) {
howToRemoveSomeoneWhoIsntInAllRoles(usersWhoAreOnlyInThisPermissionType._collection[userIndex]);
}
}
this.debug("These users " + usersWhoAreOnlyInThisPermissionType.map(function(user) {
return user.username;
}).join(" ") + " have all the roles requested: " + groupLabel.replace("onlys", ""));
if (!usersWhoAreOnlyInThisPermissionType || usersWhoAreOnlyInThisPermissionType.length === 0) {
return empty;
}
var howToRemoveSomeoneWhoIsInTheUnWantedPermissions = function(user) {
if (usersWhoAreOnlyInThisPermissionType[user.username]) {
self.debug(" - " + user.username + " is also in " + permissionType + " so removing them from the " + groupLabel + ", there are " + usersWhoAreOnlyInThisPermissionType.length + " left");
usersWhoAreOnlyInThisPermissionType.remove(user.username);
}
};
for (permissionTypeIndex = dontWantTheseRoles.length - 1; permissionTypeIndex >= 0; permissionTypeIndex--) {
permissionType = dontWantTheseRoles[permissionTypeIndex];
if (!self[permissionType]) {
continue;
}
// remove users who are in the permission type we dont want
self[permissionType].users.map(howToRemoveSomeoneWhoIsInTheUnWantedPermissions);
if (usersWhoAreOnlyInThisPermissionType.length === 0) {
return empty;
}
}
return usersWhoAreOnlyInThisPermissionType;
}
},
/**
* Syntactic sugar for apps who want to show users in one category, not in each low level permissions.
*
* This permission is side effect of when a user has only admin permission.
* In this case the user can only access to only admin functionalities such
* as adding new users to the database. This role is used by project managers or IT staff
* who dont know anything about the data itself, and are only setting up the corpus for
* the team to use if the PI or corpus owner doesnt know how to do the permissions.
* set-up themselves.
*
* @type {Permission}
*/
adminOnlys: {
get: function() {
if (this._adminOnlys && this._adminOnlys.timestamp && (Date.now() - this._adminOnlys.timestamp < this.cacheTimeLength)) {
this.debug("Not regenerating the list of adminOnlys, its fresh enough. " + new Date(this._adminOnlys.timestamp));
} else {
this._adminOnlys = this.giveMeUsersWithTheseRolesAndNotTheseRoles(["admin"], ["writer", "reader"]);
this._adminOnlys.timestamp = Date.now();
}
return this._adminOnlys;
},
set: function() {
this.warn("adminOnlys cannot be set. it is only syntactic sugar. If you want to modify roles, see the addUser and removeUser functions");
}
},
/**
* Syntactic sugar for apps who want to show users in one category, not grouped by low level permissions.
*
* This permission is side effect of when a user has only write permission.
* In this case the user can add new data to the database, but cannot
* review or read or see existing data. They can edit data if it is specifically
* presented to them, they cannot query the database. As all data is version
* controlled edits can be undone so this user is not able to destroy a database that they cant read.
*
* This is not a common permission to use in the system.
*
* This permission can be used for psycholinguistics or crowdsourcing experiemnts
* where users are anonymous (identified anoymously by session or by device)
* and visit a given website or Android app and can respond to stimuli and their responses
* become new data points in the system. These users cannot access fieldlinguistics apps
* which permit browsing of the data, but is a rare permission used by web widgets or other smaller apps which write to a corpus.
*
* @type {Permission}
*/
writeOnlys: {
get: function() {
if (this._writeOnlys && this._writeOnlys.timestamp && (Date.now() - this._writeOnlys.timestamp < this.cacheTimeLength)) {
this.debug("Not regenerating the list of writeOnlys, its fresh enough. " + new Date(this._writeOnlys.timestamp));
} else {
this._writeOnlys = this.giveMeUsersWithTheseRolesAndNotTheseRoles(["writer"], ["admin", "reader"]);
this._writeOnlys.timestamp = Date.now();
}
return this._writeOnlys;
},
set: function() {
this.warn("writeOnlys cannot be set. it is only syntactic sugar. If you want to modify roles, see the addUser and removeUser functions");
}
},
/**
* Syntactic sugar for apps who want to show users in one category, not grouped by low level permissions.
*
* This permission is side effect of when a user has only read permission.
* In this case the user might be part of a grant commitees or the general public (for
* the aspects of the corpus which have been made @publicic),
* language consultants who might leave mean comments on other consultant's data,
* or other sorts of external viewers of the data who the team doesnt want to leave
* comments.
*
* @type {Permission}
*/
readOnlys: {
get: function() {
if (this._readOnlys && this._readOnlys.timestamp && (Date.now() - this._readOnlys.timestamp < this.cacheTimeLength)) {
this.debug("Not regenerating the list of readOnlys, its fresh enough. " + new Date(this._readOnlys.timestamp));
} else {
this._readOnlys = this.giveMeUsersWithTheseRolesAndNotTheseRoles(["reader"], ["admin", "writer"]);
this._readOnlys.timestamp = Date.now();
}
return this._readOnlys;
},
set: function() {
this.warn("readOnlys cannot be set. it is only syntactic sugar. If you want to modify roles, see the addUser and removeUser functions");
}
},
/**
* Syntactic sugar for apps who want to show users in one category, not grouped by low level permissions.
*
* This permission is side effect of when a user has only comment permission.
* This is a rare case which might be used in a web widget external to the data entry apps
* where users or anonymous visitors can leave a comment on data if it is presented to them,
* but cannot browse the database.
*
* @type {Permission}
*/
commentOnlys: {
get: function() {
if (this._commentOnlys && this._commentOnlys.timestamp && (Date.now() - this._commentOnlys.timestamp < this.cacheTimeLength)) {
this.debug("Not regenerating the list of commentOnlys, its fresh enough. " + new Date(this._commentOnlys.timestamp));
} else {
this._commentOnlys = this.giveMeUsersWithTheseRolesAndNotTheseRoles(["commenter"], ["admin", "writer", "reader"]);
this._commentOnlys.timestamp = Date.now();
}
return this._commentOnlys;
},
set: function() {
this.warn("commentOnlys cannot be set. it is only syntactic sugar. If you want to modify roles, see the addUser and removeUser functions");
}
},
/**
* Syntactic sugar for apps who want to show users in one category, not grouped by low level permissions.
*
* This permission is side effect of when a user has only read and comment permission.
* This is a common permission used by research teams where an external reviewer,
* or a second language consultant can review and coment on the data,
* but cannot modify the data itself.
*
* @type {Permission}
*/
readerCommenterOnlys: {
get: function() {
if (this._readerCommenterOnlys && this._readerCommenterOnlys.timestamp && (Date.now() - this._readerCommenterOnlys.timestamp < this.cacheTimeLength)) {
this.debug("Not regenerating the list of readerCommenterOnlys, its fresh enough. " + new Date(this._readerCommenterOnlys.timestamp));
} else {
this._readerCommenterOnlys = this.giveMeUsersWithTheseRolesAndNotTheseRoles(["reader", "commenter"], ["admin", "writer"]);
this._readerCommenterOnlys.timestamp = Date.now();
}
return this._readerCommenterOnlys;
},
set: function() {
this.warn("readerCommenterOnlys cannot be set. it is only syntactic sugar. If you want to modify roles, see the addUser and removeUser functions");
}
},
/**
* Syntactic sugar for apps who want to show users in one category, not grouped by low level permissions.
*
* This permission is side effect of when a user has only read and write permission.
* This is a rare permission where the user has been leaving abusive comments,
* and are thus only permitted to browse and edit the data itself, not add or edit comments.
*
* If you want to give someone access as a reader+writer, use readerWritersComenters.
*
* @type {Permission}
*/
readerWriters: {
get: function() {
return this.readerCommenterWriters;
},
set: function() {
this.warn("readerWriters cannot be set. it is only syntactic sugar. If you want to modify roles, see the addUser and removeUser functions");
}
},
/**
* Syntactic sugar for apps who want to show users in one category, not grouped by low level permissions.
*
* This permission is side effect of when a user has only read comment and write permission.
* This is syntactic sugar which is often refered to as "writers" in traditional databases permissions.
* It means the user can write data, read data and comment on data
*
* @return {Permission} A permissions group with an array of Users who fall into this category
*/
readerCommenterWriters: {
get: function() {
if (this._readerCommenterWriterOnlys && this._readerCommenterWriterOnlys.timestamp && (Date.now() - this._readerCommenterWriterOnlys.timestamp < this.cacheTimeLength)) {
this.debug("Not regenerating the list of readerCommenterWriterOnlys, its fresh enough. " + new Date(this._readerCommenterWriterOnlys.timestamp));
} else {
// this.debugMode = true;
this._readerCommenterWriterOnlys = this.giveMeUsersWithTheseRolesAndNotTheseRoles(["reader", "writer", "commenter"], ["admin"]);
this._readerCommenterWriterOnlys.timestamp = Date.now();
// this.debugMode = false;
}
return this._readerCommenterWriterOnlys;
},
set: function() {
this.warn("readerCommenterWriters cannot be set. it is only syntactic sugar. If you want to modify roles, see the addUser and removeUser functions");
}
},
/**
* Syntactic sugar for apps who want to show users in one category, not grouped by low level permissions.
*
* Often refered to as "admins" in traditional databases permissio ns
* It means the user can write data, read data and comment on data, and perform any operation on the data.
*
* @return {Permission} A permission group with an array of Users who fall into this category
*/
readerCommenterWriterAdmins: {
get: function() {
if (this._readerCommenterWriterAdminAlso && this._readerCommenterWriterAdminAlso.timestamp && (Date.now() - this._readerCommenterWriterAdminAlso.timestamp < this.cacheTimeLength)) {
this.debug("Not regenerating the list of readerCommenterWriterAdminAlso, its fresh enough. " + new Date(this._readerCommenterWriterAdminAlso.timestamp));
} else {
this._readerCommenterWriterAdminAlso = this.giveMeUsersWithTheseRolesAndNotTheseRoles(["reader", "writer", "admin"], []);
this._readerCommenterWriterAdminAlso.timestamp = Date.now();
}
return this._readerCommenterWriterAdminAlso;
},
set: function() {
this.warn("readerCommenterWriterAdmins cannot be set. it is only syntactic sugar. If you want to modify roles, see the addUser and removeUser functions");
}
},
/*** Permissions to control unruly users who the team is not able to convince to work as a team ***/
/**
* Syntactic sugar for apps who want to show users in one category, not grouped by low level permissions.
*
* This is a permission provided for teams who want many language consultants to contribute to one
* database without seeing the data other consultants have added. We expect this may be a common
* permission especially for teams where there is no `standard` dialect and speakers of other dialects
* are very prescriptive and think others are making `errors` which need to be corrected, this permission prevents them from `correcting` others data.
*
* @return {Permission} A permission group with an array of Users who fall into this category
*/
readOwnDataWriteOwnDataOnlys: {
get: function() {
return this.readOwnDataWriteOwnDataOnly || [];
},
set: function() {
this.warn("readOwnDataWriteOwnDataOnlys cannot be set. it is only syntactic sugar. If you want to modify roles, see the addUser and removeUser functions");
}
},
/**
* Syntactic sugar for apps who want to show users in one category, not grouped by low level permissions.
*
* This is a rare permission provided for team members who have been editing other people's
* data either to update it to their own dialect (when it was supposed to be the dialect
* of the original source) or other sorts of 'destructive' edits. A user with this permission
* will know that they have been limited to commenting on others' data, and editing their own
* data only (similar to Facebook).
*
* This permission should not be a default permission among research teams, instead the readerCommenterWriter
* permission should be used to reduce territoriality in the data and makes it harder for the database to be kept clean
* because users cannot update/comment on data when they notice a problem. All data is versioned so any
* mistakes can be undone.
*
* @return {Permission} A permission group with an array of Users who fall into this category
*/
readCommentAllWriteOwnDataOnlys: {
get: function() {
return this.readCommentAllWriteOwnDataOnly || [];
},
set: function() {
this.warn("readCommentAllWriteOwnDataOnlys cannot be set. it is only syntactic sugar. If you want to modify roles, see the addUser and removeUser functions");
}
},
/**
* Syntactic sugar for apps who want to show users in one category, not grouped by low level permissions.
*
* This is a rare permission provided for team members who have been editing other people's
* data either to update it to their own dialect (when it was supposed to be the dialect
* of the original source) or other sorts of 'destructive' edits which the team wants to
* prevent the user from doing this without making the user uncomfortable. A user with this permission
* will know that they have been limited to editing their own data only (similar to Facebook) and cannot
* edit other people's data.
*
* This permission should not be a default permission among research teams, instead the readerCommenterWriter
* permission should be used to reduce territoriality in the data and makes it harder for the database to be kept clean
* because users cannot update/comment on data when they notice a problem. All data is versioned so any
* mistakes can be undone.
*
* @return {Permission} A permission group with an array of Users who fall into this category
*/
readAllWriteOwnDataOnlys: {
get: function() {
return this.readAllWriteOwnDataOnly || [];
},
set: function() {
this.warn("readAllWriteOwnDataOnlys cannot be set. it is only syntactic sugar. If you want to modify roles, see the addUser and removeUser functions");
}
},
/**
* This might be used by teams who want to have fine grained control over the
* permissions, or who want to understand the fine grained control at a lower level.
*
* @return {Object} an object with the 3 categories of permission like you
* would have in a PHPmyAdmin console.
*/
viewAsBasePermissionSystem: {
get: function() {
return this;
}
},
/**
* This view will be missing some members of the corpora since not all combinations of
* permission have syntactic sugar methods in this library. This shoudlnt be used
* unless the app dev is sure that the users wont be using corpora for psycholinguistics or
* crowdsourcing or computational linguistics.
*
* @return {Object} an object with the 3 categories of permission like you
* would have in a PHPmyAdmin console.
*/
viewAsGroupedPermissionSystem: {
get: function() {
return {
adminOnlys: this.adminOnlys,
writeOnlys: this.writeOnlys,
readOnlys: this.readOnlys,
readerCommenterOnlys: this.readerCommenterOnlys,
readerWriters: this.readerCommenterWriters,
admins: this.readerCommenterWriterAdmins,
commentOnlys: this.commentOnlys,
// readerCommenterWriters: readerCommenterWriters,
//writerCommenterOnlys
//writerAdminOnlys
//writerCommenterAdminOnlys
};
}
},
/**
* This is the way most field linguistics apps present the permissions system.
*
* @return {Object} an object with the 3 categories of permission like you
* would have in a PHPmyAdmin console.
*/
viewAsDataBasePermissionSystem: {
get: function() {
return {
admins: this.readerCommenterWriterAdmins,
writers: this.readerCommenterWriters,
readers: this.readerCommenterOnlys,
commenters: this.readerCommenterOnlys
};
}
},
/**
* This might be the way that some computational linguistics teams will
* understand the permission system best, but the words
* `collaborator` and `contributor` are so similar that thus far no one
* has used these terms.
*
* @return {Object} an object with the 2 categories of permission like you
* would have on GitHub
*/
viewAsEmailingTeamPermissionSystem: {
get: function() {
return {
contributors: this.contributors,
collaborators: this.collaborators,
owners: this.readerCommenterWriterAdmins
};
}
},
addUser: {
value: function(user) {
if (!user || !user.roles) {
this.warn("You should provide roles you want to add... doing nothing.");
return;
}
this.debug(user.roles);
var roles = user.roles;
delete user.roles;
for (var roleIndex = roles.length - 1; roleIndex >= 0; roleIndex--) {
var permissionType = roles[roleIndex];
if (!this[permissionType]) {
permissionType = permissionType.toLowerCase() + "s";
if (!this[permissionType]) {
var newPermission = this.buildPermissionFromAPermissionType(permissionType);
this.debug(" Creating a permssion group for " + permissionType, newPermission);
this.add(newPermission);
}
}
this[permissionType].users.add(user);
this.debug("the user was added to the permission group " + permissionType + " there are a total of " + this[permissionType].length + " users with this sort of access ", this[permissionType].users);
}
}
},
/**
* Removes user from roles on this permissions team, or removes user entirely if only a username is supplied.
*
* @param {Object} user A user with minimally a username and roles which should be removed, or alternatively can be just a username if you want to remove the user entirely from the team.
*/
removeUser: {
value: function(user) {
if (typeof user === "string") {
user = {
username: user,
roles: this.currentPermissions
};
this.warn("Remove was requested of a username, removing the username entirely from the permission team.");
}
if (!user || !user.roles) {
this.warn("You should provide roles you want to remove... doing nothing.");
return;
}
// this.debugMode = true;
this.debug(user.roles);
var roles = user.roles;
delete user.roles;
for (var roleIndex = roles.length - 1; roleIndex >= 0; roleIndex--) {
var permissionType = roles[roleIndex];
if (!this[permissionType]) {
permissionType = permissionType.toLowerCase() + "s";
}
if (this[permissionType]) {
// this[permissionType].users.debugMode = true;
if (this[permissionType].users[user.username]) {
var userWasInThisPermission = this[permissionType].users.remove(user);
this.debug("removed ", userWasInThisPermission);
} else {
this.warn("The user " + user.username + " was not in the " + permissionType + " anyway.");
}
this.debug("the user " + user.username + " is not in " + permissionType + " there are a total of " + this[permissionType].length + " users with this sort of access ", this[permissionType].users);
}
}
}
},
/**
* A list of "hats" which team members can wear in this team.
*/
currentPermissions: {
get: function() {
if (!this._collection || this._collection === 0) {
return [];
}
var self = this;
return this._collection.map(function(permission) {
return permission[self.primaryKey];
});
}
},
buildPermissionFromAPermissionType: {
value: function(permissionType) {
var verb = permissionType.replace(/s/, "").replace(/writer/, "write").replace(/er/, "");
var label = permissionType;
if (label && label.length > 2) {
label = label[0].toUpperCase() + label.substring(1, label.length);
}
var helpLinguists = "These users can perform " + verb + " operations on the corpus";
return {
users: [],
verb: verb,
id: permissionType,
labelFieldLinguists: label,
helpLinguists: helpLinguists,
directObject: "corpus",
// debugMode: true
};
}
},
fetch: {
value: function() {
var deferred = Q.defer(),
self = this;
if (!this.parent) {
Q.nextTick(function() {
self.fetching = self.loading = false;
deferred.reject({
error: "Cannot fetch if the permissions are not attached to a corpus"
});
});
return deferred.promise;
}
if (!this.application || !this.application.authentication || !this.application.authentication.user || !this.application.authentication.user.username) {
Q.nextTick(function() {
self.fetching = self.loading = false;
deferred.reject({
error: "Cannot fetch if the permissions are not in an application."
});
});
return deferred.promise;
}
if (this.loaded) {
this.warn("not fetching permissions, they are fresh.");
Q.nextTick(function() {
self.fetching = self.loading = false;
deferred.resolve(self);
});
return deferred.promise;
}
var dataToPost = {
connection: this.parent.connection.toJSON(),
username: this.application.authentication.user.username,
};
dataToPost.connection = dataToPost.couchConnection = dataToPost.connection;
this.fetching = this.loading = true;
CORS.makeCORSRequest({
type: "POST",
data: dataToPost,
dataType: "json",
url: this.parent.connection.authUrl + "/corpusteam"
}).then(function(result) {
self.fetching = self.loading = false;
self.loaded = true;
self.populate(result.users);
deferred.resolve(self);
},
function(reason) {
self.fetching = self.loading = false;
self.debug(reason);
deferred.reject(reason);
}).fail(
function(error) {
console.error(error.stack, self);
deferred.reject(error);
});
return deferred.promise;
}
},
/**
* Accepts an object containing permission groups which are an array of
* users masks which have this permission. This simple object is used to populate the permissions model.
*
* @param {Object} users an object containing keys which are verbs (permission types) and the value is an array of users who are in this category
*/
populate: {
value: function(users) {
if (!users || users === "defaults") {
users = {};
this.debug("Using default permission types");
}
users.admins = users.admins || [];
users.writers = users.writers || [];
users.readers = users.readers || [];
users.commenters = users.commenters || [];
users.exporters = users.exporters || [];
users.notonteam = users.notonteam || [];
users.allusers = users.allusers || [];
this.usersNotOnTeam = new Users(users.notonteam);
this.allUsers = new Users(users.allusers);
delete users.allusers;
delete users.notonteam;
var permissionType;
for (permissionType in users) {
if (users.hasOwnProperty(permissionType) && permissionType) {
/* if the permission is just an array of users, construct basic permission meta data around it */
if (Object.prototype.toString.call(users[permissionType]) === "[object Array]") {
var usersArray = users[permissionType];
users[permissionType] = this.buildPermissionFromAPermissionType(permissionType);
users[permissionType].users = usersArray;
}
this.debug("adding " + permissionType, users[permissionType]);
this.add(new Permission(users[permissionType]));
}
}
}
},
sanitizeStringForPrimaryKey: {
value: function(value) {
return value;
}
}
});
exports.Permissions = Permissions;
},{"./../CORS":1,"./../Collection":2,"./../user/Users":67,"./Permission":55,"q":248}],57:[function(require,module,exports){
var FieldDBObject = require("./../FieldDBObject").FieldDBObject;
/**
* @class Search progressively searches a corpus and updates a search/data list
* view as a user types keywords in the search box. Both intersection and
* union search is possible. It highlights search keywords in the list view.
*
* @property {String} searchQuery
* @property {DataList} A list of data which fulfill the search query
*
* @name Search
* @extends FieldDBObject
* @constructs
*/
var Search = function Search(options) {
if (!this._fieldDBtype) {
this._fieldDBtype = "Search";
}
this.debug("Constructing Search length: ", options);
FieldDBObject.apply(this, arguments);
};
Search.prototype = Object.create(FieldDBObject.prototype, /** @lends Search.prototype */ {
constructor: {
value: Search
},
defaults: {
value: {
searchQuery: ""
}
},
searchKeywords: {
get: function() {
this.warn("searchKeywords is deprecated, use searchQuery instead.");
return this.searchQuery;
},
set: function(value) {
this.warn("searchKeywords is deprecated, use searchQuery instead.");
this.searchQuery = value;
}
},
searchQuery: {
get: function() {
return this._searchQuery || this.defaults.searchQuery;
},
set: function(value) {
if (value === this._searchQuery) {
return;
}
if (!value) {
delete this._searchQuery;
return;
}
this._searchQuery = value.trim();
}
}
});
exports.Search = Search;
},{"./../FieldDBObject":3}],58:[function(require,module,exports){
var FieldDBObject = require("./../FieldDBObject").FieldDBObject;
/**
* @class UnicodeSymbol allows a user to use IPA symbols, characters other than Roman alphabets, etc..
* Users can add new symbols. Added symbols are saved and stored, and will show up next time the user
* opens UnicodeSymbol box.
*
* @name UnicodeSymbol
* @extends FieldDBObject
* @constructs
*/
var UnicodeSymbol = function UnicodeSymbol(options) {
if (!this._fieldDBtype) {
this._fieldDBtype = "UnicodeSymbol";
}
this.debug("Constructing UnicodeSymbol length: ", options);
FieldDBObject.apply(this, arguments);
};
UnicodeSymbol.prototype = Object.create(FieldDBObject.prototype, /** @lends UnicodeSymbol.prototype */ {
constructor: {
value: UnicodeSymbol
},
defaults: {
value: {
symbol: "",
tipa: "",
useCount: 0
}
},
symbol: {
get: function() {
return this._symbol;
},
set: function(value) {
if (value === this._symbol) {
return;
}
if (!value) {
delete this._symbol;
return;
}
if (typeof value.trim === "function") {
value = value.trim();
}
this._symbol = value.trim();
}
},
toJSON: {
value: function(includeEvenEmptyAttributes, removeEmptyAttributes) {
this.debug("Customizing toJSON ", includeEvenEmptyAttributes, removeEmptyAttributes);
var json = FieldDBObject.prototype.toJSON.apply(this, arguments);
delete json.dateCreated;
delete json.dateModified;
delete json.version;
this.debug(json);
return json;
}
}
});
exports.UnicodeSymbol = UnicodeSymbol;
},{"./../FieldDBObject":3}],59:[function(require,module,exports){
var Collection = require("./../Collection").Collection;
var UnicodeSymbol = require("./UnicodeSymbol").UnicodeSymbol;
/**
* @class UnicodeSymbols is a set of unicode symbols.
*
* @name UnicodeSymbols
*
* @extends Collection
* @constructs
*/
var UnicodeSymbols = function UnicodeSymbols(options) {
if (!this._fieldDBtype) {
this._fieldDBtype = "UnicodeSymbols";
}
this.debug("Constructing UnicodeSymbols length: ", options);
Collection.apply(this, arguments);
};
UnicodeSymbols.prototype = Object.create(Collection.prototype, /** @lends UnicodeSymbols.prototype */ {
constructor: {
value: UnicodeSymbols
},
primaryKey: {
value: "symbol"
},
INTERNAL_MODELS: {
value: {
item: UnicodeSymbol
}
},
fill: {
value: function() {
// this.add(new UnicodeSymbol({tipa: "", symbol: "ɐ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ɑ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ɒ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ɓ"}));
this.add(new UnicodeSymbol({
tipa: "",
symbol: "ɔ"
}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ɕ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ɖ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ɗ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ɘ"}));
this.add(new UnicodeSymbol({
tipa: "",
symbol: "ə"
}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ɚ"}));
this.add(new UnicodeSymbol({
tipa: "",
symbol: "ɛ"
}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ɜ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ɝ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ɞ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ɟ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ɠ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ɡ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ɢ"}));
this.add(new UnicodeSymbol({
tipa: "",
symbol: "ɣ"
}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ɤ"}));
this.add(new UnicodeSymbol({
tipa: "",
symbol: "ɥ"
}));
this.add(new UnicodeSymbol({
tipa: "",
symbol: "ɦ"
}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ɧ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ɨ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ɩ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ɪ"}));
this.add(new UnicodeSymbol({
tipa: "",
symbol: "ɫ"
}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ɬ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ɮ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ɭ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ɯ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ɰ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ɱ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ɲ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ɳ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ɴ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ɵ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ɶ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ɷ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ɸ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ɹ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ɺ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ɻ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ɼ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ɽ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ɾ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ɿ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ʀ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ʁ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ʂ"}));
this.add(new UnicodeSymbol({
tipa: "",
symbol: "ʃ"
}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ʄ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ʅ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ʆ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ʇ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ʈ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ʉ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ʊ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ʋ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ʌ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ʍ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ʎ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ʏ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ʐ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ʑ"}));
this.add(new UnicodeSymbol({
tipa: "",
symbol: "ʒ"
}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ʓ"}));
this.add(new UnicodeSymbol({
tipa: "",
symbol: "ʔ"
}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ʕ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ʖ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ʗ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ʘ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ʙ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ʚ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ʛ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ʜ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ʝ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ʞ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ʟ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ʠ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ʡ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ʢ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ʣ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ʤ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ʥ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ʦ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ʧ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ʨ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ʩ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ʪ"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ʫ"}));
this.add(new UnicodeSymbol({
tipa: "\\lambda",
symbol: "λ "
}));
this.add(new UnicodeSymbol({
tipa: "\\alpha",
symbol: "α "
}));
this.add(new UnicodeSymbol({
tipa: "\\beta",
symbol: "β "
}));
this.add(new UnicodeSymbol({
tipa: "\\forall",
symbol: "∀"
}));
this.add(new UnicodeSymbol({
tipa: "\\exists",
symbol: "∃"
}));
this.add(new UnicodeSymbol({
tipa: "^{\\circ}",
symbol: "°"
}));
//
// this.add(new UnicodeSymbol({tipa: "", symbol: "γ "}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "δ "}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ε "}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ζ "}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "η "}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "θ "}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "ι "}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "κ "}));
this.add(new UnicodeSymbol({
tipa: "",
symbol: "∄"
}));
this.add(new UnicodeSymbol({
tipa: "",
symbol: "∅"
}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "∆"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "∇"}));
this.add(new UnicodeSymbol({
tipa: "",
symbol: "∈"
}));
this.add(new UnicodeSymbol({
tipa: "",
symbol: "∉"
}));
this.add(new UnicodeSymbol({
tipa: "",
symbol: "∋"
}));
this.add(new UnicodeSymbol({
tipa: "",
symbol: "∌"
}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "∍"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "≁"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "≂"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "≃"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "≄"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "≅"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "≆"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "≇"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "≈"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "≉"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "≊"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "≋"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "≌"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "≍"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "≎"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "≏"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "≐"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "≑"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "≒"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "≓"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "≔"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "≕"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "≤"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "≥"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "≦"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "≧"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "≨"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "≩"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "≪"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "≫"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "≬"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "≭"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "≮"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "≯"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "≰"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "≱"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "≲"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "≳"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "≴"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "⊂"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "⊃"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "⊄"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "⊅"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "⊆"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "⊇"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "⊈"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "⊉"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "⊊"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "⊋"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "⊌"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "⊍"}));
// this.add(new UnicodeSymbol({tipa: "", symbol: "⊎"}));
}
},
/**
* Cleans a value to become a primary key on an object (replaces punctuation with underscore)
* (replaces the default Collection.sanitizeStringForPrimaryKey method which scrubs unicode from the primary keys)
*
* @param String value the potential primary key to be cleaned
* @return String the value cleaned and safe as a primary key
*/
sanitizeStringForPrimaryKey: {
value: function(value) {
this.debug("sanitizeStringForPrimaryKey");
if (!value) {
return null;
}
if (typeof value.replace !== "function") {
value = value + "";
}
value = value.replace(/[-""+=?./\[\]{}() ]/g, "");
return value;
}
}
});
exports.UnicodeSymbols = UnicodeSymbols;
},{"./../Collection":2,"./UnicodeSymbol":58}],60:[function(require,module,exports){
var Speaker = require("./Speaker").Speaker;
var DEFAULT_CORPUS_MODEL = require("./../corpus/corpus.json");
/**
*
* @class The Consultant (commonly refered to as a "language consultant")
* is a type of Speaker with any additional fields or metadata that a
* team might use to to cluster consultants into dialects or variations.
*
* A consultant might also be associated to a user. In this case a consultant
* has the same information as a user plus extra, some info (e.g. date of birth)
* which must be kept confidential. Consultant's gravatar are default
* unless he/she wants to be public associated with/his username.
* Consultants which are also users have permissions about the
* level of access to the data (read only, add/edit).
*
*
* @name Consultant
* @extends Speaker
* @constructs
*/
var Consultant = function Consultant(options) {
if (!this._fieldDBtype) {
this._fieldDBtype = "Consultant";
}
this.debug("Constructing Consultant: ", options);
Speaker.apply(this, arguments);
};
Consultant.prototype = Object.create(Speaker.prototype, /** @lends Consultant.prototype */ {
constructor: {
value: Consultant
},
api: {
value: "consultants"
},
defaults: {
get: function() {
var doc = {
fields: DEFAULT_CORPUS_MODEL.consultantFields || DEFAULT_CORPUS_MODEL.speakerFields
};
return JSON.parse(JSON.stringify(doc));
}
}
});
exports.Consultant = Consultant;
},{"./../corpus/corpus.json":25,"./Speaker":62}],61:[function(require,module,exports){
var Speaker = require("./Speaker").Speaker;
var DEFAULT_CORPUS_MODEL = require("./../corpus/corpus.json");
/**
* @class The Participant is a type of Speaker with any additional fields or metadata that a team might use to run their psycholinguistics analyses.
*
*
* @name Participant
* @extends Speaker
* @constructs
*/
var Participant = function Participant(options) {
if (!this._fieldDBtype) {
this._fieldDBtype = "Participant";
}
this.debug("Constructing Participant length: ", options);
Speaker.apply(this, arguments);
};
Participant.prototype = Object.create(Speaker.prototype, /** @lends Participant.prototype */ {
constructor: {
value: Participant
},
api: {
value: "participants"
},
defaults: {
get: function() {
var doc = {
fields: []
};
try {
if (this.application && this.application.corpus) {
if (this.application.corpus.participantFields) {
doc.fields = this.application.corpus.participantFields.clone();
} else if (this.application.corpus.speakerFields) {
doc.fields = this.application.corpus.speakerFields.clone();
}
}
} catch (e) {
this.warn("Cant get participant fields from the current corpus, instead using defaults.");
doc.fields = DEFAULT_CORPUS_MODEL.participantFields || DEFAULT_CORPUS_MODEL.speakerFields;
}
if (!doc.fields || doc.fields.length === 0) {
this.warn("There were no corpus specific speaker or participant fiels, instead using defaults");
doc.fields = DEFAULT_CORPUS_MODEL.participantFields || DEFAULT_CORPUS_MODEL.speakerFields;
}
return JSON.parse(JSON.stringify(doc));
}
}
});
exports.Participant = Participant;
},{"./../corpus/corpus.json":25,"./Speaker":62}],62:[function(require,module,exports){
var Confidential = require("./../confidentiality_encryption/Confidential").Confidential;
var DatumFields = require("./../datum/DatumFields").DatumFields;
var FieldDBObject = require("./../FieldDBObject").FieldDBObject;
var UserMask = require("./UserMask").UserMask;
var DEFAULT_CORPUS_MODEL = require("./../corpus/corpus.json");
/**
* @class The Speaker represents a source of data, usually a
* language consultant who is a native speaker of the language,
* or a psycholinguistics experiment participant.
* Each consultant has their own I-language and/or dialects which they
* speak (unlike a published source which usually discusses an E-language
* or standard or normal expected production of an utterance.)
* Speakers can have any number of additional fields or metadata
* that a team might use to help cluster or understand variation in data.
*
* As "Informant" is not politically correct in many contexts, and "consultant" is
* ambigious word outside of field work, the word "speaker" is used in communication with
* users and in the url of db queries/api.
*
* A speaker might also be associated to a user. In this case a speaker
* has the same information as a user plus extra, some info (e.g. date of birth)
* which must be kept confidential. Speaker's gravatar are locked to
* default unless he/she wants to be public associated with/his username.
* Speakers which are also users have permissions about the level of
* access to the data (read only, add/edit).
*
* @name Speaker
* @extends UserMask
* @constructs
*/
var Speaker = function Speaker(options) {
if (!this._fieldDBtype) {
this._fieldDBtype = "Speaker";
}
this.debug("Constructing Speaker: ", options);
if (!options || (!options._rev && !options.fields)) {
//If its a new participant with out a revision and without fields use the defaults
options = options || {};
options.fields = this.defaults.fields;
}
UserMask.apply(this, arguments);
};
Speaker.prototype = Object.create(UserMask.prototype, /** @lends Speaker.prototype */ {
constructor: {
value: Speaker
},
api: {
value: "speakers"
},
INTERNAL_MODELS: {
value: {
username: FieldDBObject.DEFAULT_STRING,
anonymousCode: FieldDBObject.DEFAULT_STRING,
gravatar: FieldDBObject.DEFAULT_STRING,
fields: DatumFields,
user: UserMask,
confidential: Confidential
}
},
defaults: {
get: function() {
var doc = {
fields: DEFAULT_CORPUS_MODEL.speakerFields
};
return JSON.parse(JSON.stringify(doc));
}
},
confidentiality: {
get: function() {
if (this.fields) {
return this.fields.confidentiality.value;
} else {
return;
}
},
set: function(value) {
if (!this.fields) {
this.fields = new DatumFields(this.defaults.fields);
}
// this.warn("Cannot change the public/private of " + this.collection + " (it must be anonymous). " + value);
this.fields.confidentiality.value = value;
}
},
fields: {
get: function() {
this.debug("getting fields");
return this._fields;
},
set: function(value) {
if (value === this._fields) {
return;
}
if (!value) {
delete this._fields;
return;
} else {
if (typeof this.INTERNAL_MODELS["fields"] === "function" && Object.prototype.toString.call(value) === "[object Array]") {
value = new this.INTERNAL_MODELS["fields"](value);
}
}
if (!value.confidential) {
value.confidential = this.confidential;
}
this._fields = value;
}
},
buildGravatar: {
value: function() {
this._gravatar = "968b8e7fb72b5ffe2915256c28a9414c";
return this._gravatar;
}
},
gravatar: {
get: function() {
return this.buildGravatar();
},
set: function(value) {
this.warn("Cannot set the gravatar of a " + this.fieldDBtype + " (it must be anonymous)." + value);
}
},
username: {
get: function() {
if (this.fields && this.fields.username && this.fields.username.value) {
// this.debug("this.fields.username.value :", this.fields.username.value + ":");
if (this.fields.confidentiality.value === "generalize") {
this.fields.username.mask = "A native speaker";
} else if (this.fields.confidentiality.value === "team") {
this.todo("IF the user is part of the team, they can see the username of the consultant.");
this.fields.username.mask = this.anonymousCode;
} else if (this.fields.confidentiality.value === "anonymous") {
this.fields.username.mask = this.anonymousCode || this.fields.username.mask;
} else if (this.fields.confidentiality.value === "public") {
this.fields.username.mask = this.fields.username.value;
} else {
this.fields.username.mask = "A native speaker";
}
if (this.fields.username.decryptedMode) {
return this.fields.username.value;
} else {
return this.fields.username.mask;
}
} else {
if (this.id) {
return this.id;
}
return;
}
},
set: function(value) {
if (!this.confidential) {
this.warn("Cannot set the username before the confidential is set");
return;
}
if (!this.fields) {
this.fields = new DatumFields(this.defaults.fields);
}
// this.fields.username.debugMode = true;
// this.fields.username.decryptedMode = true;
this.fields.username.confidential = this.confidential;
this.fields.username.value = value;
}
},
encryptByCorpus: {
value: true
},
id: {
get: function() {
return this.anonymousCode;
},
set: function(value) {
this.anonymousCode = value;
}
},
anonymousCode: {
get: function() {
try {
if (this.fields && this.fields.anonymousCode) {
return this.fields.anonymousCode.value.toUpperCase();
} else {
return this._id;
}
} catch (e) {
this.warn("there was a problem getting the anonymousCode of this speaker", e);
return this._id;
}
},
set: function(value) {
var actualUsername;
if (this.fields && this.fields.username && this.fields.username.value) {
this.fields.username.decryptedMode = true;
actualUsername = this.fields.username.value;
this.fields.username.decryptedMode = false;
}
if (actualUsername && value.toLowerCase().indexOf(actualUsername) > -1) {
this.bug("Cannot set the anonymous code to contain any part of the user's actual username, this would potentially breach their confidentiality.");
return;
}
if (!this.fields) {
this.fields = new DatumFields(this.defaults.fields);
}
this.fields.anonymousCode.value = this._id = value;
this.debug("Set the id and the anonymousCode of this user" + this._id, this);
if (!this.encryptByCorpus) {
this.confidential = new Confidential({
secretkey: value
});
}
}
},
confidential: {
get: function() {
this.debug("using this speaker's confidential encrypter");
return this.confidentialEncrypter;
},
set: function(value) {
if (value === this.confidentialEncrypter) {
return;
}
if (typeof value.encrypt !== "function" && value.secretkey) {
value = new this.INTERNAL_MODELS["confidential"](value);
}
this.confidentialEncrypter = value;
if (this.fields) {
// this.debug("setting speaker fields confidential in the Speaker.confidential set function.");
this.fields.confidential = value;
}
}
},
dateOfBirth: {
configurable: true,
get: function() {
if (this.fields && this.fields.dateOfBirth) {
return this.fields.dateOfBirth.value;
} else {
return;
}
},
set: function(value) {
this.debug("Setting dateOfBirth " + value, this.confidential);
if (!this.fields) {
this.fields = new DatumFields(this.defaults.fields);
}
// this.fields.debugMode = true;
this.fields.dateOfBirth.value = value;
}
},
firstname: {
configurable: true,
get: function() {
if (this.fields && this.fields.firstname) {
return this.fields.firstname.value;
} else {
return;
}
},
set: function(value) {
if (!this.fields) {
this.fields = new DatumFields(this.defaults.fields);
}
if (this.fields && this.fields.firstname) {
// this.fields.debugMode = true;
this.fields.firstname.value = value;
} else {
this.fields.firstname.value = value;
}
}
},
lastname: {
configurable: true,
get: function() {
if (this.fields && this.fields.lastname) {
return this.fields.lastname.value;
} else {
return;
}
},
set: function(value) {
if (!this.fields) {
this.fields = new DatumFields(this.defaults.fields);
}
if (this.fields && this.fields.lastname) {
// this.fields.debugMode = true;
this.fields.lastname.value = value;
} else {
this.fields.lastname.value = value;
}
}
},
languages: {
get: function() {
if (this.fields) {
return this.fields.languages.value;
} else {
return;
}
},
set: function(value) {
var stringvalue;
var objectvalue;
if (typeof value === "string") {
this.debug("User set the languages with a string");
if (this.fields.languages && this.fields.languages && this.fields.languages.json) {
this.confirm("Do you want to set the languages from " + JSON.stringify(this.fields.languages.json) + " to " + value);
}
stringvalue = value;
objectvalue = {
value: value,
label: "languages",
json: {
languages: value.split(",")
}
};
objectvalue.json.languages = objectvalue.json.languages.map(function(languageName) {
return {
iso: languageName.toLowerCase().trim(),
name: languageName.trim(),
nativeName: languageName.trim()
};
});
} else {
objectvalue = value;
}
if (!this.fields) {
this.fields = new DatumFields(this.defaults.fields);
}
if (stringvalue) {
this.fields.languages.value = stringvalue;
}
this.debug("setting language ", objectvalue);
for (var property in objectvalue) {
if (!objectvalue.hasOwnProperty(property)) {
continue;
}
this.debug("looking at " + property);
this.fields.languages[property] = objectvalue[property];
}
}
},
dialects: {
get: function() {
return this.languages;
},
set: function(value) {
return this.languages = value;
}
},
user: {
get: function() {
if (!this.userMask) {
var self = this;
if (this.public && this.username) {
this.userMask = new this.INTERNAL_MODELS["user"]({});
this.userMask.username = this.username;
this.userMask.fetch().then(function(result) {
self.debug("Fetched speaker\"s user mask", result);
}, function(error) {
self.debug("Failed to fetch speaker\"s user mask", error);
}).fail(function(error) {
console.error(error.stack, self);
});
} else {
this.userMask = {};
}
this.userMask = {
username: this.anonymousCode,
gravatar: this.gravatar
};
}
return this.userMask;
},
set: function(value) {
if (value === this.userMask) {
return;
}
if (!value) {
value = {};
}
this.userMask = value;
}
},
languageOne: {
get: function() {
return this.getLanguageNumber(0);
},
set: function(value) {
return this.setLanguageNumber(0, value);
}
},
languageTwo: {
get: function() {
return this.getLanguageNumber(1);
},
set: function(value) {
return this.setLanguageNumber(1, value);
}
},
languageThree: {
get: function() {
return this.getLanguageNumber(2);
},
set: function(value) {
return this.setLanguageNumber(2, value);
}
},
languageFour: {
get: function() {
return this.getLanguageNumber(3);
},
set: function(value) {
return this.setLanguageNumber(3, value);
}
},
languageFive: {
get: function() {
return this.getLanguageNumber(4);
},
set: function(value) {
return this.setLanguageNumber(4, value);
}
},
getLanguageNumber: {
value: function(number) {
if (!this.fields || !this.fields.languages || !this.fields.languages.json || !this.fields.languages.json.languages || !this.fields.languages.json.languages[number]) {
return;
}
return this.fields.languages.json.languages[number];
}
},
setLanguageNumber: {
value: function(number, value) {
if (!this.fields || !this.fields.languages) {
return;
}
this.fields.languages.json = this.fields.languages.json || {
languages: []
};
if (value === this.fields.languages.json.languages[number]) {
return;
}
if (value.iso) {
value = {
language: value,
fluency: {
"comprehensionFluency": "native",
"speakingFluency": "native"
},
dates: {
start: "",
end: "",
proportionOfUse: ""
}
};
}
value.fluency = value.fluency || {};
value.dates = value.dates || {};
value.language = value.language || {};
this.fields.languages.json.languages[number] = value;
return this.fields.languages.json.languages[number];
}
}
});
exports.Speaker = Speaker;
},{"./../FieldDBObject":3,"./../confidentiality_encryption/Confidential":17,"./../corpus/corpus.json":25,"./../datum/DatumFields":33,"./UserMask":65}],63:[function(require,module,exports){
var UserMask = require("./UserMask").UserMask;
/**
*
* @class Team extends from UserMask. It inherits the same attributes as UserMask but can
* login.
*
* @name Team
* @extends UserMask
* @constructs
*/
var Team = function Team(options) {
if (!this._fieldDBtype) {
this._fieldDBtype = "Team";
}
this.debug("Constructing Team: ", options);
UserMask.apply(this, arguments);
};
Team.prototype = Object.create(UserMask.prototype, /** @lends Team.prototype */ {
constructor: {
value: Team
},
id: {
get: function() {
return "team";
},
set: function(value) {
if (value === this._id) {
return;
}
if (value !== "team") {
this.warn("Cannot set team id to anything other than \"team.\"");
}
this._id = "team";
}
},
defaults: {
value: {
// Defaults from UserMask
username: "",
password: "",
email: "",
gravatar: "",
researchInterest: "",
affiliation: "",
description: "",
subtitle: "",
dataLists: [],
mostRecentIds: {},
// Defaults from User
firstname: "",
lastname: "",
teams: [],
sessionHistory: []
}
},
/**
* The subtitle function returns user's first and last names.
*/
subtitle: {
get: function() {
return this.name;
},
set: function(value) {
if (value === this.name) {
return;
}
this.warn("subtitle is deprecated, use name instead.");
this.name = value;
}
}
// toJSON: {
// value: function(includeEvenEmptyAttributes, removeEmptyAttributes) {
// this.debug("Customizing toJSON ", includeEvenEmptyAttributes, removeEmptyAttributes);
// var json = UserMask.prototype.toJSON.apply(this, [false, true]);
// json._id = this.id;
// delete json.fieldDBtype;
// delete json.version;
// delete json.api;
// this.debug(json);
// return json;
// }
// }
});
exports.Team = Team;
},{"./UserMask":65}],64:[function(require,module,exports){
/* globals localStorage */
var Activities = require("./../activity/Activities").Activities;
var FieldDBObject = require("./../FieldDBObject").FieldDBObject;
var UserMask = require("./UserMask").UserMask;
var DatumFields = require("./../datum/DatumFields").DatumFields;
var Connection = require("./../corpus/Connection").Connection;
var Corpora = require("./../corpus/Corpora").Corpora;
var Database = require("./../corpus/Database").Database;
var Confidential = require("./../confidentiality_encryption/Confidential").Confidential;
var UserPreference = require("./UserPreference").UserPreference;
var DEFAULT_USER_MODEL = require("./user.json");
var Q = require("q");
/**
* @class User extends from UserGeneric. It inherits the same attributes as UserGeneric but can
* login.
*
* @property {String} firstname The user's first name.
* @property {String} lastname The user's last name.
* @property {Array} teams This is a list of teams a user belongs to.
* @property {Array} sessionHistory
* @property {Array} datalistHistory
* @property {Permission} permissions This is where permissions are specified (eg. read only; add/edit data etc.)
*
* @name User
* @extends UserMask
* @constructs
*/
var User = function User(options) {
if (!this._fieldDBtype) {
this._fieldDBtype = "User";
}
this.debug("Constructing User length: ", options);
UserMask.apply(this, arguments);
};
User.prototype = Object.create(UserMask.prototype, /** @lends User.prototype */ {
constructor: {
value: User
},
api: {
value: "users"
},
defaults: {
get: function() {
return JSON.parse(JSON.stringify(DEFAULT_USER_MODEL));
}
},
INTERNAL_MODELS: {
value: {
username: FieldDBObject.DEFAULT_STRING,
firstname: FieldDBObject.DEFAULT_STRING,
lastname: FieldDBObject.DEFAULT_STRING,
email: FieldDBObject.DEFAULT_STRING,
gravatar: FieldDBObject.DEFAULT_STRING,
researchInterest: FieldDBObject.DEFAULT_STRING,
affiliation: FieldDBObject.DEFAULT_STRING,
description: FieldDBObject.DEFAULT_STRING,
appbrand: FieldDBObject.DEFAULT_STRING,
fields: DatumFields,
prefs: UserPreference,
mostRecentIds: FieldDBObject,
activityConnection: Activities,
authUrl: FieldDBObject.DEFAULT_STRING,
userMask: UserMask,
corpora: Corpora,
newCorpora: Corpora,
sessionHistory: FieldDBObject.DEFAULT_ARRAY,
datalistHistory: FieldDBObject.DEFAULT_ARRAY
}
},
hotkeys: {
get: function() {
if (this.prefs) {
return this.prefs.hotkeys;
}
},
set: function(value) {
if (!this.prefs) {
this.prefs = new this.INTERNAL_MODELS["prefs"]();
}
if (Object.prototype.toString.call(value) !== "[object Array]") {
if (!value.firstKey && !value.secondKey && !value.description) {
value = [];
} else {
value = [value];
}
}
this.prefs.hotkeys = value;
delete this.hotkeys;
}
},
authUrl: {
get: function() {
return this._authUrl || "";
},
set: function(value) {
this.debug("setting authurl", value);
if (value === this._authUrl) {
return;
}
if (!value) {
delete this._authUrl;
return;
} else {
if (typeof value.trim === "function") {
value = value.trim();
}
value = value.replace(/[^.\/]*.fieldlinguist.com:3183/g, "auth.lingsync.org");
}
this._authUrl = value;
}
},
datalists: {
get: function() {
return this.datalistHistory;
},
set: function(value) {
if (value && !this._datalistHistory) {
this.datalistHistory = value;
}
}
},
datalistHistory: {
get: function() {
return this._datalistHistory || FieldDBObject.DEFAULT_ARRAY;
},
set: function(value) {
this._datalistHistory = value;
}
},
sessionHistory: {
get: function() {
return this._sessionHistory || FieldDBObject.DEFAULT_ARRAY;
},
set: function(value) {
this._sessionHistory = value;
}
},
mostRecentIds: {
configurable: true,
get: function() {
return this._mostRecentIds || FieldDBObject.DEFAULT_OBJECT;
},
set: function(value) {
if (value === this._mostRecentIds) {
return;
}
if (!value) {
delete this._mostRecentIds;
return;
} else {
if (!(value instanceof this.INTERNAL_MODELS["mostRecentIds"])) {
value = new this.INTERNAL_MODELS["mostRecentIds"](value);
}
}
value.connection = value.connection || value.corpusConnection || value.couchConnection;
delete value.corpusConnection;
delete value.couchConnection;
if (value.connection) {
value.connection = new Connection(value.connection);
}
this._mostRecentIds = value;
}
},
prefs: {
get: function() {
// if (!this._prefs && this.INTERNAL_MODELS["prefs"] && typeof this.INTERNAL_MODELS["prefs"] === "function") {
// this.prefs = new this.INTERNAL_MODELS["prefs"](this.defaults.prefs);
// }
return this._prefs;
},
set: function(value) {
this.ensureSetViaAppropriateType("prefs", value);
// if(this._prefs){
// this._prefs.parent = this;
// }
}
},
corpuses: {
configurable: true,
get: function() {
return this.corpora;
},
set: function(value) {
this.corpora = value;
}
},
corpora: {
configurable: true,
get: function() {
return this._corpora || FieldDBObject.DEFAULT_ARRAY;
},
set: function(value) {
this.ensureSetViaAppropriateType("corpora", value);
}
},
newCorpusConnections: {
configurable: true,
get: function() {
return this.newCorpora;
},
set: function(value) {
this.newCorpora = value;
}
},
appbrand: {
get: function() {
if (this.prefs && this.prefs.preferredDashboardType === this.prefs.defaults.preferredDashboardType) {
if (this._appbrand === "phophlo") {
this.debug(" setting preferredDashboardType from user " + this._appbrand);
this.prefs.preferredDashboardType = "experimenter";
}
}
return this._appbrand || "lingsync";
},
set: function(value) {
if (value === this._appbrand) {
return;
}
if (this._appbrand) {
this.warn("appbrand cannot be modified by client side apps.");
} else {
if (value.trim) {
value = value.trim();
}
this._appbrand = value;
}
this.debug(" setting preferredDashboardType from user " + this._appbrand);
if (this.prefs && this.prefs.preferredDashboardType === this.prefs.defaults.preferredDashboardType) {
if (this._appbrand === "phophlo") {
this.prefs._preferredDashboardType = "experimenter";
this.debug(" it is now " + this.prefs.preferredDashboardType);
}
}
}
},
userMask: {
get: function() {
this.debug("getting userMask");
return this._userMask;
},
set: function(value) {
if (value && typeof value === "object") {
value.username = this.username;
value.gravatar = value.gravatar || this.gravatar;
value.researchInterest = value.researchInterest || "No public information available";
value.description = value.description || "No public information available";
value.affiliation = value.affiliation || "No public information available";
}
this.ensureSetViaAppropriateType("userMask", value);
}
},
publicSelf: {
get: function() {
return this.userMask;
},
set: function(value) {
this.userMask = value;
}
},
activityConnection: {
get: function() {
this.debug("getting activityConnection");
return this._activityConnection;
},
set: function(value) {
if (value) {
value.parent = this;
if (!value.confidential && this.confidential) {
value.confidential = this.confidential;
}
}
this.ensureSetViaAppropriateType("activityConnection", value);
if (this.username && this._activityConnection && this._activityConnection._connection && !this._activityConnection._database) {
this._activityConnection._database = new Database({
dbname: this.username + "-activity_feed",
connection: this._activityConnection._connection
});
}
}
},
activityCouchConnection: {
configurable: true,
get: function() {
return this.activityConnection;
},
set: function(value) {
this.activityConnection = value;
}
},
toJSON: {
value: function(includeEvenEmptyAttributes, removeEmptyAttributes) {
this.debug("Customizing toJSON ", includeEvenEmptyAttributes, removeEmptyAttributes);
includeEvenEmptyAttributes = true;
var json = FieldDBObject.prototype.toJSON.apply(this, arguments);
// TODO not including the corpuses, instead include corpora
if (this.corpora && typeof this.corpora.toJSON === "function") {
json.corpora = this.corpora.toJSON();
} else {
json.corpora = this.corpora;
}
delete json.corpuses;
delete json.connection;
delete json.authentication;
// TODO deprecated
json.datalists = this.datalists;
if (json.mostRecentIds) {
delete json.mostRecentIds.fieldDBtype;
delete json.mostRecentIds.version;
delete json.mostRecentIds.dateCreated;
delete json.mostRecentIds.dateModified;
delete json.mostRecentIds.comments;
if (!json.mostRecentIds.dbname) {
delete json.mostRecentIds.dbname;
}
}
this.debug(json);
return json;
}
},
save: {
value: function(options) {
this.debug("Customizing save ", options);
var key,
userKey,
encryptedUserPreferences,
deferred = Q.defer();
this.whenReady = deferred.promise;
var self = this;
Q.nextTick(function() {
deferred.resolve(self);
});
if (!this._rev) {
this.warn("Refusing to save a user doc which is incomplete, and doesn't have a rev");
return deferred.promise;
}
try {
// save the user's preferences encrypted in local storage so they can work without by connecting only to their corpus
key = localStorage.getItem("X09qKvcQn8DnANzGdrZFqCRUutIi2C");
if (!key) {
key = Confidential.secretKeyGenerator();
localStorage.setItem("X09qKvcQn8DnANzGdrZFqCRUutIi2C", key);
}
} catch (e) {
this.constructor.prototype.temp = this.constructor.prototype.temp || {};
key = this.constructor.prototype.temp.X09qKvcQn8DnANzGdrZFqCRUutIi2C;
if (!key) {
key = Confidential.secretKeyGenerator();
this.constructor.prototype.temp.X09qKvcQn8DnANzGdrZFqCRUutIi2C = key;
}
this.warn("unable to use local storage, this app wont be very usable offline ");
this.debug(" error ", e);
}
userKey = key + this.username;
var userJSON = this.toJSON();
self.debug("saving " + userKey, userJSON);
encryptedUserPreferences = new Confidential({
secretkey: userKey
}).encrypt(userJSON);
try {
localStorage.setItem(userKey, encryptedUserPreferences);
} catch (e) {
this.constructor.prototype.temp = this.constructor.prototype.temp || {};
this.constructor.prototype.temp[userKey] = encryptedUserPreferences;
this.warn("unable to use local storage, this app wont be very usable offline ");
this.debug(" error ", e);
}
return deferred.promise;
}
},
fetch: {
value: function(options) {
this.debug("Customizing fetch ", options);
var key,
userKey,
encryptedUserPreferences,
decryptedUser = {},
overwriteOrNot,
self = this,
deferred = Q.defer();
this.whenReady = deferred.promise;
Q.nextTick(function() {
deferred.resolve(self);
});
try {
// fetch the user's preferences encrypted in local storage so they can work without by connecting only to their corpus
key = localStorage.getItem("X09qKvcQn8DnANzGdrZFqCRUutIi2C");
} catch (e) {
self.constructor.prototype.temp = self.constructor.prototype.temp || {};
key = self.constructor.prototype.temp.X09qKvcQn8DnANzGdrZFqCRUutIi2C;
self.warn("unable to use local storage, this app wont be very usable offline ");
self.debug(" error ", e);
}
if (!key) {
self.warn("cannot fetch user info locally");
return deferred.promise;
}
userKey = key + self.username;
try {
encryptedUserPreferences = localStorage.getItem(userKey);
} catch (e) {
if (!self.constructor.prototype.temp) {
self.warn("no local users have been saved");
return FieldDBObject.prototype.fetch.apply(self, arguments);
}
encryptedUserPreferences = self.constructor.prototype.temp[userKey];
}
decryptedUser = {};
if (!encryptedUserPreferences) {
self.warn("This user " + self.username + " hasnt been used this device before, need to request their prefs when they login.");
return deferred.promise;
// return FieldDBObject.prototype.fetch.apply(self, arguments);
}
self.debug("userKey is " + userKey);
self.debug("user encrypted is " + encryptedUserPreferences);
decryptedUser = new Confidential({
secretkey: userKey
}).decrypt(encryptedUserPreferences);
self.debug(" Opening user prefs from previous session on self device", decryptedUser);
if (!self._rev) {
overwriteOrNot = "overwrite";
}
self.merge("self", new User(decryptedUser), overwriteOrNot);
return deferred.promise;
}
}
});
exports.User = User;
},{"./../FieldDBObject":3,"./../activity/Activities":5,"./../confidentiality_encryption/Confidential":17,"./../corpus/Connection":19,"./../corpus/Corpora":20,"./../corpus/Database":23,"./../datum/DatumFields":33,"./UserMask":65,"./UserPreference":66,"./user.json":68,"q":248}],65:[function(require,module,exports){
var FieldDBObject = require("./../FieldDBObject").FieldDBObject;
var DatumFields = require("./../datum/DatumFields").DatumFields;
var MD5 = require("MD5");
/**
* @class A mask of a user which can be saved along with the corpus. It is
* generally just a username and gravatar but could be more depending
* on what the user allows to be public.
*
*
* @extends FieldDBObject
* @tutorial tests/UserTest.js
*/
var UserMask = function UserMask(options) {
if (!this._fieldDBtype) {
this._fieldDBtype = "UserMask";
}
this.debug("Constructing a UserMask " + options);
FieldDBObject.apply(this, arguments);
};
UserMask.prototype = Object.create(FieldDBObject.prototype, /** @lends UserMask.prototype */ {
constructor: {
value: UserMask
},
api: {
value: "users"
},
INTERNAL_MODELS: {
value: {
username: FieldDBObject.DEFAULT_STRING,
firstname: FieldDBObject.DEFAULT_STRING,
lastname: FieldDBObject.DEFAULT_STRING,
gravatar: FieldDBObject.DEFAULT_STRING,
researchInterest: FieldDBObject.DEFAULT_STRING,
affiliation: FieldDBObject.DEFAULT_STRING,
description: FieldDBObject.DEFAULT_STRING,
fields: DatumFields
}
},
buildGravatar: {
value: function(emailOrOtherString) {
var existingGravatar = this._gravatar;
if (existingGravatar.indexOf("gravatar.com") > -1) {
existingGravatar = existingGravatar.replace("https://secure.gravatar.com/avatar/", "");
this._gravatar = existingGravatar;
} else if (existingGravatar.indexOf("user_gravatar.png") > -1) {
existingGravatar = "";
}
if (!existingGravatar) {
if (emailOrOtherString) {
this._gravatar = MD5(emailOrOtherString);
} else {
this._gravatar = "0df69960706112e38332395a4f2e7542";
}
}
return this._gravatar;
}
},
defaults: {
value: {
username: "",
firstname: "",
lastname: "",
email: "",
gravatar: "",
researchInterest: "",
affiliation: "",
description: ""
}
},
id: {
get: function() {
if (!this._username) {
this._username = "";
}
return this._username || this._id;
},
set: function(value) {
if (value === this._username) {
return;
}
if (!value) {
value = "";
}
this._username = this._id = value.trim();
}
},
userMask: {
get: function() {
return {
username: this.username,
gravatar: this.gravatar,
name: this.name
};
},
set: function(value) {
this.debug("users masks cant be set.", value);
}
},
username: {
get: function() {
if (!this._username) {
this._username = "";
}
return this._username;
},
set: function(value) {
if (value === this._username) {
return;
}
if (!value) {
value = "";
}
this._username = value.trim();
}
},
firstname: {
configurable: true,
get: function() {
if (!this._firstname) {
this._firstname = "";
}
return this._firstname;
},
set: function(value) {
if (value === this._firstname) {
return;
}
if (!value) {
value = "";
}
this._firstname = value.trim();
}
},
lastname: {
configurable: true,
get: function() {
if (!this._lastname) {
this._lastname = "";
}
return this._lastname;
},
set: function(value) {
if (value === this._lastname) {
return;
}
if (!value) {
value = "";
}
this._lastname = value.trim();
}
},
gravatar: {
get: function() {
if (!this._gravatar) {
this._gravatar = "";
}
return this._gravatar;
},
set: function(value) {
if (value === this._gravatar) {
return;
}
if (!value) {
value = "";
}
this._gravatar = value.trim();
}
},
email: {
get: function() {
if (!this._email) {
this._email = "";
}
return this._email;
},
set: function(value) {
if (value === this._email) {
return;
}
if (!value) {
value = "";
}
var validEmailRegEx = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
if (validEmailRegEx.test(value)) {
this._email = value.trim();
}
}
},
affiliation: {
get: function() {
if (!this._affiliation) {
this._affiliation = "";
}
return this._affiliation;
},
set: function(value) {
if (value === this._affiliation) {
return;
}
if (!value) {
value = "";
}
this._affiliation = value.trim();
}
},
researchInterest: {
get: function() {
if (!this._researchInterest) {
this._researchInterest = "";
}
return this._researchInterest;
},
set: function(value) {
if (value === this._researchInterest) {
return;
}
if (!value) {
value = "";
}
this._researchInterest = value.trim();
}
},
description: {
get: function() {
if (!this._description) {
this._description = "";
}
return this._description;
},
set: function(value) {
if (value === this._description) {
return;
}
if (!value) {
value = "";
}
this._description = value.trim();
}
},
name: {
configurable: true,
get: function() {
this.firstname = this.firstname || "";
this.lastname = this.lastname || "";
var name = (this.firstname + " " + this.lastname).trim();
if (name) {
return name;
}
return this.anonymousCode || this.username;
},
set: function(value) {
if (!value) {
return;
}
if (value.indexOf(" ") > -1) {
var pieces = value.replace(/ +/g, " ").split(" ");
if (pieces[0]) {
this._firstname = pieces[0];
}
if (pieces[1]) {
this._lastname = pieces[1];
}
}
}
},
validateUsername: {
value: function(value) {
if (!value) {
return {
valid: false,
username: null,
original: null,
suggestion: null
};
}
var safeName = value.toLowerCase().replace(/[^a-z0-9_]/g, "");
var validation = {
valid: true,
username: value,
original: value
};
if (safeName !== value) {
validation.valid = false;
validation.suggestion = safeName;
validation.username = safeName;
}
return validation;
}
},
fields: {
configurable: true,
get: function() {
if (this._fields) {
// this.debug("setting speaker fields confidential in the Speaker.fields get function.");
// this._fields.encrypted = true;
// this._fields.decryptedMode = true;
this._fields.confidential = this.confidential;
}
return this._fields;
},
set: function(value) {
if (value === this._fields) {
return;
}
if (!value) {
delete this._fields;
return;
} else {
if (Object.prototype.toString.call(value) === "[object Array]") {
value = new this.INTERNAL_MODELS["fields"](value);
}
}
this._fields = value;
}
}
});
exports.UserMask = UserMask;
},{"./../FieldDBObject":3,"./../datum/DatumFields":33,"MD5":69}],66:[function(require,module,exports){
var FieldDBObject = require("./../FieldDBObject").FieldDBObject;
var HotKeys = require("./../hotkey/HotKeys").HotKeys;
var UnicodeSymbols = require("./../unicode/UnicodeSymbols").UnicodeSymbols;
/**
* @class Hold preferences for users like the skin of the app
*
* @property {int} skin This is user's preferred skin.
* @property {int} numVisibleDatum The number of Datum visible at the time on
* the Datum*View"s.
*
* @name UserPreference
* @extends FieldDBObject
* @constructs
*/
var UserPreference = function UserPreference(options) {
if (!this._fieldDBtype) {
this._fieldDBtype = "UserPreference";
}
this.debug("Constructing UserPreference length: ", options);
FieldDBObject.apply(this, arguments);
};
UserPreference.preferredDashboardLayouts = ["layoutAllTheData", "layoutJustEntering", "layoutWhatsHappening", "layoutCompareDataLists"];
UserPreference.preferredDashboardTypes = ["fieldlinguistNormalUser", "fieldlinguistPowerUser"];
UserPreference.prototype = Object.create(FieldDBObject.prototype, /** @lends UserPreference.prototype */ {
constructor: {
value: UserPreference
},
defaults: {
get: function() {
return {
skin: "",
numVisibleDatum: 2, //Use two as default so users can see minimal pairs
transparentDashboard: false,
alwaysRandomizeSkin: true,
numberOfItemsInPaginatedViews: 10,
preferredDashboardLayout: "layoutAllTheData",
preferredDashboardType: "fieldlinguistNormalUser",
preferredSpreadsheetShape: {
columns: 2,
rows: 3
},
hotkeys: [],
unicodes: []
};
}
},
INTERNAL_MODELS: {
value: {
hotkeys: HotKeys,
unicodes: UnicodeSymbols
}
},
skin: {
get: function() {
return this._skin || this.defaults.skin;
},
set: function(value) {
this.debug("setting _skin from " + value);
if (value === this._skin) {
return;
}
if (!value) {
delete this._skin;
return;
}
if (value.trim) {
value = value.trim();
}
this._skin = value;
}
},
transparentDashboard: {
get: function() {
return this._transparentDashboard || this.defaults.transparentDashboard;
},
set: function(value) {
this.debug("setting _transparentDashboard from " + value);
if (value === this._transparentDashboard) {
return;
}
if (value === false || value === "false" || !value) {
this._transparentDashboard = false;
} else {
this._transparentDashboard = true;
}
}
},
alwaysRandomizeSkin: {
get: function() {
return this._alwaysRandomizeSkin || this.defaults.alwaysRandomizeSkin;
},
set: function(value) {
this.debug("setting _alwaysRandomizeSkin from " + value);
if (value === this._alwaysRandomizeSkin) {
return;
}
if (value === false || value === "false" || !value) {
this._alwaysRandomizeSkin = false;
} else {
this._alwaysRandomizeSkin = true;
}
}
},
preferedDashboardType: {
get: function() {
this.warn("preferedDashboardType is deprecated use preferredDashboardType instead");
return this.preferredDashboardType;
},
set: function(value) {
this.warn("preferedDashboardType is deprecated use preferredDashboardType instead");
this.preferredDashboardType = value;
}
},
preferredDashboardType: {
get: function() {
return this._preferredDashboardType || this.defaults.preferredDashboardType;
},
set: function(value) {
this.debug("setting _preferredDashboardType from " + value);
if (value === this._preferredDashboardType) {
return;
}
if (!value) {
delete this._preferredDashboardType;
return;
}
if (value.trim) {
value = value.trim();
}
this._preferredDashboardType = value;
}
},
preferedDashboardLayout: {
get: function() {
this.warn("preferedDashboardLayout is deprecated use preferredDashboardLayout instead");
return this.preferredDashboardLayout;
},
set: function(value) {
this.warn("preferedDashboardType is deprecated use preferredDashboardLayout instead");
this.preferredDashboardLayout = value;
}
},
preferredDashboardLayout: {
get: function() {
return this._preferredDashboardLayout || this.defaults.preferredDashboardLayout;
},
set: function(value) {
if (value === this._preferredDashboardLayout) {
return;
}
if (!value) {
delete this._preferredDashboardLayout;
return;
}
// Guess which kind of user this is
if (!this.preferredDashboardType) {
if (this._preferredDashboardLayout === "layoutAllTheData" || this._preferredDashboardLayout === "layoutJustEntering" || this._preferredDashboardLayout === "layoutWhatsHappening") {
this.preferredDashboardType = "fieldlinguistNormalUser";
} else if (this._preferredDashboardLayout === "layoutCompareDataLists" || this._preferredDashboardLayout === "layoutEverythingAtOnce") {
this.preferredDashboardType = "fieldlinguistPowerUser";
}
}
this._preferredDashboardLayout = value;
}
},
preferedSpreadsheetShape: {
get: function() {
this.warn("preferedSpreadsheetShape is deprecated use preferredSpreadsheetShape instead");
return this.preferredSpreadsheetShape;
},
set: function(value) {
this.warn("preferedDashboardType is deprecated use preferredSpreadsheetShape instead");
this.preferredSpreadsheetShape = value;
}
},
preferredSpreadsheetShape: {
get: function() {
if (!this._preferredSpreadsheetShape) {
this._preferredSpreadsheetShape = JSON.parse(JSON.stringify(this.defaults.preferredSpreadsheetShape));
}
return this._preferredSpreadsheetShape;
},
set: function(value) {
this._preferredSpreadsheetShape = value;
}
},
hotkeys: {
get: function() {
return this._hotkeys || FieldDBObject.DEFAULT_COLLECTION;
},
set: function(value) {
if (value === this._hotkeys) {
return;
}
if (!value) {
delete this._hotkeys;
return;
} else {
if (value.firstKey) {
value = [value];
}
if (Object.prototype.toString.call(value) === "[object Array]") {
value = new this.INTERNAL_MODELS["hotkeys"](value);
}
}
this._hotkeys = value;
}
},
unicodes: {
get: function() {
return this._unicodes || FieldDBObject.DEFAULT_COLLECTION;
},
set: function(value) {
if (value === this._unicodes) {
return;
}
if (!value) {
delete this._unicodes;
return;
} else {
if (Object.prototype.toString.call(value) === "[object Array]") {
value = new this.INTERNAL_MODELS["unicodes"](value);
}
}
this._unicodes = value;
}
},
numVisibleDatum: {
get: function() {
return this._numVisibleDatum || this.defaults.numVisibleDatum;
},
set: function(value) {
if (value === this._numVisibleDatum) {
return;
}
if (!value) {
delete this._numVisibleDatum;
return;
} else {
if (typeof value.trim === "function") {
value = value.trim();
}
}
value = parseInt(value, 10);
this._numVisibleDatum = value;
}
},
numberOfItemsInPaginatedViews: {
get: function() {
return this._numberOfItemsInPaginatedViews || this.defaults.numberOfItemsInPaginatedViews;
},
set: function(value) {
if (value === this._numberOfItemsInPaginatedViews) {
return;
}
if (!value) {
delete this._numberOfItemsInPaginatedViews;
return;
} else {
if (typeof value.trim === "function") {
value = value.trim();
}
}
value = parseInt(value, 10);
this._numberOfItemsInPaginatedViews = value;
}
},
preferedLocale: {
get: function() {
this.warn("preferedLocale is deprecated use preferredLocale instead");
return this.preferredLocale;
},
set: function(value) {
this.warn("preferedDashboardType is deprecated use preferredLocale instead");
this.preferredLocale = value;
}
},
preferredLocale: {
get: function() {
return this._preferredLocale;
},
set: function(value) {
this.debug("setting _preferredLocale from " + value);
if (value === this._preferredLocale) {
return;
}
if (!value) {
delete this._preferredLocale;
return;
}
if (value.trim) {
value = value.trim();
}
this._preferredLocale = value;
}
},
toJSON: {
value: function(includeEvenEmptyAttributes, removeEmptyAttributes) {
this.debug("Customizing toJSON ", includeEvenEmptyAttributes, removeEmptyAttributes);
var attributesNotToJsonify = ["fieldDBtype", "dateCreated", "version"];
var json = FieldDBObject.prototype.toJSON.apply(this, [includeEvenEmptyAttributes, removeEmptyAttributes, attributesNotToJsonify]);
if (!json) {
this.warn("Not returning json right now.");
return;
}
this.debug("JSON before removing items which match defaults", json);
if (!includeEvenEmptyAttributes) {
for (var pref in this.defaults) {
if (!this.defaults.hasOwnProperty(pref)) {
continue;
}
if (new FieldDBObject(json[pref]).equals(this.defaults[pref]) || (Object.prototype.toString.call(json[pref]) === "[object Array]" && json[pref].length === 0)) {
this.debug("removing pref which is set to a default " + pref);
delete json[pref];
}
}
// if (json.preferredSpreadsheetShape && json.preferredSpreadsheetShape.columns === this.defaults.preferredSpreadsheetShape.columns && json.preferredSpreadsheetShape.rows === this.defaults.preferredSpreadsheetShape.rows) {
// delete json.preferredSpreadsheetShape;
// }
}
if (JSON.stringify(json) === "{}") {
return {};
}
json.fieldDBtype = this.fieldDBtype;
json.version = this.version;
json.dateCreated = this.dateCreated;
this.debug("Json", json);
return json;
}
}
});
exports.UserPreference = UserPreference;
},{"./../FieldDBObject":3,"./../hotkey/HotKeys":45,"./../unicode/UnicodeSymbols":59}],67:[function(require,module,exports){
var Collection = require("./../Collection").Collection;
var UserMask = require("./UserMask").UserMask;
/**
* @class Collection of Datum validation states
* @name Users
* @description The Users is a minimal customization of the Collection
* to add an internal model of UserMask.
*
* @extends Collection
* @constructs
*/
var Users = function Users(options) {
if (!this._fieldDBtype) {
this._fieldDBtype = "Users";
}
this.debug("Constructing Users ", options);
Collection.apply(this, arguments);
};
Users.prototype = Object.create(Collection.prototype, /** @lends Users.prototype */ {
constructor: {
value: Users
},
primaryKey: {
value: "username"
},
INTERNAL_MODELS: {
value: {
item: UserMask
}
},
sanitizeStringForPrimaryKey: {
value: function(value) {
return value;
}
}
});
exports.Users = Users;
},{"./../Collection":2,"./UserMask":65}],68:[function(require,module,exports){
module.exports={
"_id": "",
"jsonType": "user",
"username": "",
"email": "",
"corpora": [{
"protocol": "",
"domain": "",
"port": "",
"dbname": "",
"path": "",
"authUrl": "",
"userFriendlyServerName": "",
"title": "",
"corpusid": "",
"titleAsUrl": "",
"description": "The details of this corpus are not public."
}],
"activityConnection": {
"protocol": "",
"domain": "",
"port": "",
"dbname": "",
"path": "",
"authUrl": "",
"userFriendlyServerName": ""
},
"appbrand": "",
"gravatar": "",
"appVersionWhenCreated": "",
"authServerVersionWhenCreated": "",
"authUrl": "",
"created_at": "",
"updated_at": "",
"researchInterest": "",
"affiliation": "",
"description": "",
"subtitle": "",
"dataLists": [],
"prefs": {
"skin": "",
"numVisibleDatum": 10,
"transparentDashboard": false,
"alwaysRandomizeSkin": true,
"numberOfItemsInPaginatedViews": 10,
"unicodes": [{
"symbol": "ɔ",
"tipa": "",
"useCount": 0
}, {
"symbol": "ə",
"tipa": "",
"useCount": 0
}, {
"symbol": "ɛ",
"tipa": "",
"useCount": 0
}, {
"symbol": "ɣ",
"tipa": "",
"useCount": 0
}, {
"symbol": "ɥ",
"tipa": "",
"useCount": 0
}, {
"symbol": "ɦ",
"tipa": "",
"useCount": 0
}, {
"symbol": "ɫ",
"tipa": "",
"useCount": 0
}, {
"symbol": "ʃ",
"tipa": "",
"useCount": 0
}, {
"symbol": "ʒ",
"tipa": "",
"useCount": 0
}, {
"symbol": "ʔ",
"tipa": "",
"useCount": 0
}, {
"symbol": "λ ",
"tipa": "lambda",
"useCount": 0
}, {
"symbol": "α ",
"tipa": "alpha",
"useCount": 0
}, {
"symbol": "β ",
"tipa": "\beta",
"useCount": 0
}, {
"symbol": "∀",
"tipa": "\forall",
"useCount": 0
}, {
"symbol": "∃",
"tipa": "exists",
"useCount": 0
}, {
"symbol": "°",
"tipa": "^{circ}",
"useCount": 0
}, {
"symbol": "∄",
"tipa": "",
"useCount": 0
}, {
"symbol": "∅",
"tipa": "",
"useCount": 0
}, {
"symbol": "∈",
"tipa": "",
"useCount": 0
}, {
"symbol": "∉",
"tipa": "",
"useCount": 0
}, {
"symbol": "∋",
"tipa": "",
"useCount": 0
}, {
"symbol": "∌",
"tipa": "",
"useCount": 0
}],
"preferredDashboardLayout": "default",
"showNewDatumAtTopOrBottomOfDataEntryArea": "bottom",
"hotkeys": []
},
"mostRecentIds": {
"corpusid": "",
"datalistid": "",
"sessionid": "",
"connection": {
"protocol": "",
"domain": "",
"port": "",
"dbname": "",
"path": "",
"authUrl": "",
"userFriendlyServerName": "",
"corpusid": ""
}
},
"firstname": "",
"lastname": "",
"sessionHistory": [],
"hotkeys": [],
"newCorpora": [],
"roles": []
}
},{}],69:[function(require,module,exports){
(function (Buffer){
(function(){
var crypt = require('crypt'),
utf8 = require('charenc').utf8,
bin = require('charenc').bin,
// The core
md5 = function (message, options) {
// Convert to byte array
if (message.constructor == String)
if (options && options.encoding === 'binary')
message = bin.stringToBytes(message);
else
message = utf8.stringToBytes(message);
else if (typeof Buffer != 'undefined' &&
typeof Buffer.isBuffer == 'function' && Buffer.isBuffer(message))
message = Array.prototype.slice.call(message, 0);
else if (!Array.isArray(message))
message = message.toString();
// else, assume byte array already
var m = crypt.bytesToWords(message),
l = message.length * 8,
a = 1732584193,
b = -271733879,
c = -1732584194,
d = 271733878;
// Swap endian
for (var i = 0; i < m.length; i++) {
m[i] = ((m[i] << 8) | (m[i] >>> 24)) & 0x00FF00FF |
((m[i] << 24) | (m[i] >>> 8)) & 0xFF00FF00;
}
// Padding
m[l >>> 5] |= 0x80 << (l % 32);
m[(((l + 64) >>> 9) << 4) + 14] = l;
// Method shortcuts
var FF = md5._ff,
GG = md5._gg,
HH = md5._hh,
II = md5._ii;
for (var i = 0; i < m.length; i += 16) {
var aa = a,
bb = b,
cc = c,
dd = d;
a = FF(a, b, c, d, m[i+ 0], 7, -680876936);
d = FF(d, a, b, c, m[i+ 1], 12, -389564586);
c = FF(c, d, a, b, m[i+ 2], 17, 606105819);
b = FF(b, c, d, a, m[i+ 3], 22, -1044525330);
a = FF(a, b, c, d, m[i+ 4], 7, -176418897);
d = FF(d, a, b, c, m[i+ 5], 12, 1200080426);
c = FF(c, d, a, b, m[i+ 6], 17, -1473231341);
b = FF(b, c, d, a, m[i+ 7], 22, -45705983);
a = FF(a, b, c, d, m[i+ 8], 7, 1770035416);
d = FF(d, a, b, c, m[i+ 9], 12, -1958414417);
c = FF(c, d, a, b, m[i+10], 17, -42063);
b = FF(b, c, d, a, m[i+11], 22, -1990404162);
a = FF(a, b, c, d, m[i+12], 7, 1804603682);
d = FF(d, a, b, c, m[i+13], 12, -40341101);
c = FF(c, d, a, b, m[i+14], 17, -1502002290);
b = FF(b, c, d, a, m[i+15], 22, 1236535329);
a = GG(a, b, c, d, m[i+ 1], 5, -165796510);
d = GG(d, a, b, c, m[i+ 6], 9, -1069501632);
c = GG(c, d, a, b, m[i+11], 14, 643717713);
b = GG(b, c, d, a, m[i+ 0], 20, -373897302);
a = GG(a, b, c, d, m[i+ 5], 5, -701558691);
d = GG(d, a, b, c, m[i+10], 9, 38016083);
c = GG(c, d, a, b, m[i+15], 14, -660478335);
b = GG(b, c, d, a, m[i+ 4], 20, -405537848);
a = GG(a, b, c, d, m[i+ 9], 5, 568446438);
d = GG(d, a, b, c, m[i+14], 9, -1019803690);
c = GG(c, d, a, b, m[i+ 3], 14, -187363961);
b = GG(b, c, d, a, m[i+ 8], 20, 1163531501);
a = GG(a, b, c, d, m[i+13], 5, -1444681467);
d = GG(d, a, b, c, m[i+ 2], 9, -51403784);
c = GG(c, d, a, b, m[i+ 7], 14, 1735328473);
b = GG(b, c, d, a, m[i+12], 20, -1926607734);
a = HH(a, b, c, d, m[i+ 5], 4, -378558);
d = HH(d, a, b, c, m[i+ 8], 11, -2022574463);
c = HH(c, d, a, b, m[i+11], 16, 1839030562);
b = HH(b, c, d, a, m[i+14], 23, -35309556);
a = HH(a, b, c, d, m[i+ 1], 4, -1530992060);
d = HH(d, a, b, c, m[i+ 4], 11, 1272893353);
c = HH(c, d, a, b, m[i+ 7], 16, -155497632);
b = HH(b, c, d, a, m[i+10], 23, -1094730640);
a = HH(a, b, c, d, m[i+13], 4, 681279174);
d = HH(d, a, b, c, m[i+ 0], 11, -358537222);
c = HH(c, d, a, b, m[i+ 3], 16, -722521979);
b = HH(b, c, d, a, m[i+ 6], 23, 76029189);
a = HH(a, b, c, d, m[i+ 9], 4, -640364487);
d = HH(d, a, b, c, m[i+12], 11, -421815835);
c = HH(c, d, a, b, m[i+15], 16, 530742520);
b = HH(b, c, d, a, m[i+ 2], 23, -995338651);
a = II(a, b, c, d, m[i+ 0], 6, -198630844);
d = II(d, a, b, c, m[i+ 7], 10, 1126891415);
c = II(c, d, a, b, m[i+14], 15, -1416354905);
b = II(b, c, d, a, m[i+ 5], 21, -57434055);
a = II(a, b, c, d, m[i+12], 6, 1700485571);
d = II(d, a, b, c, m[i+ 3], 10, -1894986606);
c = II(c, d, a, b, m[i+10], 15, -1051523);
b = II(b, c, d, a, m[i+ 1], 21, -2054922799);
a = II(a, b, c, d, m[i+ 8], 6, 1873313359);
d = II(d, a, b, c, m[i+15], 10, -30611744);
c = II(c, d, a, b, m[i+ 6], 15, -1560198380);
b = II(b, c, d, a, m[i+13], 21, 1309151649);
a = II(a, b, c, d, m[i+ 4], 6, -145523070);
d = II(d, a, b, c, m[i+11], 10, -1120210379);
c = II(c, d, a, b, m[i+ 2], 15, 718787259);
b = II(b, c, d, a, m[i+ 9], 21, -343485551);
a = (a + aa) >>> 0;
b = (b + bb) >>> 0;
c = (c + cc) >>> 0;
d = (d + dd) >>> 0;
}
return crypt.endian([a, b, c, d]);
};
// Auxiliary functions
md5._ff = function (a, b, c, d, x, s, t) {
var n = a + (b & c | ~b & d) + (x >>> 0) + t;
return ((n << s) | (n >>> (32 - s))) + b;
};
md5._gg = function (a, b, c, d, x, s, t) {
var n = a + (b & d | c & ~d) + (x >>> 0) + t;
return ((n << s) | (n >>> (32 - s))) + b;
};
md5._hh = function (a, b, c, d, x, s, t) {
var n = a + (b ^ c ^ d) + (x >>> 0) + t;
return ((n << s) | (n >>> (32 - s))) + b;
};
md5._ii = function (a, b, c, d, x, s, t) {
var n = a + (c ^ (b | ~d)) + (x >>> 0) + t;
return ((n << s) | (n >>> (32 - s))) + b;
};
// Package private blocksize
md5._blocksize = 16;
md5._digestsize = 16;
module.exports = function (message, options) {
if(typeof message == 'undefined')
return;
var digestbytes = crypt.wordsToBytes(md5(message, options));
return options && options.asBytes ? digestbytes :
options && options.asString ? bin.bytesToString(digestbytes) :
crypt.bytesToHex(digestbytes);
};
})();
}).call(this,require("buffer").Buffer)
},{"buffer":76,"charenc":70,"crypt":71}],70:[function(require,module,exports){
var charenc = {
// UTF-8 encoding
utf8: {
// Convert a string to a byte array
stringToBytes: function(str) {
return charenc.bin.stringToBytes(unescape(encodeURIComponent(str)));
},
// Convert a byte array to a string
bytesToString: function(bytes) {
return decodeURIComponent(escape(charenc.bin.bytesToString(bytes)));
}
},
// Binary encoding
bin: {
// Convert a string to a byte array
stringToBytes: function(str) {
for (var bytes = [], i = 0; i < str.length; i++)
bytes.push(str.charCodeAt(i) & 0xFF);
return bytes;
},
// Convert a byte array to a string
bytesToString: function(bytes) {
for (var str = [], i = 0; i < bytes.length; i++)
str.push(String.fromCharCode(bytes[i]));
return str.join('');
}
}
};
module.exports = charenc;
},{}],71:[function(require,module,exports){
(function() {
var base64map
= 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
crypt = {
// Bit-wise rotation left
rotl: function(n, b) {
return (n << b) | (n >>> (32 - b));
},
// Bit-wise rotation right
rotr: function(n, b) {
return (n << (32 - b)) | (n >>> b);
},
// Swap big-endian to little-endian and vice versa
endian: function(n) {
// If number given, swap endian
if (n.constructor == Number) {
return crypt.rotl(n, 8) & 0x00FF00FF | crypt.rotl(n, 24) & 0xFF00FF00;
}
// Else, assume array and swap all items
for (var i = 0; i < n.length; i++)
n[i] = crypt.endian(n[i]);
return n;
},
// Generate an array of any length of random bytes
randomBytes: function(n) {
for (var bytes = []; n > 0; n--)
bytes.push(Math.floor(Math.random() * 256));
return bytes;
},
// Convert a byte array to big-endian 32-bit words
bytesToWords: function(bytes) {
for (var words = [], i = 0, b = 0; i < bytes.length; i++, b += 8)
words[b >>> 5] |= bytes[i] << (24 - b % 32);
return words;
},
// Convert big-endian 32-bit words to a byte array
wordsToBytes: function(words) {
for (var bytes = [], b = 0; b < words.length * 32; b += 8)
bytes.push((words[b >>> 5] >>> (24 - b % 32)) & 0xFF);
return bytes;
},
// Convert a byte array to a hex string
bytesToHex: function(bytes) {
for (var hex = [], i = 0; i < bytes.length; i++) {
hex.push((bytes[i] >>> 4).toString(16));
hex.push((bytes[i] & 0xF).toString(16));
}
return hex.join('');
},
// Convert a hex string to a byte array
hexToBytes: function(hex) {
for (var bytes = [], c = 0; c < hex.length; c += 2)
bytes.push(parseInt(hex.substr(c, 2), 16));
return bytes;
},
// Convert a byte array to a base-64 string
bytesToBase64: function(bytes) {
for (var base64 = [], i = 0; i < bytes.length; i += 3) {
var triplet = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2];
for (var j = 0; j < 4; j++)
if (i * 8 + j * 6 <= bytes.length * 8)
base64.push(base64map.charAt((triplet >>> 6 * (3 - j)) & 0x3F));
else
base64.push('=');
}
return base64.join('');
},
// Convert a base-64 string to a byte array
base64ToBytes: function(base64) {
// Remove non-base-64 characters
base64 = base64.replace(/[^A-Z0-9+\/]/ig, '');
for (var bytes = [], i = 0, imod4 = 0; i < base64.length;
imod4 = ++i % 4) {
if (imod4 == 0) continue;
bytes.push(((base64map.indexOf(base64.charAt(i - 1))
& (Math.pow(2, -2 * imod4 + 8) - 1)) << (imod4 * 2))
| (base64map.indexOf(base64.charAt(i)) >>> (6 - imod4 * 2)));
}
return bytes;
}
};
module.exports = crypt;
})();
},{}],72:[function(require,module,exports){
(function (Buffer){
(function () {
"use strict";
function atob(str) {
return new Buffer(str, 'base64').toString('binary');
}
module.exports = atob;
}());
}).call(this,require("buffer").Buffer)
},{"buffer":76}],73:[function(require,module,exports){
(function (process,Buffer){
var crypto = require("crypto");
var BCRYPT_SALT_LEN = 16;
var GENSALT_DEFAULT_LOG2_ROUNDS = 10;
var BLOWFISH_NUM_ROUNDS = 16;
var MAX_EXECUTION_TIME = 100;
var P_orig = [0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822,
0x299f31d0, 0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377,
0xbe5466cf, 0x34e90c6c, 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5,
0xb5470917, 0x9216d5d9, 0x8979fb1b];
var S_orig = [0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed,
0x6a267e96, 0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7,
0x0801f2e2, 0x858efc16, 0x636920d8, 0x71574e69, 0xa458fea3,
0xf4933d7e, 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, 0xc5d1b023,
0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e,
0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda,
0x55605c60, 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, 0xa15486af,
0x7c72e993, 0xb3ee1411, 0x636fbc2a, 0x2ba9c55d, 0x741831f6,
0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, 0x7a325381,
0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d,
0xe98575b1, 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5,
0x0f6d6ff3, 0x83f44239, 0x2e0b4482, 0xa4842004, 0x69c8f04a,
0x9e1f9b5e, 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, 0x6eef0b6c,
0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176,
0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3,
0x3b8b5ebe, 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, 0x37d0d724,
0xd00a1248, 0xdb0fead3, 0x49f1c09b, 0x075372c9, 0x80991b7b,
0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b, 0x976ce0bd,
0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f,
0x9b30952c, 0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd,
0x660f2807, 0x192e4bb3, 0xc0cba857, 0x45c8740f, 0xd20b5f39,
0xb9d3fbdb, 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, 0x3c7516df,
0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760,
0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e,
0xdf1769db, 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98,
0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, 0x9a53e479, 0xb6f84565,
0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341,
0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0,
0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64,
0x8888b812, 0x900df01c, 0x4fad5ea0, 0x688fc31c, 0xd1cff191,
0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, 0xb4a84fe0,
0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705,
0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5,
0xfb9d35cf, 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, 0x2464369b,
0xf009b91e, 0x5563911d, 0x59dfa6aa, 0x78c14389, 0xd95a537f,
0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9, 0x11c81968,
0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5,
0x571be91f, 0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6,
0xff34052e, 0xc5855664, 0x53b02d5d, 0xa99f8fa1, 0x08ba4799,
0x6e85076a, 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, 0xecaa8c71,
0x699a17ff, 0x5664526c, 0xc2b19ee1, 0x193602a5, 0x75094c29,
0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65, 0x6b8fe4d6,
0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f,
0x3ebaefc9, 0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286,
0xb79c5305, 0xaa500737, 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec,
0x5716f2b8, 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, 0xd19113f9,
0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc,
0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e,
0xa4751e41, 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, 0x2cb81290,
0x24977c79, 0x5679b072, 0xbcaf89af, 0xde9a771f, 0xd9930810,
0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, 0x501adde6,
0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847,
0x3215d908, 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451,
0x50940002, 0x133ae4dd, 0x71dff89e, 0x10314e55, 0x81ac77d6,
0x5f11199b, 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, 0x86e34570,
0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa,
0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978,
0x9c10b36a, 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,
0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, 0x5223a708,
0xf71312b6, 0xebadfe6e, 0xeac31f66, 0xe3bc4595, 0xa67bc883,
0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5, 0x65582185,
0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830,
0xeb61bd96, 0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239,
0xd59e9e0b, 0xcbaade14, 0xeecc86bc, 0x60622ca7, 0x9cab5cab,
0xb2f3846e, 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, 0x9b540b19,
0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77,
0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1,
0x7858ba99, 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef,
0x34c6ffea, 0xfe28ed61, 0xee7c3c73, 0x5d4a14d9, 0xe864b7e3,
0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15,
0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2,
0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492,
0x47848a0b, 0x5692b285, 0x095bbf00, 0xad19489d, 0x1462b174,
0x23820e00, 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, 0x7cde3759,
0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e,
0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc,
0x800bcadc, 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340, 0xc5c43465,
0x713e38d8, 0x3d28f89e, 0xf16dff20, 0x153e21e7, 0x8fb03d4a,
0xe6e39f2b, 0xdb83adf7, 0xe93d5a68, 0x948140f7, 0xf64c261c,
0x94692934, 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, 0x1e39f62e,
0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af,
0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0,
0x31cb8504, 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, 0x68dc1462,
0xd7486900, 0x680ec0a4, 0x27a18dee, 0x4f3ffea2, 0xe887ad8c,
0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec, 0xce78a399,
0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74,
0xdd5b4332, 0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397,
0x454056ac, 0xba489527, 0x55533a3a, 0x20838d87, 0xfe6ba9b7,
0xd096954b, 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, 0xfdf8e802,
0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22,
0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4,
0x5d886e17, 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2,
0x02e1329e, 0xaf664fd1, 0xcad18115, 0x6b2395e0, 0x333e92e1,
0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, 0xde720c8c,
0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341,
0x992eff74, 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8,
0x991be14c, 0xdb6e6b0d, 0xc67b5510, 0x6d672c37, 0x2765d43b,
0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, 0xbb132f88,
0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979,
0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc,
0x782ef11c, 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, 0x44421659,
0x0a121386, 0xd90cec6e, 0xd5abea2a, 0x64af674e, 0xda86a85f,
0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086, 0x60787bf8,
0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be,
0xbde8ae24, 0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2,
0xf474ef38, 0x8789bdc2, 0x5366f9c3, 0xc8b38e74, 0xb475f255,
0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, 0xb90bace1,
0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09,
0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025,
0x1d6efe10, 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01,
0xa70683fa, 0xa002b5c4, 0x0de6d027, 0x9af88c27, 0x773f8641,
0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, 0x006058aa,
0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409,
0x4b7c0188, 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9,
0x1ac15bb4, 0xd39eb8fc, 0xed545578, 0x08fca5b5, 0xd83d7cd3,
0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, 0xd79a3234,
0x92638212, 0x670efa8e, 0x406000e0, 0x3a39ce37, 0xd3faf5cf,
0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742, 0xd3822740,
0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f,
0xbc946e79, 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d,
0xd5730a1d, 0x4cd04dc6, 0x2939bbdb, 0xa9ba4650, 0xac9526e8,
0xbe5ee304, 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, 0x83c061ba,
0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1,
0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69,
0x77fa0a59, 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a,
0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, 0x1f9f25cf, 0xadf2b89b,
0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6, 0x47b0acfd,
0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4,
0x88f46dba, 0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2,
0x97271aec, 0xa93a072a, 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb,
0x26dcf319, 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,
0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, 0x4de81751,
0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce,
0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369,
0x6413e680, 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd,
0x1b588d40, 0xccd2017f, 0x6bb4e3bb, 0xdda26a7e, 0x3a59ff45,
0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb, 0x8d6612ae,
0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08,
0x4eb4e2cc, 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d,
0x06b89fb4, 0xce6ea048, 0x6f3f3b82, 0x3520ab82, 0x011a1d4b,
0x277227f8, 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, 0xe01cc87e,
0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a,
0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c,
0xe0b12b4f, 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, 0xfae59361,
0xceb69ceb, 0xc2a86459, 0x12baa8d1, 0xb6c1075e, 0xe3056a0c,
0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be,
0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d,
0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891,
0xce6279cf, 0xcd3e7e6f, 0x1618b166, 0xfd2c1d05, 0x848fd2c5,
0xf6fb2299, 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,
0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, 0xde966292,
0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a,
0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2,
0x35bdd2f6, 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, 0xba38209c,
0xf746ce76, 0x77afa1c5, 0x20756060, 0x85cbfe4e, 0x8ae88dd8,
0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c, 0x01c36ae4,
0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6];
var bf_crypt_ciphertext = [0x4f727068, 0x65616e42, 0x65686f6c, 0x64657253,
0x63727944, 0x6f756274];
var base64_code = ['.', '/', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8',
'9'];
var index_64 = [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1,
54, 55, 56, 57, 58, 59, 60, 61, 62, 63, -1, -1, -1, -1, -1, -1, -1,
2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
21, 22, 23, 24, 25, 26, 27, -1, -1, -1, -1, -1, -1, 28, 29, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
49, 50, 51, 52, 53, -1, -1, -1, -1, -1];
function getByte(c) {
var ret = 0;
try {
var b = c.charCodeAt(0);
} catch (err) {
b = c;
}
if (b > 127) {
return -128 + (b % 128);
} else {
return b;
}
};
function encode_base64(d, len) {
var off = 0;
var rs = [];
var c1;
var c2;
if (len <= 0 || len > d.length)
throw "Invalid len";
while (off < len) {
c1 = d[off++] & 0xff;
rs.push(base64_code[(c1 >> 2) & 0x3f]);
c1 = (c1 & 0x03) << 4;
if (off >= len) {
rs.push(base64_code[c1 & 0x3f]);
break;
}
c2 = d[off++] & 0xff;
c1 |= (c2 >> 4) & 0x0f;
rs.push(base64_code[c1 & 0x3f]);
c1 = (c2 & 0x0f) << 2;
if (off >= len) {
rs.push(base64_code[c1 & 0x3f]);
break;
}
c2 = d[off++] & 0xff;
c1 |= (c2 >> 6) & 0x03;
rs.push(base64_code[c1 & 0x3f]);
rs.push(base64_code[c2 & 0x3f]);
}
return rs.join('');
};
function char64(x) {
var code = x.charCodeAt(0);
if (code < 0 || code > index_64.length) {
return -1;
}
return index_64[code];
};
function decode_base64(s, maxolen) {
var off = 0;
var slen = s.length;
var olen = 0;
var rs = [];
var c1, c2, c3, c4, o;
if (maxolen <= 0) throw "Invalid maxolen";
while (off < slen - 1 && olen < maxolen) {
c1 = char64(s.charAt(off++));
c2 = char64(s.charAt(off++));
if (c1 == -1 || c2 == -1) {
break;
}
o = getByte(c1 << 2);
o |= (c2 & 0x30) >> 4;
rs.push(String.fromCharCode(o));
if (++olen >= maxolen || off >= slen) {
break;
}
c3 = char64(s.charAt(off++));
if (c3 == -1) {
break;
}
o = getByte((c2 & 0x0f) << 4);
o |= (c3 & 0x3c) >> 2;
rs.push(String.fromCharCode(o));
if (++olen >= maxolen || off >= slen) {
break;
}
c4 = char64(s.charAt(off++));
o = getByte((c3 & 0x03) << 6);
o |= c4;
rs.push(String.fromCharCode(o));
++olen;
}
var ret = [];
for (off = 0; off < olen; off++) {
ret.push(getByte(rs[off]));
}
return ret;
};
function encipher(lr, off, P, S) {
var i;
var n;
var l = lr[off];
var r = lr[off + 1];
l ^= P[0];
for (i = 0; i <= BLOWFISH_NUM_ROUNDS - 2;) {
// Feistel substitution on left word
n = S[(l >> 24) & 0xff];
n += S[0x100 | ((l >> 16) & 0xff)];
n ^= S[0x200 | ((l >> 8) & 0xff)];
n += S[0x300 | (l & 0xff)];
r ^= n ^ P[++i];
// Feistel substitution on right word
n = S[(r >> 24) & 0xff];
n += S[0x100 | ((r >> 16) & 0xff)];
n ^= S[0x200 | ((r >> 8) & 0xff)];
n += S[0x300 | (r & 0xff)];
l ^= n ^ P[++i];
}
lr[off] = r ^ P[BLOWFISH_NUM_ROUNDS + 1];
lr[off + 1] = l;
return lr;
};
function streamtoword(data, offp) {
var i;
var word = 0;
for (i = 0; i < 4; i++) {
word = (word << 8) | (data[offp] & 0xff);
offp = (offp + 1) % data.length;
}
return {key:word, offp:offp};
};
function key(key, P, S) {
var i;
var offp = 0;
var lr = new Array(0x00000000, 0x00000000);
var plen = P.length;
var slen = S.length;
for (i = 0; i < plen; i++) {
var sw = streamtoword(key, offp);
offp = sw.offp;
P[i] = P[i] ^ sw.key;
}
for (i = 0; i < plen; i += 2) {
lr = encipher(lr, 0, P, S);
P[i] = lr[0];
P[i + 1] = lr[1];
}
for (i = 0; i < slen; i += 2) {
lr = encipher(lr, 0, P, S);
S[i] = lr[0];
S[i + 1] = lr[1];
}
};
function ekskey(data, key, P, S) {
var i;
var offp = 0;
var lr = new Array(0x00000000, 0x00000000);
var plen = P.length;
var slen = S.length;
var sw;
for (i = 0; i < plen; i++) {
sw = streamtoword(key, offp);
offp = sw.offp;
P[i] = P[i] ^ sw.key;
}
offp = 0;
for (i = 0; i < plen; i += 2) {
sw = streamtoword(data, offp);
offp = sw.offp;
lr[0] ^= sw.key;
sw = streamtoword(data, offp);
offp = sw.offp;
lr[1] ^= sw.key;
lr = encipher(lr, 0, P, S);
P[i] = lr[0];
P[i + 1] = lr[1];
}
for (i = 0; i < slen; i += 2) {
sw = streamtoword(data, offp);
offp = sw.offp;
lr[0] ^= sw.key;
sw = streamtoword(data, offp);
offp = sw.offp;
lr[1] ^= sw.key;
lr = encipher(lr, 0, P, S);
S[i] = lr[0];
S[i + 1] = lr[1];
}
};
function crypt_raw(password, salt, log_rounds, progress) {
var rounds;
var j;
var cdata = bf_crypt_ciphertext.slice();
var clen = cdata.length;
var one_percent;
if (log_rounds < 4 || log_rounds > 31)
throw "Bad number of rounds";
if (salt.length != BCRYPT_SALT_LEN)
throw "Bad salt length";
rounds = 1 << log_rounds;
one_percent = Math.floor(rounds / 100) + 1;
var P = P_orig.slice();
var S = S_orig.slice();
ekskey(salt, password, P, S);
var i = 0;
while(true) {
if(i < rounds){
var start = new Date();
for (; i < rounds;) {
i = i + 1;
key(password, P, S);
key(salt, P, S);
if(i % one_percent == 0){
progress();
}
if((new Date() - start) > MAX_EXECUTION_TIME){
break;
}
}
} else {
for (i = 0; i < 64; i++) {
for (j = 0; j < (clen >> 1); j++) {
lr = encipher(cdata, j << 1, P, S);
}
}
var ret = [];
for (i = 0; i < clen; i++) {
ret.push(getByte((cdata[i] >> 24) & 0xff));
ret.push(getByte((cdata[i] >> 16) & 0xff));
ret.push(getByte((cdata[i] >> 8) & 0xff));
ret.push(getByte(cdata[i] & 0xff));
}
return(ret);
}
}
};
function hashpw(password, salt, progress) {
var real_salt;
var passwordb = [];
var saltb = [];
var hashed = [];
var minor = String.fromCharCode(0);
var rounds = 0;
var off = 0;
if (!progress){
var progress = function() {};
}
if (salt.charAt(0) != '$' || salt.charAt(1) != '2')
throw "Invalid salt version";
if (salt.charAt(2) == '$')
off = 3;
else {
minor = salt.charAt(2);
if (minor != 'a' || salt.charAt(3) != '$')
throw "Invalid salt revision";
off = 4;
}
// Extract number of rounds
if (salt.charAt(off + 2) > '$')
throw "Missing salt rounds";
var r1 = parseInt(salt.substring(off, off + 1)) * 10;
var r2 = parseInt(salt.substring(off + 1, off + 2));
rounds = r1 + r2;
real_salt = salt.substring(off + 3, off + 25);
password = password + (minor >= 'a' ? "\000" : "");
var buf = new Buffer(password);
for (var r = 0; r < buf.length; r++) {
passwordb.push(buf[r]);
}
saltb = decode_base64(real_salt, BCRYPT_SALT_LEN);
var hashed = crypt_raw(passwordb, saltb, rounds, progress);
var rs = [];
rs.push("$2");
if (minor >= 'a')
rs.push(minor);
rs.push("$");
if (rounds < 10)
rs.push("0");
rs.push(rounds.toString());
rs.push("$");
rs.push(encode_base64(saltb, saltb.length));
rs.push(encode_base64(hashed, bf_crypt_ciphertext.length * 4 - 1));
return(rs.join(''));
};
function gensalt(rounds) {
var iteration_count = rounds;
if (iteration_count < 4 || iteration_count > 31) {
iteration_count = GENSALT_DEFAULT_LOG2_ROUNDS;
}
var output = [];
output.push("$2a$");
if (iteration_count < 10)
output.push("0");
output.push(iteration_count.toString());
output.push('$');
var rand_buf;
try {
rand_buf = crypto.randomBytes(BCRYPT_SALT_LEN);
} catch (ex) {
throw ex;
}
output.push(encode_base64(rand_buf, BCRYPT_SALT_LEN));
return output.join('');
};
function genSaltSync(rounds) {
/*
rounds - [OPTIONAL] - the number of rounds to process the data for. (default - 10)
seed_length - [OPTIONAL] - RAND_bytes wants a length. to make that a bit flexible, you can specify a seed_length. (default - 20)
*/
if(!rounds) {
rounds = GENSALT_DEFAULT_LOG2_ROUNDS;
}
return gensalt(rounds);
}
function genSalt(rounds, callback) {
/*
rounds - [OPTIONAL] - the number of rounds to process the data for. (default - 10)
seed_length - [OPTIONAL] - RAND_bytes wants a length. to make that a bit flexible, you can specify a seed_length. (default - 20)
callback - [REQUIRED] - a callback to be fired once the salt has been generated. uses eio making it asynchronous.
error - First parameter to the callback detailing any errors.
salt - Second parameter to the callback providing the generated salt.
*/
if(!callback) {
throw "No callback function was given."
}
process.nextTick(function() {
var result = null;
var error = null;
try {
result = genSaltSync(rounds)
} catch(err) {
error = err;
}
callback(error, result);
});
}
function hashSync(data, salt, progress) {
/*
data - [REQUIRED] - the data to be encrypted.
salt - [REQUIRED] - the salt to be used in encryption.
*/
if(!salt) {
salt = genSaltSync();
}
return hashpw(data, salt, progress);
}
function hash(data, salt, progress, callback) {
/*
data - [REQUIRED] - the data to be encrypted.
salt - [REQUIRED] - the salt to be used to hash the password. if specified as a number then a salt will be generated and used (see examples).
progress - a callback to be called during the hash calculation to signify progress
callback - [REQUIRED] - a callback to be fired once the data has been encrypted. uses eio making it asynchronous.
error - First parameter to the callback detailing any errors.
encrypted - Second parameter to the callback providing the encrypted form.
*/
if(!callback) {
throw "No callback function was given."
}
process.nextTick(function() {
var result = null;
var error = null;
try {
result = hashSync(data, salt, progress)
} catch(err) {
error = err;
}
callback(error, result);
});
}
function compareSync(data, encrypted) {
/*
data - [REQUIRED] - data to compare.
encrypted - [REQUIRED] - data to be compared to.
*/
if(typeof data != "string" || typeof encrypted != "string") {
throw "Incorrect arguments";
}
var encrypted_length = encrypted.length;
if(encrypted_length != 60) {
throw "Not a valid BCrypt hash.";
}
var same = true;
var hash_data = hashSync(data, encrypted.substr(0, encrypted_length-31));
var hash_data_length = hash_data.length;
same = hash_data_length == encrypted_length;
var max_length = (hash_data_length < encrypted_length) ? hash_data_length : encrypted_length;
// to prevent timing attacks, should check entire string
// don't exit after found to be false
for (var i = 0; i < max_length; ++i) {
if (hash_data_length >= i && encrypted_length >= i && hash_data[i] != encrypted[i]) {
same = false;
}
}
return same;
}
function compare(data, encrypted, callback) {
/*
data - [REQUIRED] - data to compare.
encrypted - [REQUIRED] - data to be compared to.
callback - [REQUIRED] - a callback to be fired once the data has been compared. uses eio making it asynchronous.
error - First parameter to the callback detailing any errors.
same - Second parameter to the callback providing whether the data and encrypted forms match [true | false].
*/
if(!callback) {
throw "No callback function was given."
}
process.nextTick(function() {
var result = null;
var error = null;
try {
result = compareSync(data, encrypted)
} catch(err) {
error = err;
}
callback(error, result);
});
}
function getRounds(encrypted) {
//encrypted - [REQUIRED] - hash from which the number of rounds used should be extracted.
if(typeof encrypted != "string") {
throw "Incorrect arguments";
}
return Number(encrypted.split("$")[2]);
}
exports.genSaltSync = genSaltSync;
exports.genSalt = genSalt;
exports.hashSync = hashSync;
exports.hash = hash;
exports.compareSync = compareSync;
exports.compare = compare;
exports.getRounds = getRounds;
}).call(this,require('_process'),require("buffer").Buffer)
},{"_process":225,"buffer":76,"crypto":80}],74:[function(require,module,exports){
//this file was generated
"use strict"
var mime = module.exports = {
lookup: function (path, fallback) {
var ext = path.replace(/.*[\.\/]/, '').toLowerCase();
return this.types[ext] || fallback || this.default_type;
}
, default_type: "application/octet-stream"
, types: {
"123": "application/vnd.lotus-1-2-3",
"ez": "application/andrew-inset",
"aw": "application/applixware",
"atom": "application/atom+xml",
"atomcat": "application/atomcat+xml",
"atomsvc": "application/atomsvc+xml",
"ccxml": "application/ccxml+xml",
"cdmia": "application/cdmi-capability",
"cdmic": "application/cdmi-container",
"cdmid": "application/cdmi-domain",
"cdmio": "application/cdmi-object",
"cdmiq": "application/cdmi-queue",
"cu": "application/cu-seeme",
"davmount": "application/davmount+xml",
"dbk": "application/docbook+xml",
"dssc": "application/dssc+der",
"xdssc": "application/dssc+xml",
"ecma": "application/ecmascript",
"emma": "application/emma+xml",
"epub": "application/epub+zip",
"exi": "application/exi",
"pfr": "application/font-tdpfr",
"gml": "application/gml+xml",
"gpx": "application/gpx+xml",
"gxf": "application/gxf",
"stk": "application/hyperstudio",
"ink": "application/inkml+xml",
"inkml": "application/inkml+xml",
"ipfix": "application/ipfix",
"jar": "application/java-archive",
"ser": "application/java-serialized-object",
"class": "application/java-vm",
"js": "application/javascript",
"json": "application/json",
"jsonml": "application/jsonml+json",
"lostxml": "application/lost+xml",
"hqx": "application/mac-binhex40",
"cpt": "application/mac-compactpro",
"mads": "application/mads+xml",
"mrc": "application/marc",
"mrcx": "application/marcxml+xml",
"ma": "application/mathematica",
"nb": "application/mathematica",
"mb": "application/mathematica",
"mathml": "application/mathml+xml",
"mbox": "application/mbox",
"mscml": "application/mediaservercontrol+xml",
"metalink": "application/metalink+xml",
"meta4": "application/metalink4+xml",
"mets": "application/mets+xml",
"mods": "application/mods+xml",
"m21": "application/mp21",
"mp21": "application/mp21",
"mp4s": "application/mp4",
"doc": "application/msword",
"dot": "application/msword",
"mxf": "application/mxf",
"bin": "application/octet-stream",
"dms": "application/octet-stream",
"lrf": "application/octet-stream",
"mar": "application/octet-stream",
"so": "application/octet-stream",
"dist": "application/octet-stream",
"distz": "application/octet-stream",
"pkg": "application/octet-stream",
"bpk": "application/octet-stream",
"dump": "application/octet-stream",
"elc": "application/octet-stream",
"deploy": "application/octet-stream",
"oda": "application/oda",
"opf": "application/oebps-package+xml",
"ogx": "application/ogg",
"omdoc": "application/omdoc+xml",
"onetoc": "application/onenote",
"onetoc2": "application/onenote",
"onetmp": "application/onenote",
"onepkg": "application/onenote",
"oxps": "application/oxps",
"xer": "application/patch-ops-error+xml",
"pdf": "application/pdf",
"pgp": "application/pgp-encrypted",
"asc": "application/pgp-signature",
"sig": "application/pgp-signature",
"prf": "application/pics-rules",
"p10": "application/pkcs10",
"p7m": "application/pkcs7-mime",
"p7c": "application/pkcs7-mime",
"p7s": "application/pkcs7-signature",
"p8": "application/pkcs8",
"ac": "application/pkix-attr-cert",
"cer": "application/pkix-cert",
"crl": "application/pkix-crl",
"pkipath": "application/pkix-pkipath",
"pki": "application/pkixcmp",
"pls": "application/pls+xml",
"ai": "application/postscript",
"eps": "application/postscript",
"ps": "application/postscript",
"cww": "application/prs.cww",
"pskcxml": "application/pskc+xml",
"rdf": "application/rdf+xml",
"rif": "application/reginfo+xml",
"rnc": "application/relax-ng-compact-syntax",
"rl": "application/resource-lists+xml",
"rld": "application/resource-lists-diff+xml",
"rs": "application/rls-services+xml",
"gbr": "application/rpki-ghostbusters",
"mft": "application/rpki-manifest",
"roa": "application/rpki-roa",
"rsd": "application/rsd+xml",
"rss": "application/rss+xml",
"rtf": "application/rtf",
"sbml": "application/sbml+xml",
"scq": "application/scvp-cv-request",
"scs": "application/scvp-cv-response",
"spq": "application/scvp-vp-request",
"spp": "application/scvp-vp-response",
"sdp": "application/sdp",
"setpay": "application/set-payment-initiation",
"setreg": "application/set-registration-initiation",
"shf": "application/shf+xml",
"smi": "application/smil+xml",
"smil": "application/smil+xml",
"rq": "application/sparql-query",
"srx": "application/sparql-results+xml",
"gram": "application/srgs",
"grxml": "application/srgs+xml",
"sru": "application/sru+xml",
"ssdl": "application/ssdl+xml",
"ssml": "application/ssml+xml",
"tei": "application/tei+xml",
"teicorpus": "application/tei+xml",
"tfi": "application/thraud+xml",
"tsd": "application/timestamped-data",
"plb": "application/vnd.3gpp.pic-bw-large",
"psb": "application/vnd.3gpp.pic-bw-small",
"pvb": "application/vnd.3gpp.pic-bw-var",
"tcap": "application/vnd.3gpp2.tcap",
"pwn": "application/vnd.3m.post-it-notes",
"aso": "application/vnd.accpac.simply.aso",
"imp": "application/vnd.accpac.simply.imp",
"acu": "application/vnd.acucobol",
"atc": "application/vnd.acucorp",
"acutc": "application/vnd.acucorp",
"air": "application/vnd.adobe.air-application-installer-package+zip",
"fcdt": "application/vnd.adobe.formscentral.fcdt",
"fxp": "application/vnd.adobe.fxp",
"fxpl": "application/vnd.adobe.fxp",
"xdp": "application/vnd.adobe.xdp+xml",
"xfdf": "application/vnd.adobe.xfdf",
"ahead": "application/vnd.ahead.space",
"azf": "application/vnd.airzip.filesecure.azf",
"azs": "application/vnd.airzip.filesecure.azs",
"azw": "application/vnd.amazon.ebook",
"acc": "application/vnd.americandynamics.acc",
"ami": "application/vnd.amiga.ami",
"apk": "application/vnd.android.package-archive",
"cii": "application/vnd.anser-web-certificate-issue-initiation",
"fti": "application/vnd.anser-web-funds-transfer-initiation",
"atx": "application/vnd.antix.game-component",
"mpkg": "application/vnd.apple.installer+xml",
"m3u8": "application/vnd.apple.mpegurl",
"swi": "application/vnd.aristanetworks.swi",
"iota": "application/vnd.astraea-software.iota",
"aep": "application/vnd.audiograph",
"mpm": "application/vnd.blueice.multipass",
"bmi": "application/vnd.bmi",
"rep": "application/vnd.businessobjects",
"cdxml": "application/vnd.chemdraw+xml",
"mmd": "application/vnd.chipnuts.karaoke-mmd",
"cdy": "application/vnd.cinderella",
"cla": "application/vnd.claymore",
"rp9": "application/vnd.cloanto.rp9",
"c4g": "application/vnd.clonk.c4group",
"c4d": "application/vnd.clonk.c4group",
"c4f": "application/vnd.clonk.c4group",
"c4p": "application/vnd.clonk.c4group",
"c4u": "application/vnd.clonk.c4group",
"c11amc": "application/vnd.cluetrust.cartomobile-config",
"c11amz": "application/vnd.cluetrust.cartomobile-config-pkg",
"csp": "application/vnd.commonspace",
"cdbcmsg": "application/vnd.contact.cmsg",
"cmc": "application/vnd.cosmocaller",
"clkx": "application/vnd.crick.clicker",
"clkk": "application/vnd.crick.clicker.keyboard",
"clkp": "application/vnd.crick.clicker.palette",
"clkt": "application/vnd.crick.clicker.template",
"clkw": "application/vnd.crick.clicker.wordbank",
"wbs": "application/vnd.criticaltools.wbs+xml",
"pml": "application/vnd.ctc-posml",
"ppd": "application/vnd.cups-ppd",
"car": "application/vnd.curl.car",
"pcurl": "application/vnd.curl.pcurl",
"dart": "application/vnd.dart",
"rdz": "application/vnd.data-vision.rdz",
"uvf": "application/vnd.dece.data",
"uvvf": "application/vnd.dece.data",
"uvd": "application/vnd.dece.data",
"uvvd": "application/vnd.dece.data",
"uvt": "application/vnd.dece.ttml+xml",
"uvvt": "application/vnd.dece.ttml+xml",
"uvx": "application/vnd.dece.unspecified",
"uvvx": "application/vnd.dece.unspecified",
"uvz": "application/vnd.dece.zip",
"uvvz": "application/vnd.dece.zip",
"fe_launch": "application/vnd.denovo.fcselayout-link",
"dna": "application/vnd.dna",
"mlp": "application/vnd.dolby.mlp",
"dpg": "application/vnd.dpgraph",
"dfac": "application/vnd.dreamfactory",
"kpxx": "application/vnd.ds-keypoint",
"ait": "application/vnd.dvb.ait",
"svc": "application/vnd.dvb.service",
"geo": "application/vnd.dynageo",
"mag": "application/vnd.ecowin.chart",
"nml": "application/vnd.enliven",
"esf": "application/vnd.epson.esf",
"msf": "application/vnd.epson.msf",
"qam": "application/vnd.epson.quickanime",
"slt": "application/vnd.epson.salt",
"ssf": "application/vnd.epson.ssf",
"es3": "application/vnd.eszigno3+xml",
"et3": "application/vnd.eszigno3+xml",
"ez2": "application/vnd.ezpix-album",
"ez3": "application/vnd.ezpix-package",
"fdf": "application/vnd.fdf",
"mseed": "application/vnd.fdsn.mseed",
"seed": "application/vnd.fdsn.seed",
"dataless": "application/vnd.fdsn.seed",
"gph": "application/vnd.flographit",
"ftc": "application/vnd.fluxtime.clip",
"fm": "application/vnd.framemaker",
"frame": "application/vnd.framemaker",
"maker": "application/vnd.framemaker",
"book": "application/vnd.framemaker",
"fnc": "application/vnd.frogans.fnc",
"ltf": "application/vnd.frogans.ltf",
"fsc": "application/vnd.fsc.weblaunch",
"oas": "application/vnd.fujitsu.oasys",
"oa2": "application/vnd.fujitsu.oasys2",
"oa3": "application/vnd.fujitsu.oasys3",
"fg5": "application/vnd.fujitsu.oasysgp",
"bh2": "application/vnd.fujitsu.oasysprs",
"ddd": "application/vnd.fujixerox.ddd",
"xdw": "application/vnd.fujixerox.docuworks",
"xbd": "application/vnd.fujixerox.docuworks.binder",
"fzs": "application/vnd.fuzzysheet",
"txd": "application/vnd.genomatix.tuxedo",
"ggb": "application/vnd.geogebra.file",
"ggt": "application/vnd.geogebra.tool",
"gex": "application/vnd.geometry-explorer",
"gre": "application/vnd.geometry-explorer",
"gxt": "application/vnd.geonext",
"g2w": "application/vnd.geoplan",
"g3w": "application/vnd.geospace",
"gmx": "application/vnd.gmx",
"kml": "application/vnd.google-earth.kml+xml",
"kmz": "application/vnd.google-earth.kmz",
"gqf": "application/vnd.grafeq",
"gqs": "application/vnd.grafeq",
"gac": "application/vnd.groove-account",
"ghf": "application/vnd.groove-help",
"gim": "application/vnd.groove-identity-message",
"grv": "application/vnd.groove-injector",
"gtm": "application/vnd.groove-tool-message",
"tpl": "application/vnd.groove-tool-template",
"vcg": "application/vnd.groove-vcard",
"hal": "application/vnd.hal+xml",
"zmm": "application/vnd.handheld-entertainment+xml",
"hbci": "application/vnd.hbci",
"les": "application/vnd.hhe.lesson-player",
"hpgl": "application/vnd.hp-hpgl",
"hpid": "application/vnd.hp-hpid",
"hps": "application/vnd.hp-hps",
"jlt": "application/vnd.hp-jlyt",
"pcl": "application/vnd.hp-pcl",
"pclxl": "application/vnd.hp-pclxl",
"sfd-hdstx": "application/vnd.hydrostatix.sof-data",
"mpy": "application/vnd.ibm.minipay",
"afp": "application/vnd.ibm.modcap",
"listafp": "application/vnd.ibm.modcap",
"list3820": "application/vnd.ibm.modcap",
"irm": "application/vnd.ibm.rights-management",
"sc": "application/vnd.ibm.secure-container",
"icc": "application/vnd.iccprofile",
"icm": "application/vnd.iccprofile",
"igl": "application/vnd.igloader",
"ivp": "application/vnd.immervision-ivp",
"ivu": "application/vnd.immervision-ivu",
"igm": "application/vnd.insors.igm",
"xpw": "application/vnd.intercon.formnet",
"xpx": "application/vnd.intercon.formnet",
"i2g": "application/vnd.intergeo",
"qbo": "application/vnd.intu.qbo",
"qfx": "application/vnd.intu.qfx",
"rcprofile": "application/vnd.ipunplugged.rcprofile",
"irp": "application/vnd.irepository.package+xml",
"xpr": "application/vnd.is-xpr",
"fcs": "application/vnd.isac.fcs",
"jam": "application/vnd.jam",
"rms": "application/vnd.jcp.javame.midlet-rms",
"jisp": "application/vnd.jisp",
"joda": "application/vnd.joost.joda-archive",
"ktz": "application/vnd.kahootz",
"ktr": "application/vnd.kahootz",
"karbon": "application/vnd.kde.karbon",
"chrt": "application/vnd.kde.kchart",
"kfo": "application/vnd.kde.kformula",
"flw": "application/vnd.kde.kivio",
"kon": "application/vnd.kde.kontour",
"kpr": "application/vnd.kde.kpresenter",
"kpt": "application/vnd.kde.kpresenter",
"ksp": "application/vnd.kde.kspread",
"kwd": "application/vnd.kde.kword",
"kwt": "application/vnd.kde.kword",
"htke": "application/vnd.kenameaapp",
"kia": "application/vnd.kidspiration",
"kne": "application/vnd.kinar",
"knp": "application/vnd.kinar",
"skp": "application/vnd.koan",
"skd": "application/vnd.koan",
"skt": "application/vnd.koan",
"skm": "application/vnd.koan",
"sse": "application/vnd.kodak-descriptor",
"lasxml": "application/vnd.las.las+xml",
"lbd": "application/vnd.llamagraphics.life-balance.desktop",
"lbe": "application/vnd.llamagraphics.life-balance.exchange+xml",
"apr": "application/vnd.lotus-approach",
"pre": "application/vnd.lotus-freelance",
"nsf": "application/vnd.lotus-notes",
"org": "application/vnd.lotus-organizer",
"scm": "application/vnd.lotus-screencam",
"lwp": "application/vnd.lotus-wordpro",
"portpkg": "application/vnd.macports.portpkg",
"mcd": "application/vnd.mcd",
"mc1": "application/vnd.medcalcdata",
"cdkey": "application/vnd.mediastation.cdkey",
"mwf": "application/vnd.mfer",
"mfm": "application/vnd.mfmp",
"flo": "application/vnd.micrografx.flo",
"igx": "application/vnd.micrografx.igx",
"mif": "application/vnd.mif",
"daf": "application/vnd.mobius.daf",
"dis": "application/vnd.mobius.dis",
"mbk": "application/vnd.mobius.mbk",
"mqy": "application/vnd.mobius.mqy",
"msl": "application/vnd.mobius.msl",
"plc": "application/vnd.mobius.plc",
"txf": "application/vnd.mobius.txf",
"mpn": "application/vnd.mophun.application",
"mpc": "application/vnd.mophun.certificate",
"xul": "application/vnd.mozilla.xul+xml",
"cil": "application/vnd.ms-artgalry",
"cab": "application/vnd.ms-cab-compressed",
"xls": "application/vnd.ms-excel",
"xlm": "application/vnd.ms-excel",
"xla": "application/vnd.ms-excel",
"xlc": "application/vnd.ms-excel",
"xlt": "application/vnd.ms-excel",
"xlw": "application/vnd.ms-excel",
"xlam": "application/vnd.ms-excel.addin.macroenabled.12",
"xlsb": "application/vnd.ms-excel.sheet.binary.macroenabled.12",
"xlsm": "application/vnd.ms-excel.sheet.macroenabled.12",
"xltm": "application/vnd.ms-excel.template.macroenabled.12",
"eot": "application/vnd.ms-fontobject",
"chm": "application/vnd.ms-htmlhelp",
"ims": "application/vnd.ms-ims",
"lrm": "application/vnd.ms-lrm",
"thmx": "application/vnd.ms-officetheme",
"cat": "application/vnd.ms-pki.seccat",
"stl": "application/vnd.ms-pki.stl",
"ppt": "application/vnd.ms-powerpoint",
"pps": "application/vnd.ms-powerpoint",
"pot": "application/vnd.ms-powerpoint",
"ppam": "application/vnd.ms-powerpoint.addin.macroenabled.12",
"pptm": "application/vnd.ms-powerpoint.presentation.macroenabled.12",
"sldm": "application/vnd.ms-powerpoint.slide.macroenabled.12",
"ppsm": "application/vnd.ms-powerpoint.slideshow.macroenabled.12",
"potm": "application/vnd.ms-powerpoint.template.macroenabled.12",
"mpp": "application/vnd.ms-project",
"mpt": "application/vnd.ms-project",
"docm": "application/vnd.ms-word.document.macroenabled.12",
"dotm": "application/vnd.ms-word.template.macroenabled.12",
"wps": "application/vnd.ms-works",
"wks": "application/vnd.ms-works",
"wcm": "application/vnd.ms-works",
"wdb": "application/vnd.ms-works",
"wpl": "application/vnd.ms-wpl",
"xps": "application/vnd.ms-xpsdocument",
"mseq": "application/vnd.mseq",
"mus": "application/vnd.musician",
"msty": "application/vnd.muvee.style",
"taglet": "application/vnd.mynfc",
"nlu": "application/vnd.neurolanguage.nlu",
"ntf": "application/vnd.nitf",
"nitf": "application/vnd.nitf",
"nnd": "application/vnd.noblenet-directory",
"nns": "application/vnd.noblenet-sealer",
"nnw": "application/vnd.noblenet-web",
"ngdat": "application/vnd.nokia.n-gage.data",
"n-gage": "application/vnd.nokia.n-gage.symbian.install",
"rpst": "application/vnd.nokia.radio-preset",
"rpss": "application/vnd.nokia.radio-presets",
"edm": "application/vnd.novadigm.edm",
"edx": "application/vnd.novadigm.edx",
"ext": "application/vnd.novadigm.ext",
"odc": "application/vnd.oasis.opendocument.chart",
"otc": "application/vnd.oasis.opendocument.chart-template",
"odb": "application/vnd.oasis.opendocument.database",
"odf": "application/vnd.oasis.opendocument.formula",
"odft": "application/vnd.oasis.opendocument.formula-template",
"odg": "application/vnd.oasis.opendocument.graphics",
"otg": "application/vnd.oasis.opendocument.graphics-template",
"odi": "application/vnd.oasis.opendocument.image",
"oti": "application/vnd.oasis.opendocument.image-template",
"odp": "application/vnd.oasis.opendocument.presentation",
"otp": "application/vnd.oasis.opendocument.presentation-template",
"ods": "application/vnd.oasis.opendocument.spreadsheet",
"ots": "application/vnd.oasis.opendocument.spreadsheet-template",
"odt": "application/vnd.oasis.opendocument.text",
"odm": "application/vnd.oasis.opendocument.text-master",
"ott": "application/vnd.oasis.opendocument.text-template",
"oth": "application/vnd.oasis.opendocument.text-web",
"xo": "application/vnd.olpc-sugar",
"dd2": "application/vnd.oma.dd2+xml",
"oxt": "application/vnd.openofficeorg.extension",
"pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
"sldx": "application/vnd.openxmlformats-officedocument.presentationml.slide",
"ppsx": "application/vnd.openxmlformats-officedocument.presentationml.slideshow",
"potx": "application/vnd.openxmlformats-officedocument.presentationml.template",
"xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"xltx": "application/vnd.openxmlformats-officedocument.spreadsheetml.template",
"docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"dotx": "application/vnd.openxmlformats-officedocument.wordprocessingml.template",
"mgp": "application/vnd.osgeo.mapguide.package",
"dp": "application/vnd.osgi.dp",
"esa": "application/vnd.osgi.subsystem",
"pdb": "application/vnd.palm",
"pqa": "application/vnd.palm",
"oprc": "application/vnd.palm",
"paw": "application/vnd.pawaafile",
"str": "application/vnd.pg.format",
"ei6": "application/vnd.pg.osasli",
"efif": "application/vnd.picsel",
"wg": "application/vnd.pmi.widget",
"plf": "application/vnd.pocketlearn",
"pbd": "application/vnd.powerbuilder6",
"box": "application/vnd.previewsystems.box",
"mgz": "application/vnd.proteus.magazine",
"qps": "application/vnd.publishare-delta-tree",
"ptid": "application/vnd.pvi.ptid1",
"qxd": "application/vnd.quark.quarkxpress",
"qxt": "application/vnd.quark.quarkxpress",
"qwd": "application/vnd.quark.quarkxpress",
"qwt": "application/vnd.quark.quarkxpress",
"qxl": "application/vnd.quark.quarkxpress",
"qxb": "application/vnd.quark.quarkxpress",
"bed": "application/vnd.realvnc.bed",
"mxl": "application/vnd.recordare.musicxml",
"musicxml": "application/vnd.recordare.musicxml+xml",
"cryptonote": "application/vnd.rig.cryptonote",
"cod": "application/vnd.rim.cod",
"rm": "application/vnd.rn-realmedia",
"rmvb": "application/vnd.rn-realmedia-vbr",
"link66": "application/vnd.route66.link66+xml",
"st": "application/vnd.sailingtracker.track",
"see": "application/vnd.seemail",
"sema": "application/vnd.sema",
"semd": "application/vnd.semd",
"semf": "application/vnd.semf",
"ifm": "application/vnd.shana.informed.formdata",
"itp": "application/vnd.shana.informed.formtemplate",
"iif": "application/vnd.shana.informed.interchange",
"ipk": "application/vnd.shana.informed.package",
"twd": "application/vnd.simtech-mindmapper",
"twds": "application/vnd.simtech-mindmapper",
"mmf": "application/vnd.smaf",
"teacher": "application/vnd.smart.teacher",
"sdkm": "application/vnd.solent.sdkm+xml",
"sdkd": "application/vnd.solent.sdkm+xml",
"dxp": "application/vnd.spotfire.dxp",
"sfs": "application/vnd.spotfire.sfs",
"sdc": "application/vnd.stardivision.calc",
"sda": "application/vnd.stardivision.draw",
"sdd": "application/vnd.stardivision.impress",
"smf": "application/vnd.stardivision.math",
"sdw": "application/vnd.stardivision.writer",
"vor": "application/vnd.stardivision.writer",
"sgl": "application/vnd.stardivision.writer-global",
"smzip": "application/vnd.stepmania.package",
"sm": "application/vnd.stepmania.stepchart",
"sxc": "application/vnd.sun.xml.calc",
"stc": "application/vnd.sun.xml.calc.template",
"sxd": "application/vnd.sun.xml.draw",
"std": "application/vnd.sun.xml.draw.template",
"sxi": "application/vnd.sun.xml.impress",
"sti": "application/vnd.sun.xml.impress.template",
"sxm": "application/vnd.sun.xml.math",
"sxw": "application/vnd.sun.xml.writer",
"sxg": "application/vnd.sun.xml.writer.global",
"stw": "application/vnd.sun.xml.writer.template",
"sus": "application/vnd.sus-calendar",
"susp": "application/vnd.sus-calendar",
"svd": "application/vnd.svd",
"sis": "application/vnd.symbian.install",
"sisx": "application/vnd.symbian.install",
"xsm": "application/vnd.syncml+xml",
"bdm": "application/vnd.syncml.dm+wbxml",
"xdm": "application/vnd.syncml.dm+xml",
"tao": "application/vnd.tao.intent-module-archive",
"pcap": "application/vnd.tcpdump.pcap",
"cap": "application/vnd.tcpdump.pcap",
"dmp": "application/vnd.tcpdump.pcap",
"tmo": "application/vnd.tmobile-livetv",
"tpt": "application/vnd.trid.tpt",
"mxs": "application/vnd.triscape.mxs",
"tra": "application/vnd.trueapp",
"ufd": "application/vnd.ufdl",
"ufdl": "application/vnd.ufdl",
"utz": "application/vnd.uiq.theme",
"umj": "application/vnd.umajin",
"unityweb": "application/vnd.unity",
"uoml": "application/vnd.uoml+xml",
"vcx": "application/vnd.vcx",
"vsd": "application/vnd.visio",
"vst": "application/vnd.visio",
"vss": "application/vnd.visio",
"vsw": "application/vnd.visio",
"vis": "application/vnd.visionary",
"vsf": "application/vnd.vsf",
"wbxml": "application/vnd.wap.wbxml",
"wmlc": "application/vnd.wap.wmlc",
"wmlsc": "application/vnd.wap.wmlscriptc",
"wtb": "application/vnd.webturbo",
"nbp": "application/vnd.wolfram.player",
"wpd": "application/vnd.wordperfect",
"wqd": "application/vnd.wqd",
"stf": "application/vnd.wt.stf",
"xar": "application/vnd.xara",
"xfdl": "application/vnd.xfdl",
"hvd": "application/vnd.yamaha.hv-dic",
"hvs": "application/vnd.yamaha.hv-script",
"hvp": "application/vnd.yamaha.hv-voice",
"osf": "application/vnd.yamaha.openscoreformat",
"osfpvg": "application/vnd.yamaha.openscoreformat.osfpvg+xml",
"saf": "application/vnd.yamaha.smaf-audio",
"spf": "application/vnd.yamaha.smaf-phrase",
"cmp": "application/vnd.yellowriver-custom-menu",
"zir": "application/vnd.zul",
"zirz": "application/vnd.zul",
"zaz": "application/vnd.zzazz.deck+xml",
"vxml": "application/voicexml+xml",
"wgt": "application/widget",
"hlp": "application/winhlp",
"wsdl": "application/wsdl+xml",
"wspolicy": "application/wspolicy+xml",
"7z": "application/x-7z-compressed",
"abw": "application/x-abiword",
"ace": "application/x-ace-compressed",
"dmg": "application/x-apple-diskimage",
"aab": "application/x-authorware-bin",
"x32": "application/x-authorware-bin",
"u32": "application/x-authorware-bin",
"vox": "application/x-authorware-bin",
"aam": "application/x-authorware-map",
"aas": "application/x-authorware-seg",
"bcpio": "application/x-bcpio",
"torrent": "application/x-bittorrent",
"blb": "application/x-blorb",
"blorb": "application/x-blorb",
"bz": "application/x-bzip",
"bz2": "application/x-bzip2",
"boz": "application/x-bzip2",
"cbr": "application/x-cbr",
"cba": "application/x-cbr",
"cbt": "application/x-cbr",
"cbz": "application/x-cbr",
"cb7": "application/x-cbr",
"vcd": "application/x-cdlink",
"cfs": "application/x-cfs-compressed",
"chat": "application/x-chat",
"pgn": "application/x-chess-pgn",
"nsc": "application/x-conference",
"cpio": "application/x-cpio",
"csh": "application/x-csh",
"deb": "application/x-debian-package",
"udeb": "application/x-debian-package",
"dgc": "application/x-dgc-compressed",
"dir": "application/x-director",
"dcr": "application/x-director",
"dxr": "application/x-director",
"cst": "application/x-director",
"cct": "application/x-director",
"cxt": "application/x-director",
"w3d": "application/x-director",
"fgd": "application/x-director",
"swa": "application/x-director",
"wad": "application/x-doom",
"ncx": "application/x-dtbncx+xml",
"dtb": "application/x-dtbook+xml",
"res": "application/x-dtbresource+xml",
"dvi": "application/x-dvi",
"evy": "application/x-envoy",
"eva": "application/x-eva",
"bdf": "application/x-font-bdf",
"gsf": "application/x-font-ghostscript",
"psf": "application/x-font-linux-psf",
"otf": "application/x-font-otf",
"pcf": "application/x-font-pcf",
"snf": "application/x-font-snf",
"ttf": "application/x-font-ttf",
"ttc": "application/x-font-ttf",
"pfa": "application/x-font-type1",
"pfb": "application/x-font-type1",
"pfm": "application/x-font-type1",
"afm": "application/x-font-type1",
"woff": "application/x-font-woff",
"arc": "application/x-freearc",
"spl": "application/x-futuresplash",
"gca": "application/x-gca-compressed",
"ulx": "application/x-glulx",
"gnumeric": "application/x-gnumeric",
"gramps": "application/x-gramps-xml",
"gtar": "application/x-gtar",
"hdf": "application/x-hdf",
"install": "application/x-install-instructions",
"iso": "application/x-iso9660-image",
"jnlp": "application/x-java-jnlp-file",
"latex": "application/x-latex",
"lzh": "application/x-lzh-compressed",
"lha": "application/x-lzh-compressed",
"mie": "application/x-mie",
"prc": "application/x-mobipocket-ebook",
"mobi": "application/x-mobipocket-ebook",
"application": "application/x-ms-application",
"lnk": "application/x-ms-shortcut",
"wmd": "application/x-ms-wmd",
"wmz": "application/x-msmetafile",
"xbap": "application/x-ms-xbap",
"mdb": "application/x-msaccess",
"obd": "application/x-msbinder",
"crd": "application/x-mscardfile",
"clp": "application/x-msclip",
"exe": "application/x-msdownload",
"dll": "application/x-msdownload",
"com": "application/x-msdownload",
"bat": "application/x-msdownload",
"msi": "application/x-msdownload",
"mvb": "application/x-msmediaview",
"m13": "application/x-msmediaview",
"m14": "application/x-msmediaview",
"wmf": "application/x-msmetafile",
"emf": "application/x-msmetafile",
"emz": "application/x-msmetafile",
"mny": "application/x-msmoney",
"pub": "application/x-mspublisher",
"scd": "application/x-msschedule",
"trm": "application/x-msterminal",
"wri": "application/x-mswrite",
"nc": "application/x-netcdf",
"cdf": "application/x-netcdf",
"nzb": "application/x-nzb",
"p12": "application/x-pkcs12",
"pfx": "application/x-pkcs12",
"p7b": "application/x-pkcs7-certificates",
"spc": "application/x-pkcs7-certificates",
"p7r": "application/x-pkcs7-certreqresp",
"rar": "application/x-rar-compressed",
"ris": "application/x-research-info-systems",
"sh": "application/x-sh",
"shar": "application/x-shar",
"swf": "application/x-shockwave-flash",
"xap": "application/x-silverlight-app",
"sql": "application/x-sql",
"sit": "application/x-stuffit",
"sitx": "application/x-stuffitx",
"srt": "application/x-subrip",
"sv4cpio": "application/x-sv4cpio",
"sv4crc": "application/x-sv4crc",
"t3": "application/x-t3vm-image",
"gam": "application/x-tads",
"tar": "application/x-tar",
"tcl": "application/x-tcl",
"tex": "application/x-tex",
"tfm": "application/x-tex-tfm",
"texinfo": "application/x-texinfo",
"texi": "application/x-texinfo",
"obj": "application/x-tgif",
"ustar": "application/x-ustar",
"src": "application/x-wais-source",
"der": "application/x-x509-ca-cert",
"crt": "application/x-x509-ca-cert",
"fig": "application/x-xfig",
"xlf": "application/x-xliff+xml",
"xpi": "application/x-xpinstall",
"xz": "application/x-xz",
"z1": "application/x-zmachine",
"z2": "application/x-zmachine",
"z3": "application/x-zmachine",
"z4": "application/x-zmachine",
"z5": "application/x-zmachine",
"z6": "application/x-zmachine",
"z7": "application/x-zmachine",
"z8": "application/x-zmachine",
"xaml": "application/xaml+xml",
"xdf": "application/xcap-diff+xml",
"xenc": "application/xenc+xml",
"xhtml": "application/xhtml+xml",
"xht": "application/xhtml+xml",
"xml": "application/xml",
"xsl": "application/xml",
"dtd": "application/xml-dtd",
"xop": "application/xop+xml",
"xpl": "application/xproc+xml",
"xslt": "application/xslt+xml",
"xspf": "application/xspf+xml",
"mxml": "application/xv+xml",
"xhvml": "application/xv+xml",
"xvml": "application/xv+xml",
"xvm": "application/xv+xml",
"yang": "application/yang",
"yin": "application/yin+xml",
"zip": "application/zip",
"adp": "audio/adpcm",
"au": "audio/basic",
"snd": "audio/basic",
"mid": "audio/midi",
"midi": "audio/midi",
"kar": "audio/midi",
"rmi": "audio/midi",
"mp4a": "audio/mp4",
"mpga": "audio/mpeg",
"mp2": "audio/mpeg",
"mp2a": "audio/mpeg",
"mp3": "audio/mpeg",
"m2a": "audio/mpeg",
"m3a": "audio/mpeg",
"oga": "audio/ogg",
"ogg": "audio/ogg",
"spx": "audio/ogg",
"s3m": "audio/s3m",
"sil": "audio/silk",
"uva": "audio/vnd.dece.audio",
"uvva": "audio/vnd.dece.audio",
"eol": "audio/vnd.digital-winds",
"dra": "audio/vnd.dra",
"dts": "audio/vnd.dts",
"dtshd": "audio/vnd.dts.hd",
"lvp": "audio/vnd.lucent.voice",
"pya": "audio/vnd.ms-playready.media.pya",
"ecelp4800": "audio/vnd.nuera.ecelp4800",
"ecelp7470": "audio/vnd.nuera.ecelp7470",
"ecelp9600": "audio/vnd.nuera.ecelp9600",
"rip": "audio/vnd.rip",
"weba": "audio/webm",
"aac": "audio/x-aac",
"aif": "audio/x-aiff",
"aiff": "audio/x-aiff",
"aifc": "audio/x-aiff",
"caf": "audio/x-caf",
"flac": "audio/x-flac",
"mka": "audio/x-matroska",
"m3u": "audio/x-mpegurl",
"wax": "audio/x-ms-wax",
"wma": "audio/x-ms-wma",
"ram": "audio/x-pn-realaudio",
"ra": "audio/x-pn-realaudio",
"rmp": "audio/x-pn-realaudio-plugin",
"wav": "audio/x-wav",
"xm": "audio/xm",
"cdx": "chemical/x-cdx",
"cif": "chemical/x-cif",
"cmdf": "chemical/x-cmdf",
"cml": "chemical/x-cml",
"csml": "chemical/x-csml",
"xyz": "chemical/x-xyz",
"bmp": "image/bmp",
"cgm": "image/cgm",
"g3": "image/g3fax",
"gif": "image/gif",
"ief": "image/ief",
"jpeg": "image/jpeg",
"jpg": "image/jpeg",
"jpe": "image/jpeg",
"ktx": "image/ktx",
"png": "image/png",
"btif": "image/prs.btif",
"sgi": "image/sgi",
"svg": "image/svg+xml",
"svgz": "image/svg+xml",
"tiff": "image/tiff",
"tif": "image/tiff",
"psd": "image/vnd.adobe.photoshop",
"uvi": "image/vnd.dece.graphic",
"uvvi": "image/vnd.dece.graphic",
"uvg": "image/vnd.dece.graphic",
"uvvg": "image/vnd.dece.graphic",
"sub": "text/vnd.dvb.subtitle",
"djvu": "image/vnd.djvu",
"djv": "image/vnd.djvu",
"dwg": "image/vnd.dwg",
"dxf": "image/vnd.dxf",
"fbs": "image/vnd.fastbidsheet",
"fpx": "image/vnd.fpx",
"fst": "image/vnd.fst",
"mmr": "image/vnd.fujixerox.edmics-mmr",
"rlc": "image/vnd.fujixerox.edmics-rlc",
"mdi": "image/vnd.ms-modi",
"wdp": "image/vnd.ms-photo",
"npx": "image/vnd.net-fpx",
"wbmp": "image/vnd.wap.wbmp",
"xif": "image/vnd.xiff",
"webp": "image/webp",
"3ds": "image/x-3ds",
"ras": "image/x-cmu-raster",
"cmx": "image/x-cmx",
"fh": "image/x-freehand",
"fhc": "image/x-freehand",
"fh4": "image/x-freehand",
"fh5": "image/x-freehand",
"fh7": "image/x-freehand",
"ico": "image/x-icon",
"sid": "image/x-mrsid-image",
"pcx": "image/x-pcx",
"pic": "image/x-pict",
"pct": "image/x-pict",
"pnm": "image/x-portable-anymap",
"pbm": "image/x-portable-bitmap",
"pgm": "image/x-portable-graymap",
"ppm": "image/x-portable-pixmap",
"rgb": "image/x-rgb",
"tga": "image/x-tga",
"xbm": "image/x-xbitmap",
"xpm": "image/x-xpixmap",
"xwd": "image/x-xwindowdump",
"eml": "message/rfc822",
"mime": "message/rfc822",
"igs": "model/iges",
"iges": "model/iges",
"msh": "model/mesh",
"mesh": "model/mesh",
"silo": "model/mesh",
"dae": "model/vnd.collada+xml",
"dwf": "model/vnd.dwf",
"gdl": "model/vnd.gdl",
"gtw": "model/vnd.gtw",
"mts": "model/vnd.mts",
"vtu": "model/vnd.vtu",
"wrl": "model/vrml",
"vrml": "model/vrml",
"x3db": "model/x3d+binary",
"x3dbz": "model/x3d+binary",
"x3dv": "model/x3d+vrml",
"x3dvz": "model/x3d+vrml",
"x3d": "model/x3d+xml",
"x3dz": "model/x3d+xml",
"appcache": "text/cache-manifest",
"ics": "text/calendar",
"ifb": "text/calendar",
"css": "text/css",
"csv": "text/csv",
"html": "text/html",
"htm": "text/html",
"n3": "text/n3",
"txt": "text/plain",
"text": "text/plain",
"conf": "text/plain",
"def": "text/plain",
"list": "text/plain",
"log": "text/plain",
"in": "text/plain",
"dsc": "text/prs.lines.tag",
"rtx": "text/richtext",
"sgml": "text/sgml",
"sgm": "text/sgml",
"tsv": "text/tab-separated-values",
"t": "text/troff",
"tr": "text/troff",
"roff": "text/troff",
"man": "text/troff",
"me": "text/troff",
"ms": "text/troff",
"ttl": "text/turtle",
"uri": "text/uri-list",
"uris": "text/uri-list",
"urls": "text/uri-list",
"vcard": "text/vcard",
"curl": "text/vnd.curl",
"dcurl": "text/vnd.curl.dcurl",
"scurl": "text/vnd.curl.scurl",
"mcurl": "text/vnd.curl.mcurl",
"fly": "text/vnd.fly",
"flx": "text/vnd.fmi.flexstor",
"gv": "text/vnd.graphviz",
"3dml": "text/vnd.in3d.3dml",
"spot": "text/vnd.in3d.spot",
"jad": "text/vnd.sun.j2me.app-descriptor",
"wml": "text/vnd.wap.wml",
"wmls": "text/vnd.wap.wmlscript",
"s": "text/x-asm",
"asm": "text/x-asm",
"c": "text/x-c",
"cc": "text/x-c",
"cxx": "text/x-c",
"cpp": "text/x-c",
"h": "text/x-c",
"hh": "text/x-c",
"dic": "text/x-c",
"f": "text/x-fortran",
"for": "text/x-fortran",
"f77": "text/x-fortran",
"f90": "text/x-fortran",
"java": "text/x-java-source",
"opml": "text/x-opml",
"p": "text/x-pascal",
"pas": "text/x-pascal",
"nfo": "text/x-nfo",
"etx": "text/x-setext",
"sfv": "text/x-sfv",
"uu": "text/x-uuencode",
"vcs": "text/x-vcalendar",
"vcf": "text/x-vcard",
"3gp": "video/3gpp",
"3g2": "video/3gpp2",
"h261": "video/h261",
"h263": "video/h263",
"h264": "video/h264",
"jpgv": "video/jpeg",
"jpm": "video/jpm",
"jpgm": "video/jpm",
"mj2": "video/mj2",
"mjp2": "video/mj2",
"mp4": "video/mp4",
"mp4v": "video/mp4",
"mpg4": "video/mp4",
"mpeg": "video/mpeg",
"mpg": "video/mpeg",
"mpe": "video/mpeg",
"m1v": "video/mpeg",
"m2v": "video/mpeg",
"ogv": "video/ogg",
"qt": "video/quicktime",
"mov": "video/quicktime",
"uvh": "video/vnd.dece.hd",
"uvvh": "video/vnd.dece.hd",
"uvm": "video/vnd.dece.mobile",
"uvvm": "video/vnd.dece.mobile",
"uvp": "video/vnd.dece.pd",
"uvvp": "video/vnd.dece.pd",
"uvs": "video/vnd.dece.sd",
"uvvs": "video/vnd.dece.sd",
"uvv": "video/vnd.dece.video",
"uvvv": "video/vnd.dece.video",
"dvb": "video/vnd.dvb.file",
"fvt": "video/vnd.fvt",
"mxu": "video/vnd.mpegurl",
"m4u": "video/vnd.mpegurl",
"pyv": "video/vnd.ms-playready.media.pyv",
"uvu": "video/vnd.uvvu.mp4",
"uvvu": "video/vnd.uvvu.mp4",
"viv": "video/vnd.vivo",
"webm": "video/webm",
"f4v": "video/x-f4v",
"fli": "video/x-fli",
"flv": "video/x-flv",
"m4v": "video/x-m4v",
"mkv": "video/x-matroska",
"mk3d": "video/x-matroska",
"mks": "video/x-matroska",
"mng": "video/x-mng",
"asf": "video/x-ms-asf",
"asx": "video/x-ms-asf",
"vob": "video/x-ms-vob",
"wm": "video/x-ms-wm",
"wmv": "video/x-ms-wmv",
"wmx": "video/x-ms-wmx",
"wvx": "video/x-ms-wvx",
"avi": "video/x-msvideo",
"movie": "video/x-sgi-movie",
"smv": "video/x-smv",
"ice": "x-conference/x-cooltalk",
"vtt": "text/vtt",
"crx": "application/x-chrome-extension",
"htc": "text/x-component",
"manifest": "text/cache-manifest",
"buffer": "application/octet-stream",
"m4p": "application/mp4",
"m4a": "audio/mp4",
"ts": "video/MP2T",
"event-stream": "text/event-stream",
"webapp": "application/x-web-app-manifest+json",
"lua": "text/x-lua",
"luac": "application/x-lua-bytecode",
"markdown": "text/x-markdown",
"md": "text/x-markdown",
"mkd": "text/x-markdown"
}
, extensions: {
"application/andrew-inset": "ez",
"application/applixware": "aw",
"application/atom+xml": "atom",
"application/atomcat+xml": "atomcat",
"application/atomsvc+xml": "atomsvc",
"application/ccxml+xml": "ccxml",
"application/cdmi-capability": "cdmia",
"application/cdmi-container": "cdmic",
"application/cdmi-domain": "cdmid",
"application/cdmi-object": "cdmio",
"application/cdmi-queue": "cdmiq",
"application/cu-seeme": "cu",
"application/davmount+xml": "davmount",
"application/docbook+xml": "dbk",
"application/dssc+der": "dssc",
"application/dssc+xml": "xdssc",
"application/ecmascript": "ecma",
"application/emma+xml": "emma",
"application/epub+zip": "epub",
"application/exi": "exi",
"application/font-tdpfr": "pfr",
"application/gml+xml": "gml",
"application/gpx+xml": "gpx",
"application/gxf": "gxf",
"application/hyperstudio": "stk",
"application/inkml+xml": "ink",
"application/ipfix": "ipfix",
"application/java-archive": "jar",
"application/java-serialized-object": "ser",
"application/java-vm": "class",
"application/javascript": "js",
"application/json": "json",
"application/jsonml+json": "jsonml",
"application/lost+xml": "lostxml",
"application/mac-binhex40": "hqx",
"application/mac-compactpro": "cpt",
"application/mads+xml": "mads",
"application/marc": "mrc",
"application/marcxml+xml": "mrcx",
"application/mathematica": "ma",
"application/mathml+xml": "mathml",
"application/mbox": "mbox",
"application/mediaservercontrol+xml": "mscml",
"application/metalink+xml": "metalink",
"application/metalink4+xml": "meta4",
"application/mets+xml": "mets",
"application/mods+xml": "mods",
"application/mp21": "m21",
"application/mp4": "mp4s",
"application/msword": "doc",
"application/mxf": "mxf",
"application/octet-stream": "bin",
"application/oda": "oda",
"application/oebps-package+xml": "opf",
"application/ogg": "ogx",
"application/omdoc+xml": "omdoc",
"application/onenote": "onetoc",
"application/oxps": "oxps",
"application/patch-ops-error+xml": "xer",
"application/pdf": "pdf",
"application/pgp-encrypted": "pgp",
"application/pgp-signature": "asc",
"application/pics-rules": "prf",
"application/pkcs10": "p10",
"application/pkcs7-mime": "p7m",
"application/pkcs7-signature": "p7s",
"application/pkcs8": "p8",
"application/pkix-attr-cert": "ac",
"application/pkix-cert": "cer",
"application/pkix-crl": "crl",
"application/pkix-pkipath": "pkipath",
"application/pkixcmp": "pki",
"application/pls+xml": "pls",
"application/postscript": "ai",
"application/prs.cww": "cww",
"application/pskc+xml": "pskcxml",
"application/rdf+xml": "rdf",
"application/reginfo+xml": "rif",
"application/relax-ng-compact-syntax": "rnc",
"application/resource-lists+xml": "rl",
"application/resource-lists-diff+xml": "rld",
"application/rls-services+xml": "rs",
"application/rpki-ghostbusters": "gbr",
"application/rpki-manifest": "mft",
"application/rpki-roa": "roa",
"application/rsd+xml": "rsd",
"application/rss+xml": "rss",
"application/rtf": "rtf",
"application/sbml+xml": "sbml",
"application/scvp-cv-request": "scq",
"application/scvp-cv-response": "scs",
"application/scvp-vp-request": "spq",
"application/scvp-vp-response": "spp",
"application/sdp": "sdp",
"application/set-payment-initiation": "setpay",
"application/set-registration-initiation": "setreg",
"application/shf+xml": "shf",
"application/smil+xml": "smi",
"application/sparql-query": "rq",
"application/sparql-results+xml": "srx",
"application/srgs": "gram",
"application/srgs+xml": "grxml",
"application/sru+xml": "sru",
"application/ssdl+xml": "ssdl",
"application/ssml+xml": "ssml",
"application/tei+xml": "tei",
"application/thraud+xml": "tfi",
"application/timestamped-data": "tsd",
"application/vnd.3gpp.pic-bw-large": "plb",
"application/vnd.3gpp.pic-bw-small": "psb",
"application/vnd.3gpp.pic-bw-var": "pvb",
"application/vnd.3gpp2.tcap": "tcap",
"application/vnd.3m.post-it-notes": "pwn",
"application/vnd.accpac.simply.aso": "aso",
"application/vnd.accpac.simply.imp": "imp",
"application/vnd.acucobol": "acu",
"application/vnd.acucorp": "atc",
"application/vnd.adobe.air-application-installer-package+zip": "air",
"application/vnd.adobe.formscentral.fcdt": "fcdt",
"application/vnd.adobe.fxp": "fxp",
"application/vnd.adobe.xdp+xml": "xdp",
"application/vnd.adobe.xfdf": "xfdf",
"application/vnd.ahead.space": "ahead",
"application/vnd.airzip.filesecure.azf": "azf",
"application/vnd.airzip.filesecure.azs": "azs",
"application/vnd.amazon.ebook": "azw",
"application/vnd.americandynamics.acc": "acc",
"application/vnd.amiga.ami": "ami",
"application/vnd.android.package-archive": "apk",
"application/vnd.anser-web-certificate-issue-initiation": "cii",
"application/vnd.anser-web-funds-transfer-initiation": "fti",
"application/vnd.antix.game-component": "atx",
"application/vnd.apple.installer+xml": "mpkg",
"application/vnd.apple.mpegurl": "m3u8",
"application/vnd.aristanetworks.swi": "swi",
"application/vnd.astraea-software.iota": "iota",
"application/vnd.audiograph": "aep",
"application/vnd.blueice.multipass": "mpm",
"application/vnd.bmi": "bmi",
"application/vnd.businessobjects": "rep",
"application/vnd.chemdraw+xml": "cdxml",
"application/vnd.chipnuts.karaoke-mmd": "mmd",
"application/vnd.cinderella": "cdy",
"application/vnd.claymore": "cla",
"application/vnd.cloanto.rp9": "rp9",
"application/vnd.clonk.c4group": "c4g",
"application/vnd.cluetrust.cartomobile-config": "c11amc",
"application/vnd.cluetrust.cartomobile-config-pkg": "c11amz",
"application/vnd.commonspace": "csp",
"application/vnd.contact.cmsg": "cdbcmsg",
"application/vnd.cosmocaller": "cmc",
"application/vnd.crick.clicker": "clkx",
"application/vnd.crick.clicker.keyboard": "clkk",
"application/vnd.crick.clicker.palette": "clkp",
"application/vnd.crick.clicker.template": "clkt",
"application/vnd.crick.clicker.wordbank": "clkw",
"application/vnd.criticaltools.wbs+xml": "wbs",
"application/vnd.ctc-posml": "pml",
"application/vnd.cups-ppd": "ppd",
"application/vnd.curl.car": "car",
"application/vnd.curl.pcurl": "pcurl",
"application/vnd.dart": "dart",
"application/vnd.data-vision.rdz": "rdz",
"application/vnd.dece.data": "uvf",
"application/vnd.dece.ttml+xml": "uvt",
"application/vnd.dece.unspecified": "uvx",
"application/vnd.dece.zip": "uvz",
"application/vnd.denovo.fcselayout-link": "fe_launch",
"application/vnd.dna": "dna",
"application/vnd.dolby.mlp": "mlp",
"application/vnd.dpgraph": "dpg",
"application/vnd.dreamfactory": "dfac",
"application/vnd.ds-keypoint": "kpxx",
"application/vnd.dvb.ait": "ait",
"application/vnd.dvb.service": "svc",
"application/vnd.dynageo": "geo",
"application/vnd.ecowin.chart": "mag",
"application/vnd.enliven": "nml",
"application/vnd.epson.esf": "esf",
"application/vnd.epson.msf": "msf",
"application/vnd.epson.quickanime": "qam",
"application/vnd.epson.salt": "slt",
"application/vnd.epson.ssf": "ssf",
"application/vnd.eszigno3+xml": "es3",
"application/vnd.ezpix-album": "ez2",
"application/vnd.ezpix-package": "ez3",
"application/vnd.fdf": "fdf",
"application/vnd.fdsn.mseed": "mseed",
"application/vnd.fdsn.seed": "seed",
"application/vnd.flographit": "gph",
"application/vnd.fluxtime.clip": "ftc",
"application/vnd.framemaker": "fm",
"application/vnd.frogans.fnc": "fnc",
"application/vnd.frogans.ltf": "ltf",
"application/vnd.fsc.weblaunch": "fsc",
"application/vnd.fujitsu.oasys": "oas",
"application/vnd.fujitsu.oasys2": "oa2",
"application/vnd.fujitsu.oasys3": "oa3",
"application/vnd.fujitsu.oasysgp": "fg5",
"application/vnd.fujitsu.oasysprs": "bh2",
"application/vnd.fujixerox.ddd": "ddd",
"application/vnd.fujixerox.docuworks": "xdw",
"application/vnd.fujixerox.docuworks.binder": "xbd",
"application/vnd.fuzzysheet": "fzs",
"application/vnd.genomatix.tuxedo": "txd",
"application/vnd.geogebra.file": "ggb",
"application/vnd.geogebra.tool": "ggt",
"application/vnd.geometry-explorer": "gex",
"application/vnd.geonext": "gxt",
"application/vnd.geoplan": "g2w",
"application/vnd.geospace": "g3w",
"application/vnd.gmx": "gmx",
"application/vnd.google-earth.kml+xml": "kml",
"application/vnd.google-earth.kmz": "kmz",
"application/vnd.grafeq": "gqf",
"application/vnd.groove-account": "gac",
"application/vnd.groove-help": "ghf",
"application/vnd.groove-identity-message": "gim",
"application/vnd.groove-injector": "grv",
"application/vnd.groove-tool-message": "gtm",
"application/vnd.groove-tool-template": "tpl",
"application/vnd.groove-vcard": "vcg",
"application/vnd.hal+xml": "hal",
"application/vnd.handheld-entertainment+xml": "zmm",
"application/vnd.hbci": "hbci",
"application/vnd.hhe.lesson-player": "les",
"application/vnd.hp-hpgl": "hpgl",
"application/vnd.hp-hpid": "hpid",
"application/vnd.hp-hps": "hps",
"application/vnd.hp-jlyt": "jlt",
"application/vnd.hp-pcl": "pcl",
"application/vnd.hp-pclxl": "pclxl",
"application/vnd.hydrostatix.sof-data": "sfd-hdstx",
"application/vnd.ibm.minipay": "mpy",
"application/vnd.ibm.modcap": "afp",
"application/vnd.ibm.rights-management": "irm",
"application/vnd.ibm.secure-container": "sc",
"application/vnd.iccprofile": "icc",
"application/vnd.igloader": "igl",
"application/vnd.immervision-ivp": "ivp",
"application/vnd.immervision-ivu": "ivu",
"application/vnd.insors.igm": "igm",
"application/vnd.intercon.formnet": "xpw",
"application/vnd.intergeo": "i2g",
"application/vnd.intu.qbo": "qbo",
"application/vnd.intu.qfx": "qfx",
"application/vnd.ipunplugged.rcprofile": "rcprofile",
"application/vnd.irepository.package+xml": "irp",
"application/vnd.is-xpr": "xpr",
"application/vnd.isac.fcs": "fcs",
"application/vnd.jam": "jam",
"application/vnd.jcp.javame.midlet-rms": "rms",
"application/vnd.jisp": "jisp",
"application/vnd.joost.joda-archive": "joda",
"application/vnd.kahootz": "ktz",
"application/vnd.kde.karbon": "karbon",
"application/vnd.kde.kchart": "chrt",
"application/vnd.kde.kformula": "kfo",
"application/vnd.kde.kivio": "flw",
"application/vnd.kde.kontour": "kon",
"application/vnd.kde.kpresenter": "kpr",
"application/vnd.kde.kspread": "ksp",
"application/vnd.kde.kword": "kwd",
"application/vnd.kenameaapp": "htke",
"application/vnd.kidspiration": "kia",
"application/vnd.kinar": "kne",
"application/vnd.koan": "skp",
"application/vnd.kodak-descriptor": "sse",
"application/vnd.las.las+xml": "lasxml",
"application/vnd.llamagraphics.life-balance.desktop": "lbd",
"application/vnd.llamagraphics.life-balance.exchange+xml": "lbe",
"application/vnd.lotus-1-2-3": "123",
"application/vnd.lotus-approach": "apr",
"application/vnd.lotus-freelance": "pre",
"application/vnd.lotus-notes": "nsf",
"application/vnd.lotus-organizer": "org",
"application/vnd.lotus-screencam": "scm",
"application/vnd.lotus-wordpro": "lwp",
"application/vnd.macports.portpkg": "portpkg",
"application/vnd.mcd": "mcd",
"application/vnd.medcalcdata": "mc1",
"application/vnd.mediastation.cdkey": "cdkey",
"application/vnd.mfer": "mwf",
"application/vnd.mfmp": "mfm",
"application/vnd.micrografx.flo": "flo",
"application/vnd.micrografx.igx": "igx",
"application/vnd.mif": "mif",
"application/vnd.mobius.daf": "daf",
"application/vnd.mobius.dis": "dis",
"application/vnd.mobius.mbk": "mbk",
"application/vnd.mobius.mqy": "mqy",
"application/vnd.mobius.msl": "msl",
"application/vnd.mobius.plc": "plc",
"application/vnd.mobius.txf": "txf",
"application/vnd.mophun.application": "mpn",
"application/vnd.mophun.certificate": "mpc",
"application/vnd.mozilla.xul+xml": "xul",
"application/vnd.ms-artgalry": "cil",
"application/vnd.ms-cab-compressed": "cab",
"application/vnd.ms-excel": "xls",
"application/vnd.ms-excel.addin.macroenabled.12": "xlam",
"application/vnd.ms-excel.sheet.binary.macroenabled.12": "xlsb",
"application/vnd.ms-excel.sheet.macroenabled.12": "xlsm",
"application/vnd.ms-excel.template.macroenabled.12": "xltm",
"application/vnd.ms-fontobject": "eot",
"application/vnd.ms-htmlhelp": "chm",
"application/vnd.ms-ims": "ims",
"application/vnd.ms-lrm": "lrm",
"application/vnd.ms-officetheme": "thmx",
"application/vnd.ms-pki.seccat": "cat",
"application/vnd.ms-pki.stl": "stl",
"application/vnd.ms-powerpoint": "ppt",
"application/vnd.ms-powerpoint.addin.macroenabled.12": "ppam",
"application/vnd.ms-powerpoint.presentation.macroenabled.12": "pptm",
"application/vnd.ms-powerpoint.slide.macroenabled.12": "sldm",
"application/vnd.ms-powerpoint.slideshow.macroenabled.12": "ppsm",
"application/vnd.ms-powerpoint.template.macroenabled.12": "potm",
"application/vnd.ms-project": "mpp",
"application/vnd.ms-word.document.macroenabled.12": "docm",
"application/vnd.ms-word.template.macroenabled.12": "dotm",
"application/vnd.ms-works": "wps",
"application/vnd.ms-wpl": "wpl",
"application/vnd.ms-xpsdocument": "xps",
"application/vnd.mseq": "mseq",
"application/vnd.musician": "mus",
"application/vnd.muvee.style": "msty",
"application/vnd.mynfc": "taglet",
"application/vnd.neurolanguage.nlu": "nlu",
"application/vnd.nitf": "ntf",
"application/vnd.noblenet-directory": "nnd",
"application/vnd.noblenet-sealer": "nns",
"application/vnd.noblenet-web": "nnw",
"application/vnd.nokia.n-gage.data": "ngdat",
"application/vnd.nokia.n-gage.symbian.install": "n-gage",
"application/vnd.nokia.radio-preset": "rpst",
"application/vnd.nokia.radio-presets": "rpss",
"application/vnd.novadigm.edm": "edm",
"application/vnd.novadigm.edx": "edx",
"application/vnd.novadigm.ext": "ext",
"application/vnd.oasis.opendocument.chart": "odc",
"application/vnd.oasis.opendocument.chart-template": "otc",
"application/vnd.oasis.opendocument.database": "odb",
"application/vnd.oasis.opendocument.formula": "odf",
"application/vnd.oasis.opendocument.formula-template": "odft",
"application/vnd.oasis.opendocument.graphics": "odg",
"application/vnd.oasis.opendocument.graphics-template": "otg",
"application/vnd.oasis.opendocument.image": "odi",
"application/vnd.oasis.opendocument.image-template": "oti",
"application/vnd.oasis.opendocument.presentation": "odp",
"application/vnd.oasis.opendocument.presentation-template": "otp",
"application/vnd.oasis.opendocument.spreadsheet": "ods",
"application/vnd.oasis.opendocument.spreadsheet-template": "ots",
"application/vnd.oasis.opendocument.text": "odt",
"application/vnd.oasis.opendocument.text-master": "odm",
"application/vnd.oasis.opendocument.text-template": "ott",
"application/vnd.oasis.opendocument.text-web": "oth",
"application/vnd.olpc-sugar": "xo",
"application/vnd.oma.dd2+xml": "dd2",
"application/vnd.openofficeorg.extension": "oxt",
"application/vnd.openxmlformats-officedocument.presentationml.presentation": "pptx",
"application/vnd.openxmlformats-officedocument.presentationml.slide": "sldx",
"application/vnd.openxmlformats-officedocument.presentationml.slideshow": "ppsx",
"application/vnd.openxmlformats-officedocument.presentationml.template": "potx",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": "xlsx",
"application/vnd.openxmlformats-officedocument.spreadsheetml.template": "xltx",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document": "docx",
"application/vnd.openxmlformats-officedocument.wordprocessingml.template": "dotx",
"application/vnd.osgeo.mapguide.package": "mgp",
"application/vnd.osgi.dp": "dp",
"application/vnd.osgi.subsystem": "esa",
"application/vnd.palm": "pdb",
"application/vnd.pawaafile": "paw",
"application/vnd.pg.format": "str",
"application/vnd.pg.osasli": "ei6",
"application/vnd.picsel": "efif",
"application/vnd.pmi.widget": "wg",
"application/vnd.pocketlearn": "plf",
"application/vnd.powerbuilder6": "pbd",
"application/vnd.previewsystems.box": "box",
"application/vnd.proteus.magazine": "mgz",
"application/vnd.publishare-delta-tree": "qps",
"application/vnd.pvi.ptid1": "ptid",
"application/vnd.quark.quarkxpress": "qxd",
"application/vnd.realvnc.bed": "bed",
"application/vnd.recordare.musicxml": "mxl",
"application/vnd.recordare.musicxml+xml": "musicxml",
"application/vnd.rig.cryptonote": "cryptonote",
"application/vnd.rim.cod": "cod",
"application/vnd.rn-realmedia": "rm",
"application/vnd.rn-realmedia-vbr": "rmvb",
"application/vnd.route66.link66+xml": "link66",
"application/vnd.sailingtracker.track": "st",
"application/vnd.seemail": "see",
"application/vnd.sema": "sema",
"application/vnd.semd": "semd",
"application/vnd.semf": "semf",
"application/vnd.shana.informed.formdata": "ifm",
"application/vnd.shana.informed.formtemplate": "itp",
"application/vnd.shana.informed.interchange": "iif",
"application/vnd.shana.informed.package": "ipk",
"application/vnd.simtech-mindmapper": "twd",
"application/vnd.smaf": "mmf",
"application/vnd.smart.teacher": "teacher",
"application/vnd.solent.sdkm+xml": "sdkm",
"application/vnd.spotfire.dxp": "dxp",
"application/vnd.spotfire.sfs": "sfs",
"application/vnd.stardivision.calc": "sdc",
"application/vnd.stardivision.draw": "sda",
"application/vnd.stardivision.impress": "sdd",
"application/vnd.stardivision.math": "smf",
"application/vnd.stardivision.writer": "sdw",
"application/vnd.stardivision.writer-global": "sgl",
"application/vnd.stepmania.package": "smzip",
"application/vnd.stepmania.stepchart": "sm",
"application/vnd.sun.xml.calc": "sxc",
"application/vnd.sun.xml.calc.template": "stc",
"application/vnd.sun.xml.draw": "sxd",
"application/vnd.sun.xml.draw.template": "std",
"application/vnd.sun.xml.impress": "sxi",
"application/vnd.sun.xml.impress.template": "sti",
"application/vnd.sun.xml.math": "sxm",
"application/vnd.sun.xml.writer": "sxw",
"application/vnd.sun.xml.writer.global": "sxg",
"application/vnd.sun.xml.writer.template": "stw",
"application/vnd.sus-calendar": "sus",
"application/vnd.svd": "svd",
"application/vnd.symbian.install": "sis",
"application/vnd.syncml+xml": "xsm",
"application/vnd.syncml.dm+wbxml": "bdm",
"application/vnd.syncml.dm+xml": "xdm",
"application/vnd.tao.intent-module-archive": "tao",
"application/vnd.tcpdump.pcap": "pcap",
"application/vnd.tmobile-livetv": "tmo",
"application/vnd.trid.tpt": "tpt",
"application/vnd.triscape.mxs": "mxs",
"application/vnd.trueapp": "tra",
"application/vnd.ufdl": "ufd",
"application/vnd.uiq.theme": "utz",
"application/vnd.umajin": "umj",
"application/vnd.unity": "unityweb",
"application/vnd.uoml+xml": "uoml",
"application/vnd.vcx": "vcx",
"application/vnd.visio": "vsd",
"application/vnd.visionary": "vis",
"application/vnd.vsf": "vsf",
"application/vnd.wap.wbxml": "wbxml",
"application/vnd.wap.wmlc": "wmlc",
"application/vnd.wap.wmlscriptc": "wmlsc",
"application/vnd.webturbo": "wtb",
"application/vnd.wolfram.player": "nbp",
"application/vnd.wordperfect": "wpd",
"application/vnd.wqd": "wqd",
"application/vnd.wt.stf": "stf",
"application/vnd.xara": "xar",
"application/vnd.xfdl": "xfdl",
"application/vnd.yamaha.hv-dic": "hvd",
"application/vnd.yamaha.hv-script": "hvs",
"application/vnd.yamaha.hv-voice": "hvp",
"application/vnd.yamaha.openscoreformat": "osf",
"application/vnd.yamaha.openscoreformat.osfpvg+xml": "osfpvg",
"application/vnd.yamaha.smaf-audio": "saf",
"application/vnd.yamaha.smaf-phrase": "spf",
"application/vnd.yellowriver-custom-menu": "cmp",
"application/vnd.zul": "zir",
"application/vnd.zzazz.deck+xml": "zaz",
"application/voicexml+xml": "vxml",
"application/widget": "wgt",
"application/winhlp": "hlp",
"application/wsdl+xml": "wsdl",
"application/wspolicy+xml": "wspolicy",
"application/x-7z-compressed": "7z",
"application/x-abiword": "abw",
"application/x-ace-compressed": "ace",
"application/x-apple-diskimage": "dmg",
"application/x-authorware-bin": "aab",
"application/x-authorware-map": "aam",
"application/x-authorware-seg": "aas",
"application/x-bcpio": "bcpio",
"application/x-bittorrent": "torrent",
"application/x-blorb": "blb",
"application/x-bzip": "bz",
"application/x-bzip2": "bz2",
"application/x-cbr": "cbr",
"application/x-cdlink": "vcd",
"application/x-cfs-compressed": "cfs",
"application/x-chat": "chat",
"application/x-chess-pgn": "pgn",
"application/x-conference": "nsc",
"application/x-cpio": "cpio",
"application/x-csh": "csh",
"application/x-debian-package": "deb",
"application/x-dgc-compressed": "dgc",
"application/x-director": "dir",
"application/x-doom": "wad",
"application/x-dtbncx+xml": "ncx",
"application/x-dtbook+xml": "dtb",
"application/x-dtbresource+xml": "res",
"application/x-dvi": "dvi",
"application/x-envoy": "evy",
"application/x-eva": "eva",
"application/x-font-bdf": "bdf",
"application/x-font-ghostscript": "gsf",
"application/x-font-linux-psf": "psf",
"application/x-font-otf": "otf",
"application/x-font-pcf": "pcf",
"application/x-font-snf": "snf",
"application/x-font-ttf": "ttf",
"application/x-font-type1": "pfa",
"application/x-font-woff": "woff",
"application/x-freearc": "arc",
"application/x-futuresplash": "spl",
"application/x-gca-compressed": "gca",
"application/x-glulx": "ulx",
"application/x-gnumeric": "gnumeric",
"application/x-gramps-xml": "gramps",
"application/x-gtar": "gtar",
"application/x-hdf": "hdf",
"application/x-install-instructions": "install",
"application/x-iso9660-image": "iso",
"application/x-java-jnlp-file": "jnlp",
"application/x-latex": "latex",
"application/x-lzh-compressed": "lzh",
"application/x-mie": "mie",
"application/x-mobipocket-ebook": "prc",
"application/x-ms-application": "application",
"application/x-ms-shortcut": "lnk",
"application/x-ms-wmd": "wmd",
"application/x-ms-wmz": "wmz",
"application/x-ms-xbap": "xbap",
"application/x-msaccess": "mdb",
"application/x-msbinder": "obd",
"application/x-mscardfile": "crd",
"application/x-msclip": "clp",
"application/x-msdownload": "exe",
"application/x-msmediaview": "mvb",
"application/x-msmetafile": "wmf",
"application/x-msmoney": "mny",
"application/x-mspublisher": "pub",
"application/x-msschedule": "scd",
"application/x-msterminal": "trm",
"application/x-mswrite": "wri",
"application/x-netcdf": "nc",
"application/x-nzb": "nzb",
"application/x-pkcs12": "p12",
"application/x-pkcs7-certificates": "p7b",
"application/x-pkcs7-certreqresp": "p7r",
"application/x-rar-compressed": "rar",
"application/x-research-info-systems": "ris",
"application/x-sh": "sh",
"application/x-shar": "shar",
"application/x-shockwave-flash": "swf",
"application/x-silverlight-app": "xap",
"application/x-sql": "sql",
"application/x-stuffit": "sit",
"application/x-stuffitx": "sitx",
"application/x-subrip": "srt",
"application/x-sv4cpio": "sv4cpio",
"application/x-sv4crc": "sv4crc",
"application/x-t3vm-image": "t3",
"application/x-tads": "gam",
"application/x-tar": "tar",
"application/x-tcl": "tcl",
"application/x-tex": "tex",
"application/x-tex-tfm": "tfm",
"application/x-texinfo": "texinfo",
"application/x-tgif": "obj",
"application/x-ustar": "ustar",
"application/x-wais-source": "src",
"application/x-x509-ca-cert": "der",
"application/x-xfig": "fig",
"application/x-xliff+xml": "xlf",
"application/x-xpinstall": "xpi",
"application/x-xz": "xz",
"application/x-zmachine": "z1",
"application/xaml+xml": "xaml",
"application/xcap-diff+xml": "xdf",
"application/xenc+xml": "xenc",
"application/xhtml+xml": "xhtml",
"application/xml": "xml",
"application/xml-dtd": "dtd",
"application/xop+xml": "xop",
"application/xproc+xml": "xpl",
"application/xslt+xml": "xslt",
"application/xspf+xml": "xspf",
"application/xv+xml": "mxml",
"application/yang": "yang",
"application/yin+xml": "yin",
"application/zip": "zip",
"audio/adpcm": "adp",
"audio/basic": "au",
"audio/midi": "mid",
"audio/mp4": "mp4a",
"audio/mpeg": "mpga",
"audio/ogg": "oga",
"audio/s3m": "s3m",
"audio/silk": "sil",
"audio/vnd.dece.audio": "uva",
"audio/vnd.digital-winds": "eol",
"audio/vnd.dra": "dra",
"audio/vnd.dts": "dts",
"audio/vnd.dts.hd": "dtshd",
"audio/vnd.lucent.voice": "lvp",
"audio/vnd.ms-playready.media.pya": "pya",
"audio/vnd.nuera.ecelp4800": "ecelp4800",
"audio/vnd.nuera.ecelp7470": "ecelp7470",
"audio/vnd.nuera.ecelp9600": "ecelp9600",
"audio/vnd.rip": "rip",
"audio/webm": "weba",
"audio/x-aac": "aac",
"audio/x-aiff": "aif",
"audio/x-caf": "caf",
"audio/x-flac": "flac",
"audio/x-matroska": "mka",
"audio/x-mpegurl": "m3u",
"audio/x-ms-wax": "wax",
"audio/x-ms-wma": "wma",
"audio/x-pn-realaudio": "ram",
"audio/x-pn-realaudio-plugin": "rmp",
"audio/x-wav": "wav",
"audio/xm": "xm",
"chemical/x-cdx": "cdx",
"chemical/x-cif": "cif",
"chemical/x-cmdf": "cmdf",
"chemical/x-cml": "cml",
"chemical/x-csml": "csml",
"chemical/x-xyz": "xyz",
"image/bmp": "bmp",
"image/cgm": "cgm",
"image/g3fax": "g3",
"image/gif": "gif",
"image/ief": "ief",
"image/jpeg": "jpeg",
"image/ktx": "ktx",
"image/png": "png",
"image/prs.btif": "btif",
"image/sgi": "sgi",
"image/svg+xml": "svg",
"image/tiff": "tiff",
"image/vnd.adobe.photoshop": "psd",
"image/vnd.dece.graphic": "uvi",
"image/vnd.dvb.subtitle": "sub",
"image/vnd.djvu": "djvu",
"image/vnd.dwg": "dwg",
"image/vnd.dxf": "dxf",
"image/vnd.fastbidsheet": "fbs",
"image/vnd.fpx": "fpx",
"image/vnd.fst": "fst",
"image/vnd.fujixerox.edmics-mmr": "mmr",
"image/vnd.fujixerox.edmics-rlc": "rlc",
"image/vnd.ms-modi": "mdi",
"image/vnd.ms-photo": "wdp",
"image/vnd.net-fpx": "npx",
"image/vnd.wap.wbmp": "wbmp",
"image/vnd.xiff": "xif",
"image/webp": "webp",
"image/x-3ds": "3ds",
"image/x-cmu-raster": "ras",
"image/x-cmx": "cmx",
"image/x-freehand": "fh",
"image/x-icon": "ico",
"image/x-mrsid-image": "sid",
"image/x-pcx": "pcx",
"image/x-pict": "pic",
"image/x-portable-anymap": "pnm",
"image/x-portable-bitmap": "pbm",
"image/x-portable-graymap": "pgm",
"image/x-portable-pixmap": "ppm",
"image/x-rgb": "rgb",
"image/x-tga": "tga",
"image/x-xbitmap": "xbm",
"image/x-xpixmap": "xpm",
"image/x-xwindowdump": "xwd",
"message/rfc822": "eml",
"model/iges": "igs",
"model/mesh": "msh",
"model/vnd.collada+xml": "dae",
"model/vnd.dwf": "dwf",
"model/vnd.gdl": "gdl",
"model/vnd.gtw": "gtw",
"model/vnd.mts": "mts",
"model/vnd.vtu": "vtu",
"model/vrml": "wrl",
"model/x3d+binary": "x3db",
"model/x3d+vrml": "x3dv",
"model/x3d+xml": "x3d",
"text/cache-manifest": "appcache",
"text/calendar": "ics",
"text/css": "css",
"text/csv": "csv",
"text/html": "html",
"text/n3": "n3",
"text/plain": "txt",
"text/prs.lines.tag": "dsc",
"text/richtext": "rtx",
"text/sgml": "sgml",
"text/tab-separated-values": "tsv",
"text/troff": "t",
"text/turtle": "ttl",
"text/uri-list": "uri",
"text/vcard": "vcard",
"text/vnd.curl": "curl",
"text/vnd.curl.dcurl": "dcurl",
"text/vnd.curl.scurl": "scurl",
"text/vnd.curl.mcurl": "mcurl",
"text/vnd.dvb.subtitle": "sub",
"text/vnd.fly": "fly",
"text/vnd.fmi.flexstor": "flx",
"text/vnd.graphviz": "gv",
"text/vnd.in3d.3dml": "3dml",
"text/vnd.in3d.spot": "spot",
"text/vnd.sun.j2me.app-descriptor": "jad",
"text/vnd.wap.wml": "wml",
"text/vnd.wap.wmlscript": "wmls",
"text/x-asm": "s",
"text/x-c": "c",
"text/x-fortran": "f",
"text/x-java-source": "java",
"text/x-opml": "opml",
"text/x-pascal": "p",
"text/x-nfo": "nfo",
"text/x-setext": "etx",
"text/x-sfv": "sfv",
"text/x-uuencode": "uu",
"text/x-vcalendar": "vcs",
"text/x-vcard": "vcf",
"video/3gpp": "3gp",
"video/3gpp2": "3g2",
"video/h261": "h261",
"video/h263": "h263",
"video/h264": "h264",
"video/jpeg": "jpgv",
"video/jpm": "jpm",
"video/mj2": "mj2",
"video/mp4": "mp4",
"video/mpeg": "mpeg",
"video/ogg": "ogv",
"video/quicktime": "qt",
"video/vnd.dece.hd": "uvh",
"video/vnd.dece.mobile": "uvm",
"video/vnd.dece.pd": "uvp",
"video/vnd.dece.sd": "uvs",
"video/vnd.dece.video": "uvv",
"video/vnd.dvb.file": "dvb",
"video/vnd.fvt": "fvt",
"video/vnd.mpegurl": "mxu",
"video/vnd.ms-playready.media.pyv": "pyv",
"video/vnd.uvvu.mp4": "uvu",
"video/vnd.vivo": "viv",
"video/webm": "webm",
"video/x-f4v": "f4v",
"video/x-fli": "fli",
"video/x-flv": "flv",
"video/x-m4v": "m4v",
"video/x-matroska": "mkv",
"video/x-mng": "mng",
"video/x-ms-asf": "asf",
"video/x-ms-vob": "vob",
"video/x-ms-wm": "wm",
"video/x-ms-wmv": "wmv",
"video/x-ms-wmx": "wmx",
"video/x-ms-wvx": "wvx",
"video/x-msvideo": "avi",
"video/x-sgi-movie": "movie",
"video/x-smv": "smv",
"x-conference/x-cooltalk": "ice",
"text/vtt": "vtt",
"application/x-chrome-extension": "crx",
"text/x-component": "htc",
"video/MP2T": "ts",
"text/event-stream": "event-stream",
"application/x-web-app-manifest+json": "webapp",
"text/x-lua": "lua",
"application/x-lua-bytecode": "luac",
"text/x-markdown": "markdown"
}
, extension: function (mimeType) {
var type = mimeType.match(/^\s*([^;\s]*)(?:;|\s|$)/)[1].toLowerCase();
return this.extensions[type];
}
, define: function (map) {
for (var type in map) {
var exts = map[type];
for (var i = 0; i < exts.length; i++) {
if (false && this.types[exts]) {
console.warn(this._loading.replace(/.*\//, ''), 'changes "' + exts[i] + '" extension type from ' +
this.types[exts] + ' to ' + type);
}
this.types[exts[i]] = type;
}
// Default extension is the first one we encounter
if (!this.extensions[type]) {
this.extensions[type] = exts[0];
}
}
}
, charsets: {lookup: function (mimeType, fallback) {
// Assume text types are utf8
return (/^text\//).test(mimeType) ? 'UTF-8' : fallback;
}}
}
mime.types.constructor = undefined
mime.extensions.constructor = undefined
},{}],75:[function(require,module,exports){
},{}],76:[function(require,module,exports){
/*!
* The buffer module from node.js, for the browser.
*
* @author Feross Aboukhadijeh
* @license MIT
*/
var base64 = require('base64-js')
var ieee754 = require('ieee754')
var isArray = require('is-array')
exports.Buffer = Buffer
exports.SlowBuffer = SlowBuffer
exports.INSPECT_MAX_BYTES = 50
Buffer.poolSize = 8192 // not used by this implementation
var rootParent = {}
/**
* If `Buffer.TYPED_ARRAY_SUPPORT`:
* === true Use Uint8Array implementation (fastest)
* === false Use Object implementation (most compatible, even IE6)
*
* Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+,
* Opera 11.6+, iOS 4.2+.
*
* Due to various browser bugs, sometimes the Object implementation will be used even
* when the browser supports typed arrays.
*
* Note:
*
* - Firefox 4-29 lacks support for adding new properties to `Uint8Array` instances,
* See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438.
*
* - Safari 5-7 lacks support for changing the `Object.prototype.constructor` property
* on objects.
*
* - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function.
*
* - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of
* incorrect length in some situations.
* We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they
* get the Object implementation, which is slower but behaves correctly.
*/
Buffer.TYPED_ARRAY_SUPPORT = (function () {
function Bar () {}
try {
var arr = new Uint8Array(1)
arr.foo = function () { return 42 }
arr.constructor = Bar
return arr.foo() === 42 && // typed array instances can be augmented
arr.constructor === Bar && // constructor can be set
typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray`
arr.subarray(1, 1).byteLength === 0 // ie10 has broken `subarray`
} catch (e) {
return false
}
})()
function kMaxLength () {
return Buffer.TYPED_ARRAY_SUPPORT
? 0x7fffffff
: 0x3fffffff
}
/**
* Class: Buffer
* =============
*
* The Buffer constructor returns instances of `Uint8Array` that are augmented
* with function properties for all the node `Buffer` API functions. We use
* `Uint8Array` so that square bracket notation works as expected -- it returns
* a single octet.
*
* By augmenting the instances, we can avoid modifying the `Uint8Array`
* prototype.
*/
function Buffer (arg) {
if (!(this instanceof Buffer)) {
// Avoid going through an ArgumentsAdaptorTrampoline in the common case.
if (arguments.length > 1) return new Buffer(arg, arguments[1])
return new Buffer(arg)
}
this.length = 0
this.parent = undefined
// Common case.
if (typeof arg === 'number') {
return fromNumber(this, arg)
}
// Slightly less common case.
if (typeof arg === 'string') {
return fromString(this, arg, arguments.length > 1 ? arguments[1] : 'utf8')
}
// Unusual.
return fromObject(this, arg)
}
function fromNumber (that, length) {
that = allocate(that, length < 0 ? 0 : checked(length) | 0)
if (!Buffer.TYPED_ARRAY_SUPPORT) {
for (var i = 0; i < length; i++) {
that[i] = 0
}
}
return that
}
function fromString (that, string, encoding) {
if (typeof encoding !== 'string' || encoding === '') encoding = 'utf8'
// Assumption: byteLength() return value is always < kMaxLength.
var length = byteLength(string, encoding) | 0
that = allocate(that, length)
that.write(string, encoding)
return that
}
function fromObject (that, object) {
if (Buffer.isBuffer(object)) return fromBuffer(that, object)
if (isArray(object)) return fromArray(that, object)
if (object == null) {
throw new TypeError('must start with number, buffer, array or string')
}
if (typeof ArrayBuffer !== 'undefined' && object.buffer instanceof ArrayBuffer) {
return fromTypedArray(that, object)
}
if (object.length) return fromArrayLike(that, object)
return fromJsonObject(that, object)
}
function fromBuffer (that, buffer) {
var length = checked(buffer.length) | 0
that = allocate(that, length)
buffer.copy(that, 0, 0, length)
return that
}
function fromArray (that, array) {
var length = checked(array.length) | 0
that = allocate(that, length)
for (var i = 0; i < length; i += 1) {
that[i] = array[i] & 255
}
return that
}
// Duplicate of fromArray() to keep fromArray() monomorphic.
function fromTypedArray (that, array) {
var length = checked(array.length) | 0
that = allocate(that, length)
// Truncating the elements is probably not what people expect from typed
// arrays with BYTES_PER_ELEMENT > 1 but it's compatible with the behavior
// of the old Buffer constructor.
for (var i = 0; i < length; i += 1) {
that[i] = array[i] & 255
}
return that
}
function fromArrayLike (that, array) {
var length = checked(array.length) | 0
that = allocate(that, length)
for (var i = 0; i < length; i += 1) {
that[i] = array[i] & 255
}
return that
}
// Deserialize { type: 'Buffer', data: [1,2,3,...] } into a Buffer object.
// Returns a zero-length buffer for inputs that don't conform to the spec.
function fromJsonObject (that, object) {
var array
var length = 0
if (object.type === 'Buffer' && isArray(object.data)) {
array = object.data
length = checked(array.length) | 0
}
that = allocate(that, length)
for (var i = 0; i < length; i += 1) {
that[i] = array[i] & 255
}
return that
}
function allocate (that, length) {
if (Buffer.TYPED_ARRAY_SUPPORT) {
// Return an augmented `Uint8Array` instance, for best performance
that = Buffer._augment(new Uint8Array(length))
} else {
// Fallback: Return an object instance of the Buffer class
that.length = length
that._isBuffer = true
}
var fromPool = length !== 0 && length <= Buffer.poolSize >>> 1
if (fromPool) that.parent = rootParent
return that
}
function checked (length) {
// Note: cannot use `length < kMaxLength` here because that fails when
// length is NaN (which is otherwise coerced to zero.)
if (length >= kMaxLength()) {
throw new RangeError('Attempt to allocate Buffer larger than maximum ' +
'size: 0x' + kMaxLength().toString(16) + ' bytes')
}
return length | 0
}
function SlowBuffer (subject, encoding) {
if (!(this instanceof SlowBuffer)) return new SlowBuffer(subject, encoding)
var buf = new Buffer(subject, encoding)
delete buf.parent
return buf
}
Buffer.isBuffer = function isBuffer (b) {
return !!(b != null && b._isBuffer)
}
Buffer.compare = function compare (a, b) {
if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) {
throw new TypeError('Arguments must be Buffers')
}
if (a === b) return 0
var x = a.length
var y = b.length
var i = 0
var len = Math.min(x, y)
while (i < len) {
if (a[i] !== b[i]) break
++i
}
if (i !== len) {
x = a[i]
y = b[i]
}
if (x < y) return -1
if (y < x) return 1
return 0
}
Buffer.isEncoding = function isEncoding (encoding) {
switch (String(encoding).toLowerCase()) {
case 'hex':
case 'utf8':
case 'utf-8':
case 'ascii':
case 'binary':
case 'base64':
case 'raw':
case 'ucs2':
case 'ucs-2':
case 'utf16le':
case 'utf-16le':
return true
default:
return false
}
}
Buffer.concat = function concat (list, length) {
if (!isArray(list)) throw new TypeError('list argument must be an Array of Buffers.')
if (list.length === 0) {
return new Buffer(0)
} else if (list.length === 1) {
return list[0]
}
var i
if (length === undefined) {
length = 0
for (i = 0; i < list.length; i++) {
length += list[i].length
}
}
var buf = new Buffer(length)
var pos = 0
for (i = 0; i < list.length; i++) {
var item = list[i]
item.copy(buf, pos)
pos += item.length
}
return buf
}
function byteLength (string, encoding) {
if (typeof string !== 'string') string = '' + string
var len = string.length
if (len === 0) return 0
// Use a for loop to avoid recursion
var loweredCase = false
for (;;) {
switch (encoding) {
case 'ascii':
case 'binary':
// Deprecated
case 'raw':
case 'raws':
return len
case 'utf8':
case 'utf-8':
return utf8ToBytes(string).length
case 'ucs2':
case 'ucs-2':
case 'utf16le':
case 'utf-16le':
return len * 2
case 'hex':
return len >>> 1
case 'base64':
return base64ToBytes(string).length
default:
if (loweredCase) return utf8ToBytes(string).length // assume utf8
encoding = ('' + encoding).toLowerCase()
loweredCase = true
}
}
}
Buffer.byteLength = byteLength
// pre-set for values that may exist in the future
Buffer.prototype.length = undefined
Buffer.prototype.parent = undefined
function slowToString (encoding, start, end) {
var loweredCase = false
start = start | 0
end = end === undefined || end === Infinity ? this.length : end | 0
if (!encoding) encoding = 'utf8'
if (start < 0) start = 0
if (end > this.length) end = this.length
if (end <= start) return ''
while (true) {
switch (encoding) {
case 'hex':
return hexSlice(this, start, end)
case 'utf8':
case 'utf-8':
return utf8Slice(this, start, end)
case 'ascii':
return asciiSlice(this, start, end)
case 'binary':
return binarySlice(this, start, end)
case 'base64':
return base64Slice(this, start, end)
case 'ucs2':
case 'ucs-2':
case 'utf16le':
case 'utf-16le':
return utf16leSlice(this, start, end)
default:
if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
encoding = (encoding + '').toLowerCase()
loweredCase = true
}
}
}
Buffer.prototype.toString = function toString () {
var length = this.length | 0
if (length === 0) return ''
if (arguments.length === 0) return utf8Slice(this, 0, length)
return slowToString.apply(this, arguments)
}
Buffer.prototype.equals = function equals (b) {
if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
if (this === b) return true
return Buffer.compare(this, b) === 0
}
Buffer.prototype.inspect = function inspect () {
var str = ''
var max = exports.INSPECT_MAX_BYTES
if (this.length > 0) {
str = this.toString('hex', 0, max).match(/.{2}/g).join(' ')
if (this.length > max) str += ' ... '
}
return ''
}
Buffer.prototype.compare = function compare (b) {
if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
if (this === b) return 0
return Buffer.compare(this, b)
}
Buffer.prototype.indexOf = function indexOf (val, byteOffset) {
if (byteOffset > 0x7fffffff) byteOffset = 0x7fffffff
else if (byteOffset < -0x80000000) byteOffset = -0x80000000
byteOffset >>= 0
if (this.length === 0) return -1
if (byteOffset >= this.length) return -1
// Negative offsets start from the end of the buffer
if (byteOffset < 0) byteOffset = Math.max(this.length + byteOffset, 0)
if (typeof val === 'string') {
if (val.length === 0) return -1 // special case: looking for empty string always fails
return String.prototype.indexOf.call(this, val, byteOffset)
}
if (Buffer.isBuffer(val)) {
return arrayIndexOf(this, val, byteOffset)
}
if (typeof val === 'number') {
if (Buffer.TYPED_ARRAY_SUPPORT && Uint8Array.prototype.indexOf === 'function') {
return Uint8Array.prototype.indexOf.call(this, val, byteOffset)
}
return arrayIndexOf(this, [ val ], byteOffset)
}
function arrayIndexOf (arr, val, byteOffset) {
var foundIndex = -1
for (var i = 0; byteOffset + i < arr.length; i++) {
if (arr[byteOffset + i] === val[foundIndex === -1 ? 0 : i - foundIndex]) {
if (foundIndex === -1) foundIndex = i
if (i - foundIndex + 1 === val.length) return byteOffset + foundIndex
} else {
foundIndex = -1
}
}
return -1
}
throw new TypeError('val must be string, number or Buffer')
}
// `get` will be removed in Node 0.13+
Buffer.prototype.get = function get (offset) {
console.log('.get() is deprecated. Access using array indexes instead.')
return this.readUInt8(offset)
}
// `set` will be removed in Node 0.13+
Buffer.prototype.set = function set (v, offset) {
console.log('.set() is deprecated. Access using array indexes instead.')
return this.writeUInt8(v, offset)
}
function hexWrite (buf, string, offset, length) {
offset = Number(offset) || 0
var remaining = buf.length - offset
if (!length) {
length = remaining
} else {
length = Number(length)
if (length > remaining) {
length = remaining
}
}
// must be an even number of digits
var strLen = string.length
if (strLen % 2 !== 0) throw new Error('Invalid hex string')
if (length > strLen / 2) {
length = strLen / 2
}
for (var i = 0; i < length; i++) {
var parsed = parseInt(string.substr(i * 2, 2), 16)
if (isNaN(parsed)) throw new Error('Invalid hex string')
buf[offset + i] = parsed
}
return i
}
function utf8Write (buf, string, offset, length) {
return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length)
}
function asciiWrite (buf, string, offset, length) {
return blitBuffer(asciiToBytes(string), buf, offset, length)
}
function binaryWrite (buf, string, offset, length) {
return asciiWrite(buf, string, offset, length)
}
function base64Write (buf, string, offset, length) {
return blitBuffer(base64ToBytes(string), buf, offset, length)
}
function ucs2Write (buf, string, offset, length) {
return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length)
}
Buffer.prototype.write = function write (string, offset, length, encoding) {
// Buffer#write(string)
if (offset === undefined) {
encoding = 'utf8'
length = this.length
offset = 0
// Buffer#write(string, encoding)
} else if (length === undefined && typeof offset === 'string') {
encoding = offset
length = this.length
offset = 0
// Buffer#write(string, offset[, length][, encoding])
} else if (isFinite(offset)) {
offset = offset | 0
if (isFinite(length)) {
length = length | 0
if (encoding === undefined) encoding = 'utf8'
} else {
encoding = length
length = undefined
}
// legacy write(string, encoding, offset, length) - remove in v0.13
} else {
var swap = encoding
encoding = offset
offset = length | 0
length = swap
}
var remaining = this.length - offset
if (length === undefined || length > remaining) length = remaining
if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) {
throw new RangeError('attempt to write outside buffer bounds')
}
if (!encoding) encoding = 'utf8'
var loweredCase = false
for (;;) {
switch (encoding) {
case 'hex':
return hexWrite(this, string, offset, length)
case 'utf8':
case 'utf-8':
return utf8Write(this, string, offset, length)
case 'ascii':
return asciiWrite(this, string, offset, length)
case 'binary':
return binaryWrite(this, string, offset, length)
case 'base64':
// Warning: maxLength not taken into account in base64Write
return base64Write(this, string, offset, length)
case 'ucs2':
case 'ucs-2':
case 'utf16le':
case 'utf-16le':
return ucs2Write(this, string, offset, length)
default:
if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
encoding = ('' + encoding).toLowerCase()
loweredCase = true
}
}
}
Buffer.prototype.toJSON = function toJSON () {
return {
type: 'Buffer',
data: Array.prototype.slice.call(this._arr || this, 0)
}
}
function base64Slice (buf, start, end) {
if (start === 0 && end === buf.length) {
return base64.fromByteArray(buf)
} else {
return base64.fromByteArray(buf.slice(start, end))
}
}
function utf8Slice (buf, start, end) {
var res = ''
var tmp = ''
end = Math.min(buf.length, end)
for (var i = start; i < end; i++) {
if (buf[i] <= 0x7F) {
res += decodeUtf8Char(tmp) + String.fromCharCode(buf[i])
tmp = ''
} else {
tmp += '%' + buf[i].toString(16)
}
}
return res + decodeUtf8Char(tmp)
}
function asciiSlice (buf, start, end) {
var ret = ''
end = Math.min(buf.length, end)
for (var i = start; i < end; i++) {
ret += String.fromCharCode(buf[i] & 0x7F)
}
return ret
}
function binarySlice (buf, start, end) {
var ret = ''
end = Math.min(buf.length, end)
for (var i = start; i < end; i++) {
ret += String.fromCharCode(buf[i])
}
return ret
}
function hexSlice (buf, start, end) {
var len = buf.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(buf[i])
}
return out
}
function utf16leSlice (buf, start, end) {
var bytes = buf.slice(start, end)
var res = ''
for (var i = 0; i < bytes.length; i += 2) {
res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256)
}
return res
}
Buffer.prototype.slice = function slice (start, end) {
var len = this.length
start = ~~start
end = end === undefined ? len : ~~end
if (start < 0) {
start += len
if (start < 0) start = 0
} else if (start > len) {
start = len
}
if (end < 0) {
end += len
if (end < 0) end = 0
} else if (end > len) {
end = len
}
if (end < start) end = start
var newBuf
if (Buffer.TYPED_ARRAY_SUPPORT) {
newBuf = Buffer._augment(this.subarray(start, end))
} else {
var sliceLen = end - start
newBuf = new Buffer(sliceLen, undefined)
for (var i = 0; i < sliceLen; i++) {
newBuf[i] = this[i + start]
}
}
if (newBuf.length) newBuf.parent = this.parent || this
return newBuf
}
/*
* Need to make sure that buffer isn't trying to write out of bounds.
*/
function checkOffset (offset, ext, length) {
if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint')
if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length')
}
Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) {
offset = offset | 0
byteLength = byteLength | 0
if (!noAssert) checkOffset(offset, byteLength, this.length)
var val = this[offset]
var mul = 1
var i = 0
while (++i < byteLength && (mul *= 0x100)) {
val += this[offset + i] * mul
}
return val
}
Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) {
offset = offset | 0
byteLength = byteLength | 0
if (!noAssert) {
checkOffset(offset, byteLength, this.length)
}
var val = this[offset + --byteLength]
var mul = 1
while (byteLength > 0 && (mul *= 0x100)) {
val += this[offset + --byteLength] * mul
}
return val
}
Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) {
if (!noAssert) checkOffset(offset, 1, this.length)
return this[offset]
}
Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) {
if (!noAssert) checkOffset(offset, 2, this.length)
return this[offset] | (this[offset + 1] << 8)
}
Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) {
if (!noAssert) checkOffset(offset, 2, this.length)
return (this[offset] << 8) | this[offset + 1]
}
Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) {
if (!noAssert) checkOffset(offset, 4, this.length)
return ((this[offset]) |
(this[offset + 1] << 8) |
(this[offset + 2] << 16)) +
(this[offset + 3] * 0x1000000)
}
Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) {
if (!noAssert) checkOffset(offset, 4, this.length)
return (this[offset] * 0x1000000) +
((this[offset + 1] << 16) |
(this[offset + 2] << 8) |
this[offset + 3])
}
Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) {
offset = offset | 0
byteLength = byteLength | 0
if (!noAssert) checkOffset(offset, byteLength, this.length)
var val = this[offset]
var mul = 1
var i = 0
while (++i < byteLength && (mul *= 0x100)) {
val += this[offset + i] * mul
}
mul *= 0x80
if (val >= mul) val -= Math.pow(2, 8 * byteLength)
return val
}
Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) {
offset = offset | 0
byteLength = byteLength | 0
if (!noAssert) checkOffset(offset, byteLength, this.length)
var i = byteLength
var mul = 1
var val = this[offset + --i]
while (i > 0 && (mul *= 0x100)) {
val += this[offset + --i] * mul
}
mul *= 0x80
if (val >= mul) val -= Math.pow(2, 8 * byteLength)
return val
}
Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) {
if (!noAssert) checkOffset(offset, 1, this.length)
if (!(this[offset] & 0x80)) return (this[offset])
return ((0xff - this[offset] + 1) * -1)
}
Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) {
if (!noAssert) checkOffset(offset, 2, this.length)
var val = this[offset] | (this[offset + 1] << 8)
return (val & 0x8000) ? val | 0xFFFF0000 : val
}
Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) {
if (!noAssert) checkOffset(offset, 2, this.length)
var val = this[offset + 1] | (this[offset] << 8)
return (val & 0x8000) ? val | 0xFFFF0000 : val
}
Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) {
if (!noAssert) checkOffset(offset, 4, this.length)
return (this[offset]) |
(this[offset + 1] << 8) |
(this[offset + 2] << 16) |
(this[offset + 3] << 24)
}
Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) {
if (!noAssert) checkOffset(offset, 4, this.length)
return (this[offset] << 24) |
(this[offset + 1] << 16) |
(this[offset + 2] << 8) |
(this[offset + 3])
}
Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) {
if (!noAssert) checkOffset(offset, 4, this.length)
return ieee754.read(this, offset, true, 23, 4)
}
Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) {
if (!noAssert) checkOffset(offset, 4, this.length)
return ieee754.read(this, offset, false, 23, 4)
}
Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) {
if (!noAssert) checkOffset(offset, 8, this.length)
return ieee754.read(this, offset, true, 52, 8)
}
Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) {
if (!noAssert) checkOffset(offset, 8, this.length)
return ieee754.read(this, offset, false, 52, 8)
}
function checkInt (buf, value, offset, ext, max, min) {
if (!Buffer.isBuffer(buf)) throw new TypeError('buffer must be a Buffer instance')
if (value > max || value < min) throw new RangeError('value is out of bounds')
if (offset + ext > buf.length) throw new RangeError('index out of range')
}
Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) {
value = +value
offset = offset | 0
byteLength = byteLength | 0
if (!noAssert) checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0)
var mul = 1
var i = 0
this[offset] = value & 0xFF
while (++i < byteLength && (mul *= 0x100)) {
this[offset + i] = (value / mul) & 0xFF
}
return offset + byteLength
}
Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) {
value = +value
offset = offset | 0
byteLength = byteLength | 0
if (!noAssert) checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0)
var i = byteLength - 1
var mul = 1
this[offset + i] = value & 0xFF
while (--i >= 0 && (mul *= 0x100)) {
this[offset + i] = (value / mul) & 0xFF
}
return offset + byteLength
}
Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) {
value = +value
offset = offset | 0
if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0)
if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
this[offset] = value
return offset + 1
}
function objectWriteUInt16 (buf, value, offset, littleEndian) {
if (value < 0) value = 0xffff + value + 1
for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; i++) {
buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>>
(littleEndian ? i : 1 - i) * 8
}
}
Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) {
value = +value
offset = offset | 0
if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
if (Buffer.TYPED_ARRAY_SUPPORT) {
this[offset] = value
this[offset + 1] = (value >>> 8)
} else {
objectWriteUInt16(this, value, offset, true)
}
return offset + 2
}
Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) {
value = +value
offset = offset | 0
if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
if (Buffer.TYPED_ARRAY_SUPPORT) {
this[offset] = (value >>> 8)
this[offset + 1] = value
} else {
objectWriteUInt16(this, value, offset, false)
}
return offset + 2
}
function objectWriteUInt32 (buf, value, offset, littleEndian) {
if (value < 0) value = 0xffffffff + value + 1
for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; i++) {
buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff
}
}
Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) {
value = +value
offset = offset | 0
if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
if (Buffer.TYPED_ARRAY_SUPPORT) {
this[offset + 3] = (value >>> 24)
this[offset + 2] = (value >>> 16)
this[offset + 1] = (value >>> 8)
this[offset] = value
} else {
objectWriteUInt32(this, value, offset, true)
}
return offset + 4
}
Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) {
value = +value
offset = offset | 0
if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
if (Buffer.TYPED_ARRAY_SUPPORT) {
this[offset] = (value >>> 24)
this[offset + 1] = (value >>> 16)
this[offset + 2] = (value >>> 8)
this[offset + 3] = value
} else {
objectWriteUInt32(this, value, offset, false)
}
return offset + 4
}
Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) {
value = +value
offset = offset | 0
if (!noAssert) {
var limit = Math.pow(2, 8 * byteLength - 1)
checkInt(this, value, offset, byteLength, limit - 1, -limit)
}
var i = 0
var mul = 1
var sub = value < 0 ? 1 : 0
this[offset] = value & 0xFF
while (++i < byteLength && (mul *= 0x100)) {
this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
}
return offset + byteLength
}
Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) {
value = +value
offset = offset | 0
if (!noAssert) {
var limit = Math.pow(2, 8 * byteLength - 1)
checkInt(this, value, offset, byteLength, limit - 1, -limit)
}
var i = byteLength - 1
var mul = 1
var sub = value < 0 ? 1 : 0
this[offset + i] = value & 0xFF
while (--i >= 0 && (mul *= 0x100)) {
this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
}
return offset + byteLength
}
Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) {
value = +value
offset = offset | 0
if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80)
if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
if (value < 0) value = 0xff + value + 1
this[offset] = value
return offset + 1
}
Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) {
value = +value
offset = offset | 0
if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
if (Buffer.TYPED_ARRAY_SUPPORT) {
this[offset] = value
this[offset + 1] = (value >>> 8)
} else {
objectWriteUInt16(this, value, offset, true)
}
return offset + 2
}
Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) {
value = +value
offset = offset | 0
if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
if (Buffer.TYPED_ARRAY_SUPPORT) {
this[offset] = (value >>> 8)
this[offset + 1] = value
} else {
objectWriteUInt16(this, value, offset, false)
}
return offset + 2
}
Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) {
value = +value
offset = offset | 0
if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
if (Buffer.TYPED_ARRAY_SUPPORT) {
this[offset] = value
this[offset + 1] = (value >>> 8)
this[offset + 2] = (value >>> 16)
this[offset + 3] = (value >>> 24)
} else {
objectWriteUInt32(this, value, offset, true)
}
return offset + 4
}
Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) {
value = +value
offset = offset | 0
if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
if (value < 0) value = 0xffffffff + value + 1
if (Buffer.TYPED_ARRAY_SUPPORT) {
this[offset] = (value >>> 24)
this[offset + 1] = (value >>> 16)
this[offset + 2] = (value >>> 8)
this[offset + 3] = value
} else {
objectWriteUInt32(this, value, offset, false)
}
return offset + 4
}
function checkIEEE754 (buf, value, offset, ext, max, min) {
if (value > max || value < min) throw new RangeError('value is out of bounds')
if (offset + ext > buf.length) throw new RangeError('index out of range')
if (offset < 0) throw new RangeError('index out of range')
}
function writeFloat (buf, value, offset, littleEndian, noAssert) {
if (!noAssert) {
checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38)
}
ieee754.write(buf, value, offset, littleEndian, 23, 4)
return offset + 4
}
Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) {
return writeFloat(this, value, offset, true, noAssert)
}
Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) {
return writeFloat(this, value, offset, false, noAssert)
}
function writeDouble (buf, value, offset, littleEndian, noAssert) {
if (!noAssert) {
checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308)
}
ieee754.write(buf, value, offset, littleEndian, 52, 8)
return offset + 8
}
Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) {
return writeDouble(this, value, offset, true, noAssert)
}
Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) {
return writeDouble(this, value, offset, false, noAssert)
}
// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
Buffer.prototype.copy = function copy (target, targetStart, start, end) {
if (!start) start = 0
if (!end && end !== 0) end = this.length
if (targetStart >= target.length) targetStart = target.length
if (!targetStart) targetStart = 0
if (end > 0 && end < start) end = start
// Copy 0 bytes; we're done
if (end === start) return 0
if (target.length === 0 || this.length === 0) return 0
// Fatal error conditions
if (targetStart < 0) {
throw new RangeError('targetStart out of bounds')
}
if (start < 0 || start >= this.length) throw new RangeError('sourceStart out of bounds')
if (end < 0) throw new RangeError('sourceEnd out of bounds')
// Are we oob?
if (end > this.length) end = this.length
if (target.length - targetStart < end - start) {
end = target.length - targetStart + start
}
var len = end - start
if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) {
for (var i = 0; i < len; i++) {
target[i + targetStart] = this[i + start]
}
} else {
target._set(this.subarray(start, start + len), targetStart)
}
return len
}
// fill(value, start=0, end=buffer.length)
Buffer.prototype.fill = function fill (value, start, end) {
if (!value) value = 0
if (!start) start = 0
if (!end) end = this.length
if (end < start) throw new RangeError('end < start')
// Fill 0 bytes; we're done
if (end === start) return
if (this.length === 0) return
if (start < 0 || start >= this.length) throw new RangeError('start out of bounds')
if (end < 0 || end > this.length) throw new RangeError('end out of bounds')
var i
if (typeof value === 'number') {
for (i = start; i < end; i++) {
this[i] = value
}
} else {
var bytes = utf8ToBytes(value.toString())
var len = bytes.length
for (i = start; i < end; i++) {
this[i] = bytes[i % len]
}
}
return this
}
/**
* Creates a new `ArrayBuffer` with the *copied* memory of the buffer instance.
* Added in Node 0.12. Only available in browsers that support ArrayBuffer.
*/
Buffer.prototype.toArrayBuffer = function toArrayBuffer () {
if (typeof Uint8Array !== 'undefined') {
if (Buffer.TYPED_ARRAY_SUPPORT) {
return (new Buffer(this)).buffer
} else {
var buf = new Uint8Array(this.length)
for (var i = 0, len = buf.length; i < len; i += 1) {
buf[i] = this[i]
}
return buf.buffer
}
} else {
throw new TypeError('Buffer.toArrayBuffer not supported in this browser')
}
}
// HELPER FUNCTIONS
// ================
var BP = Buffer.prototype
/**
* Augment a Uint8Array *instance* (not the Uint8Array class!) with Buffer methods
*/
Buffer._augment = function _augment (arr) {
arr.constructor = Buffer
arr._isBuffer = true
// save reference to original Uint8Array set method before overwriting
arr._set = arr.set
// deprecated, will be removed in node 0.13+
arr.get = BP.get
arr.set = BP.set
arr.write = BP.write
arr.toString = BP.toString
arr.toLocaleString = BP.toString
arr.toJSON = BP.toJSON
arr.equals = BP.equals
arr.compare = BP.compare
arr.indexOf = BP.indexOf
arr.copy = BP.copy
arr.slice = BP.slice
arr.readUIntLE = BP.readUIntLE
arr.readUIntBE = BP.readUIntBE
arr.readUInt8 = BP.readUInt8
arr.readUInt16LE = BP.readUInt16LE
arr.readUInt16BE = BP.readUInt16BE
arr.readUInt32LE = BP.readUInt32LE
arr.readUInt32BE = BP.readUInt32BE
arr.readIntLE = BP.readIntLE
arr.readIntBE = BP.readIntBE
arr.readInt8 = BP.readInt8
arr.readInt16LE = BP.readInt16LE
arr.readInt16BE = BP.readInt16BE
arr.readInt32LE = BP.readInt32LE
arr.readInt32BE = BP.readInt32BE
arr.readFloatLE = BP.readFloatLE
arr.readFloatBE = BP.readFloatBE
arr.readDoubleLE = BP.readDoubleLE
arr.readDoubleBE = BP.readDoubleBE
arr.writeUInt8 = BP.writeUInt8
arr.writeUIntLE = BP.writeUIntLE
arr.writeUIntBE = BP.writeUIntBE
arr.writeUInt16LE = BP.writeUInt16LE
arr.writeUInt16BE = BP.writeUInt16BE
arr.writeUInt32LE = BP.writeUInt32LE
arr.writeUInt32BE = BP.writeUInt32BE
arr.writeIntLE = BP.writeIntLE
arr.writeIntBE = BP.writeIntBE
arr.writeInt8 = BP.writeInt8
arr.writeInt16LE = BP.writeInt16LE
arr.writeInt16BE = BP.writeInt16BE
arr.writeInt32LE = BP.writeInt32LE
arr.writeInt32BE = BP.writeInt32BE
arr.writeFloatLE = BP.writeFloatLE
arr.writeFloatBE = BP.writeFloatBE
arr.writeDoubleLE = BP.writeDoubleLE
arr.writeDoubleBE = BP.writeDoubleBE
arr.fill = BP.fill
arr.inspect = BP.inspect
arr.toArrayBuffer = BP.toArrayBuffer
return arr
}
var INVALID_BASE64_RE = /[^+\/0-9A-Za-z-_]/g
function base64clean (str) {
// Node strips out invalid characters like \n and \t from the string, base64-js does not
str = stringtrim(str).replace(INVALID_BASE64_RE, '')
// Node converts strings with length < 2 to ''
if (str.length < 2) return ''
// Node allows for non-padded base64 strings (missing trailing ===), base64-js does not
while (str.length % 4 !== 0) {
str = str + '='
}
return str
}
function stringtrim (str) {
if (str.trim) return str.trim()
return str.replace(/^\s+|\s+$/g, '')
}
function toHex (n) {
if (n < 16) return '0' + n.toString(16)
return n.toString(16)
}
function utf8ToBytes (string, units) {
units = units || Infinity
var codePoint
var length = string.length
var leadSurrogate = null
var bytes = []
var i = 0
for (; i < length; i++) {
codePoint = string.charCodeAt(i)
// is surrogate component
if (codePoint > 0xD7FF && codePoint < 0xE000) {
// last char was a lead
if (leadSurrogate) {
// 2 leads in a row
if (codePoint < 0xDC00) {
if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
leadSurrogate = codePoint
continue
} else {
// valid surrogate pair
codePoint = leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00 | 0x10000
leadSurrogate = null
}
} else {
// no lead yet
if (codePoint > 0xDBFF) {
// unexpected trail
if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
continue
} else if (i + 1 === length) {
// unpaired lead
if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
continue
} else {
// valid lead
leadSurrogate = codePoint
continue
}
}
} else if (leadSurrogate) {
// valid bmp char, but last char was a lead
if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
leadSurrogate = null
}
// encode utf8
if (codePoint < 0x80) {
if ((units -= 1) < 0) break
bytes.push(codePoint)
} else if (codePoint < 0x800) {
if ((units -= 2) < 0) break
bytes.push(
codePoint >> 0x6 | 0xC0,
codePoint & 0x3F | 0x80
)
} else if (codePoint < 0x10000) {
if ((units -= 3) < 0) break
bytes.push(
codePoint >> 0xC | 0xE0,
codePoint >> 0x6 & 0x3F | 0x80,
codePoint & 0x3F | 0x80
)
} else if (codePoint < 0x200000) {
if ((units -= 4) < 0) break
bytes.push(
codePoint >> 0x12 | 0xF0,
codePoint >> 0xC & 0x3F | 0x80,
codePoint >> 0x6 & 0x3F | 0x80,
codePoint & 0x3F | 0x80
)
} else {
throw new Error('Invalid code point')
}
}
return bytes
}
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 utf16leToBytes (str, units) {
var c, hi, lo
var byteArray = []
for (var i = 0; i < str.length; i++) {
if ((units -= 2) < 0) break
c = str.charCodeAt(i)
hi = c >> 8
lo = c % 256
byteArray.push(lo)
byteArray.push(hi)
}
return byteArray
}
function base64ToBytes (str) {
return base64.toByteArray(base64clean(str))
}
function blitBuffer (src, dst, offset, length) {
for (var i = 0; i < length; i++) {
if ((i + offset >= dst.length) || (i >= src.length)) break
dst[i + offset] = src[i]
}
return i
}
function decodeUtf8Char (str) {
try {
return decodeURIComponent(str)
} catch (err) {
return String.fromCharCode(0xFFFD) // UTF 8 invalid char
}
}
},{"base64-js":77,"ieee754":78,"is-array":79}],77:[function(require,module,exports){
var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
;(function (exports) {
'use strict';
var Arr = (typeof Uint8Array !== 'undefined')
? Uint8Array
: Array
var PLUS = '+'.charCodeAt(0)
var SLASH = '/'.charCodeAt(0)
var NUMBER = '0'.charCodeAt(0)
var LOWER = 'a'.charCodeAt(0)
var UPPER = 'A'.charCodeAt(0)
var PLUS_URL_SAFE = '-'.charCodeAt(0)
var SLASH_URL_SAFE = '_'.charCodeAt(0)
function decode (elt) {
var code = elt.charCodeAt(0)
if (code === PLUS ||
code === PLUS_URL_SAFE)
return 62 // '+'
if (code === SLASH ||
code === SLASH_URL_SAFE)
return 63 // '/'
if (code < NUMBER)
return -1 //no match
if (code < NUMBER + 10)
return code - NUMBER + 26 + 26
if (code < UPPER + 26)
return code - UPPER
if (code < LOWER + 26)
return code - LOWER + 26
}
function b64ToByteArray (b64) {
var i, j, l, tmp, placeHolders, arr
if (b64.length % 4 > 0) {
throw new Error('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
var len = b64.length
placeHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0
// base64 is 4/3 + up to two characters of the original data
arr = new Arr(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
var L = 0
function push (v) {
arr[L++] = v
}
for (i = 0, j = 0; i < l; i += 4, j += 3) {
tmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3))
push((tmp & 0xFF0000) >> 16)
push((tmp & 0xFF00) >> 8)
push(tmp & 0xFF)
}
if (placeHolders === 2) {
tmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4)
push(tmp & 0xFF)
} else if (placeHolders === 1) {
tmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2)
push((tmp >> 8) & 0xFF)
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 encode (num) {
return lookup.charAt(num)
}
function tripletToBase64 (num) {
return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(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 += encode(temp >> 2)
output += encode((temp << 4) & 0x3F)
output += '=='
break
case 2:
temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1])
output += encode(temp >> 10)
output += encode((temp >> 4) & 0x3F)
output += encode((temp << 2) & 0x3F)
output += '='
break
}
return output
}
exports.toByteArray = b64ToByteArray
exports.fromByteArray = uint8ToBase64
}(typeof exports === 'undefined' ? (this.base64js = {}) : exports))
},{}],78:[function(require,module,exports){
exports.read = function (buffer, offset, isLE, mLen, nBytes) {
var e, m
var eLen = nBytes * 8 - mLen - 1
var eMax = (1 << eLen) - 1
var eBias = eMax >> 1
var nBits = -7
var i = isLE ? (nBytes - 1) : 0
var d = isLE ? -1 : 1
var 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.write = function (buffer, value, offset, isLE, mLen, nBytes) {
var e, m, c
var eLen = nBytes * 8 - mLen - 1
var eMax = (1 << eLen) - 1
var eBias = eMax >> 1
var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0)
var i = isLE ? 0 : (nBytes - 1)
var d = isLE ? 1 : -1
var 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
}
},{}],79:[function(require,module,exports){
/**
* isArray
*/
var isArray = Array.isArray;
/**
* toString
*/
var str = Object.prototype.toString;
/**
* Whether or not the given `val`
* is an array.
*
* example:
*
* isArray([]);
* // > true
* isArray(arguments);
* // > false
* isArray('');
* // > false
*
* @param {mixed} val
* @return {bool}
*/
module.exports = isArray || function (val) {
return !! val && '[object Array]' == str.call(val);
};
},{}],80:[function(require,module,exports){
'use strict';
exports.randomBytes = exports.rng = exports.pseudoRandomBytes = exports.prng = require('randombytes')
exports.createHash = exports.Hash = require('create-hash')
exports.createHmac = exports.Hmac = require('create-hmac')
var hashes = ['sha1', 'sha224', 'sha256', 'sha384', 'sha512', 'md5', 'rmd160'].concat(Object.keys(require('browserify-sign/algos')))
exports.getHashes = function () {
return hashes;
}
var p = require('pbkdf2')
exports.pbkdf2 = p.pbkdf2
exports.pbkdf2Sync = p.pbkdf2Sync
var aes = require('browserify-aes');
[
'Cipher',
'createCipher',
'Cipheriv',
'createCipheriv',
'Decipher',
'createDecipher',
'Decipheriv',
'createDecipheriv',
'getCiphers',
'listCiphers'
].forEach(function (key) {
exports[key] = aes[key];
})
var dh = require('diffie-hellman');
[
'DiffieHellmanGroup',
'createDiffieHellmanGroup',
'getDiffieHellman',
'createDiffieHellman',
'DiffieHellman'
].forEach(function (key) {
exports[key] = dh[key];
})
var sign = require('browserify-sign');
[
'createSign',
'Sign',
'createVerify',
'Verify'
].forEach(function (key) {
exports[key] = sign[key];
})
exports.createECDH = require('create-ecdh')
var publicEncrypt = require('public-encrypt');
[
'publicEncrypt',
'privateEncrypt',
'publicDecrypt',
'privateDecrypt'
].forEach(function (key) {
exports[key] = publicEncrypt[key];
})
// the least I can do is make error messages for the rest of the node.js/crypto api.
;[
'createCredentials'
].forEach(function (name) {
exports[name] = function () {
throw new Error([
'sorry, ' + name + ' is not implemented yet',
'we accept pull requests',
'https://github.com/crypto-browserify/crypto-browserify'
].join('\n'));
}
})
},{"browserify-aes":84,"browserify-sign":100,"browserify-sign/algos":99,"create-ecdh":148,"create-hash":171,"create-hmac":183,"diffie-hellman":184,"pbkdf2":192,"public-encrypt":193,"randombytes":221}],81:[function(require,module,exports){
(function (Buffer){
var md5 = require('create-hash/md5')
module.exports = EVP_BytesToKey
function EVP_BytesToKey (password, keyLen, ivLen) {
if (!Buffer.isBuffer(password)) {
password = new Buffer(password, 'binary')
}
keyLen = keyLen / 8
ivLen = ivLen || 0
var ki = 0
var ii = 0
var key = new Buffer(keyLen)
var iv = new Buffer(ivLen)
var addmd = 0
var md_buf
var i
var bufs = []
while (true) {
if (addmd++ > 0) {
bufs.push(md_buf)
}
bufs.push(password)
md_buf = md5(Buffer.concat(bufs))
bufs = []
i = 0
if (keyLen > 0) {
while (true) {
if (keyLen === 0) {
break
}
if (i === md_buf.length) {
break
}
key[ki++] = md_buf[i]
keyLen--
i++
}
}
if (ivLen > 0 && i !== md_buf.length) {
while (true) {
if (ivLen === 0) {
break
}
if (i === md_buf.length) {
break
}
iv[ii++] = md_buf[i]
ivLen--
i++
}
}
if (keyLen === 0 && ivLen === 0) {
break
}
}
for (i = 0; i < md_buf.length; i++) {
md_buf[i] = 0
}
return {
key: key,
iv: iv
}
}
}).call(this,require("buffer").Buffer)
},{"buffer":76,"create-hash/md5":173}],82:[function(require,module,exports){
(function (Buffer){
// based on the aes implimentation in triple sec
// https://github.com/keybase/triplesec
// which is in turn based on the one from crypto-js
// https://code.google.com/p/crypto-js/
var uint_max = Math.pow(2, 32)
function fixup_uint32 (x) {
var ret, x_pos
ret = x > uint_max || x < 0 ? (x_pos = Math.abs(x) % uint_max, x < 0 ? uint_max - x_pos : x_pos) : x
return ret
}
function scrub_vec (v) {
for (var i = 0; i < v.length; v++) {
v[i] = 0
}
return false
}
function Global () {
this.SBOX = []
this.INV_SBOX = []
this.SUB_MIX = [[], [], [], []]
this.INV_SUB_MIX = [[], [], [], []]
this.init()
this.RCON = [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36]
}
Global.prototype.init = function () {
var d, i, sx, t, x, x2, x4, x8, xi, _i
d = (function () {
var _i, _results
_results = []
for (i = _i = 0; _i < 256; i = ++_i) {
if (i < 128) {
_results.push(i << 1)
} else {
_results.push((i << 1) ^ 0x11b)
}
}
return _results
})()
x = 0
xi = 0
for (i = _i = 0; _i < 256; i = ++_i) {
sx = xi ^ (xi << 1) ^ (xi << 2) ^ (xi << 3) ^ (xi << 4)
sx = (sx >>> 8) ^ (sx & 0xff) ^ 0x63
this.SBOX[x] = sx
this.INV_SBOX[sx] = x
x2 = d[x]
x4 = d[x2]
x8 = d[x4]
t = (d[sx] * 0x101) ^ (sx * 0x1010100)
this.SUB_MIX[0][x] = (t << 24) | (t >>> 8)
this.SUB_MIX[1][x] = (t << 16) | (t >>> 16)
this.SUB_MIX[2][x] = (t << 8) | (t >>> 24)
this.SUB_MIX[3][x] = t
t = (x8 * 0x1010101) ^ (x4 * 0x10001) ^ (x2 * 0x101) ^ (x * 0x1010100)
this.INV_SUB_MIX[0][sx] = (t << 24) | (t >>> 8)
this.INV_SUB_MIX[1][sx] = (t << 16) | (t >>> 16)
this.INV_SUB_MIX[2][sx] = (t << 8) | (t >>> 24)
this.INV_SUB_MIX[3][sx] = t
if (x === 0) {
x = xi = 1
} else {
x = x2 ^ d[d[d[x8 ^ x2]]]
xi ^= d[d[xi]]
}
}
return true
}
var G = new Global()
AES.blockSize = 4 * 4
AES.prototype.blockSize = AES.blockSize
AES.keySize = 256 / 8
AES.prototype.keySize = AES.keySize
function bufferToArray (buf) {
var len = buf.length / 4
var out = new Array(len)
var i = -1
while (++i < len) {
out[i] = buf.readUInt32BE(i * 4)
}
return out
}
function AES (key) {
this._key = bufferToArray(key)
this._doReset()
}
AES.prototype._doReset = function () {
var invKsRow, keySize, keyWords, ksRow, ksRows, t
keyWords = this._key
keySize = keyWords.length
this._nRounds = keySize + 6
ksRows = (this._nRounds + 1) * 4
this._keySchedule = []
for (ksRow = 0; ksRow < ksRows; ksRow++) {
this._keySchedule[ksRow] = ksRow < keySize ? keyWords[ksRow] : (t = this._keySchedule[ksRow - 1], (ksRow % keySize) === 0 ? (t = (t << 8) | (t >>> 24), t = (G.SBOX[t >>> 24] << 24) | (G.SBOX[(t >>> 16) & 0xff] << 16) | (G.SBOX[(t >>> 8) & 0xff] << 8) | G.SBOX[t & 0xff], t ^= G.RCON[(ksRow / keySize) | 0] << 24) : keySize > 6 && ksRow % keySize === 4 ? t = (G.SBOX[t >>> 24] << 24) | (G.SBOX[(t >>> 16) & 0xff] << 16) | (G.SBOX[(t >>> 8) & 0xff] << 8) | G.SBOX[t & 0xff] : void 0, this._keySchedule[ksRow - keySize] ^ t)
}
this._invKeySchedule = []
for (invKsRow = 0; invKsRow < ksRows; invKsRow++) {
ksRow = ksRows - invKsRow
t = this._keySchedule[ksRow - (invKsRow % 4 ? 0 : 4)]
this._invKeySchedule[invKsRow] = invKsRow < 4 || ksRow <= 4 ? t : G.INV_SUB_MIX[0][G.SBOX[t >>> 24]] ^ G.INV_SUB_MIX[1][G.SBOX[(t >>> 16) & 0xff]] ^ G.INV_SUB_MIX[2][G.SBOX[(t >>> 8) & 0xff]] ^ G.INV_SUB_MIX[3][G.SBOX[t & 0xff]]
}
return true
}
AES.prototype.encryptBlock = function (M) {
M = bufferToArray(new Buffer(M))
var out = this._doCryptBlock(M, this._keySchedule, G.SUB_MIX, G.SBOX)
var buf = new Buffer(16)
buf.writeUInt32BE(out[0], 0)
buf.writeUInt32BE(out[1], 4)
buf.writeUInt32BE(out[2], 8)
buf.writeUInt32BE(out[3], 12)
return buf
}
AES.prototype.decryptBlock = function (M) {
M = bufferToArray(new Buffer(M))
var temp = [M[3], M[1]]
M[1] = temp[0]
M[3] = temp[1]
var out = this._doCryptBlock(M, this._invKeySchedule, G.INV_SUB_MIX, G.INV_SBOX)
var buf = new Buffer(16)
buf.writeUInt32BE(out[0], 0)
buf.writeUInt32BE(out[3], 4)
buf.writeUInt32BE(out[2], 8)
buf.writeUInt32BE(out[1], 12)
return buf
}
AES.prototype.scrub = function () {
scrub_vec(this._keySchedule)
scrub_vec(this._invKeySchedule)
scrub_vec(this._key)
}
AES.prototype._doCryptBlock = function (M, keySchedule, SUB_MIX, SBOX) {
var ksRow, s0, s1, s2, s3, t0, t1, t2, t3
s0 = M[0] ^ keySchedule[0]
s1 = M[1] ^ keySchedule[1]
s2 = M[2] ^ keySchedule[2]
s3 = M[3] ^ keySchedule[3]
ksRow = 4
for (var round = 1; round < this._nRounds; round++) {
t0 = SUB_MIX[0][s0 >>> 24] ^ SUB_MIX[1][(s1 >>> 16) & 0xff] ^ SUB_MIX[2][(s2 >>> 8) & 0xff] ^ SUB_MIX[3][s3 & 0xff] ^ keySchedule[ksRow++]
t1 = SUB_MIX[0][s1 >>> 24] ^ SUB_MIX[1][(s2 >>> 16) & 0xff] ^ SUB_MIX[2][(s3 >>> 8) & 0xff] ^ SUB_MIX[3][s0 & 0xff] ^ keySchedule[ksRow++]
t2 = SUB_MIX[0][s2 >>> 24] ^ SUB_MIX[1][(s3 >>> 16) & 0xff] ^ SUB_MIX[2][(s0 >>> 8) & 0xff] ^ SUB_MIX[3][s1 & 0xff] ^ keySchedule[ksRow++]
t3 = SUB_MIX[0][s3 >>> 24] ^ SUB_MIX[1][(s0 >>> 16) & 0xff] ^ SUB_MIX[2][(s1 >>> 8) & 0xff] ^ SUB_MIX[3][s2 & 0xff] ^ keySchedule[ksRow++]
s0 = t0
s1 = t1
s2 = t2
s3 = t3
}
t0 = ((SBOX[s0 >>> 24] << 24) | (SBOX[(s1 >>> 16) & 0xff] << 16) | (SBOX[(s2 >>> 8) & 0xff] << 8) | SBOX[s3 & 0xff]) ^ keySchedule[ksRow++]
t1 = ((SBOX[s1 >>> 24] << 24) | (SBOX[(s2 >>> 16) & 0xff] << 16) | (SBOX[(s3 >>> 8) & 0xff] << 8) | SBOX[s0 & 0xff]) ^ keySchedule[ksRow++]
t2 = ((SBOX[s2 >>> 24] << 24) | (SBOX[(s3 >>> 16) & 0xff] << 16) | (SBOX[(s0 >>> 8) & 0xff] << 8) | SBOX[s1 & 0xff]) ^ keySchedule[ksRow++]
t3 = ((SBOX[s3 >>> 24] << 24) | (SBOX[(s0 >>> 16) & 0xff] << 16) | (SBOX[(s1 >>> 8) & 0xff] << 8) | SBOX[s2 & 0xff]) ^ keySchedule[ksRow++]
return [
fixup_uint32(t0),
fixup_uint32(t1),
fixup_uint32(t2),
fixup_uint32(t3)
]
}
exports.AES = AES
}).call(this,require("buffer").Buffer)
},{"buffer":76}],83:[function(require,module,exports){
(function (Buffer){
var aes = require('./aes')
var Transform = require('./cipherBase')
var inherits = require('inherits')
var GHASH = require('./ghash')
var xor = require('buffer-xor')
inherits(StreamCipher, Transform)
module.exports = StreamCipher
function StreamCipher (mode, key, iv, decrypt) {
if (!(this instanceof StreamCipher)) {
return new StreamCipher(mode, key, iv)
}
Transform.call(this)
this._finID = Buffer.concat([iv, new Buffer([0, 0, 0, 1])])
iv = Buffer.concat([iv, new Buffer([0, 0, 0, 2])])
this._cipher = new aes.AES(key)
this._prev = new Buffer(iv.length)
this._cache = new Buffer('')
this._secCache = new Buffer('')
this._decrypt = decrypt
this._alen = 0
this._len = 0
iv.copy(this._prev)
this._mode = mode
var h = new Buffer(4)
h.fill(0)
this._ghash = new GHASH(this._cipher.encryptBlock(h))
this._authTag = null
this._called = false
}
StreamCipher.prototype._update = function (chunk) {
if (!this._called && this._alen) {
var rump = 16 - (this._alen % 16)
if (rump < 16) {
rump = new Buffer(rump)
rump.fill(0)
this._ghash.update(rump)
}
}
this._called = true
var out = this._mode.encrypt(this, chunk)
if (this._decrypt) {
this._ghash.update(chunk)
} else {
this._ghash.update(out)
}
this._len += chunk.length
return out
}
StreamCipher.prototype._final = function () {
if (this._decrypt && !this._authTag) {
throw new Error('Unsupported state or unable to authenticate data')
}
var tag = xor(this._ghash.final(this._alen * 8, this._len * 8), this._cipher.encryptBlock(this._finID))
if (this._decrypt) {
if (xorTest(tag, this._authTag)) {
throw new Error('Unsupported state or unable to authenticate data')
}
} else {
this._authTag = tag
}
this._cipher.scrub()
}
StreamCipher.prototype.getAuthTag = function getAuthTag () {
if (!this._decrypt && Buffer.isBuffer(this._authTag)) {
return this._authTag
} else {
throw new Error('Attempting to get auth tag in unsupported state')
}
}
StreamCipher.prototype.setAuthTag = function setAuthTag (tag) {
if (this._decrypt) {
this._authTag = tag
} else {
throw new Error('Attempting to set auth tag in unsupported state')
}
}
StreamCipher.prototype.setAAD = function setAAD (buf) {
if (!this._called) {
this._ghash.update(buf)
this._alen += buf.length
} else {
throw new Error('Attempting to set AAD in unsupported state')
}
}
function xorTest (a, b) {
var out = 0
if (a.length !== b.length) {
out++
}
var len = Math.min(a.length, b.length)
var i = -1
while (++i < len) {
out += (a[i] ^ b[i])
}
return out
}
}).call(this,require("buffer").Buffer)
},{"./aes":82,"./cipherBase":85,"./ghash":88,"buffer":76,"buffer-xor":97,"inherits":223}],84:[function(require,module,exports){
var ciphers = require('./encrypter')
exports.createCipher = exports.Cipher = ciphers.createCipher
exports.createCipheriv = exports.Cipheriv = ciphers.createCipheriv
var deciphers = require('./decrypter')
exports.createDecipher = exports.Decipher = deciphers.createDecipher
exports.createDecipheriv = exports.Decipheriv = deciphers.createDecipheriv
var modes = require('./modes')
function getCiphers () {
return Object.keys(modes)
}
exports.listCiphers = exports.getCiphers = getCiphers
},{"./decrypter":86,"./encrypter":87,"./modes":89}],85:[function(require,module,exports){
(function (Buffer){
var Transform = require('stream').Transform
var inherits = require('inherits')
module.exports = CipherBase
inherits(CipherBase, Transform)
function CipherBase () {
Transform.call(this)
this._base64Cache = new Buffer('')
}
CipherBase.prototype.update = function (data, inputEnc, outputEnc) {
if (typeof data === 'string') {
data = new Buffer(data, inputEnc)
}
var outData = this._update(data)
if (outputEnc) {
outData = this._toString(outData, outputEnc)
}
return outData
}
CipherBase.prototype._transform = function (data, _, next) {
this.push(this._update(data))
next()
}
CipherBase.prototype._flush = function (next) {
try {
this.push(this._final())
} catch(e) {
return next(e)
}
next()
}
CipherBase.prototype.final = function (outputEnc) {
var outData = this._final() || new Buffer('')
if (outputEnc) {
outData = this._toString(outData, outputEnc, true)
}
return outData
}
CipherBase.prototype._toString = function (value, enc, final) {
if (enc !== 'base64') {
return value.toString(enc)
}
this._base64Cache = Buffer.concat([this._base64Cache, value])
var out
if (final) {
out = this._base64Cache
this._base64Cache = null
return out.toString('base64')
}
var len = this._base64Cache.length
var overhang = len % 3
if (!overhang) {
out = this._base64Cache
this._base64Cache = new Buffer('')
return out.toString('base64')
}
var newLen = len - overhang
if (!newLen) {
return ''
}
out = this._base64Cache.slice(0, newLen)
this._base64Cache = this._base64Cache.slice(-overhang)
return out.toString('base64')
}
}).call(this,require("buffer").Buffer)
},{"buffer":76,"inherits":223,"stream":241}],86:[function(require,module,exports){
(function (Buffer){
var aes = require('./aes')
var Transform = require('./cipherBase')
var inherits = require('inherits')
var modes = require('./modes')
var StreamCipher = require('./streamCipher')
var AuthCipher = require('./authCipher')
var ebtk = require('./EVP_BytesToKey')
inherits(Decipher, Transform)
function Decipher (mode, key, iv) {
if (!(this instanceof Decipher)) {
return new Decipher(mode, key, iv)
}
Transform.call(this)
this._cache = new Splitter()
this._last = void 0
this._cipher = new aes.AES(key)
this._prev = new Buffer(iv.length)
iv.copy(this._prev)
this._mode = mode
this._autopadding = true
}
Decipher.prototype._update = function (data) {
this._cache.add(data)
var chunk
var thing
var out = []
while ((chunk = this._cache.get(this._autopadding))) {
thing = this._mode.decrypt(this, chunk)
out.push(thing)
}
return Buffer.concat(out)
}
Decipher.prototype._final = function () {
var chunk = this._cache.flush()
if (this._autopadding) {
return unpad(this._mode.decrypt(this, chunk))
} else if (chunk) {
throw new Error('data not multiple of block length')
}
}
Decipher.prototype.setAutoPadding = function (setTo) {
this._autopadding = !!setTo
}
function Splitter () {
if (!(this instanceof Splitter)) {
return new Splitter()
}
this.cache = new Buffer('')
}
Splitter.prototype.add = function (data) {
this.cache = Buffer.concat([this.cache, data])
}
Splitter.prototype.get = function (autoPadding) {
var out
if (autoPadding) {
if (this.cache.length > 16) {
out = this.cache.slice(0, 16)
this.cache = this.cache.slice(16)
return out
}
} else {
if (this.cache.length >= 16) {
out = this.cache.slice(0, 16)
this.cache = this.cache.slice(16)
return out
}
}
return null
}
Splitter.prototype.flush = function () {
if (this.cache.length) {
return this.cache
}
}
function unpad (last) {
var padded = last[15]
var i = -1
while (++i < padded) {
if (last[(i + (16 - padded))] !== padded) {
throw new Error('unable to decrypt data')
}
}
if (padded === 16) {
return
}
return last.slice(0, 16 - padded)
}
var modelist = {
ECB: require('./modes/ecb'),
CBC: require('./modes/cbc'),
CFB: require('./modes/cfb'),
CFB8: require('./modes/cfb8'),
CFB1: require('./modes/cfb1'),
OFB: require('./modes/ofb'),
CTR: require('./modes/ctr'),
GCM: require('./modes/ctr')
}
function createDecipheriv (suite, password, iv) {
var config = modes[suite.toLowerCase()]
if (!config) {
throw new TypeError('invalid suite type')
}
if (typeof iv === 'string') {
iv = new Buffer(iv)
}
if (typeof password === 'string') {
password = new Buffer(password)
}
if (password.length !== config.key / 8) {
throw new TypeError('invalid key length ' + password.length)
}
if (iv.length !== config.iv) {
throw new TypeError('invalid iv length ' + iv.length)
}
if (config.type === 'stream') {
return new StreamCipher(modelist[config.mode], password, iv, true)
} else if (config.type === 'auth') {
return new AuthCipher(modelist[config.mode], password, iv, true)
}
return new Decipher(modelist[config.mode], password, iv)
}
function createDecipher (suite, password) {
var config = modes[suite.toLowerCase()]
if (!config) {
throw new TypeError('invalid suite type')
}
var keys = ebtk(password, config.key, config.iv)
return createDecipheriv(suite, keys.key, keys.iv)
}
exports.createDecipher = createDecipher
exports.createDecipheriv = createDecipheriv
}).call(this,require("buffer").Buffer)
},{"./EVP_BytesToKey":81,"./aes":82,"./authCipher":83,"./cipherBase":85,"./modes":89,"./modes/cbc":90,"./modes/cfb":91,"./modes/cfb1":92,"./modes/cfb8":93,"./modes/ctr":94,"./modes/ecb":95,"./modes/ofb":96,"./streamCipher":98,"buffer":76,"inherits":223}],87:[function(require,module,exports){
(function (Buffer){
var aes = require('./aes')
var Transform = require('./cipherBase')
var inherits = require('inherits')
var modes = require('./modes')
var ebtk = require('./EVP_BytesToKey')
var StreamCipher = require('./streamCipher')
var AuthCipher = require('./authCipher')
inherits(Cipher, Transform)
function Cipher (mode, key, iv) {
if (!(this instanceof Cipher)) {
return new Cipher(mode, key, iv)
}
Transform.call(this)
this._cache = new Splitter()
this._cipher = new aes.AES(key)
this._prev = new Buffer(iv.length)
iv.copy(this._prev)
this._mode = mode
this._autopadding = true
}
Cipher.prototype._update = function (data) {
this._cache.add(data)
var chunk
var thing
var out = []
while ((chunk = this._cache.get())) {
thing = this._mode.encrypt(this, chunk)
out.push(thing)
}
return Buffer.concat(out)
}
Cipher.prototype._final = function () {
var chunk = this._cache.flush()
if (this._autopadding) {
chunk = this._mode.encrypt(this, chunk)
this._cipher.scrub()
return chunk
} else if (chunk.toString('hex') !== '10101010101010101010101010101010') {
this._cipher.scrub()
throw new Error('data not multiple of block length')
}
}
Cipher.prototype.setAutoPadding = function (setTo) {
this._autopadding = !!setTo
}
function Splitter () {
if (!(this instanceof Splitter)) {
return new Splitter()
}
this.cache = new Buffer('')
}
Splitter.prototype.add = function (data) {
this.cache = Buffer.concat([this.cache, data])
}
Splitter.prototype.get = function () {
if (this.cache.length > 15) {
var out = this.cache.slice(0, 16)
this.cache = this.cache.slice(16)
return out
}
return null
}
Splitter.prototype.flush = function () {
var len = 16 - this.cache.length
var padBuff = new Buffer(len)
var i = -1
while (++i < len) {
padBuff.writeUInt8(len, i)
}
var out = Buffer.concat([this.cache, padBuff])
return out
}
var modelist = {
ECB: require('./modes/ecb'),
CBC: require('./modes/cbc'),
CFB: require('./modes/cfb'),
CFB8: require('./modes/cfb8'),
CFB1: require('./modes/cfb1'),
OFB: require('./modes/ofb'),
CTR: require('./modes/ctr'),
GCM: require('./modes/ctr')
}
function createCipheriv (suite, password, iv) {
var config = modes[suite.toLowerCase()]
if (!config) {
throw new TypeError('invalid suite type')
}
if (typeof iv === 'string') {
iv = new Buffer(iv)
}
if (typeof password === 'string') {
password = new Buffer(password)
}
if (password.length !== config.key / 8) {
throw new TypeError('invalid key length ' + password.length)
}
if (iv.length !== config.iv) {
throw new TypeError('invalid iv length ' + iv.length)
}
if (config.type === 'stream') {
return new StreamCipher(modelist[config.mode], password, iv)
} else if (config.type === 'auth') {
return new AuthCipher(modelist[config.mode], password, iv)
}
return new Cipher(modelist[config.mode], password, iv)
}
function createCipher (suite, password) {
var config = modes[suite.toLowerCase()]
if (!config) {
throw new TypeError('invalid suite type')
}
var keys = ebtk(password, config.key, config.iv)
return createCipheriv(suite, keys.key, keys.iv)
}
exports.createCipheriv = createCipheriv
exports.createCipher = createCipher
}).call(this,require("buffer").Buffer)
},{"./EVP_BytesToKey":81,"./aes":82,"./authCipher":83,"./cipherBase":85,"./modes":89,"./modes/cbc":90,"./modes/cfb":91,"./modes/cfb1":92,"./modes/cfb8":93,"./modes/ctr":94,"./modes/ecb":95,"./modes/ofb":96,"./streamCipher":98,"buffer":76,"inherits":223}],88:[function(require,module,exports){
(function (Buffer){
var zeros = new Buffer(16)
zeros.fill(0)
module.exports = GHASH
function GHASH (key) {
this.h = key
this.state = new Buffer(16)
this.state.fill(0)
this.cache = new Buffer('')
}
// from http://bitwiseshiftleft.github.io/sjcl/doc/symbols/src/core_gcm.js.html
// by Juho Vähä-Herttua
GHASH.prototype.ghash = function (block) {
var i = -1
while (++i < block.length) {
this.state[i] ^= block[i]
}
this._multiply()
}
GHASH.prototype._multiply = function () {
var Vi = toArray(this.h)
var Zi = [0, 0, 0, 0]
var j, xi, lsb_Vi
var i = -1
while (++i < 128) {
xi = (this.state[~~(i / 8)] & (1 << (7 - i % 8))) !== 0
if (xi) {
// Z_i+1 = Z_i ^ V_i
Zi = xor(Zi, Vi)
}
// Store the value of LSB(V_i)
lsb_Vi = (Vi[3] & 1) !== 0
// V_i+1 = V_i >> 1
for (j = 3; j > 0; j--) {
Vi[j] = (Vi[j] >>> 1) | ((Vi[j - 1] & 1) << 31)
}
Vi[0] = Vi[0] >>> 1
// If LSB(V_i) is 1, V_i+1 = (V_i >> 1) ^ R
if (lsb_Vi) {
Vi[0] = Vi[0] ^ (0xe1 << 24)
}
}
this.state = fromArray(Zi)
}
GHASH.prototype.update = function (buf) {
this.cache = Buffer.concat([this.cache, buf])
var chunk
while (this.cache.length >= 16) {
chunk = this.cache.slice(0, 16)
this.cache = this.cache.slice(16)
this.ghash(chunk)
}
}
GHASH.prototype.final = function (abl, bl) {
if (this.cache.length) {
this.ghash(Buffer.concat([this.cache, zeros], 16))
}
this.ghash(fromArray([
0, abl,
0, bl
]))
return this.state
}
function toArray (buf) {
return [
buf.readUInt32BE(0),
buf.readUInt32BE(4),
buf.readUInt32BE(8),
buf.readUInt32BE(12)
]
}
function fromArray (out) {
out = out.map(fixup_uint32)
var buf = new Buffer(16)
buf.writeUInt32BE(out[0], 0)
buf.writeUInt32BE(out[1], 4)
buf.writeUInt32BE(out[2], 8)
buf.writeUInt32BE(out[3], 12)
return buf
}
var uint_max = Math.pow(2, 32)
function fixup_uint32 (x) {
var ret, x_pos
ret = x > uint_max || x < 0 ? (x_pos = Math.abs(x) % uint_max, x < 0 ? uint_max - x_pos : x_pos) : x
return ret
}
function xor (a, b) {
return [
a[0] ^ b[0],
a[1] ^ b[1],
a[2] ^ b[2],
a[3] ^ b[3]
]
}
}).call(this,require("buffer").Buffer)
},{"buffer":76}],89:[function(require,module,exports){
exports['aes-128-ecb'] = {
cipher: 'AES',
key: 128,
iv: 0,
mode: 'ECB',
type: 'block'
}
exports['aes-192-ecb'] = {
cipher: 'AES',
key: 192,
iv: 0,
mode: 'ECB',
type: 'block'
}
exports['aes-256-ecb'] = {
cipher: 'AES',
key: 256,
iv: 0,
mode: 'ECB',
type: 'block'
}
exports['aes-128-cbc'] = {
cipher: 'AES',
key: 128,
iv: 16,
mode: 'CBC',
type: 'block'
}
exports['aes-192-cbc'] = {
cipher: 'AES',
key: 192,
iv: 16,
mode: 'CBC',
type: 'block'
}
exports['aes-256-cbc'] = {
cipher: 'AES',
key: 256,
iv: 16,
mode: 'CBC',
type: 'block'
}
exports['aes128'] = exports['aes-128-cbc']
exports['aes192'] = exports['aes-192-cbc']
exports['aes256'] = exports['aes-256-cbc']
exports['aes-128-cfb'] = {
cipher: 'AES',
key: 128,
iv: 16,
mode: 'CFB',
type: 'stream'
}
exports['aes-192-cfb'] = {
cipher: 'AES',
key: 192,
iv: 16,
mode: 'CFB',
type: 'stream'
}
exports['aes-256-cfb'] = {
cipher: 'AES',
key: 256,
iv: 16,
mode: 'CFB',
type: 'stream'
}
exports['aes-128-cfb8'] = {
cipher: 'AES',
key: 128,
iv: 16,
mode: 'CFB8',
type: 'stream'
}
exports['aes-192-cfb8'] = {
cipher: 'AES',
key: 192,
iv: 16,
mode: 'CFB8',
type: 'stream'
}
exports['aes-256-cfb8'] = {
cipher: 'AES',
key: 256,
iv: 16,
mode: 'CFB8',
type: 'stream'
}
exports['aes-128-cfb1'] = {
cipher: 'AES',
key: 128,
iv: 16,
mode: 'CFB1',
type: 'stream'
}
exports['aes-192-cfb1'] = {
cipher: 'AES',
key: 192,
iv: 16,
mode: 'CFB1',
type: 'stream'
}
exports['aes-256-cfb1'] = {
cipher: 'AES',
key: 256,
iv: 16,
mode: 'CFB1',
type: 'stream'
}
exports['aes-128-ofb'] = {
cipher: 'AES',
key: 128,
iv: 16,
mode: 'OFB',
type: 'stream'
}
exports['aes-192-ofb'] = {
cipher: 'AES',
key: 192,
iv: 16,
mode: 'OFB',
type: 'stream'
}
exports['aes-256-ofb'] = {
cipher: 'AES',
key: 256,
iv: 16,
mode: 'OFB',
type: 'stream'
}
exports['aes-128-ctr'] = {
cipher: 'AES',
key: 128,
iv: 16,
mode: 'CTR',
type: 'stream'
}
exports['aes-192-ctr'] = {
cipher: 'AES',
key: 192,
iv: 16,
mode: 'CTR',
type: 'stream'
}
exports['aes-256-ctr'] = {
cipher: 'AES',
key: 256,
iv: 16,
mode: 'CTR',
type: 'stream'
}
exports['aes-128-gcm'] = {
cipher: 'AES',
key: 128,
iv: 12,
mode: 'GCM',
type: 'auth'
}
exports['aes-192-gcm'] = {
cipher: 'AES',
key: 192,
iv: 12,
mode: 'GCM',
type: 'auth'
}
exports['aes-256-gcm'] = {
cipher: 'AES',
key: 256,
iv: 12,
mode: 'GCM',
type: 'auth'
}
},{}],90:[function(require,module,exports){
var xor = require('buffer-xor')
exports.encrypt = function (self, block) {
var data = xor(block, self._prev)
self._prev = self._cipher.encryptBlock(data)
return self._prev
}
exports.decrypt = function (self, block) {
var pad = self._prev
self._prev = block
var out = self._cipher.decryptBlock(block)
return xor(out, pad)
}
},{"buffer-xor":97}],91:[function(require,module,exports){
(function (Buffer){
var xor = require('buffer-xor')
exports.encrypt = function (self, data, decrypt) {
var out = new Buffer('')
var len
while (data.length) {
if (self._cache.length === 0) {
self._cache = self._cipher.encryptBlock(self._prev)
self._prev = new Buffer('')
}
if (self._cache.length <= data.length) {
len = self._cache.length
out = Buffer.concat([out, encryptStart(self, data.slice(0, len), decrypt)])
data = data.slice(len)
} else {
out = Buffer.concat([out, encryptStart(self, data, decrypt)])
break
}
}
return out
}
function encryptStart (self, data, decrypt) {
var len = data.length
var out = xor(data, self._cache)
self._cache = self._cache.slice(len)
self._prev = Buffer.concat([self._prev, decrypt ? data : out])
return out
}
}).call(this,require("buffer").Buffer)
},{"buffer":76,"buffer-xor":97}],92:[function(require,module,exports){
(function (Buffer){
function encryptByte (self, byteParam, decrypt) {
var pad
var i = -1
var len = 8
var out = 0
var bit, value
while (++i < len) {
pad = self._cipher.encryptBlock(self._prev)
bit = (byteParam & (1 << (7 - i))) ? 0x80 : 0
value = pad[0] ^ bit
out += ((value & 0x80) >> (i % 8))
self._prev = shiftIn(self._prev, decrypt ? bit : value)
}
return out
}
exports.encrypt = function (self, chunk, decrypt) {
var len = chunk.length
var out = new Buffer(len)
var i = -1
while (++i < len) {
out[i] = encryptByte(self, chunk[i], decrypt)
}
return out
}
function shiftIn (buffer, value) {
var len = buffer.length
var i = -1
var out = new Buffer(buffer.length)
buffer = Buffer.concat([buffer, new Buffer([value])])
while (++i < len) {
out[i] = buffer[i] << 1 | buffer[i + 1] >> (7)
}
return out
}
}).call(this,require("buffer").Buffer)
},{"buffer":76}],93:[function(require,module,exports){
(function (Buffer){
function encryptByte (self, byteParam, decrypt) {
var pad = self._cipher.encryptBlock(self._prev)
var out = pad[0] ^ byteParam
self._prev = Buffer.concat([self._prev.slice(1), new Buffer([decrypt ? byteParam : out])])
return out
}
exports.encrypt = function (self, chunk, decrypt) {
var len = chunk.length
var out = new Buffer(len)
var i = -1
while (++i < len) {
out[i] = encryptByte(self, chunk[i], decrypt)
}
return out
}
}).call(this,require("buffer").Buffer)
},{"buffer":76}],94:[function(require,module,exports){
(function (Buffer){
var xor = require('buffer-xor')
function incr32 (iv) {
var len = iv.length
var item
while (len--) {
item = iv.readUInt8(len)
if (item === 255) {
iv.writeUInt8(0, len)
} else {
item++
iv.writeUInt8(item, len)
break
}
}
}
function getBlock (self) {
var out = self._cipher.encryptBlock(self._prev)
incr32(self._prev)
return out
}
exports.encrypt = function (self, chunk) {
while (self._cache.length < chunk.length) {
self._cache = Buffer.concat([self._cache, getBlock(self)])
}
var pad = self._cache.slice(0, chunk.length)
self._cache = self._cache.slice(chunk.length)
return xor(chunk, pad)
}
}).call(this,require("buffer").Buffer)
},{"buffer":76,"buffer-xor":97}],95:[function(require,module,exports){
exports.encrypt = function (self, block) {
return self._cipher.encryptBlock(block)
}
exports.decrypt = function (self, block) {
return self._cipher.decryptBlock(block)
}
},{}],96:[function(require,module,exports){
(function (Buffer){
var xor = require('buffer-xor')
function getBlock (self) {
self._prev = self._cipher.encryptBlock(self._prev)
return self._prev
}
exports.encrypt = function (self, chunk) {
while (self._cache.length < chunk.length) {
self._cache = Buffer.concat([self._cache, getBlock(self)])
}
var pad = self._cache.slice(0, chunk.length)
self._cache = self._cache.slice(chunk.length)
return xor(chunk, pad)
}
}).call(this,require("buffer").Buffer)
},{"buffer":76,"buffer-xor":97}],97:[function(require,module,exports){
(function (Buffer){
module.exports = function xor (a, b) {
var length = Math.min(a.length, b.length)
var buffer = new Buffer(length)
for (var i = 0; i < length; ++i) {
buffer[i] = a[i] ^ b[i]
}
return buffer
}
}).call(this,require("buffer").Buffer)
},{"buffer":76}],98:[function(require,module,exports){
(function (Buffer){
var aes = require('./aes')
var Transform = require('./cipherBase')
var inherits = require('inherits')
inherits(StreamCipher, Transform)
module.exports = StreamCipher
function StreamCipher (mode, key, iv, decrypt) {
if (!(this instanceof StreamCipher)) {
return new StreamCipher(mode, key, iv)
}
Transform.call(this)
this._cipher = new aes.AES(key)
this._prev = new Buffer(iv.length)
this._cache = new Buffer('')
this._secCache = new Buffer('')
this._decrypt = decrypt
iv.copy(this._prev)
this._mode = mode
}
StreamCipher.prototype._update = function (chunk) {
return this._mode.encrypt(this, chunk, this._decrypt)
}
StreamCipher.prototype._final = function () {
this._cipher.scrub()
}
}).call(this,require("buffer").Buffer)
},{"./aes":82,"./cipherBase":85,"buffer":76,"inherits":223}],99:[function(require,module,exports){
(function (Buffer){
'use strict'
exports['RSA-SHA224'] = exports.sha224WithRSAEncryption = {
sign: 'rsa',
hash: 'sha224',
id: new Buffer('302d300d06096086480165030402040500041c', 'hex')
}
exports['RSA-SHA256'] = exports.sha256WithRSAEncryption = {
sign: 'rsa',
hash: 'sha256',
id: new Buffer('3031300d060960864801650304020105000420', 'hex')
}
exports['RSA-SHA384'] = exports.sha384WithRSAEncryption = {
sign: 'rsa',
hash: 'sha384',
id: new Buffer('3041300d060960864801650304020205000430', 'hex')
}
exports['RSA-SHA512'] = exports.sha512WithRSAEncryption = {
sign: 'rsa',
hash: 'sha512',
id: new Buffer('3051300d060960864801650304020305000440', 'hex')
}
exports['RSA-SHA1'] = {
sign: 'rsa',
hash: 'sha1',
id: new Buffer('3021300906052b0e03021a05000414', 'hex')
}
exports['ecdsa-with-SHA1'] = {
sign: 'ecdsa',
hash: 'sha1',
id: new Buffer('', 'hex')
}
exports.DSA = exports['DSA-SHA1'] = exports['DSA-SHA'] = {
sign: 'dsa',
hash: 'sha1',
id: new Buffer('', 'hex')
}
exports['DSA-SHA224'] = exports['DSA-WITH-SHA224'] = {
sign: 'dsa',
hash: 'sha224',
id: new Buffer('', 'hex')
}
exports['DSA-SHA256'] = exports['DSA-WITH-SHA256'] = {
sign: 'dsa',
hash: 'sha256',
id: new Buffer('', 'hex')
}
exports['DSA-SHA384'] = exports['DSA-WITH-SHA384'] = {
sign: 'dsa',
hash: 'sha384',
id: new Buffer('', 'hex')
}
exports['DSA-SHA512'] = exports['DSA-WITH-SHA512'] = {
sign: 'dsa',
hash: 'sha512',
id: new Buffer('', 'hex')
}
exports['DSA-RIPEMD160'] = {
sign: 'dsa',
hash: 'rmd160',
id: new Buffer('', 'hex')
}
exports['RSA-RIPEMD160'] = exports.ripemd160WithRSA = {
sign: 'rsa',
hash: 'rmd160',
id: new Buffer('3021300906052b2403020105000414', 'hex')
}
exports['RSA-MD5'] = exports.md5WithRSAEncryption = {
sign: 'rsa',
hash: 'md5',
id: new Buffer('3020300c06082a864886f70d020505000410', 'hex')
}
}).call(this,require("buffer").Buffer)
},{"buffer":76}],100:[function(require,module,exports){
(function (Buffer){
'use strict'
var sign = require('./sign')
var verify = require('./verify')
var stream = require('stream')
var inherits = require('inherits')
var _algos = require('./algos')
var createHash = require('create-hash')
var algos = {}
Object.keys(_algos).forEach(function (key) {
algos[key] = algos[key.toLowerCase()] = _algos[key]
})
exports.createSign = exports.Sign = createSign
function createSign (algorithm) {
return new Sign(algorithm)
}
exports.createVerify = exports.Verify = createVerify
function createVerify (algorithm) {
return new Verify(algorithm)
}
inherits(Sign, stream.Writable)
function Sign (algorithm) {
stream.Writable.call(this)
var data = algos[algorithm]
if (!data)
throw new Error('Unknown message digest')
this._hashType = data.hash
this._hash = createHash(data.hash)
this._tag = data.id
this._signType = data.sign
}
Sign.prototype._write = function _write (data, _, done) {
this._hash.update(data)
done()
}
Sign.prototype.update = function update (data, enc) {
if (typeof data === 'string')
data = new Buffer(data, enc)
this._hash.update(data)
return this
}
Sign.prototype.sign = function signMethod (key, enc) {
this.end()
var hash = this._hash.digest()
var sig = sign(Buffer.concat([this._tag, hash]), key, this._hashType, this._signType)
if (enc) {
sig = sig.toString(enc)
}
return sig
}
inherits(Verify, stream.Writable)
function Verify (algorithm) {
stream.Writable.call(this)
var data = algos[algorithm]
if (!data)
throw new Error('Unknown message digest')
this._hash = createHash(data.hash)
this._tag = data.id
this._signType = data.sign
}
Verify.prototype._write = function _write (data, _, done) {
this._hash.update(data)
done()
}
Verify.prototype.update = function update (data, enc) {
if (typeof data === 'string')
data = new Buffer(data, enc)
this._hash.update(data)
return this
}
Verify.prototype.verify = function verifyMethod (key, sig, enc) {
this.end()
var hash = this._hash.digest()
if (typeof sig === 'string')
sig = new Buffer(sig, enc)
return verify(sig, Buffer.concat([this._tag, hash]), key, this._signType)
}
}).call(this,require("buffer").Buffer)
},{"./algos":99,"./sign":145,"./verify":146,"buffer":76,"create-hash":171,"inherits":223,"stream":241}],101:[function(require,module,exports){
'use strict'
exports['1.3.132.0.10'] = 'secp256k1'
exports['1.3.132.0.33'] = 'p224'
exports['1.2.840.10045.3.1.1'] = 'p192'
exports['1.2.840.10045.3.1.7'] = 'p256'
},{}],102:[function(require,module,exports){
(function (module, exports) {
'use strict';
// Utils
function assert(val, msg) {
if (!val)
throw new Error(msg || 'Assertion failed');
}
// Could use `inherits` module, but don't want to move from single file
// architecture yet.
function inherits(ctor, superCtor) {
ctor.super_ = superCtor;
var TempCtor = function () {};
TempCtor.prototype = superCtor.prototype;
ctor.prototype = new TempCtor();
ctor.prototype.constructor = ctor;
}
// BN
function BN(number, base, endian) {
// May be `new BN(bn)` ?
if (number !== null &&
typeof number === 'object' &&
Array.isArray(number.words)) {
return number;
}
this.sign = false;
this.words = null;
this.length = 0;
// Reduction context
this.red = null;
if (base === 'le' || base === 'be') {
endian = base;
base = 10;
}
if (number !== null)
this._init(number || 0, base || 10, endian || 'be');
}
if (typeof module === 'object')
module.exports = BN;
else
exports.BN = BN;
BN.BN = BN;
BN.wordSize = 26;
BN.prototype._init = function init(number, base, endian) {
if (typeof number === 'number') {
return this._initNumber(number, base, endian);
} else if (typeof number === 'object') {
return this._initArray(number, base, endian);
}
if (base === 'hex')
base = 16;
assert(base === (base | 0) && base >= 2 && base <= 36);
number = number.toString().replace(/\s+/g, '');
var start = 0;
if (number[0] === '-')
start++;
if (base === 16)
this._parseHex(number, start);
else
this._parseBase(number, base, start);
if (number[0] === '-')
this.sign = true;
this.strip();
if (endian !== 'le')
return;
this._initArray(this.toArray(), base, endian);
};
BN.prototype._initNumber = function _initNumber(number, base, endian) {
if (number < 0) {
this.sign = true;
number = -number;
}
if (number < 0x4000000) {
this.words = [ number & 0x3ffffff ];
this.length = 1;
} else if (number < 0x10000000000000) {
this.words = [
number & 0x3ffffff,
(number / 0x4000000) & 0x3ffffff
];
this.length = 2;
} else {
assert(number < 0x20000000000000); // 2 ^ 53 (unsafe)
this.words = [
number & 0x3ffffff,
(number / 0x4000000) & 0x3ffffff,
1
];
this.length = 3;
}
if (endian !== 'le')
return;
// Reverse the bytes
this._initArray(this.toArray(), base, endian);
};
BN.prototype._initArray = function _initArray(number, base, endian) {
// Perhaps a Uint8Array
assert(typeof number.length === 'number');
if (number.length <= 0) {
this.words = [ 0 ];
this.length = 1;
return this;
}
this.length = Math.ceil(number.length / 3);
this.words = new Array(this.length);
for (var i = 0; i < this.length; i++)
this.words[i] = 0;
var off = 0;
if (endian === 'be') {
for (var i = number.length - 1, j = 0; i >= 0; i -= 3) {
var w = number[i] | (number[i - 1] << 8) | (number[i - 2] << 16);
this.words[j] |= (w << off) & 0x3ffffff;
this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff;
off += 24;
if (off >= 26) {
off -= 26;
j++;
}
}
} else if (endian === 'le') {
for (var i = 0, j = 0; i < number.length; i += 3) {
var w = number[i] | (number[i + 1] << 8) | (number[i + 2] << 16);
this.words[j] |= (w << off) & 0x3ffffff;
this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff;
off += 24;
if (off >= 26) {
off -= 26;
j++;
}
}
}
return this.strip();
};
function parseHex(str, start, end) {
var r = 0;
var len = Math.min(str.length, end);
for (var i = start; i < len; i++) {
var c = str.charCodeAt(i) - 48;
r <<= 4;
// 'a' - 'f'
if (c >= 49 && c <= 54)
r |= c - 49 + 0xa;
// 'A' - 'F'
else if (c >= 17 && c <= 22)
r |= c - 17 + 0xa;
// '0' - '9'
else
r |= c & 0xf;
}
return r;
}
BN.prototype._parseHex = function _parseHex(number, start) {
// Create possibly bigger array to ensure that it fits the number
this.length = Math.ceil((number.length - start) / 6);
this.words = new Array(this.length);
for (var i = 0; i < this.length; i++)
this.words[i] = 0;
// Scan 24-bit chunks and add them to the number
var off = 0;
for (var i = number.length - 6, j = 0; i >= start; i -= 6) {
var w = parseHex(number, i, i + 6);
this.words[j] |= (w << off) & 0x3ffffff;
this.words[j + 1] |= w >>> (26 - off) & 0x3fffff;
off += 24;
if (off >= 26) {
off -= 26;
j++;
}
}
if (i + 6 !== start) {
var w = parseHex(number, start, i + 6);
this.words[j] |= (w << off) & 0x3ffffff;
this.words[j + 1] |= w >>> (26 - off) & 0x3fffff;
}
this.strip();
};
function parseBase(str, start, end, mul) {
var r = 0;
var len = Math.min(str.length, end);
for (var i = start; i < len; i++) {
var c = str.charCodeAt(i) - 48;
r *= mul;
// 'a'
if (c >= 49)
r += c - 49 + 0xa;
// 'A'
else if (c >= 17)
r += c - 17 + 0xa;
// '0' - '9'
else
r += c;
}
return r;
}
BN.prototype._parseBase = function _parseBase(number, base, start) {
// Initialize as zero
this.words = [ 0 ];
this.length = 1;
// Find length of limb in base
for (var limbLen = 0, limbPow = 1; limbPow <= 0x3ffffff; limbPow *= base)
limbLen++;
limbLen--;
limbPow = (limbPow / base) | 0;
var total = number.length - start;
var mod = total % limbLen;
var end = Math.min(total, total - mod) + start;
var word = 0;
for (var i = start; i < end; i += limbLen) {
word = parseBase(number, i, i + limbLen, base);
this.imuln(limbPow);
if (this.words[0] + word < 0x4000000)
this.words[0] += word;
else
this._iaddn(word);
}
if (mod !== 0) {
var pow = 1;
var word = parseBase(number, i, number.length, base);
for (var i = 0; i < mod; i++)
pow *= base;
this.imuln(pow);
if (this.words[0] + word < 0x4000000)
this.words[0] += word;
else
this._iaddn(word);
}
};
BN.prototype.copy = function copy(dest) {
dest.words = new Array(this.length);
for (var i = 0; i < this.length; i++)
dest.words[i] = this.words[i];
dest.length = this.length;
dest.sign = this.sign;
dest.red = this.red;
};
BN.prototype.clone = function clone() {
var r = new BN(null);
this.copy(r);
return r;
};
// Remove leading `0` from `this`
BN.prototype.strip = function strip() {
while (this.length > 1 && this.words[this.length - 1] === 0)
this.length--;
return this._normSign();
};
BN.prototype._normSign = function _normSign() {
// -0 = 0
if (this.length === 1 && this.words[0] === 0)
this.sign = false;
return this;
};
BN.prototype.inspect = function inspect() {
return (this.red ? '';
};
/*
var zeros = [];
var groupSizes = [];
var groupBases = [];
var s = '';
var i = -1;
while (++i < BN.wordSize) {
zeros[i] = s;
s += '0';
}
groupSizes[0] = 0;
groupSizes[1] = 0;
groupBases[0] = 0;
groupBases[1] = 0;
var base = 2 - 1;
while (++base < 36 + 1) {
var groupSize = 0;
var groupBase = 1;
while (groupBase < (1 << BN.wordSize) / base) {
groupBase *= base;
groupSize += 1;
}
groupSizes[base] = groupSize;
groupBases[base] = groupBase;
}
*/
var zeros = [
'',
'0',
'00',
'000',
'0000',
'00000',
'000000',
'0000000',
'00000000',
'000000000',
'0000000000',
'00000000000',
'000000000000',
'0000000000000',
'00000000000000',
'000000000000000',
'0000000000000000',
'00000000000000000',
'000000000000000000',
'0000000000000000000',
'00000000000000000000',
'000000000000000000000',
'0000000000000000000000',
'00000000000000000000000',
'000000000000000000000000',
'0000000000000000000000000'
];
var groupSizes = [
0, 0,
25, 16, 12, 11, 10, 9, 8,
8, 7, 7, 7, 7, 6, 6,
6, 6, 6, 6, 6, 5, 5,
5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5
];
var groupBases = [
0, 0,
33554432, 43046721, 16777216, 48828125, 60466176, 40353607, 16777216,
43046721, 10000000, 19487171, 35831808, 62748517, 7529536, 11390625,
16777216, 24137569, 34012224, 47045881, 64000000, 4084101, 5153632,
6436343, 7962624, 9765625, 11881376, 14348907, 17210368, 20511149,
24300000, 28629151, 33554432, 39135393, 45435424, 52521875, 60466176
];
BN.prototype.toString = function toString(base, padding) {
base = base || 10;
if (base === 16 || base === 'hex') {
var out = '';
var off = 0;
var padding = padding | 0 || 1;
var carry = 0;
for (var i = 0; i < this.length; i++) {
var w = this.words[i];
var word = (((w << off) | carry) & 0xffffff).toString(16);
carry = (w >>> (24 - off)) & 0xffffff;
if (carry !== 0 || i !== this.length - 1)
out = zeros[6 - word.length] + word + out;
else
out = word + out;
off += 2;
if (off >= 26) {
off -= 26;
i--;
}
}
if (carry !== 0)
out = carry.toString(16) + out;
while (out.length % padding !== 0)
out = '0' + out;
if (this.sign)
out = '-' + out;
return out;
} else if (base === (base | 0) && base >= 2 && base <= 36) {
// var groupSize = Math.floor(BN.wordSize * Math.LN2 / Math.log(base));
var groupSize = groupSizes[base];
// var groupBase = Math.pow(base, groupSize);
var groupBase = groupBases[base];
var out = '';
var c = this.clone();
c.sign = false;
while (c.cmpn(0) !== 0) {
var r = c.modn(groupBase).toString(base);
c = c.idivn(groupBase);
if (c.cmpn(0) !== 0)
out = zeros[groupSize - r.length] + r + out;
else
out = r + out;
}
if (this.cmpn(0) === 0)
out = '0' + out;
if (this.sign)
out = '-' + out;
return out;
} else {
assert(false, 'Base should be between 2 and 36');
}
};
BN.prototype.toJSON = function toJSON() {
return this.toString(16);
};
BN.prototype.toArray = function toArray(endian) {
this.strip();
var res = new Array(this.byteLength());
res[0] = 0;
var q = this.clone();
if (endian !== 'le') {
// Assume big-endian
for (var i = 0; q.cmpn(0) !== 0; i++) {
var b = q.andln(0xff);
q.ishrn(8);
res[res.length - i - 1] = b;
}
} else {
// Assume little-endian
for (var i = 0; q.cmpn(0) !== 0; i++) {
var b = q.andln(0xff);
q.ishrn(8);
res[i] = b;
}
}
return res;
};
if (Math.clz32) {
BN.prototype._countBits = function _countBits(w) {
return 32 - Math.clz32(w);
};
} else {
BN.prototype._countBits = function _countBits(w) {
var t = w;
var r = 0;
if (t >= 0x1000) {
r += 13;
t >>>= 13;
}
if (t >= 0x40) {
r += 7;
t >>>= 7;
}
if (t >= 0x8) {
r += 4;
t >>>= 4;
}
if (t >= 0x02) {
r += 2;
t >>>= 2;
}
return r + t;
};
}
BN.prototype._zeroBits = function _zeroBits(w) {
// Short-cut
if (w === 0)
return 26;
var t = w;
var r = 0;
if ((t & 0x1fff) === 0) {
r += 13;
t >>>= 13;
}
if ((t & 0x7f) === 0) {
r += 7;
t >>>= 7;
}
if ((t & 0xf) === 0) {
r += 4;
t >>>= 4;
}
if ((t & 0x3) === 0) {
r += 2;
t >>>= 2;
}
if ((t & 0x1) === 0)
r++;
return r;
};
// Return number of used bits in a BN
BN.prototype.bitLength = function bitLength() {
var hi = 0;
var w = this.words[this.length - 1];
var hi = this._countBits(w);
return (this.length - 1) * 26 + hi;
};
// Number of trailing zero bits
BN.prototype.zeroBits = function zeroBits() {
if (this.cmpn(0) === 0)
return 0;
var r = 0;
for (var i = 0; i < this.length; i++) {
var b = this._zeroBits(this.words[i]);
r += b;
if (b !== 26)
break;
}
return r;
};
BN.prototype.byteLength = function byteLength() {
return Math.ceil(this.bitLength() / 8);
};
// Return negative clone of `this`
BN.prototype.neg = function neg() {
if (this.cmpn(0) === 0)
return this.clone();
var r = this.clone();
r.sign = !this.sign;
return r;
};
// Or `num` with `this` in-place
BN.prototype.ior = function ior(num) {
this.sign = this.sign || num.sign;
while (this.length < num.length)
this.words[this.length++] = 0;
for (var i = 0; i < num.length; i++)
this.words[i] = this.words[i] | num.words[i];
return this.strip();
};
// Or `num` with `this`
BN.prototype.or = function or(num) {
if (this.length > num.length)
return this.clone().ior(num);
else
return num.clone().ior(this);
};
// And `num` with `this` in-place
BN.prototype.iand = function iand(num) {
this.sign = this.sign && num.sign;
// b = min-length(num, this)
var b;
if (this.length > num.length)
b = num;
else
b = this;
for (var i = 0; i < b.length; i++)
this.words[i] = this.words[i] & num.words[i];
this.length = b.length;
return this.strip();
};
// And `num` with `this`
BN.prototype.and = function and(num) {
if (this.length > num.length)
return this.clone().iand(num);
else
return num.clone().iand(this);
};
// Xor `num` with `this` in-place
BN.prototype.ixor = function ixor(num) {
this.sign = this.sign || num.sign;
// a.length > b.length
var a;
var b;
if (this.length > num.length) {
a = this;
b = num;
} else {
a = num;
b = this;
}
for (var i = 0; i < b.length; i++)
this.words[i] = a.words[i] ^ b.words[i];
if (this !== a)
for (; i < a.length; i++)
this.words[i] = a.words[i];
this.length = a.length;
return this.strip();
};
// Xor `num` with `this`
BN.prototype.xor = function xor(num) {
if (this.length > num.length)
return this.clone().ixor(num);
else
return num.clone().ixor(this);
};
// Set `bit` of `this`
BN.prototype.setn = function setn(bit, val) {
assert(typeof bit === 'number' && bit >= 0);
var off = (bit / 26) | 0;
var wbit = bit % 26;
while (this.length <= off)
this.words[this.length++] = 0;
if (val)
this.words[off] = this.words[off] | (1 << wbit);
else
this.words[off] = this.words[off] & ~(1 << wbit);
return this.strip();
};
// Add `num` to `this` in-place
BN.prototype.iadd = function iadd(num) {
// negative + positive
if (this.sign && !num.sign) {
this.sign = false;
var r = this.isub(num);
this.sign = !this.sign;
return this._normSign();
// positive + negative
} else if (!this.sign && num.sign) {
num.sign = false;
var r = this.isub(num);
num.sign = true;
return r._normSign();
}
// a.length > b.length
var a;
var b;
if (this.length > num.length) {
a = this;
b = num;
} else {
a = num;
b = this;
}
var carry = 0;
for (var i = 0; i < b.length; i++) {
var r = a.words[i] + b.words[i] + carry;
this.words[i] = r & 0x3ffffff;
carry = r >>> 26;
}
for (; carry !== 0 && i < a.length; i++) {
var r = a.words[i] + carry;
this.words[i] = r & 0x3ffffff;
carry = r >>> 26;
}
this.length = a.length;
if (carry !== 0) {
this.words[this.length] = carry;
this.length++;
// Copy the rest of the words
} else if (a !== this) {
for (; i < a.length; i++)
this.words[i] = a.words[i];
}
return this;
};
// Add `num` to `this`
BN.prototype.add = function add(num) {
if (num.sign && !this.sign) {
num.sign = false;
var res = this.sub(num);
num.sign = true;
return res;
} else if (!num.sign && this.sign) {
this.sign = false;
var res = num.sub(this);
this.sign = true;
return res;
}
if (this.length > num.length)
return this.clone().iadd(num);
else
return num.clone().iadd(this);
};
// Subtract `num` from `this` in-place
BN.prototype.isub = function isub(num) {
// this - (-num) = this + num
if (num.sign) {
num.sign = false;
var r = this.iadd(num);
num.sign = true;
return r._normSign();
// -this - num = -(this + num)
} else if (this.sign) {
this.sign = false;
this.iadd(num);
this.sign = true;
return this._normSign();
}
// At this point both numbers are positive
var cmp = this.cmp(num);
// Optimization - zeroify
if (cmp === 0) {
this.sign = false;
this.length = 1;
this.words[0] = 0;
return this;
}
// a > b
var a;
var b;
if (cmp > 0) {
a = this;
b = num;
} else {
a = num;
b = this;
}
var carry = 0;
for (var i = 0; i < b.length; i++) {
var r = a.words[i] - b.words[i] + carry;
carry = r >> 26;
this.words[i] = r & 0x3ffffff;
}
for (; carry !== 0 && i < a.length; i++) {
var r = a.words[i] + carry;
carry = r >> 26;
this.words[i] = r & 0x3ffffff;
}
// Copy rest of the words
if (carry === 0 && i < a.length && a !== this)
for (; i < a.length; i++)
this.words[i] = a.words[i];
this.length = Math.max(this.length, i);
if (a !== this)
this.sign = true;
return this.strip();
};
// Subtract `num` from `this`
BN.prototype.sub = function sub(num) {
return this.clone().isub(num);
};
/*
// NOTE: This could be potentionally used to generate loop-less multiplications
function _genCombMulTo(alen, blen) {
var len = alen + blen - 1;
var src = [
'var a = this.words, b = num.words, o = out.words, c = 0, w, ' +
'mask = 0x3ffffff, shift = 0x4000000;',
'out.length = ' + len + ';'
];
for (var k = 0; k < len; k++) {
var minJ = Math.max(0, k - alen + 1);
var maxJ = Math.min(k, blen - 1);
for (var j = minJ; j <= maxJ; j++) {
var i = k - j;
var mul = 'a[' + i + '] * b[' + j + ']';
if (j === minJ) {
src.push('w = ' + mul + ' + c;');
src.push('c = (w / shift) | 0;');
} else {
src.push('w += ' + mul + ';');
src.push('c += (w / shift) | 0;');
}
src.push('w &= mask;');
}
src.push('o[' + k + '] = w;');
}
src.push('if (c !== 0) {',
' o[' + k + '] = c;',
' out.length++;',
'}',
'return out;');
return src.join('\n');
}
*/
BN.prototype._smallMulTo = function _smallMulTo(num, out) {
out.sign = num.sign !== this.sign;
out.length = this.length + num.length;
var carry = 0;
for (var k = 0; k < out.length - 1; k++) {
// Sum all words with the same `i + j = k` and accumulate `ncarry`,
// note that ncarry could be >= 0x3ffffff
var ncarry = carry >>> 26;
var rword = carry & 0x3ffffff;
var maxJ = Math.min(k, num.length - 1);
for (var j = Math.max(0, k - this.length + 1); j <= maxJ; j++) {
var i = k - j;
var a = this.words[i] | 0;
var b = num.words[j] | 0;
var r = a * b;
var lo = r & 0x3ffffff;
ncarry = (ncarry + ((r / 0x4000000) | 0)) | 0;
lo = (lo + rword) | 0;
rword = lo & 0x3ffffff;
ncarry = (ncarry + (lo >>> 26)) | 0;
}
out.words[k] = rword;
carry = ncarry;
}
if (carry !== 0) {
out.words[k] = carry;
} else {
out.length--;
}
return out.strip();
};
BN.prototype._bigMulTo = function _bigMulTo(num, out) {
out.sign = num.sign !== this.sign;
out.length = this.length + num.length;
var carry = 0;
var hncarry = 0;
for (var k = 0; k < out.length - 1; k++) {
// Sum all words with the same `i + j = k` and accumulate `ncarry`,
// note that ncarry could be >= 0x3ffffff
var ncarry = hncarry;
hncarry = 0;
var rword = carry & 0x3ffffff;
var maxJ = Math.min(k, num.length - 1);
for (var j = Math.max(0, k - this.length + 1); j <= maxJ; j++) {
var i = k - j;
var a = this.words[i] | 0;
var b = num.words[j] | 0;
var r = a * b;
var lo = r & 0x3ffffff;
ncarry = (ncarry + ((r / 0x4000000) | 0)) | 0;
lo = (lo + rword) | 0;
rword = lo & 0x3ffffff;
ncarry = (ncarry + (lo >>> 26)) | 0;
hncarry += ncarry >>> 26;
ncarry &= 0x3ffffff;
}
out.words[k] = rword;
carry = ncarry;
ncarry = hncarry;
}
if (carry !== 0) {
out.words[k] = carry;
} else {
out.length--;
}
return out.strip();
};
BN.prototype.mulTo = function mulTo(num, out) {
var res;
if (this.length + num.length < 63)
res = this._smallMulTo(num, out);
else
res = this._bigMulTo(num, out);
return res;
};
// Multiply `this` by `num`
BN.prototype.mul = function mul(num) {
var out = new BN(null);
out.words = new Array(this.length + num.length);
return this.mulTo(num, out);
};
// In-place Multiplication
BN.prototype.imul = function imul(num) {
if (this.cmpn(0) === 0 || num.cmpn(0) === 0) {
this.words[0] = 0;
this.length = 1;
return this;
}
var tlen = this.length;
var nlen = num.length;
this.sign = num.sign !== this.sign;
this.length = this.length + num.length;
this.words[this.length - 1] = 0;
for (var k = this.length - 2; k >= 0; k--) {
// Sum all words with the same `i + j = k` and accumulate `carry`,
// note that carry could be >= 0x3ffffff
var carry = 0;
var rword = 0;
var maxJ = Math.min(k, nlen - 1);
for (var j = Math.max(0, k - tlen + 1); j <= maxJ; j++) {
var i = k - j;
var a = this.words[i];
var b = num.words[j];
var r = a * b;
var lo = r & 0x3ffffff;
carry += (r / 0x4000000) | 0;
lo += rword;
rword = lo & 0x3ffffff;
carry += lo >>> 26;
}
this.words[k] = rword;
this.words[k + 1] += carry;
carry = 0;
}
// Propagate overflows
var carry = 0;
for (var i = 1; i < this.length; i++) {
var w = this.words[i] + carry;
this.words[i] = w & 0x3ffffff;
carry = w >>> 26;
}
return this.strip();
};
BN.prototype.imuln = function imuln(num) {
assert(typeof num === 'number');
// Carry
var carry = 0;
for (var i = 0; i < this.length; i++) {
var w = this.words[i] * num;
var lo = (w & 0x3ffffff) + (carry & 0x3ffffff);
carry >>= 26;
carry += (w / 0x4000000) | 0;
// NOTE: lo is 27bit maximum
carry += lo >>> 26;
this.words[i] = lo & 0x3ffffff;
}
if (carry !== 0) {
this.words[i] = carry;
this.length++;
}
return this;
};
BN.prototype.muln = function muln(num) {
return this.clone().imuln(num);
};
// `this` * `this`
BN.prototype.sqr = function sqr() {
return this.mul(this);
};
// `this` * `this` in-place
BN.prototype.isqr = function isqr() {
return this.mul(this);
};
// Shift-left in-place
BN.prototype.ishln = function ishln(bits) {
assert(typeof bits === 'number' && bits >= 0);
var r = bits % 26;
var s = (bits - r) / 26;
var carryMask = (0x3ffffff >>> (26 - r)) << (26 - r);
if (r !== 0) {
var carry = 0;
for (var i = 0; i < this.length; i++) {
var newCarry = this.words[i] & carryMask;
var c = (this.words[i] - newCarry) << r;
this.words[i] = c | carry;
carry = newCarry >>> (26 - r);
}
if (carry) {
this.words[i] = carry;
this.length++;
}
}
if (s !== 0) {
for (var i = this.length - 1; i >= 0; i--)
this.words[i + s] = this.words[i];
for (var i = 0; i < s; i++)
this.words[i] = 0;
this.length += s;
}
return this.strip();
};
// Shift-right in-place
// NOTE: `hint` is a lowest bit before trailing zeroes
// NOTE: if `extended` is present - it will be filled with destroyed bits
BN.prototype.ishrn = function ishrn(bits, hint, extended) {
assert(typeof bits === 'number' && bits >= 0);
var h;
if (hint)
h = (hint - (hint % 26)) / 26;
else
h = 0;
var r = bits % 26;
var s = Math.min((bits - r) / 26, this.length);
var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r);
var maskedWords = extended;
h -= s;
h = Math.max(0, h);
// Extended mode, copy masked part
if (maskedWords) {
for (var i = 0; i < s; i++)
maskedWords.words[i] = this.words[i];
maskedWords.length = s;
}
if (s === 0) {
// No-op, we should not move anything at all
} else if (this.length > s) {
this.length -= s;
for (var i = 0; i < this.length; i++)
this.words[i] = this.words[i + s];
} else {
this.words[0] = 0;
this.length = 1;
}
var carry = 0;
for (var i = this.length - 1; i >= 0 && (carry !== 0 || i >= h); i--) {
var word = this.words[i];
this.words[i] = (carry << (26 - r)) | (word >>> r);
carry = word & mask;
}
// Push carried bits as a mask
if (maskedWords && carry !== 0)
maskedWords.words[maskedWords.length++] = carry;
if (this.length === 0) {
this.words[0] = 0;
this.length = 1;
}
this.strip();
return this;
};
// Shift-left
BN.prototype.shln = function shln(bits) {
return this.clone().ishln(bits);
};
// Shift-right
BN.prototype.shrn = function shrn(bits) {
return this.clone().ishrn(bits);
};
// Test if n bit is set
BN.prototype.testn = function testn(bit) {
assert(typeof bit === 'number' && bit >= 0);
var r = bit % 26;
var s = (bit - r) / 26;
var q = 1 << r;
// Fast case: bit is much higher than all existing words
if (this.length <= s) {
return false;
}
// Check bit and return
var w = this.words[s];
return !!(w & q);
};
// Return only lowers bits of number (in-place)
BN.prototype.imaskn = function imaskn(bits) {
assert(typeof bits === 'number' && bits >= 0);
var r = bits % 26;
var s = (bits - r) / 26;
assert(!this.sign, 'imaskn works only with positive numbers');
if (r !== 0)
s++;
this.length = Math.min(s, this.length);
if (r !== 0) {
var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r);
this.words[this.length - 1] &= mask;
}
return this.strip();
};
// Return only lowers bits of number
BN.prototype.maskn = function maskn(bits) {
return this.clone().imaskn(bits);
};
// Add plain number `num` to `this`
BN.prototype.iaddn = function iaddn(num) {
assert(typeof num === 'number');
if (num < 0)
return this.isubn(-num);
// Possible sign change
if (this.sign) {
if (this.length === 1 && this.words[0] < num) {
this.words[0] = num - this.words[0];
this.sign = false;
return this;
}
this.sign = false;
this.isubn(num);
this.sign = true;
return this;
}
// Add without checks
return this._iaddn(num);
};
BN.prototype._iaddn = function _iaddn(num) {
this.words[0] += num;
// Carry
for (var i = 0; i < this.length && this.words[i] >= 0x4000000; i++) {
this.words[i] -= 0x4000000;
if (i === this.length - 1)
this.words[i + 1] = 1;
else
this.words[i + 1]++;
}
this.length = Math.max(this.length, i + 1);
return this;
};
// Subtract plain number `num` from `this`
BN.prototype.isubn = function isubn(num) {
assert(typeof num === 'number');
if (num < 0)
return this.iaddn(-num);
if (this.sign) {
this.sign = false;
this.iaddn(num);
this.sign = true;
return this;
}
this.words[0] -= num;
// Carry
for (var i = 0; i < this.length && this.words[i] < 0; i++) {
this.words[i] += 0x4000000;
this.words[i + 1] -= 1;
}
return this.strip();
};
BN.prototype.addn = function addn(num) {
return this.clone().iaddn(num);
};
BN.prototype.subn = function subn(num) {
return this.clone().isubn(num);
};
BN.prototype.iabs = function iabs() {
this.sign = false;
return this;
};
BN.prototype.abs = function abs() {
return this.clone().iabs();
};
BN.prototype._ishlnsubmul = function _ishlnsubmul(num, mul, shift) {
// Bigger storage is needed
var len = num.length + shift;
var i;
if (this.words.length < len) {
var t = new Array(len);
for (var i = 0; i < this.length; i++)
t[i] = this.words[i];
this.words = t;
} else {
i = this.length;
}
// Zeroify rest
this.length = Math.max(this.length, len);
for (; i < this.length; i++)
this.words[i] = 0;
var carry = 0;
for (var i = 0; i < num.length; i++) {
var w = this.words[i + shift] + carry;
var right = num.words[i] * mul;
w -= right & 0x3ffffff;
carry = (w >> 26) - ((right / 0x4000000) | 0);
this.words[i + shift] = w & 0x3ffffff;
}
for (; i < this.length - shift; i++) {
var w = this.words[i + shift] + carry;
carry = w >> 26;
this.words[i + shift] = w & 0x3ffffff;
}
if (carry === 0)
return this.strip();
// Subtraction overflow
assert(carry === -1);
carry = 0;
for (var i = 0; i < this.length; i++) {
var w = -this.words[i] + carry;
carry = w >> 26;
this.words[i] = w & 0x3ffffff;
}
this.sign = true;
return this.strip();
};
BN.prototype._wordDiv = function _wordDiv(num, mode) {
var shift = this.length - num.length;
var a = this.clone();
var b = num;
// Normalize
var bhi = b.words[b.length - 1];
var bhiBits = this._countBits(bhi);
shift = 26 - bhiBits;
if (shift !== 0) {
b = b.shln(shift);
a.ishln(shift);
bhi = b.words[b.length - 1];
}
// Initialize quotient
var m = a.length - b.length;
var q;
if (mode !== 'mod') {
q = new BN(null);
q.length = m + 1;
q.words = new Array(q.length);
for (var i = 0; i < q.length; i++)
q.words[i] = 0;
}
var diff = a.clone()._ishlnsubmul(b, 1, m);
if (!diff.sign) {
a = diff;
if (q)
q.words[m] = 1;
}
for (var j = m - 1; j >= 0; j--) {
var qj = a.words[b.length + j] * 0x4000000 + a.words[b.length + j - 1];
// NOTE: (qj / bhi) is (0x3ffffff * 0x4000000 + 0x3ffffff) / 0x2000000 max
// (0x7ffffff)
qj = Math.min((qj / bhi) | 0, 0x3ffffff);
a._ishlnsubmul(b, qj, j);
while (a.sign) {
qj--;
a.sign = false;
a._ishlnsubmul(b, 1, j);
if (a.cmpn(0) !== 0)
a.sign = !a.sign;
}
if (q)
q.words[j] = qj;
}
if (q)
q.strip();
a.strip();
// Denormalize
if (mode !== 'div' && shift !== 0)
a.ishrn(shift);
return { div: q ? q : null, mod: a };
};
BN.prototype.divmod = function divmod(num, mode) {
assert(num.cmpn(0) !== 0);
if (this.sign && !num.sign) {
var res = this.neg().divmod(num, mode);
var div;
var mod;
if (mode !== 'mod')
div = res.div.neg();
if (mode !== 'div')
mod = res.mod.cmpn(0) === 0 ? res.mod : num.sub(res.mod);
return {
div: div,
mod: mod
};
} else if (!this.sign && num.sign) {
var res = this.divmod(num.neg(), mode);
var div;
if (mode !== 'mod')
div = res.div.neg();
return { div: div, mod: res.mod };
} else if (this.sign && num.sign) {
return this.neg().divmod(num.neg(), mode);
}
// Both numbers are positive at this point
// Strip both numbers to approximate shift value
if (num.length > this.length || this.cmp(num) < 0)
return { div: new BN(0), mod: this };
// Very short reduction
if (num.length === 1) {
if (mode === 'div')
return { div: this.divn(num.words[0]), mod: null };
else if (mode === 'mod')
return { div: null, mod: new BN(this.modn(num.words[0])) };
return {
div: this.divn(num.words[0]),
mod: new BN(this.modn(num.words[0]))
};
}
return this._wordDiv(num, mode);
};
// Find `this` / `num`
BN.prototype.div = function div(num) {
return this.divmod(num, 'div').div;
};
// Find `this` % `num`
BN.prototype.mod = function mod(num) {
return this.divmod(num, 'mod').mod;
};
// Find Round(`this` / `num`)
BN.prototype.divRound = function divRound(num) {
var dm = this.divmod(num);
// Fast case - exact division
if (dm.mod.cmpn(0) === 0)
return dm.div;
var mod = dm.div.sign ? dm.mod.isub(num) : dm.mod;
var half = num.shrn(1);
var r2 = num.andln(1);
var cmp = mod.cmp(half);
// Round down
if (cmp < 0 || r2 === 1 && cmp === 0)
return dm.div;
// Round up
return dm.div.sign ? dm.div.isubn(1) : dm.div.iaddn(1);
};
BN.prototype.modn = function modn(num) {
assert(num <= 0x3ffffff);
var p = (1 << 26) % num;
var acc = 0;
for (var i = this.length - 1; i >= 0; i--)
acc = (p * acc + this.words[i]) % num;
return acc;
};
// In-place division by number
BN.prototype.idivn = function idivn(num) {
assert(num <= 0x3ffffff);
var carry = 0;
for (var i = this.length - 1; i >= 0; i--) {
var w = this.words[i] + carry * 0x4000000;
this.words[i] = (w / num) | 0;
carry = w % num;
}
return this.strip();
};
BN.prototype.divn = function divn(num) {
return this.clone().idivn(num);
};
BN.prototype.egcd = function egcd(p) {
assert(!p.sign);
assert(p.cmpn(0) !== 0);
var x = this;
var y = p.clone();
if (x.sign)
x = x.mod(p);
else
x = x.clone();
// A * x + B * y = x
var A = new BN(1);
var B = new BN(0);
// C * x + D * y = y
var C = new BN(0);
var D = new BN(1);
var g = 0;
while (x.isEven() && y.isEven()) {
x.ishrn(1);
y.ishrn(1);
++g;
}
var yp = y.clone();
var xp = x.clone();
while (x.cmpn(0) !== 0) {
while (x.isEven()) {
x.ishrn(1);
if (A.isEven() && B.isEven()) {
A.ishrn(1);
B.ishrn(1);
} else {
A.iadd(yp).ishrn(1);
B.isub(xp).ishrn(1);
}
}
while (y.isEven()) {
y.ishrn(1);
if (C.isEven() && D.isEven()) {
C.ishrn(1);
D.ishrn(1);
} else {
C.iadd(yp).ishrn(1);
D.isub(xp).ishrn(1);
}
}
if (x.cmp(y) >= 0) {
x.isub(y);
A.isub(C);
B.isub(D);
} else {
y.isub(x);
C.isub(A);
D.isub(B);
}
}
return {
a: C,
b: D,
gcd: y.ishln(g)
};
};
// This is reduced incarnation of the binary EEA
// above, designated to invert members of the
// _prime_ fields F(p) at a maximal speed
BN.prototype._invmp = function _invmp(p) {
assert(!p.sign);
assert(p.cmpn(0) !== 0);
var a = this;
var b = p.clone();
if (a.sign)
a = a.mod(p);
else
a = a.clone();
var x1 = new BN(1);
var x2 = new BN(0);
var delta = b.clone();
while (a.cmpn(1) > 0 && b.cmpn(1) > 0) {
while (a.isEven()) {
a.ishrn(1);
if (x1.isEven())
x1.ishrn(1);
else
x1.iadd(delta).ishrn(1);
}
while (b.isEven()) {
b.ishrn(1);
if (x2.isEven())
x2.ishrn(1);
else
x2.iadd(delta).ishrn(1);
}
if (a.cmp(b) >= 0) {
a.isub(b);
x1.isub(x2);
} else {
b.isub(a);
x2.isub(x1);
}
}
if (a.cmpn(1) === 0)
return x1;
else
return x2;
};
BN.prototype.gcd = function gcd(num) {
if (this.cmpn(0) === 0)
return num.clone();
if (num.cmpn(0) === 0)
return this.clone();
var a = this.clone();
var b = num.clone();
a.sign = false;
b.sign = false;
// Remove common factor of two
for (var shift = 0; a.isEven() && b.isEven(); shift++) {
a.ishrn(1);
b.ishrn(1);
}
do {
while (a.isEven())
a.ishrn(1);
while (b.isEven())
b.ishrn(1);
var r = a.cmp(b);
if (r < 0) {
// Swap `a` and `b` to make `a` always bigger than `b`
var t = a;
a = b;
b = t;
} else if (r === 0 || b.cmpn(1) === 0) {
break;
}
a.isub(b);
} while (true);
return b.ishln(shift);
};
// Invert number in the field F(num)
BN.prototype.invm = function invm(num) {
return this.egcd(num).a.mod(num);
};
BN.prototype.isEven = function isEven() {
return (this.words[0] & 1) === 0;
};
BN.prototype.isOdd = function isOdd() {
return (this.words[0] & 1) === 1;
};
// And first word and num
BN.prototype.andln = function andln(num) {
return this.words[0] & num;
};
// Increment at the bit position in-line
BN.prototype.bincn = function bincn(bit) {
assert(typeof bit === 'number');
var r = bit % 26;
var s = (bit - r) / 26;
var q = 1 << r;
// Fast case: bit is much higher than all existing words
if (this.length <= s) {
for (var i = this.length; i < s + 1; i++)
this.words[i] = 0;
this.words[s] |= q;
this.length = s + 1;
return this;
}
// Add bit and propagate, if needed
var carry = q;
for (var i = s; carry !== 0 && i < this.length; i++) {
var w = this.words[i];
w += carry;
carry = w >>> 26;
w &= 0x3ffffff;
this.words[i] = w;
}
if (carry !== 0) {
this.words[i] = carry;
this.length++;
}
return this;
};
BN.prototype.cmpn = function cmpn(num) {
var sign = num < 0;
if (sign)
num = -num;
if (this.sign && !sign)
return -1;
else if (!this.sign && sign)
return 1;
num &= 0x3ffffff;
this.strip();
var res;
if (this.length > 1) {
res = 1;
} else {
var w = this.words[0];
res = w === num ? 0 : w < num ? -1 : 1;
}
if (this.sign)
res = -res;
return res;
};
// Compare two numbers and return:
// 1 - if `this` > `num`
// 0 - if `this` == `num`
// -1 - if `this` < `num`
BN.prototype.cmp = function cmp(num) {
if (this.sign && !num.sign)
return -1;
else if (!this.sign && num.sign)
return 1;
var res = this.ucmp(num);
if (this.sign)
return -res;
else
return res;
};
// Unsigned comparison
BN.prototype.ucmp = function ucmp(num) {
// At this point both numbers have the same sign
if (this.length > num.length)
return 1;
else if (this.length < num.length)
return -1;
var res = 0;
for (var i = this.length - 1; i >= 0; i--) {
var a = this.words[i];
var b = num.words[i];
if (a === b)
continue;
if (a < b)
res = -1;
else if (a > b)
res = 1;
break;
}
return res;
};
//
// A reduce context, could be using montgomery or something better, depending
// on the `m` itself.
//
BN.red = function red(num) {
return new Red(num);
};
BN.prototype.toRed = function toRed(ctx) {
assert(!this.red, 'Already a number in reduction context');
assert(!this.sign, 'red works only with positives');
return ctx.convertTo(this)._forceRed(ctx);
};
BN.prototype.fromRed = function fromRed() {
assert(this.red, 'fromRed works only with numbers in reduction context');
return this.red.convertFrom(this);
};
BN.prototype._forceRed = function _forceRed(ctx) {
this.red = ctx;
return this;
};
BN.prototype.forceRed = function forceRed(ctx) {
assert(!this.red, 'Already a number in reduction context');
return this._forceRed(ctx);
};
BN.prototype.redAdd = function redAdd(num) {
assert(this.red, 'redAdd works only with red numbers');
return this.red.add(this, num);
};
BN.prototype.redIAdd = function redIAdd(num) {
assert(this.red, 'redIAdd works only with red numbers');
return this.red.iadd(this, num);
};
BN.prototype.redSub = function redSub(num) {
assert(this.red, 'redSub works only with red numbers');
return this.red.sub(this, num);
};
BN.prototype.redISub = function redISub(num) {
assert(this.red, 'redISub works only with red numbers');
return this.red.isub(this, num);
};
BN.prototype.redShl = function redShl(num) {
assert(this.red, 'redShl works only with red numbers');
return this.red.shl(this, num);
};
BN.prototype.redMul = function redMul(num) {
assert(this.red, 'redMul works only with red numbers');
this.red._verify2(this, num);
return this.red.mul(this, num);
};
BN.prototype.redIMul = function redIMul(num) {
assert(this.red, 'redMul works only with red numbers');
this.red._verify2(this, num);
return this.red.imul(this, num);
};
BN.prototype.redSqr = function redSqr() {
assert(this.red, 'redSqr works only with red numbers');
this.red._verify1(this);
return this.red.sqr(this);
};
BN.prototype.redISqr = function redISqr() {
assert(this.red, 'redISqr works only with red numbers');
this.red._verify1(this);
return this.red.isqr(this);
};
// Square root over p
BN.prototype.redSqrt = function redSqrt() {
assert(this.red, 'redSqrt works only with red numbers');
this.red._verify1(this);
return this.red.sqrt(this);
};
BN.prototype.redInvm = function redInvm() {
assert(this.red, 'redInvm works only with red numbers');
this.red._verify1(this);
return this.red.invm(this);
};
// Return negative clone of `this` % `red modulo`
BN.prototype.redNeg = function redNeg() {
assert(this.red, 'redNeg works only with red numbers');
this.red._verify1(this);
return this.red.neg(this);
};
BN.prototype.redPow = function redPow(num) {
assert(this.red && !num.red, 'redPow(normalNum)');
this.red._verify1(this);
return this.red.pow(this, num);
};
// Prime numbers with efficient reduction
var primes = {
k256: null,
p224: null,
p192: null,
p25519: null
};
// Pseudo-Mersenne prime
function MPrime(name, p) {
// P = 2 ^ N - K
this.name = name;
this.p = new BN(p, 16);
this.n = this.p.bitLength();
this.k = new BN(1).ishln(this.n).isub(this.p);
this.tmp = this._tmp();
}
MPrime.prototype._tmp = function _tmp() {
var tmp = new BN(null);
tmp.words = new Array(Math.ceil(this.n / 13));
return tmp;
};
MPrime.prototype.ireduce = function ireduce(num) {
// Assumes that `num` is less than `P^2`
// num = HI * (2 ^ N - K) + HI * K + LO = HI * K + LO (mod P)
var r = num;
var rlen;
do {
this.split(r, this.tmp);
r = this.imulK(r);
r = r.iadd(this.tmp);
rlen = r.bitLength();
} while (rlen > this.n);
var cmp = rlen < this.n ? -1 : r.ucmp(this.p);
if (cmp === 0) {
r.words[0] = 0;
r.length = 1;
} else if (cmp > 0) {
r.isub(this.p);
} else {
r.strip();
}
return r;
};
MPrime.prototype.split = function split(input, out) {
input.ishrn(this.n, 0, out);
};
MPrime.prototype.imulK = function imulK(num) {
return num.imul(this.k);
};
function K256() {
MPrime.call(
this,
'k256',
'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f');
}
inherits(K256, MPrime);
K256.prototype.split = function split(input, output) {
// 256 = 9 * 26 + 22
var mask = 0x3fffff;
var outLen = Math.min(input.length, 9);
for (var i = 0; i < outLen; i++)
output.words[i] = input.words[i];
output.length = outLen;
if (input.length <= 9) {
input.words[0] = 0;
input.length = 1;
return;
}
// Shift by 9 limbs
var prev = input.words[9];
output.words[output.length++] = prev & mask;
for (var i = 10; i < input.length; i++) {
var next = input.words[i];
input.words[i - 10] = ((next & mask) << 4) | (prev >>> 22);
prev = next;
}
input.words[i - 10] = prev >>> 22;
input.length -= 9;
};
K256.prototype.imulK = function imulK(num) {
// K = 0x1000003d1 = [ 0x40, 0x3d1 ]
num.words[num.length] = 0;
num.words[num.length + 1] = 0;
num.length += 2;
// bounded at: 0x40 * 0x3ffffff + 0x3d0 = 0x100000390
var hi;
var lo = 0;
for (var i = 0; i < num.length; i++) {
var w = num.words[i];
hi = w * 0x40;
lo += w * 0x3d1;
hi += (lo / 0x4000000) | 0;
lo &= 0x3ffffff;
num.words[i] = lo;
lo = hi;
}
// Fast length reduction
if (num.words[num.length - 1] === 0) {
num.length--;
if (num.words[num.length - 1] === 0)
num.length--;
}
return num;
};
function P224() {
MPrime.call(
this,
'p224',
'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001');
}
inherits(P224, MPrime);
function P192() {
MPrime.call(
this,
'p192',
'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff');
}
inherits(P192, MPrime);
function P25519() {
// 2 ^ 255 - 19
MPrime.call(
this,
'25519',
'7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed');
}
inherits(P25519, MPrime);
P25519.prototype.imulK = function imulK(num) {
// K = 0x13
var carry = 0;
for (var i = 0; i < num.length; i++) {
var hi = num.words[i] * 0x13 + carry;
var lo = hi & 0x3ffffff;
hi >>>= 26;
num.words[i] = lo;
carry = hi;
}
if (carry !== 0)
num.words[num.length++] = carry;
return num;
};
// Exported mostly for testing purposes, use plain name instead
BN._prime = function prime(name) {
// Cached version of prime
if (primes[name])
return primes[name];
var prime;
if (name === 'k256')
prime = new K256();
else if (name === 'p224')
prime = new P224();
else if (name === 'p192')
prime = new P192();
else if (name === 'p25519')
prime = new P25519();
else
throw new Error('Unknown prime ' + name);
primes[name] = prime;
return prime;
};
//
// Base reduction engine
//
function Red(m) {
if (typeof m === 'string') {
var prime = BN._prime(m);
this.m = prime.p;
this.prime = prime;
} else {
this.m = m;
this.prime = null;
}
}
Red.prototype._verify1 = function _verify1(a) {
assert(!a.sign, 'red works only with positives');
assert(a.red, 'red works only with red numbers');
};
Red.prototype._verify2 = function _verify2(a, b) {
assert(!a.sign && !b.sign, 'red works only with positives');
assert(a.red && a.red === b.red,
'red works only with red numbers');
};
Red.prototype.imod = function imod(a) {
if (this.prime)
return this.prime.ireduce(a)._forceRed(this);
return a.mod(this.m)._forceRed(this);
};
Red.prototype.neg = function neg(a) {
var r = a.clone();
r.sign = !r.sign;
return r.iadd(this.m)._forceRed(this);
};
Red.prototype.add = function add(a, b) {
this._verify2(a, b);
var res = a.add(b);
if (res.cmp(this.m) >= 0)
res.isub(this.m);
return res._forceRed(this);
};
Red.prototype.iadd = function iadd(a, b) {
this._verify2(a, b);
var res = a.iadd(b);
if (res.cmp(this.m) >= 0)
res.isub(this.m);
return res;
};
Red.prototype.sub = function sub(a, b) {
this._verify2(a, b);
var res = a.sub(b);
if (res.cmpn(0) < 0)
res.iadd(this.m);
return res._forceRed(this);
};
Red.prototype.isub = function isub(a, b) {
this._verify2(a, b);
var res = a.isub(b);
if (res.cmpn(0) < 0)
res.iadd(this.m);
return res;
};
Red.prototype.shl = function shl(a, num) {
this._verify1(a);
return this.imod(a.shln(num));
};
Red.prototype.imul = function imul(a, b) {
this._verify2(a, b);
return this.imod(a.imul(b));
};
Red.prototype.mul = function mul(a, b) {
this._verify2(a, b);
return this.imod(a.mul(b));
};
Red.prototype.isqr = function isqr(a) {
return this.imul(a, a);
};
Red.prototype.sqr = function sqr(a) {
return this.mul(a, a);
};
Red.prototype.sqrt = function sqrt(a) {
if (a.cmpn(0) === 0)
return a.clone();
var mod3 = this.m.andln(3);
assert(mod3 % 2 === 1);
// Fast case
if (mod3 === 3) {
var pow = this.m.add(new BN(1)).ishrn(2);
var r = this.pow(a, pow);
return r;
}
// Tonelli-Shanks algorithm (Totally unoptimized and slow)
//
// Find Q and S, that Q * 2 ^ S = (P - 1)
var q = this.m.subn(1);
var s = 0;
while (q.cmpn(0) !== 0 && q.andln(1) === 0) {
s++;
q.ishrn(1);
}
assert(q.cmpn(0) !== 0);
var one = new BN(1).toRed(this);
var nOne = one.redNeg();
// Find quadratic non-residue
// NOTE: Max is such because of generalized Riemann hypothesis.
var lpow = this.m.subn(1).ishrn(1);
var z = this.m.bitLength();
z = new BN(2 * z * z).toRed(this);
while (this.pow(z, lpow).cmp(nOne) !== 0)
z.redIAdd(nOne);
var c = this.pow(z, q);
var r = this.pow(a, q.addn(1).ishrn(1));
var t = this.pow(a, q);
var m = s;
while (t.cmp(one) !== 0) {
var tmp = t;
for (var i = 0; tmp.cmp(one) !== 0; i++)
tmp = tmp.redSqr();
assert(i < m);
var b = this.pow(c, new BN(1).ishln(m - i - 1));
r = r.redMul(b);
c = b.redSqr();
t = t.redMul(c);
m = i;
}
return r;
};
Red.prototype.invm = function invm(a) {
var inv = a._invmp(this.m);
if (inv.sign) {
inv.sign = false;
return this.imod(inv).redNeg();
} else {
return this.imod(inv);
}
};
Red.prototype.pow = function pow(a, num) {
var w = [];
if (num.cmpn(0) === 0)
return new BN(1);
var q = num.clone();
while (q.cmpn(0) !== 0) {
w.push(q.andln(1));
q.ishrn(1);
}
// Skip leading zeroes
var res = a;
for (var i = 0; i < w.length; i++, res = this.sqr(res))
if (w[i] !== 0)
break;
if (++i < w.length) {
for (var q = this.sqr(res); i < w.length; i++, q = this.sqr(q)) {
if (w[i] === 0)
continue;
res = this.mul(res, q);
}
}
return res;
};
Red.prototype.convertTo = function convertTo(num) {
var r = num.mod(this.m);
if (r === num)
return r.clone();
else
return r;
};
Red.prototype.convertFrom = function convertFrom(num) {
var res = num.clone();
res.red = null;
return res;
};
//
// Montgomery method engine
//
BN.mont = function mont(num) {
return new Mont(num);
};
function Mont(m) {
Red.call(this, m);
this.shift = this.m.bitLength();
if (this.shift % 26 !== 0)
this.shift += 26 - (this.shift % 26);
this.r = new BN(1).ishln(this.shift);
this.r2 = this.imod(this.r.sqr());
this.rinv = this.r._invmp(this.m);
this.minv = this.rinv.mul(this.r).isubn(1).div(this.m);
this.minv.sign = true;
this.minv = this.minv.mod(this.r);
}
inherits(Mont, Red);
Mont.prototype.convertTo = function convertTo(num) {
return this.imod(num.shln(this.shift));
};
Mont.prototype.convertFrom = function convertFrom(num) {
var r = this.imod(num.mul(this.rinv));
r.red = null;
return r;
};
Mont.prototype.imul = function imul(a, b) {
if (a.cmpn(0) === 0 || b.cmpn(0) === 0) {
a.words[0] = 0;
a.length = 1;
return a;
}
var t = a.imul(b);
var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m);
var u = t.isub(c).ishrn(this.shift);
var res = u;
if (u.cmp(this.m) >= 0)
res = u.isub(this.m);
else if (u.cmpn(0) < 0)
res = u.iadd(this.m);
return res._forceRed(this);
};
Mont.prototype.mul = function mul(a, b) {
if (a.cmpn(0) === 0 || b.cmpn(0) === 0)
return new BN(0)._forceRed(this);
var t = a.mul(b);
var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m);
var u = t.isub(c).ishrn(this.shift);
var res = u;
if (u.cmp(this.m) >= 0)
res = u.isub(this.m);
else if (u.cmpn(0) < 0)
res = u.iadd(this.m);
return res._forceRed(this);
};
Mont.prototype.invm = function invm(a) {
// (AR)^-1 * R^2 = (A^-1 * R^-1) * R^2 = A^-1 * R
var res = this.imod(a._invmp(this.m).mul(this.r2));
return res._forceRed(this);
};
})(typeof module === 'undefined' || module, this);
},{}],103:[function(require,module,exports){
(function (Buffer){
var bn = require('bn.js');
var randomBytes = require('randombytes');
module.exports = crt;
function blind(priv) {
var r = getr(priv);
var blinder = r.toRed(bn.mont(priv.modulus))
.redPow(new bn(priv.publicExponent)).fromRed();
return {
blinder: blinder,
unblinder:r.invm(priv.modulus)
};
}
function crt(msg, priv) {
var blinds = blind(priv);
var len = priv.modulus.byteLength();
var mod = bn.mont(priv.modulus);
var blinded = new bn(msg).mul(blinds.blinder).mod(priv.modulus);
var c1 = blinded.toRed(bn.mont(priv.prime1));
var c2 = blinded.toRed(bn.mont(priv.prime2));
var qinv = priv.coefficient;
var p = priv.prime1;
var q = priv.prime2;
var m1 = c1.redPow(priv.exponent1);
var m2 = c2.redPow(priv.exponent2);
m1 = m1.fromRed();
m2 = m2.fromRed();
var h = m1.isub(m2).imul(qinv).mod(p);
h.imul(q);
m2.iadd(h);
var out = new Buffer(m2.imul(blinds.unblinder).mod(priv.modulus).toArray());
if (out.length < len) {
var prefix = new Buffer(len - out.length);
prefix.fill(0);
out = Buffer.concat([prefix, out], len);
}
return out;
}
crt.getr = getr;
function getr(priv) {
var len = priv.modulus.byteLength();
var r = new bn(randomBytes(len));
while (r.cmp(priv.modulus) >= 0 || !r.mod(priv.prime1) || !r.mod(priv.prime2)) {
r = new bn(randomBytes(len));
}
return r;
}
}).call(this,require("buffer").Buffer)
},{"bn.js":102,"buffer":76,"randombytes":221}],104:[function(require,module,exports){
'use strict';
var elliptic = exports;
elliptic.version = require('../package.json').version;
elliptic.utils = require('./elliptic/utils');
elliptic.rand = require('brorand');
elliptic.hmacDRBG = require('./elliptic/hmac-drbg');
elliptic.curve = require('./elliptic/curve');
elliptic.curves = require('./elliptic/curves');
// Protocols
elliptic.ec = require('./elliptic/ec');
},{"../package.json":124,"./elliptic/curve":107,"./elliptic/curves":110,"./elliptic/ec":111,"./elliptic/hmac-drbg":114,"./elliptic/utils":116,"brorand":117}],105:[function(require,module,exports){
'use strict';
var bn = require('bn.js');
var elliptic = require('../../elliptic');
var getNAF = elliptic.utils.getNAF;
var getJSF = elliptic.utils.getJSF;
var assert = elliptic.utils.assert;
function BaseCurve(type, conf) {
this.type = type;
this.p = new bn(conf.p, 16);
// Use Montgomery, when there is no fast reduction for the prime
this.red = conf.prime ? bn.red(conf.prime) : bn.mont(this.p);
// Useful for many curves
this.zero = new bn(0).toRed(this.red);
this.one = new bn(1).toRed(this.red);
this.two = new bn(2).toRed(this.red);
// Curve configuration, optional
this.n = conf.n && new bn(conf.n, 16);
this.g = conf.g && this.pointFromJSON(conf.g, conf.gRed);
// Temporary arrays
this._wnafT1 = new Array(4);
this._wnafT2 = new Array(4);
this._wnafT3 = new Array(4);
this._wnafT4 = new Array(4);
}
module.exports = BaseCurve;
BaseCurve.prototype.point = function point() {
throw new Error('Not implemented');
};
BaseCurve.prototype.validate = function validate() {
throw new Error('Not implemented');
};
BaseCurve.prototype._fixedNafMul = function _fixedNafMul(p, k) {
assert(p.precomputed);
var doubles = p._getDoubles();
var naf = getNAF(k, 1);
var I = (1 << (doubles.step + 1)) - (doubles.step % 2 === 0 ? 2 : 1);
I /= 3;
// Translate into more windowed form
var repr = [];
for (var j = 0; j < naf.length; j += doubles.step) {
var nafW = 0;
for (var k = j + doubles.step - 1; k >= j; k--)
nafW = (nafW << 1) + naf[k];
repr.push(nafW);
}
var a = this.jpoint(null, null, null);
var b = this.jpoint(null, null, null);
for (var i = I; i > 0; i--) {
for (var j = 0; j < repr.length; j++) {
var nafW = repr[j];
if (nafW === i)
b = b.mixedAdd(doubles.points[j]);
else if (nafW === -i)
b = b.mixedAdd(doubles.points[j].neg());
}
a = a.add(b);
}
return a.toP();
};
BaseCurve.prototype._wnafMul = function _wnafMul(p, k) {
var w = 4;
// Precompute window
var nafPoints = p._getNAFPoints(w);
w = nafPoints.wnd;
var wnd = nafPoints.points;
// Get NAF form
var naf = getNAF(k, w);
// Add `this`*(N+1) for every w-NAF index
var acc = this.jpoint(null, null, null);
for (var i = naf.length - 1; i >= 0; i--) {
// Count zeroes
for (var k = 0; i >= 0 && naf[i] === 0; i--)
k++;
if (i >= 0)
k++;
acc = acc.dblp(k);
if (i < 0)
break;
var z = naf[i];
assert(z !== 0);
if (p.type === 'affine') {
// J +- P
if (z > 0)
acc = acc.mixedAdd(wnd[(z - 1) >> 1]);
else
acc = acc.mixedAdd(wnd[(-z - 1) >> 1].neg());
} else {
// J +- J
if (z > 0)
acc = acc.add(wnd[(z - 1) >> 1]);
else
acc = acc.add(wnd[(-z - 1) >> 1].neg());
}
}
return p.type === 'affine' ? acc.toP() : acc;
};
BaseCurve.prototype._wnafMulAdd = function _wnafMulAdd(defW,
points,
coeffs,
len) {
var wndWidth = this._wnafT1;
var wnd = this._wnafT2;
var naf = this._wnafT3;
// Fill all arrays
var max = 0;
for (var i = 0; i < len; i++) {
var p = points[i];
var nafPoints = p._getNAFPoints(defW);
wndWidth[i] = nafPoints.wnd;
wnd[i] = nafPoints.points;
}
// Comb small window NAFs
for (var i = len - 1; i >= 1; i -= 2) {
var a = i - 1;
var b = i;
if (wndWidth[a] !== 1 || wndWidth[b] !== 1) {
naf[a] = getNAF(coeffs[a], wndWidth[a]);
naf[b] = getNAF(coeffs[b], wndWidth[b]);
max = Math.max(naf[a].length, max);
max = Math.max(naf[b].length, max);
continue;
}
var comb = [
points[a], /* 1 */
null, /* 3 */
null, /* 5 */
points[b] /* 7 */
];
// Try to avoid Projective points, if possible
if (points[a].y.cmp(points[b].y) === 0) {
comb[1] = points[a].add(points[b]);
comb[2] = points[a].toJ().mixedAdd(points[b].neg());
} else if (points[a].y.cmp(points[b].y.redNeg()) === 0) {
comb[1] = points[a].toJ().mixedAdd(points[b]);
comb[2] = points[a].add(points[b].neg());
} else {
comb[1] = points[a].toJ().mixedAdd(points[b]);
comb[2] = points[a].toJ().mixedAdd(points[b].neg());
}
var index = [
-3, /* -1 -1 */
-1, /* -1 0 */
-5, /* -1 1 */
-7, /* 0 -1 */
0, /* 0 0 */
7, /* 0 1 */
5, /* 1 -1 */
1, /* 1 0 */
3 /* 1 1 */
];
var jsf = getJSF(coeffs[a], coeffs[b]);
max = Math.max(jsf[0].length, max);
naf[a] = new Array(max);
naf[b] = new Array(max);
for (var j = 0; j < max; j++) {
var ja = jsf[0][j] | 0;
var jb = jsf[1][j] | 0;
naf[a][j] = index[(ja + 1) * 3 + (jb + 1)];
naf[b][j] = 0;
wnd[a] = comb;
}
}
var acc = this.jpoint(null, null, null);
var tmp = this._wnafT4;
for (var i = max; i >= 0; i--) {
var k = 0;
while (i >= 0) {
var zero = true;
for (var j = 0; j < len; j++) {
tmp[j] = naf[j][i] | 0;
if (tmp[j] !== 0)
zero = false;
}
if (!zero)
break;
k++;
i--;
}
if (i >= 0)
k++;
acc = acc.dblp(k);
if (i < 0)
break;
for (var j = 0; j < len; j++) {
var z = tmp[j];
var p;
if (z === 0)
continue;
else if (z > 0)
p = wnd[j][(z - 1) >> 1];
else if (z < 0)
p = wnd[j][(-z - 1) >> 1].neg();
if (p.type === 'affine')
acc = acc.mixedAdd(p);
else
acc = acc.add(p);
}
}
// Zeroify references
for (var i = 0; i < len; i++)
wnd[i] = null;
return acc.toP();
};
function BasePoint(curve, type) {
this.curve = curve;
this.type = type;
this.precomputed = null;
}
BaseCurve.BasePoint = BasePoint;
BasePoint.prototype.validate = function validate() {
return this.curve.validate(this);
};
BasePoint.prototype.precompute = function precompute(power) {
if (this.precomputed)
return this;
var precomputed = {
doubles: null,
naf: null,
beta: null
};
precomputed.naf = this._getNAFPoints(8);
precomputed.doubles = this._getDoubles(4, power);
precomputed.beta = this._getBeta();
this.precomputed = precomputed;
return this;
};
BasePoint.prototype._hasDoubles = function _hasDoubles(k) {
if (!this.precomputed)
return false;
var doubles = this.precomputed.doubles;
if (!doubles)
return false;
return doubles.points.length >= Math.ceil((k.bitLength() + 1) / doubles.step);
};
BasePoint.prototype._getDoubles = function _getDoubles(step, power) {
if (this.precomputed && this.precomputed.doubles)
return this.precomputed.doubles;
var doubles = [ this ];
var acc = this;
for (var i = 0; i < power; i += step) {
for (var j = 0; j < step; j++)
acc = acc.dbl();
doubles.push(acc);
}
return {
step: step,
points: doubles
};
};
BasePoint.prototype._getNAFPoints = function _getNAFPoints(wnd) {
if (this.precomputed && this.precomputed.naf)
return this.precomputed.naf;
var res = [ this ];
var max = (1 << wnd) - 1;
var dbl = max === 1 ? null : this.dbl();
for (var i = 1; i < max; i++)
res[i] = res[i - 1].add(dbl);
return {
wnd: wnd,
points: res
};
};
BasePoint.prototype._getBeta = function _getBeta() {
return null;
};
BasePoint.prototype.dblp = function dblp(k) {
var r = this;
for (var i = 0; i < k; i++)
r = r.dbl();
return r;
};
},{"../../elliptic":104,"bn.js":102}],106:[function(require,module,exports){
'use strict';
var curve = require('../curve');
var elliptic = require('../../elliptic');
var bn = require('bn.js');
var inherits = require('inherits');
var Base = curve.base;
var assert = elliptic.utils.assert;
function EdwardsCurve(conf) {
// NOTE: Important as we are creating point in Base.call()
this.twisted = (conf.a | 0) !== 1;
this.mOneA = this.twisted && (conf.a | 0) === -1;
this.extended = this.mOneA;
Base.call(this, 'edwards', conf);
this.a = new bn(conf.a, 16).mod(this.red.m).toRed(this.red);
this.c = new bn(conf.c, 16).toRed(this.red);
this.c2 = this.c.redSqr();
this.d = new bn(conf.d, 16).toRed(this.red);
this.dd = this.d.redAdd(this.d);
assert(!this.twisted || this.c.fromRed().cmpn(1) === 0);
this.oneC = (conf.c | 0) === 1;
}
inherits(EdwardsCurve, Base);
module.exports = EdwardsCurve;
EdwardsCurve.prototype._mulA = function _mulA(num) {
if (this.mOneA)
return num.redNeg();
else
return this.a.redMul(num);
};
EdwardsCurve.prototype._mulC = function _mulC(num) {
if (this.oneC)
return num;
else
return this.c.redMul(num);
};
// Just for compatibility with Short curve
EdwardsCurve.prototype.jpoint = function jpoint(x, y, z, t) {
return this.point(x, y, z, t);
};
EdwardsCurve.prototype.pointFromX = function pointFromX(odd, x) {
x = new bn(x, 16);
if (!x.red)
x = x.toRed(this.red);
var x2 = x.redSqr();
var rhs = this.c2.redSub(this.a.redMul(x2));
var lhs = this.one.redSub(this.c2.redMul(this.d).redMul(x2));
var y = rhs.redMul(lhs.redInvm()).redSqrt();
var isOdd = y.fromRed().isOdd();
if (odd && !isOdd || !odd && isOdd)
y = y.redNeg();
return this.point(x, y, curve.one);
};
EdwardsCurve.prototype.validate = function validate(point) {
if (point.isInfinity())
return true;
// Curve: A * X^2 + Y^2 = C^2 * (1 + D * X^2 * Y^2)
point.normalize();
var x2 = point.x.redSqr();
var y2 = point.y.redSqr();
var lhs = x2.redMul(this.a).redAdd(y2);
var rhs = this.c2.redMul(this.one.redAdd(this.d.redMul(x2).redMul(y2)));
return lhs.cmp(rhs) === 0;
};
function Point(curve, x, y, z, t) {
Base.BasePoint.call(this, curve, 'projective');
if (x === null && y === null && z === null) {
this.x = this.curve.zero;
this.y = this.curve.one;
this.z = this.curve.one;
this.t = this.curve.zero;
this.zOne = true;
} else {
this.x = new bn(x, 16);
this.y = new bn(y, 16);
this.z = z ? new bn(z, 16) : this.curve.one;
this.t = t && new bn(t, 16);
if (!this.x.red)
this.x = this.x.toRed(this.curve.red);
if (!this.y.red)
this.y = this.y.toRed(this.curve.red);
if (!this.z.red)
this.z = this.z.toRed(this.curve.red);
if (this.t && !this.t.red)
this.t = this.t.toRed(this.curve.red);
this.zOne = this.z === this.curve.one;
// Use extended coordinates
if (this.curve.extended && !this.t) {
this.t = this.x.redMul(this.y);
if (!this.zOne)
this.t = this.t.redMul(this.z.redInvm());
}
}
}
inherits(Point, Base.BasePoint);
EdwardsCurve.prototype.pointFromJSON = function pointFromJSON(obj) {
return Point.fromJSON(this, obj);
};
EdwardsCurve.prototype.point = function point(x, y, z, t) {
return new Point(this, x, y, z, t);
};
Point.fromJSON = function fromJSON(curve, obj) {
return new Point(curve, obj[0], obj[1], obj[2]);
};
Point.prototype.inspect = function inspect() {
if (this.isInfinity())
return '';
return '';
};
Point.prototype.isInfinity = function isInfinity() {
// XXX This code assumes that zero is always zero in red
return this.x.cmpn(0) === 0 &&
this.y.cmp(this.z) === 0;
};
Point.prototype._extDbl = function _extDbl() {
// hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html
// #doubling-dbl-2008-hwcd
// 4M + 4S
// A = X1^2
var a = this.x.redSqr();
// B = Y1^2
var b = this.y.redSqr();
// C = 2 * Z1^2
var c = this.z.redSqr();
c = c.redIAdd(c);
// D = a * A
var d = this.curve._mulA(a);
// E = (X1 + Y1)^2 - A - B
var e = this.x.redAdd(this.y).redSqr().redISub(a).redISub(b);
// G = D + B
var g = d.redAdd(b);
// F = G - C
var f = g.redSub(c);
// H = D - B
var h = d.redSub(b);
// X3 = E * F
var nx = e.redMul(f);
// Y3 = G * H
var ny = g.redMul(h);
// T3 = E * H
var nt = e.redMul(h);
// Z3 = F * G
var nz = f.redMul(g);
return this.curve.point(nx, ny, nz, nt);
};
Point.prototype._projDbl = function _projDbl() {
// hyperelliptic.org/EFD/g1p/auto-twisted-projective.html
// #doubling-dbl-2008-bbjlp
// #doubling-dbl-2007-bl
// and others
// Generally 3M + 4S or 2M + 4S
// B = (X1 + Y1)^2
var b = this.x.redAdd(this.y).redSqr();
// C = X1^2
var c = this.x.redSqr();
// D = Y1^2
var d = this.y.redSqr();
var nx;
var ny;
var nz;
if (this.curve.twisted) {
// E = a * C
var e = this.curve._mulA(c);
// F = E + D
var f = e.redAdd(d);
if (this.zOne) {
// X3 = (B - C - D) * (F - 2)
nx = b.redSub(c).redSub(d).redMul(f.redSub(this.curve.two));
// Y3 = F * (E - D)
ny = f.redMul(e.redSub(d));
// Z3 = F^2 - 2 * F
nz = f.redSqr().redSub(f).redSub(f);
} else {
// H = Z1^2
var h = this.z.redSqr();
// J = F - 2 * H
var j = f.redSub(h).redISub(h);
// X3 = (B-C-D)*J
nx = b.redSub(c).redISub(d).redMul(j);
// Y3 = F * (E - D)
ny = f.redMul(e.redSub(d));
// Z3 = F * J
nz = f.redMul(j);
}
} else {
// E = C + D
var e = c.redAdd(d);
// H = (c * Z1)^2
var h = this.curve._mulC(this.c.redMul(this.z)).redSqr();
// J = E - 2 * H
var j = e.redSub(h).redSub(h);
// X3 = c * (B - E) * J
nx = this.curve._mulC(b.redISub(e)).redMul(j);
// Y3 = c * E * (C - D)
ny = this.curve._mulC(e).redMul(c.redISub(d));
// Z3 = E * J
nz = e.redMul(j);
}
return this.curve.point(nx, ny, nz);
};
Point.prototype.dbl = function dbl() {
if (this.isInfinity())
return this;
// Double in extended coordinates
if (this.curve.extended)
return this._extDbl();
else
return this._projDbl();
};
Point.prototype._extAdd = function _extAdd(p) {
// hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html
// #addition-add-2008-hwcd-3
// 8M
// A = (Y1 - X1) * (Y2 - X2)
var a = this.y.redSub(this.x).redMul(p.y.redSub(p.x));
// B = (Y1 + X1) * (Y2 + X2)
var b = this.y.redAdd(this.x).redMul(p.y.redAdd(p.x));
// C = T1 * k * T2
var c = this.t.redMul(this.curve.dd).redMul(p.t);
// D = Z1 * 2 * Z2
var d = this.z.redMul(p.z.redAdd(p.z));
// E = B - A
var e = b.redSub(a);
// F = D - C
var f = d.redSub(c);
// G = D + C
var g = d.redAdd(c);
// H = B + A
var h = b.redAdd(a);
// X3 = E * F
var nx = e.redMul(f);
// Y3 = G * H
var ny = g.redMul(h);
// T3 = E * H
var nt = e.redMul(h);
// Z3 = F * G
var nz = f.redMul(g);
return this.curve.point(nx, ny, nz, nt);
};
Point.prototype._projAdd = function _projAdd(p) {
// hyperelliptic.org/EFD/g1p/auto-twisted-projective.html
// #addition-add-2008-bbjlp
// #addition-add-2007-bl
// 10M + 1S
// A = Z1 * Z2
var a = this.z.redMul(p.z);
// B = A^2
var b = a.redSqr();
// C = X1 * X2
var c = this.x.redMul(p.x);
// D = Y1 * Y2
var d = this.y.redMul(p.y);
// E = d * C * D
var e = this.curve.d.redMul(c).redMul(d);
// F = B - E
var f = b.redSub(e);
// G = B + E
var g = b.redAdd(e);
// X3 = A * F * ((X1 + Y1) * (X2 + Y2) - C - D)
var tmp = this.x.redAdd(this.y).redMul(p.x.redAdd(p.y)).redISub(c).redISub(d);
var nx = a.redMul(f).redMul(tmp);
var ny;
var nz;
if (this.curve.twisted) {
// Y3 = A * G * (D - a * C)
ny = a.redMul(g).redMul(d.redSub(this.curve._mulA(c)));
// Z3 = F * G
nz = f.redMul(g);
} else {
// Y3 = A * G * (D - C)
ny = a.redMul(g).redMul(d.redSub(c));
// Z3 = c * F * G
nz = this.curve._mulC(f).redMul(g);
}
return this.curve.point(nx, ny, nz);
};
Point.prototype.add = function add(p) {
if (this.isInfinity())
return p;
if (p.isInfinity())
return this;
if (this.curve.extended)
return this._extAdd(p);
else
return this._projAdd(p);
};
Point.prototype.mul = function mul(k) {
if (this._hasDoubles(k))
return this.curve._fixedNafMul(this, k);
else
return this.curve._wnafMul(this, k);
};
Point.prototype.mulAdd = function mulAdd(k1, p, k2) {
return this.curve._wnafMulAdd(1, [ this, p ], [ k1, k2 ], 2);
};
Point.prototype.normalize = function normalize() {
if (this.zOne)
return this;
// Normalize coordinates
var zi = this.z.redInvm();
this.x = this.x.redMul(zi);
this.y = this.y.redMul(zi);
if (this.t)
this.t = this.t.redMul(zi);
this.z = this.curve.one;
this.zOne = true;
return this;
};
Point.prototype.neg = function neg() {
return this.curve.point(this.x.redNeg(),
this.y,
this.z,
this.t && this.t.redNeg());
};
Point.prototype.getX = function getX() {
this.normalize();
return this.x.fromRed();
};
Point.prototype.getY = function getY() {
this.normalize();
return this.y.fromRed();
};
// Compatibility with BaseCurve
Point.prototype.toP = Point.prototype.normalize;
Point.prototype.mixedAdd = Point.prototype.add;
},{"../../elliptic":104,"../curve":107,"bn.js":102,"inherits":223}],107:[function(require,module,exports){
'use strict';
var curve = exports;
curve.base = require('./base');
curve.short = require('./short');
curve.mont = require('./mont');
curve.edwards = require('./edwards');
},{"./base":105,"./edwards":106,"./mont":108,"./short":109}],108:[function(require,module,exports){
'use strict';
var curve = require('../curve');
var bn = require('bn.js');
var inherits = require('inherits');
var Base = curve.base;
function MontCurve(conf) {
Base.call(this, 'mont', conf);
this.a = new bn(conf.a, 16).toRed(this.red);
this.b = new bn(conf.b, 16).toRed(this.red);
this.i4 = new bn(4).toRed(this.red).redInvm();
this.two = new bn(2).toRed(this.red);
this.a24 = this.i4.redMul(this.a.redAdd(this.two));
}
inherits(MontCurve, Base);
module.exports = MontCurve;
MontCurve.prototype.validate = function validate(point) {
var x = point.normalize().x;
var x2 = x.redSqr();
var rhs = x2.redMul(x).redAdd(x2.redMul(this.a)).redAdd(x);
var y = rhs.redSqrt();
return y.redSqr().cmp(rhs) === 0;
};
function Point(curve, x, z) {
Base.BasePoint.call(this, curve, 'projective');
if (x === null && z === null) {
this.x = this.curve.one;
this.z = this.curve.zero;
} else {
this.x = new bn(x, 16);
this.z = new bn(z, 16);
if (!this.x.red)
this.x = this.x.toRed(this.curve.red);
if (!this.z.red)
this.z = this.z.toRed(this.curve.red);
}
}
inherits(Point, Base.BasePoint);
MontCurve.prototype.point = function point(x, z) {
return new Point(this, x, z);
};
MontCurve.prototype.pointFromJSON = function pointFromJSON(obj) {
return Point.fromJSON(this, obj);
};
Point.prototype.precompute = function precompute() {
// No-op
};
Point.fromJSON = function fromJSON(curve, obj) {
return new Point(curve, obj[0], obj[1] || curve.one);
};
Point.prototype.inspect = function inspect() {
if (this.isInfinity())
return '';
return '';
};
Point.prototype.isInfinity = function isInfinity() {
// XXX This code assumes that zero is always zero in red
return this.z.cmpn(0) === 0;
};
Point.prototype.dbl = function dbl() {
// http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#doubling-dbl-1987-m-3
// 2M + 2S + 4A
// A = X1 + Z1
var a = this.x.redAdd(this.z);
// AA = A^2
var aa = a.redSqr();
// B = X1 - Z1
var b = this.x.redSub(this.z);
// BB = B^2
var bb = b.redSqr();
// C = AA - BB
var c = aa.redSub(bb);
// X3 = AA * BB
var nx = aa.redMul(bb);
// Z3 = C * (BB + A24 * C)
var nz = c.redMul(bb.redAdd(this.curve.a24.redMul(c)));
return this.curve.point(nx, nz);
};
Point.prototype.add = function add() {
throw new Error('Not supported on Montgomery curve');
};
Point.prototype.diffAdd = function diffAdd(p, diff) {
// http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#diffadd-dadd-1987-m-3
// 4M + 2S + 6A
// A = X2 + Z2
var a = this.x.redAdd(this.z);
// B = X2 - Z2
var b = this.x.redSub(this.z);
// C = X3 + Z3
var c = p.x.redAdd(p.z);
// D = X3 - Z3
var d = p.x.redSub(p.z);
// DA = D * A
var da = d.redMul(a);
// CB = C * B
var cb = c.redMul(b);
// X5 = Z1 * (DA + CB)^2
var nx = diff.z.redMul(da.redAdd(cb).redSqr());
// Z5 = X1 * (DA - CB)^2
var nz = diff.x.redMul(da.redISub(cb).redSqr());
return this.curve.point(nx, nz);
};
Point.prototype.mul = function mul(k) {
var t = k.clone();
var a = this; // (N / 2) * Q + Q
var b = this.curve.point(null, null); // (N / 2) * Q
var c = this; // Q
for (var bits = []; t.cmpn(0) !== 0; t.ishrn(1))
bits.push(t.andln(1));
for (var i = bits.length - 1; i >= 0; i--) {
if (bits[i] === 0) {
// N * Q + Q = ((N / 2) * Q + Q)) + (N / 2) * Q
a = a.diffAdd(b, c);
// N * Q = 2 * ((N / 2) * Q + Q))
b = b.dbl();
} else {
// N * Q = ((N / 2) * Q + Q) + ((N / 2) * Q)
b = a.diffAdd(b, c);
// N * Q + Q = 2 * ((N / 2) * Q + Q)
a = a.dbl();
}
}
return b;
};
Point.prototype.mulAdd = function mulAdd() {
throw new Error('Not supported on Montgomery curve');
};
Point.prototype.normalize = function normalize() {
this.x = this.x.redMul(this.z.redInvm());
this.z = this.curve.one;
return this;
};
Point.prototype.getX = function getX() {
// Normalize coordinates
this.normalize();
return this.x.fromRed();
};
},{"../curve":107,"bn.js":102,"inherits":223}],109:[function(require,module,exports){
'use strict';
var curve = require('../curve');
var elliptic = require('../../elliptic');
var bn = require('bn.js');
var inherits = require('inherits');
var Base = curve.base;
var assert = elliptic.utils.assert;
function ShortCurve(conf) {
Base.call(this, 'short', conf);
this.a = new bn(conf.a, 16).toRed(this.red);
this.b = new bn(conf.b, 16).toRed(this.red);
this.tinv = this.two.redInvm();
this.zeroA = this.a.fromRed().cmpn(0) === 0;
this.threeA = this.a.fromRed().sub(this.p).cmpn(-3) === 0;
// If the curve is endomorphic, precalculate beta and lambda
this.endo = this._getEndomorphism(conf);
this._endoWnafT1 = new Array(4);
this._endoWnafT2 = new Array(4);
}
inherits(ShortCurve, Base);
module.exports = ShortCurve;
ShortCurve.prototype._getEndomorphism = function _getEndomorphism(conf) {
// No efficient endomorphism
if (!this.zeroA || !this.g || !this.n || this.p.modn(3) !== 1)
return;
// Compute beta and lambda, that lambda * P = (beta * Px; Py)
var beta;
var lambda;
if (conf.beta) {
beta = new bn(conf.beta, 16).toRed(this.red);
} else {
var betas = this._getEndoRoots(this.p);
// Choose the smallest beta
beta = betas[0].cmp(betas[1]) < 0 ? betas[0] : betas[1];
beta = beta.toRed(this.red);
}
if (conf.lambda) {
lambda = new bn(conf.lambda, 16);
} else {
// Choose the lambda that is matching selected beta
var lambdas = this._getEndoRoots(this.n);
if (this.g.mul(lambdas[0]).x.cmp(this.g.x.redMul(beta)) === 0) {
lambda = lambdas[0];
} else {
lambda = lambdas[1];
assert(this.g.mul(lambda).x.cmp(this.g.x.redMul(beta)) === 0);
}
}
// Get basis vectors, used for balanced length-two representation
var basis;
if (conf.basis) {
basis = conf.basis.map(function(vec) {
return {
a: new bn(vec.a, 16),
b: new bn(vec.b, 16)
};
});
} else {
basis = this._getEndoBasis(lambda);
}
return {
beta: beta,
lambda: lambda,
basis: basis
};
};
ShortCurve.prototype._getEndoRoots = function _getEndoRoots(num) {
// Find roots of for x^2 + x + 1 in F
// Root = (-1 +- Sqrt(-3)) / 2
//
var red = num === this.p ? this.red : bn.mont(num);
var tinv = new bn(2).toRed(red).redInvm();
var ntinv = tinv.redNeg();
var s = new bn(3).toRed(red).redNeg().redSqrt().redMul(tinv);
var l1 = ntinv.redAdd(s).fromRed();
var l2 = ntinv.redSub(s).fromRed();
return [ l1, l2 ];
};
ShortCurve.prototype._getEndoBasis = function _getEndoBasis(lambda) {
// aprxSqrt >= sqrt(this.n)
var aprxSqrt = this.n.shrn(Math.floor(this.n.bitLength() / 2));
// 3.74
// Run EGCD, until r(L + 1) < aprxSqrt
var u = lambda;
var v = this.n.clone();
var x1 = new bn(1);
var y1 = new bn(0);
var x2 = new bn(0);
var y2 = new bn(1);
// NOTE: all vectors are roots of: a + b * lambda = 0 (mod n)
var a0;
var b0;
// First vector
var a1;
var b1;
// Second vector
var a2;
var b2;
var prevR;
var i = 0;
var r;
var x;
while (u.cmpn(0) !== 0) {
var q = v.div(u);
r = v.sub(q.mul(u));
x = x2.sub(q.mul(x1));
var y = y2.sub(q.mul(y1));
if (!a1 && r.cmp(aprxSqrt) < 0) {
a0 = prevR.neg();
b0 = x1;
a1 = r.neg();
b1 = x;
} else if (a1 && ++i === 2) {
break;
}
prevR = r;
v = u;
u = r;
x2 = x1;
x1 = x;
y2 = y1;
y1 = y;
}
a2 = r.neg();
b2 = x;
var len1 = a1.sqr().add(b1.sqr());
var len2 = a2.sqr().add(b2.sqr());
if (len2.cmp(len1) >= 0) {
a2 = a0;
b2 = b0;
}
// Normalize signs
if (a1.sign) {
a1 = a1.neg();
b1 = b1.neg();
}
if (a2.sign) {
a2 = a2.neg();
b2 = b2.neg();
}
return [
{ a: a1, b: b1 },
{ a: a2, b: b2 }
];
};
ShortCurve.prototype._endoSplit = function _endoSplit(k) {
var basis = this.endo.basis;
var v1 = basis[0];
var v2 = basis[1];
var c1 = v2.b.mul(k).divRound(this.n);
var c2 = v1.b.neg().mul(k).divRound(this.n);
var p1 = c1.mul(v1.a);
var p2 = c2.mul(v2.a);
var q1 = c1.mul(v1.b);
var q2 = c2.mul(v2.b);
// Calculate answer
var k1 = k.sub(p1).sub(p2);
var k2 = q1.add(q2).neg();
return { k1: k1, k2: k2 };
};
ShortCurve.prototype.pointFromX = function pointFromX(odd, x) {
x = new bn(x, 16);
if (!x.red)
x = x.toRed(this.red);
var y2 = x.redSqr().redMul(x).redIAdd(x.redMul(this.a)).redIAdd(this.b);
var y = y2.redSqrt();
// XXX Is there any way to tell if the number is odd without converting it
// to non-red form?
var isOdd = y.fromRed().isOdd();
if (odd && !isOdd || !odd && isOdd)
y = y.redNeg();
return this.point(x, y);
};
ShortCurve.prototype.validate = function validate(point) {
if (point.inf)
return true;
var x = point.x;
var y = point.y;
var ax = this.a.redMul(x);
var rhs = x.redSqr().redMul(x).redIAdd(ax).redIAdd(this.b);
return y.redSqr().redISub(rhs).cmpn(0) === 0;
};
ShortCurve.prototype._endoWnafMulAdd =
function _endoWnafMulAdd(points, coeffs) {
var npoints = this._endoWnafT1;
var ncoeffs = this._endoWnafT2;
for (var i = 0; i < points.length; i++) {
var split = this._endoSplit(coeffs[i]);
var p = points[i];
var beta = p._getBeta();
if (split.k1.sign) {
split.k1.sign = !split.k1.sign;
p = p.neg(true);
}
if (split.k2.sign) {
split.k2.sign = !split.k2.sign;
beta = beta.neg(true);
}
npoints[i * 2] = p;
npoints[i * 2 + 1] = beta;
ncoeffs[i * 2] = split.k1;
ncoeffs[i * 2 + 1] = split.k2;
}
var res = this._wnafMulAdd(1, npoints, ncoeffs, i * 2);
// Clean-up references to points and coefficients
for (var j = 0; j < i * 2; j++) {
npoints[j] = null;
ncoeffs[j] = null;
}
return res;
};
function Point(curve, x, y, isRed) {
Base.BasePoint.call(this, curve, 'affine');
if (x === null && y === null) {
this.x = null;
this.y = null;
this.inf = true;
} else {
this.x = new bn(x, 16);
this.y = new bn(y, 16);
// Force redgomery representation when loading from JSON
if (isRed) {
this.x.forceRed(this.curve.red);
this.y.forceRed(this.curve.red);
}
if (!this.x.red)
this.x = this.x.toRed(this.curve.red);
if (!this.y.red)
this.y = this.y.toRed(this.curve.red);
this.inf = false;
}
}
inherits(Point, Base.BasePoint);
ShortCurve.prototype.point = function point(x, y, isRed) {
return new Point(this, x, y, isRed);
};
ShortCurve.prototype.pointFromJSON = function pointFromJSON(obj, red) {
return Point.fromJSON(this, obj, red);
};
Point.prototype._getBeta = function _getBeta() {
if (!this.curve.endo)
return;
var pre = this.precomputed;
if (pre && pre.beta)
return pre.beta;
var beta = this.curve.point(this.x.redMul(this.curve.endo.beta), this.y);
if (pre) {
var curve = this.curve;
var endoMul = function(p) {
return curve.point(p.x.redMul(curve.endo.beta), p.y);
};
pre.beta = beta;
beta.precomputed = {
beta: null,
naf: pre.naf && {
wnd: pre.naf.wnd,
points: pre.naf.points.map(endoMul)
},
doubles: pre.doubles && {
step: pre.doubles.step,
points: pre.doubles.points.map(endoMul)
}
};
}
return beta;
};
Point.prototype.toJSON = function toJSON() {
if (!this.precomputed)
return [ this.x, this.y ];
return [ this.x, this.y, this.precomputed && {
doubles: this.precomputed.doubles && {
step: this.precomputed.doubles.step,
points: this.precomputed.doubles.points.slice(1)
},
naf: this.precomputed.naf && {
wnd: this.precomputed.naf.wnd,
points: this.precomputed.naf.points.slice(1)
}
} ];
};
Point.fromJSON = function fromJSON(curve, obj, red) {
if (typeof obj === 'string')
obj = JSON.parse(obj);
var res = curve.point(obj[0], obj[1], red);
if (!obj[2])
return res;
function obj2point(obj) {
return curve.point(obj[0], obj[1], red);
}
var pre = obj[2];
res.precomputed = {
beta: null,
doubles: pre.doubles && {
step: pre.doubles.step,
points: [ res ].concat(pre.doubles.points.map(obj2point))
},
naf: pre.naf && {
wnd: pre.naf.wnd,
points: [ res ].concat(pre.naf.points.map(obj2point))
}
};
return res;
};
Point.prototype.inspect = function inspect() {
if (this.isInfinity())
return '';
return '';
};
Point.prototype.isInfinity = function isInfinity() {
return this.inf;
};
Point.prototype.add = function add(p) {
// O + P = P
if (this.inf)
return p;
// P + O = P
if (p.inf)
return this;
// P + P = 2P
if (this.eq(p))
return this.dbl();
// P + (-P) = O
if (this.neg().eq(p))
return this.curve.point(null, null);
// P + Q = O
if (this.x.cmp(p.x) === 0)
return this.curve.point(null, null);
var c = this.y.redSub(p.y);
if (c.cmpn(0) !== 0)
c = c.redMul(this.x.redSub(p.x).redInvm());
var nx = c.redSqr().redISub(this.x).redISub(p.x);
var ny = c.redMul(this.x.redSub(nx)).redISub(this.y);
return this.curve.point(nx, ny);
};
Point.prototype.dbl = function dbl() {
if (this.inf)
return this;
// 2P = O
var ys1 = this.y.redAdd(this.y);
if (ys1.cmpn(0) === 0)
return this.curve.point(null, null);
var a = this.curve.a;
var x2 = this.x.redSqr();
var dyinv = ys1.redInvm();
var c = x2.redAdd(x2).redIAdd(x2).redIAdd(a).redMul(dyinv);
var nx = c.redSqr().redISub(this.x.redAdd(this.x));
var ny = c.redMul(this.x.redSub(nx)).redISub(this.y);
return this.curve.point(nx, ny);
};
Point.prototype.getX = function getX() {
return this.x.fromRed();
};
Point.prototype.getY = function getY() {
return this.y.fromRed();
};
Point.prototype.mul = function mul(k) {
k = new bn(k, 16);
if (this._hasDoubles(k))
return this.curve._fixedNafMul(this, k);
else if (this.curve.endo)
return this.curve._endoWnafMulAdd([ this ], [ k ]);
else
return this.curve._wnafMul(this, k);
};
Point.prototype.mulAdd = function mulAdd(k1, p2, k2) {
var points = [ this, p2 ];
var coeffs = [ k1, k2 ];
if (this.curve.endo)
return this.curve._endoWnafMulAdd(points, coeffs);
else
return this.curve._wnafMulAdd(1, points, coeffs, 2);
};
Point.prototype.eq = function eq(p) {
return this === p ||
this.inf === p.inf &&
(this.inf || this.x.cmp(p.x) === 0 && this.y.cmp(p.y) === 0);
};
Point.prototype.neg = function neg(_precompute) {
if (this.inf)
return this;
var res = this.curve.point(this.x, this.y.redNeg());
if (_precompute && this.precomputed) {
var pre = this.precomputed;
var negate = function(p) {
return p.neg();
};
res.precomputed = {
naf: pre.naf && {
wnd: pre.naf.wnd,
points: pre.naf.points.map(negate)
},
doubles: pre.doubles && {
step: pre.doubles.step,
points: pre.doubles.points.map(negate)
}
};
}
return res;
};
Point.prototype.toJ = function toJ() {
if (this.inf)
return this.curve.jpoint(null, null, null);
var res = this.curve.jpoint(this.x, this.y, this.curve.one);
return res;
};
function JPoint(curve, x, y, z) {
Base.BasePoint.call(this, curve, 'jacobian');
if (x === null && y === null && z === null) {
this.x = this.curve.one;
this.y = this.curve.one;
this.z = new bn(0);
} else {
this.x = new bn(x, 16);
this.y = new bn(y, 16);
this.z = new bn(z, 16);
}
if (!this.x.red)
this.x = this.x.toRed(this.curve.red);
if (!this.y.red)
this.y = this.y.toRed(this.curve.red);
if (!this.z.red)
this.z = this.z.toRed(this.curve.red);
this.zOne = this.z === this.curve.one;
}
inherits(JPoint, Base.BasePoint);
ShortCurve.prototype.jpoint = function jpoint(x, y, z) {
return new JPoint(this, x, y, z);
};
JPoint.prototype.toP = function toP() {
if (this.isInfinity())
return this.curve.point(null, null);
var zinv = this.z.redInvm();
var zinv2 = zinv.redSqr();
var ax = this.x.redMul(zinv2);
var ay = this.y.redMul(zinv2).redMul(zinv);
return this.curve.point(ax, ay);
};
JPoint.prototype.neg = function neg() {
return this.curve.jpoint(this.x, this.y.redNeg(), this.z);
};
JPoint.prototype.add = function add(p) {
// O + P = P
if (this.isInfinity())
return p;
// P + O = P
if (p.isInfinity())
return this;
// 12M + 4S + 7A
var pz2 = p.z.redSqr();
var z2 = this.z.redSqr();
var u1 = this.x.redMul(pz2);
var u2 = p.x.redMul(z2);
var s1 = this.y.redMul(pz2.redMul(p.z));
var s2 = p.y.redMul(z2.redMul(this.z));
var h = u1.redSub(u2);
var r = s1.redSub(s2);
if (h.cmpn(0) === 0) {
if (r.cmpn(0) !== 0)
return this.curve.jpoint(null, null, null);
else
return this.dbl();
}
var h2 = h.redSqr();
var h3 = h2.redMul(h);
var v = u1.redMul(h2);
var nx = r.redSqr().redIAdd(h3).redISub(v).redISub(v);
var ny = r.redMul(v.redISub(nx)).redISub(s1.redMul(h3));
var nz = this.z.redMul(p.z).redMul(h);
return this.curve.jpoint(nx, ny, nz);
};
JPoint.prototype.mixedAdd = function mixedAdd(p) {
// O + P = P
if (this.isInfinity())
return p.toJ();
// P + O = P
if (p.isInfinity())
return this;
// 8M + 3S + 7A
var z2 = this.z.redSqr();
var u1 = this.x;
var u2 = p.x.redMul(z2);
var s1 = this.y;
var s2 = p.y.redMul(z2).redMul(this.z);
var h = u1.redSub(u2);
var r = s1.redSub(s2);
if (h.cmpn(0) === 0) {
if (r.cmpn(0) !== 0)
return this.curve.jpoint(null, null, null);
else
return this.dbl();
}
var h2 = h.redSqr();
var h3 = h2.redMul(h);
var v = u1.redMul(h2);
var nx = r.redSqr().redIAdd(h3).redISub(v).redISub(v);
var ny = r.redMul(v.redISub(nx)).redISub(s1.redMul(h3));
var nz = this.z.redMul(h);
return this.curve.jpoint(nx, ny, nz);
};
JPoint.prototype.dblp = function dblp(pow) {
if (pow === 0)
return this;
if (this.isInfinity())
return this;
if (!pow)
return this.dbl();
if (this.curve.zeroA || this.curve.threeA) {
var r = this;
for (var i = 0; i < pow; i++)
r = r.dbl();
return r;
}
// 1M + 2S + 1A + N * (4S + 5M + 8A)
// N = 1 => 6M + 6S + 9A
var a = this.curve.a;
var tinv = this.curve.tinv;
var jx = this.x;
var jy = this.y;
var jz = this.z;
var jz4 = jz.redSqr().redSqr();
// Reuse results
var jyd = jy.redAdd(jy);
for (var i = 0; i < pow; i++) {
var jx2 = jx.redSqr();
var jyd2 = jyd.redSqr();
var jyd4 = jyd2.redSqr();
var c = jx2.redAdd(jx2).redIAdd(jx2).redIAdd(a.redMul(jz4));
var t1 = jx.redMul(jyd2);
var nx = c.redSqr().redISub(t1.redAdd(t1));
var t2 = t1.redISub(nx);
var dny = c.redMul(t2);
dny = dny.redIAdd(dny).redISub(jyd4);
var nz = jyd.redMul(jz);
if (i + 1 < pow)
jz4 = jz4.redMul(jyd4);
jx = nx;
jz = nz;
jyd = dny;
}
return this.curve.jpoint(jx, jyd.redMul(tinv), jz);
};
JPoint.prototype.dbl = function dbl() {
if (this.isInfinity())
return this;
if (this.curve.zeroA)
return this._zeroDbl();
else if (this.curve.threeA)
return this._threeDbl();
else
return this._dbl();
};
JPoint.prototype._zeroDbl = function _zeroDbl() {
var nx;
var ny;
var nz;
// Z = 1
if (this.zOne) {
// hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html
// #doubling-mdbl-2007-bl
// 1M + 5S + 14A
// XX = X1^2
var xx = this.x.redSqr();
// YY = Y1^2
var yy = this.y.redSqr();
// YYYY = YY^2
var yyyy = yy.redSqr();
// S = 2 * ((X1 + YY)^2 - XX - YYYY)
var s = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy);
s = s.redIAdd(s);
// M = 3 * XX + a; a = 0
var m = xx.redAdd(xx).redIAdd(xx);
// T = M ^ 2 - 2*S
var t = m.redSqr().redISub(s).redISub(s);
// 8 * YYYY
var yyyy8 = yyyy.redIAdd(yyyy);
yyyy8 = yyyy8.redIAdd(yyyy8);
yyyy8 = yyyy8.redIAdd(yyyy8);
// X3 = T
nx = t;
// Y3 = M * (S - T) - 8 * YYYY
ny = m.redMul(s.redISub(t)).redISub(yyyy8);
// Z3 = 2*Y1
nz = this.y.redAdd(this.y);
} else {
// hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html
// #doubling-dbl-2009-l
// 2M + 5S + 13A
// A = X1^2
var a = this.x.redSqr();
// B = Y1^2
var b = this.y.redSqr();
// C = B^2
var c = b.redSqr();
// D = 2 * ((X1 + B)^2 - A - C)
var d = this.x.redAdd(b).redSqr().redISub(a).redISub(c);
d = d.redIAdd(d);
// E = 3 * A
var e = a.redAdd(a).redIAdd(a);
// F = E^2
var f = e.redSqr();
// 8 * C
var c8 = c.redIAdd(c);
c8 = c8.redIAdd(c8);
c8 = c8.redIAdd(c8);
// X3 = F - 2 * D
nx = f.redISub(d).redISub(d);
// Y3 = E * (D - X3) - 8 * C
ny = e.redMul(d.redISub(nx)).redISub(c8);
// Z3 = 2 * Y1 * Z1
nz = this.y.redMul(this.z);
nz = nz.redIAdd(nz);
}
return this.curve.jpoint(nx, ny, nz);
};
JPoint.prototype._threeDbl = function _threeDbl() {
var nx;
var ny;
var nz;
// Z = 1
if (this.zOne) {
// hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html
// #doubling-mdbl-2007-bl
// 1M + 5S + 15A
// XX = X1^2
var xx = this.x.redSqr();
// YY = Y1^2
var yy = this.y.redSqr();
// YYYY = YY^2
var yyyy = yy.redSqr();
// S = 2 * ((X1 + YY)^2 - XX - YYYY)
var s = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy);
s = s.redIAdd(s);
// M = 3 * XX + a
var m = xx.redAdd(xx).redIAdd(xx).redIAdd(this.curve.a);
// T = M^2 - 2 * S
var t = m.redSqr().redISub(s).redISub(s);
// X3 = T
nx = t;
// Y3 = M * (S - T) - 8 * YYYY
var yyyy8 = yyyy.redIAdd(yyyy);
yyyy8 = yyyy8.redIAdd(yyyy8);
yyyy8 = yyyy8.redIAdd(yyyy8);
ny = m.redMul(s.redISub(t)).redISub(yyyy8);
// Z3 = 2 * Y1
nz = this.y.redAdd(this.y);
} else {
// hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b
// 3M + 5S
// delta = Z1^2
var delta = this.z.redSqr();
// gamma = Y1^2
var gamma = this.y.redSqr();
// beta = X1 * gamma
var beta = this.x.redMul(gamma);
// alpha = 3 * (X1 - delta) * (X1 + delta)
var alpha = this.x.redSub(delta).redMul(this.x.redAdd(delta));
alpha = alpha.redAdd(alpha).redIAdd(alpha);
// X3 = alpha^2 - 8 * beta
var beta4 = beta.redIAdd(beta);
beta4 = beta4.redIAdd(beta4);
var beta8 = beta4.redAdd(beta4);
nx = alpha.redSqr().redISub(beta8);
// Z3 = (Y1 + Z1)^2 - gamma - delta
nz = this.y.redAdd(this.z).redSqr().redISub(gamma).redISub(delta);
// Y3 = alpha * (4 * beta - X3) - 8 * gamma^2
var ggamma8 = gamma.redSqr();
ggamma8 = ggamma8.redIAdd(ggamma8);
ggamma8 = ggamma8.redIAdd(ggamma8);
ggamma8 = ggamma8.redIAdd(ggamma8);
ny = alpha.redMul(beta4.redISub(nx)).redISub(ggamma8);
}
return this.curve.jpoint(nx, ny, nz);
};
JPoint.prototype._dbl = function _dbl() {
var a = this.curve.a;
// 4M + 6S + 10A
var jx = this.x;
var jy = this.y;
var jz = this.z;
var jz4 = jz.redSqr().redSqr();
var jx2 = jx.redSqr();
var jy2 = jy.redSqr();
var c = jx2.redAdd(jx2).redIAdd(jx2).redIAdd(a.redMul(jz4));
var jxd4 = jx.redAdd(jx);
jxd4 = jxd4.redIAdd(jxd4);
var t1 = jxd4.redMul(jy2);
var nx = c.redSqr().redISub(t1.redAdd(t1));
var t2 = t1.redISub(nx);
var jyd8 = jy2.redSqr();
jyd8 = jyd8.redIAdd(jyd8);
jyd8 = jyd8.redIAdd(jyd8);
jyd8 = jyd8.redIAdd(jyd8);
var ny = c.redMul(t2).redISub(jyd8);
var nz = jy.redAdd(jy).redMul(jz);
return this.curve.jpoint(nx, ny, nz);
};
JPoint.prototype.trpl = function trpl() {
if (!this.curve.zeroA)
return this.dbl().add(this);
// hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#tripling-tpl-2007-bl
// 5M + 10S + ...
// XX = X1^2
var xx = this.x.redSqr();
// YY = Y1^2
var yy = this.y.redSqr();
// ZZ = Z1^2
var zz = this.z.redSqr();
// YYYY = YY^2
var yyyy = yy.redSqr();
// M = 3 * XX + a * ZZ2; a = 0
var m = xx.redAdd(xx).redIAdd(xx);
// MM = M^2
var mm = m.redSqr();
// E = 6 * ((X1 + YY)^2 - XX - YYYY) - MM
var e = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy);
e = e.redIAdd(e);
e = e.redAdd(e).redIAdd(e);
e = e.redISub(mm);
// EE = E^2
var ee = e.redSqr();
// T = 16*YYYY
var t = yyyy.redIAdd(yyyy);
t = t.redIAdd(t);
t = t.redIAdd(t);
t = t.redIAdd(t);
// U = (M + E)^2 - MM - EE - T
var u = m.redIAdd(e).redSqr().redISub(mm).redISub(ee).redISub(t);
// X3 = 4 * (X1 * EE - 4 * YY * U)
var yyu4 = yy.redMul(u);
yyu4 = yyu4.redIAdd(yyu4);
yyu4 = yyu4.redIAdd(yyu4);
var nx = this.x.redMul(ee).redISub(yyu4);
nx = nx.redIAdd(nx);
nx = nx.redIAdd(nx);
// Y3 = 8 * Y1 * (U * (T - U) - E * EE)
var ny = this.y.redMul(u.redMul(t.redISub(u)).redISub(e.redMul(ee)));
ny = ny.redIAdd(ny);
ny = ny.redIAdd(ny);
ny = ny.redIAdd(ny);
// Z3 = (Z1 + E)^2 - ZZ - EE
var nz = this.z.redAdd(e).redSqr().redISub(zz).redISub(ee);
return this.curve.jpoint(nx, ny, nz);
};
JPoint.prototype.mul = function mul(k, kbase) {
k = new bn(k, kbase);
return this.curve._wnafMul(this, k);
};
JPoint.prototype.eq = function eq(p) {
if (p.type === 'affine')
return this.eq(p.toJ());
if (this === p)
return true;
// x1 * z2^2 == x2 * z1^2
var z2 = this.z.redSqr();
var pz2 = p.z.redSqr();
if (this.x.redMul(pz2).redISub(p.x.redMul(z2)).cmpn(0) !== 0)
return false;
// y1 * z2^3 == y2 * z1^3
var z3 = z2.redMul(this.z);
var pz3 = pz2.redMul(p.z);
return this.y.redMul(pz3).redISub(p.y.redMul(z3)).cmpn(0) === 0;
};
JPoint.prototype.inspect = function inspect() {
if (this.isInfinity())
return '';
return '';
};
JPoint.prototype.isInfinity = function isInfinity() {
// XXX This code assumes that zero is always zero in red
return this.z.cmpn(0) === 0;
};
},{"../../elliptic":104,"../curve":107,"bn.js":102,"inherits":223}],110:[function(require,module,exports){
'use strict';
var curves = exports;
var hash = require('hash.js');
var elliptic = require('../elliptic');
var assert = elliptic.utils.assert;
function PresetCurve(options) {
if (options.type === 'short')
this.curve = new elliptic.curve.short(options);
else if (options.type === 'edwards')
this.curve = new elliptic.curve.edwards(options);
else
this.curve = new elliptic.curve.mont(options);
this.g = this.curve.g;
this.n = this.curve.n;
this.hash = options.hash;
assert(this.g.validate(), 'Invalid curve');
assert(this.g.mul(this.n).isInfinity(), 'Invalid curve, G*N != O');
}
curves.PresetCurve = PresetCurve;
function defineCurve(name, options) {
Object.defineProperty(curves, name, {
configurable: true,
enumerable: true,
get: function() {
var curve = new PresetCurve(options);
Object.defineProperty(curves, name, {
configurable: true,
enumerable: true,
value: curve
});
return curve;
}
});
}
defineCurve('p192', {
type: 'short',
prime: 'p192',
p: 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff',
a: 'ffffffff ffffffff ffffffff fffffffe ffffffff fffffffc',
b: '64210519 e59c80e7 0fa7e9ab 72243049 feb8deec c146b9b1',
n: 'ffffffff ffffffff ffffffff 99def836 146bc9b1 b4d22831',
hash: hash.sha256,
gRed: false,
g: [
'188da80e b03090f6 7cbf20eb 43a18800 f4ff0afd 82ff1012',
'07192b95 ffc8da78 631011ed 6b24cdd5 73f977a1 1e794811'
]
});
defineCurve('p224', {
type: 'short',
prime: 'p224',
p: 'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001',
a: 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff fffffffe',
b: 'b4050a85 0c04b3ab f5413256 5044b0b7 d7bfd8ba 270b3943 2355ffb4',
n: 'ffffffff ffffffff ffffffff ffff16a2 e0b8f03e 13dd2945 5c5c2a3d',
hash: hash.sha256,
gRed: false,
g: [
'b70e0cbd 6bb4bf7f 321390b9 4a03c1d3 56c21122 343280d6 115c1d21',
'bd376388 b5f723fb 4c22dfe6 cd4375a0 5a074764 44d58199 85007e34'
]
});
defineCurve('p256', {
type: 'short',
prime: null,
p: 'ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff ffffffff',
a: 'ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff fffffffc',
b: '5ac635d8 aa3a93e7 b3ebbd55 769886bc 651d06b0 cc53b0f6 3bce3c3e 27d2604b',
n: 'ffffffff 00000000 ffffffff ffffffff bce6faad a7179e84 f3b9cac2 fc632551',
hash: hash.sha256,
gRed: false,
g: [
'6b17d1f2 e12c4247 f8bce6e5 63a440f2 77037d81 2deb33a0 f4a13945 d898c296',
'4fe342e2 fe1a7f9b 8ee7eb4a 7c0f9e16 2bce3357 6b315ece cbb64068 37bf51f5'
]
});
defineCurve('curve25519', {
type: 'mont',
prime: 'p25519',
p: '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed',
a: '76d06',
b: '0',
n: '1000000000000000 0000000000000000 14def9dea2f79cd6 5812631a5cf5d3ed',
hash: hash.sha256,
gRed: false,
g: [
'9'
]
});
defineCurve('ed25519', {
type: 'edwards',
prime: 'p25519',
p: '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed',
a: '-1',
c: '1',
// -121665 * (121666^(-1)) (mod P)
d: '52036cee2b6ffe73 8cc740797779e898 00700a4d4141d8ab 75eb4dca135978a3',
n: '1000000000000000 0000000000000000 14def9dea2f79cd6 5812631a5cf5d3ed',
hash: hash.sha256,
gRed: false,
g: [
'216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51a',
// 4/5
'6666666666666666666666666666666666666666666666666666666666666658'
]
});
var pre;
try {
pre = require('./precomputed/secp256k1');
} catch (e) {
pre = undefined;
}
defineCurve('secp256k1', {
type: 'short',
prime: 'k256',
p: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f',
a: '0',
b: '7',
n: 'ffffffff ffffffff ffffffff fffffffe baaedce6 af48a03b bfd25e8c d0364141',
h: '1',
hash: hash.sha256,
// Precomputed endomorphism
beta: '7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee',
lambda: '5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72',
basis: [
{
a: '3086d221a7d46bcde86c90e49284eb15',
b: '-e4437ed6010e88286f547fa90abfe4c3'
},
{
a: '114ca50f7a8e2f3f657c1108d9d44cfd8',
b: '3086d221a7d46bcde86c90e49284eb15'
}
],
gRed: false,
g: [
'79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798',
'483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8',
pre
]
});
},{"../elliptic":104,"./precomputed/secp256k1":115,"hash.js":118}],111:[function(require,module,exports){
'use strict';
var bn = require('bn.js');
var elliptic = require('../../elliptic');
var utils = elliptic.utils;
var assert = utils.assert;
var KeyPair = require('./key');
var Signature = require('./signature');
function EC(options) {
if (!(this instanceof EC))
return new EC(options);
// Shortcut `elliptic.ec(curve-name)`
if (typeof options === 'string') {
assert(elliptic.curves.hasOwnProperty(options), 'Unknown curve ' + options);
options = elliptic.curves[options];
}
// Shortcut for `elliptic.ec(elliptic.curves.curveName)`
if (options instanceof elliptic.curves.PresetCurve)
options = { curve: options };
this.curve = options.curve.curve;
this.n = this.curve.n;
this.nh = this.n.shrn(1);
this.g = this.curve.g;
// Point on curve
this.g = options.curve.g;
this.g.precompute(options.curve.n.bitLength() + 1);
// Hash for function for DRBG
this.hash = options.hash || options.curve.hash;
}
module.exports = EC;
EC.prototype.keyPair = function keyPair(options) {
return new KeyPair(this, options);
};
EC.prototype.keyFromPrivate = function keyFromPrivate(priv, enc) {
return KeyPair.fromPrivate(this, priv, enc);
};
EC.prototype.keyFromPublic = function keyFromPublic(pub, enc) {
return KeyPair.fromPublic(this, pub, enc);
};
EC.prototype.genKeyPair = function genKeyPair(options) {
if (!options)
options = {};
// Instantiate Hmac_DRBG
var drbg = new elliptic.hmacDRBG({
hash: this.hash,
pers: options.pers,
entropy: options.entropy || elliptic.rand(this.hash.hmacStrength),
nonce: this.n.toArray()
});
var bytes = this.n.byteLength();
var ns2 = this.n.sub(new bn(2));
do {
var priv = new bn(drbg.generate(bytes));
if (priv.cmp(ns2) > 0)
continue;
priv.iaddn(1);
return this.keyFromPrivate(priv);
} while (true);
};
EC.prototype._truncateToN = function truncateToN(msg, truncOnly) {
var delta = msg.byteLength() * 8 - this.n.bitLength();
if (delta > 0)
msg = msg.shrn(delta);
if (!truncOnly && msg.cmp(this.n) >= 0)
return msg.sub(this.n);
else
return msg;
};
EC.prototype.sign = function sign(msg, key, enc, options) {
if (typeof enc === 'object') {
options = enc;
enc = null;
}
if (!options)
options = {};
key = this.keyFromPrivate(key, enc);
msg = this._truncateToN(new bn(msg, 16));
// Zero-extend key to provide enough entropy
var bytes = this.n.byteLength();
var bkey = key.getPrivate().toArray();
for (var i = bkey.length; i < 21; i++)
bkey.unshift(0);
// Zero-extend nonce to have the same byte size as N
var nonce = msg.toArray();
for (var i = nonce.length; i < bytes; i++)
nonce.unshift(0);
// Instantiate Hmac_DRBG
var drbg = new elliptic.hmacDRBG({
hash: this.hash,
entropy: bkey,
nonce: nonce
});
// Number of bytes to generate
var ns1 = this.n.sub(new bn(1));
do {
var k = new bn(drbg.generate(this.n.byteLength()));
k = this._truncateToN(k, true);
if (k.cmpn(1) <= 0 || k.cmp(ns1) >= 0)
continue;
var kp = this.g.mul(k);
if (kp.isInfinity())
continue;
var kpX = kp.getX();
var r = kpX.mod(this.n);
if (r.cmpn(0) === 0)
continue;
var s = k.invm(this.n).mul(r.mul(key.getPrivate()).iadd(msg)).mod(this.n);
if (s.cmpn(0) === 0)
continue;
// Use complement of `s`, if it is > `n / 2`
if (options.canonical && s.cmp(this.nh) > 0)
s = this.n.sub(s);
var recoveryParam = (kp.getY().isOdd() ? 1 : 0) |
(kpX.cmp(r) !== 0 ? 2 : 0);
return new Signature({ r: r, s: s, recoveryParam: recoveryParam });
} while (true);
};
EC.prototype.verify = function verify(msg, signature, key, enc) {
msg = this._truncateToN(new bn(msg, 16));
key = this.keyFromPublic(key, enc);
signature = new Signature(signature, 'hex');
// Perform primitive values validation
var r = signature.r;
var s = signature.s;
if (r.cmpn(1) < 0 || r.cmp(this.n) >= 0)
return false;
if (s.cmpn(1) < 0 || s.cmp(this.n) >= 0)
return false;
// Validate signature
var sinv = s.invm(this.n);
var u1 = sinv.mul(msg).mod(this.n);
var u2 = sinv.mul(r).mod(this.n);
var p = this.g.mulAdd(u1, key.getPublic(), u2);
if (p.isInfinity())
return false;
return p.getX().mod(this.n).cmp(r) === 0;
};
EC.prototype.recoverPubKey = function(msg, signature, j, enc) {
assert((3 & j) === j, 'The recovery param is more than two bits');
signature = new Signature(signature, enc);
var n = this.n;
var e = new bn(msg);
var r = signature.r;
var s = signature.s;
// A set LSB signifies that the y-coordinate is odd
var isYOdd = j & 1;
var isSecondKey = j >> 1;
if (r.cmp(this.curve.p.mod(this.curve.n)) >= 0 && isSecondKey)
throw new Error('Unable to find sencond key candinate');
// 1.1. Let x = r + jn.
r = this.curve.pointFromX(isYOdd, r);
var eNeg = e.neg().mod(n);
// 1.6.1 Compute Q = r^-1 (sR - eG)
// Q = r^-1 (sR + -eG)
var rInv = signature.r.invm(n);
return r.mul(s).add(this.g.mul(eNeg)).mul(rInv);
};
EC.prototype.getKeyRecoveryParam = function(e, signature, Q, enc) {
signature = new Signature(signature, enc);
if (signature.recoveryParam !== null)
return signature.recoveryParam;
for (var i = 0; i < 4; i++) {
var Qprime = this.recoverPubKey(e, signature, i);
if (Qprime.eq(Q))
return i;
}
throw new Error('Unable to find valid recovery factor');
};
},{"../../elliptic":104,"./key":112,"./signature":113,"bn.js":102}],112:[function(require,module,exports){
'use strict';
var bn = require('bn.js');
var elliptic = require('../../elliptic');
var utils = elliptic.utils;
function KeyPair(ec, options) {
this.ec = ec;
this.priv = null;
this.pub = null;
// KeyPair(ec, { priv: ..., pub: ... })
if (options.priv)
this._importPrivate(options.priv, options.privEnc);
if (options.pub)
this._importPublic(options.pub, options.pubEnc);
}
module.exports = KeyPair;
KeyPair.fromPublic = function fromPublic(ec, pub, enc) {
if (pub instanceof KeyPair)
return pub;
return new KeyPair(ec, {
pub: pub,
pubEnc: enc
});
};
KeyPair.fromPrivate = function fromPrivate(ec, priv, enc) {
if (priv instanceof KeyPair)
return priv;
return new KeyPair(ec, {
priv: priv,
privEnc: enc
});
};
KeyPair.prototype.validate = function validate() {
var pub = this.getPublic();
if (pub.isInfinity())
return { result: false, reason: 'Invalid public key' };
if (!pub.validate())
return { result: false, reason: 'Public key is not a point' };
if (!pub.mul(this.ec.curve.n).isInfinity())
return { result: false, reason: 'Public key * N != O' };
return { result: true, reason: null };
};
KeyPair.prototype.getPublic = function getPublic(compact, enc) {
if (!this.pub)
this.pub = this.ec.g.mul(this.priv);
// compact is optional argument
if (typeof compact === 'string') {
enc = compact;
compact = null;
}
if (!enc)
return this.pub;
var len = this.ec.curve.p.byteLength();
var x = this.pub.getX().toArray();
for (var i = x.length; i < len; i++)
x.unshift(0);
var res;
if (this.ec.curve.type !== 'mont') {
if (compact) {
res = [ this.pub.getY().isEven() ? 0x02 : 0x03 ].concat(x);
} else {
var y = this.pub.getY().toArray();
for (var i = y.length; i < len; i++)
y.unshift(0);
var res = [ 0x04 ].concat(x, y);
}
} else {
res = x;
}
return utils.encode(res, enc);
};
KeyPair.prototype.getPrivate = function getPrivate(enc) {
if (enc === 'hex')
return this.priv.toString(16, 2);
else
return this.priv;
};
KeyPair.prototype._importPrivate = function _importPrivate(key, enc) {
this.priv = new bn(key, enc || 16);
// Ensure that the priv won't be bigger than n, otherwise we may fail
// in fixed multiplication method
this.priv = this.priv.mod(this.ec.curve.n);
};
KeyPair.prototype._importPublic = function _importPublic(key, enc) {
if (key.x || key.y) {
this.pub = this.ec.curve.point(key.x, key.y);
return;
}
key = utils.toArray(key, enc);
if (this.ec.curve.type !== 'mont')
return this._importPublicShort(key);
else
return this._importPublicMont(key);
};
KeyPair.prototype._importPublicShort = function _importPublicShort(key) {
var len = this.ec.curve.p.byteLength();
if (key[0] === 0x04 && key.length - 1 === 2 * len) {
this.pub = this.ec.curve.point(
key.slice(1, 1 + len),
key.slice(1 + len, 1 + 2 * len));
} else if ((key[0] === 0x02 || key[0] === 0x03) && key.length - 1 === len) {
this.pub = this.ec.curve.pointFromX(key[0] === 0x03, key.slice(1, 1 + len));
}
};
KeyPair.prototype._importPublicMont = function _importPublicMont(key) {
this.pub = this.ec.curve.point(key, 1);
};
// ECDH
KeyPair.prototype.derive = function derive(pub) {
return pub.mul(this.priv).getX();
};
// ECDSA
KeyPair.prototype.sign = function sign(msg) {
return this.ec.sign(msg, this);
};
KeyPair.prototype.verify = function verify(msg, signature) {
return this.ec.verify(msg, signature, this);
};
KeyPair.prototype.inspect = function inspect() {
return '';
};
},{"../../elliptic":104,"bn.js":102}],113:[function(require,module,exports){
'use strict';
var bn = require('bn.js');
var elliptic = require('../../elliptic');
var utils = elliptic.utils;
var assert = utils.assert;
function Signature(options, enc) {
if (options instanceof Signature)
return options;
if (this._importDER(options, enc))
return;
assert(options.r && options.s, 'Signature without r or s');
this.r = new bn(options.r, 16);
this.s = new bn(options.s, 16);
if (options.recoveryParam !== null)
this.recoveryParam = options.recoveryParam;
else
this.recoveryParam = null;
}
module.exports = Signature;
Signature.prototype._importDER = function _importDER(data, enc) {
data = utils.toArray(data, enc);
if (data.length < 6 || data[0] !== 0x30 || data[2] !== 0x02)
return false;
var total = data[1];
if (1 + total > data.length)
return false;
var rlen = data[3];
// Short length notation
if (rlen >= 0x80)
return false;
if (4 + rlen + 2 >= data.length)
return false;
if (data[4 + rlen] !== 0x02)
return false;
var slen = data[5 + rlen];
// Short length notation
if (slen >= 0x80)
return false;
if (4 + rlen + 2 + slen > data.length)
return false;
this.r = new bn(data.slice(4, 4 + rlen));
this.s = new bn(data.slice(4 + rlen + 2, 4 + rlen + 2 + slen));
this.recoveryParam = null;
return true;
};
Signature.prototype.toDER = function toDER(enc) {
var r = this.r.toArray();
var s = this.s.toArray();
// Pad values
if (r[0] & 0x80)
r = [ 0 ].concat(r);
// Pad values
if (s[0] & 0x80)
s = [ 0 ].concat(s);
var total = r.length + s.length + 4;
var res = [ 0x30, total, 0x02, r.length ];
res = res.concat(r, [ 0x02, s.length ], s);
return utils.encode(res, enc);
};
},{"../../elliptic":104,"bn.js":102}],114:[function(require,module,exports){
'use strict';
var hash = require('hash.js');
var elliptic = require('../elliptic');
var utils = elliptic.utils;
var assert = utils.assert;
function HmacDRBG(options) {
if (!(this instanceof HmacDRBG))
return new HmacDRBG(options);
this.hash = options.hash;
this.predResist = !!options.predResist;
this.outLen = this.hash.outSize;
this.minEntropy = options.minEntropy || this.hash.hmacStrength;
this.reseed = null;
this.reseedInterval = null;
this.K = null;
this.V = null;
var entropy = utils.toArray(options.entropy, options.entropyEnc);
var nonce = utils.toArray(options.nonce, options.nonceEnc);
var pers = utils.toArray(options.pers, options.persEnc);
assert(entropy.length >= (this.minEntropy / 8),
'Not enough entropy. Minimum is: ' + this.minEntropy + ' bits');
this._init(entropy, nonce, pers);
}
module.exports = HmacDRBG;
HmacDRBG.prototype._init = function init(entropy, nonce, pers) {
var seed = entropy.concat(nonce).concat(pers);
this.K = new Array(this.outLen / 8);
this.V = new Array(this.outLen / 8);
for (var i = 0; i < this.V.length; i++) {
this.K[i] = 0x00;
this.V[i] = 0x01;
}
this._update(seed);
this.reseed = 1;
this.reseedInterval = 0x1000000000000; // 2^48
};
HmacDRBG.prototype._hmac = function hmac() {
return new hash.hmac(this.hash, this.K);
};
HmacDRBG.prototype._update = function update(seed) {
var kmac = this._hmac()
.update(this.V)
.update([ 0x00 ]);
if (seed)
kmac = kmac.update(seed);
this.K = kmac.digest();
this.V = this._hmac().update(this.V).digest();
if (!seed)
return;
this.K = this._hmac()
.update(this.V)
.update([ 0x01 ])
.update(seed)
.digest();
this.V = this._hmac().update(this.V).digest();
};
HmacDRBG.prototype.reseed = function reseed(entropy, entropyEnc, add, addEnc) {
// Optional entropy enc
if (typeof entropyEnc !== 'string') {
addEnc = add;
add = entropyEnc;
entropyEnc = null;
}
entropy = utils.toBuffer(entropy, entropyEnc);
add = utils.toBuffer(add, addEnc);
assert(entropy.length >= (this.minEntropy / 8),
'Not enough entropy. Minimum is: ' + this.minEntropy + ' bits');
this._update(entropy.concat(add || []));
this.reseed = 1;
};
HmacDRBG.prototype.generate = function generate(len, enc, add, addEnc) {
if (this.reseed > this.reseedInterval)
throw new Error('Reseed is required');
// Optional encoding
if (typeof enc !== 'string') {
addEnc = add;
add = enc;
enc = null;
}
// Optional additional data
if (add) {
add = utils.toArray(add, addEnc);
this._update(add);
}
var temp = [];
while (temp.length < len) {
this.V = this._hmac().update(this.V).digest();
temp = temp.concat(this.V);
}
var res = temp.slice(0, len);
this._update(add);
this.reseed++;
return utils.encode(res, enc);
};
},{"../elliptic":104,"hash.js":118}],115:[function(require,module,exports){
module.exports = {
doubles: {
step: 4,
points: [
[
'e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a',
'f7e3507399e595929db99f34f57937101296891e44d23f0be1f32cce69616821'
],
[
'8282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508',
'11f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf'
],
[
'175e159f728b865a72f99cc6c6fc846de0b93833fd2222ed73fce5b551e5b739',
'd3506e0d9e3c79eba4ef97a51ff71f5eacb5955add24345c6efa6ffee9fed695'
],
[
'363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640',
'4e273adfc732221953b445397f3363145b9a89008199ecb62003c7f3bee9de9'
],
[
'8b4b5f165df3c2be8c6244b5b745638843e4a781a15bcd1b69f79a55dffdf80c',
'4aad0a6f68d308b4b3fbd7813ab0da04f9e336546162ee56b3eff0c65fd4fd36'
],
[
'723cbaa6e5db996d6bf771c00bd548c7b700dbffa6c0e77bcb6115925232fcda',
'96e867b5595cc498a921137488824d6e2660a0653779494801dc069d9eb39f5f'
],
[
'eebfa4d493bebf98ba5feec812c2d3b50947961237a919839a533eca0e7dd7fa',
'5d9a8ca3970ef0f269ee7edaf178089d9ae4cdc3a711f712ddfd4fdae1de8999'
],
[
'100f44da696e71672791d0a09b7bde459f1215a29b3c03bfefd7835b39a48db0',
'cdd9e13192a00b772ec8f3300c090666b7ff4a18ff5195ac0fbd5cd62bc65a09'
],
[
'e1031be262c7ed1b1dc9227a4a04c017a77f8d4464f3b3852c8acde6e534fd2d',
'9d7061928940405e6bb6a4176597535af292dd419e1ced79a44f18f29456a00d'
],
[
'feea6cae46d55b530ac2839f143bd7ec5cf8b266a41d6af52d5e688d9094696d',
'e57c6b6c97dce1bab06e4e12bf3ecd5c981c8957cc41442d3155debf18090088'
],
[
'da67a91d91049cdcb367be4be6ffca3cfeed657d808583de33fa978bc1ec6cb1',
'9bacaa35481642bc41f463f7ec9780e5dec7adc508f740a17e9ea8e27a68be1d'
],
[
'53904faa0b334cdda6e000935ef22151ec08d0f7bb11069f57545ccc1a37b7c0',
'5bc087d0bc80106d88c9eccac20d3c1c13999981e14434699dcb096b022771c8'
],
[
'8e7bcd0bd35983a7719cca7764ca906779b53a043a9b8bcaeff959f43ad86047',
'10b7770b2a3da4b3940310420ca9514579e88e2e47fd68b3ea10047e8460372a'
],
[
'385eed34c1cdff21e6d0818689b81bde71a7f4f18397e6690a841e1599c43862',
'283bebc3e8ea23f56701de19e9ebf4576b304eec2086dc8cc0458fe5542e5453'
],
[
'6f9d9b803ecf191637c73a4413dfa180fddf84a5947fbc9c606ed86c3fac3a7',
'7c80c68e603059ba69b8e2a30e45c4d47ea4dd2f5c281002d86890603a842160'
],
[
'3322d401243c4e2582a2147c104d6ecbf774d163db0f5e5313b7e0e742d0e6bd',
'56e70797e9664ef5bfb019bc4ddaf9b72805f63ea2873af624f3a2e96c28b2a0'
],
[
'85672c7d2de0b7da2bd1770d89665868741b3f9af7643397721d74d28134ab83',
'7c481b9b5b43b2eb6374049bfa62c2e5e77f17fcc5298f44c8e3094f790313a6'
],
[
'948bf809b1988a46b06c9f1919413b10f9226c60f668832ffd959af60c82a0a',
'53a562856dcb6646dc6b74c5d1c3418c6d4dff08c97cd2bed4cb7f88d8c8e589'
],
[
'6260ce7f461801c34f067ce0f02873a8f1b0e44dfc69752accecd819f38fd8e8',
'bc2da82b6fa5b571a7f09049776a1ef7ecd292238051c198c1a84e95b2b4ae17'
],
[
'e5037de0afc1d8d43d8348414bbf4103043ec8f575bfdc432953cc8d2037fa2d',
'4571534baa94d3b5f9f98d09fb990bddbd5f5b03ec481f10e0e5dc841d755bda'
],
[
'e06372b0f4a207adf5ea905e8f1771b4e7e8dbd1c6a6c5b725866a0ae4fce725',
'7a908974bce18cfe12a27bb2ad5a488cd7484a7787104870b27034f94eee31dd'
],
[
'213c7a715cd5d45358d0bbf9dc0ce02204b10bdde2a3f58540ad6908d0559754',
'4b6dad0b5ae462507013ad06245ba190bb4850f5f36a7eeddff2c27534b458f2'
],
[
'4e7c272a7af4b34e8dbb9352a5419a87e2838c70adc62cddf0cc3a3b08fbd53c',
'17749c766c9d0b18e16fd09f6def681b530b9614bff7dd33e0b3941817dcaae6'
],
[
'fea74e3dbe778b1b10f238ad61686aa5c76e3db2be43057632427e2840fb27b6',
'6e0568db9b0b13297cf674deccb6af93126b596b973f7b77701d3db7f23cb96f'
],
[
'76e64113f677cf0e10a2570d599968d31544e179b760432952c02a4417bdde39',
'c90ddf8dee4e95cf577066d70681f0d35e2a33d2b56d2032b4b1752d1901ac01'
],
[
'c738c56b03b2abe1e8281baa743f8f9a8f7cc643df26cbee3ab150242bcbb891',
'893fb578951ad2537f718f2eacbfbbbb82314eef7880cfe917e735d9699a84c3'
],
[
'd895626548b65b81e264c7637c972877d1d72e5f3a925014372e9f6588f6c14b',
'febfaa38f2bc7eae728ec60818c340eb03428d632bb067e179363ed75d7d991f'
],
[
'b8da94032a957518eb0f6433571e8761ceffc73693e84edd49150a564f676e03',
'2804dfa44805a1e4d7c99cc9762808b092cc584d95ff3b511488e4e74efdf6e7'
],
[
'e80fea14441fb33a7d8adab9475d7fab2019effb5156a792f1a11778e3c0df5d',
'eed1de7f638e00771e89768ca3ca94472d155e80af322ea9fcb4291b6ac9ec78'
],
[
'a301697bdfcd704313ba48e51d567543f2a182031efd6915ddc07bbcc4e16070',
'7370f91cfb67e4f5081809fa25d40f9b1735dbf7c0a11a130c0d1a041e177ea1'
],
[
'90ad85b389d6b936463f9d0512678de208cc330b11307fffab7ac63e3fb04ed4',
'e507a3620a38261affdcbd9427222b839aefabe1582894d991d4d48cb6ef150'
],
[
'8f68b9d2f63b5f339239c1ad981f162ee88c5678723ea3351b7b444c9ec4c0da',
'662a9f2dba063986de1d90c2b6be215dbbea2cfe95510bfdf23cbf79501fff82'
],
[
'e4f3fb0176af85d65ff99ff9198c36091f48e86503681e3e6686fd5053231e11',
'1e63633ad0ef4f1c1661a6d0ea02b7286cc7e74ec951d1c9822c38576feb73bc'
],
[
'8c00fa9b18ebf331eb961537a45a4266c7034f2f0d4e1d0716fb6eae20eae29e',
'efa47267fea521a1a9dc343a3736c974c2fadafa81e36c54e7d2a4c66702414b'
],
[
'e7a26ce69dd4829f3e10cec0a9e98ed3143d084f308b92c0997fddfc60cb3e41',
'2a758e300fa7984b471b006a1aafbb18d0a6b2c0420e83e20e8a9421cf2cfd51'
],
[
'b6459e0ee3662ec8d23540c223bcbdc571cbcb967d79424f3cf29eb3de6b80ef',
'67c876d06f3e06de1dadf16e5661db3c4b3ae6d48e35b2ff30bf0b61a71ba45'
],
[
'd68a80c8280bb840793234aa118f06231d6f1fc67e73c5a5deda0f5b496943e8',
'db8ba9fff4b586d00c4b1f9177b0e28b5b0e7b8f7845295a294c84266b133120'
],
[
'324aed7df65c804252dc0270907a30b09612aeb973449cea4095980fc28d3d5d',
'648a365774b61f2ff130c0c35aec1f4f19213b0c7e332843967224af96ab7c84'
],
[
'4df9c14919cde61f6d51dfdbe5fee5dceec4143ba8d1ca888e8bd373fd054c96',
'35ec51092d8728050974c23a1d85d4b5d506cdc288490192ebac06cad10d5d'
],
[
'9c3919a84a474870faed8a9c1cc66021523489054d7f0308cbfc99c8ac1f98cd',
'ddb84f0f4a4ddd57584f044bf260e641905326f76c64c8e6be7e5e03d4fc599d'
],
[
'6057170b1dd12fdf8de05f281d8e06bb91e1493a8b91d4cc5a21382120a959e5',
'9a1af0b26a6a4807add9a2daf71df262465152bc3ee24c65e899be932385a2a8'
],
[
'a576df8e23a08411421439a4518da31880cef0fba7d4df12b1a6973eecb94266',
'40a6bf20e76640b2c92b97afe58cd82c432e10a7f514d9f3ee8be11ae1b28ec8'
],
[
'7778a78c28dec3e30a05fe9629de8c38bb30d1f5cf9a3a208f763889be58ad71',
'34626d9ab5a5b22ff7098e12f2ff580087b38411ff24ac563b513fc1fd9f43ac'
],
[
'928955ee637a84463729fd30e7afd2ed5f96274e5ad7e5cb09eda9c06d903ac',
'c25621003d3f42a827b78a13093a95eeac3d26efa8a8d83fc5180e935bcd091f'
],
[
'85d0fef3ec6db109399064f3a0e3b2855645b4a907ad354527aae75163d82751',
'1f03648413a38c0be29d496e582cf5663e8751e96877331582c237a24eb1f962'
],
[
'ff2b0dce97eece97c1c9b6041798b85dfdfb6d8882da20308f5404824526087e',
'493d13fef524ba188af4c4dc54d07936c7b7ed6fb90e2ceb2c951e01f0c29907'
],
[
'827fbbe4b1e880ea9ed2b2e6301b212b57f1ee148cd6dd28780e5e2cf856e241',
'c60f9c923c727b0b71bef2c67d1d12687ff7a63186903166d605b68baec293ec'
],
[
'eaa649f21f51bdbae7be4ae34ce6e5217a58fdce7f47f9aa7f3b58fa2120e2b3',
'be3279ed5bbbb03ac69a80f89879aa5a01a6b965f13f7e59d47a5305ba5ad93d'
],
[
'e4a42d43c5cf169d9391df6decf42ee541b6d8f0c9a137401e23632dda34d24f',
'4d9f92e716d1c73526fc99ccfb8ad34ce886eedfa8d8e4f13a7f7131deba9414'
],
[
'1ec80fef360cbdd954160fadab352b6b92b53576a88fea4947173b9d4300bf19',
'aeefe93756b5340d2f3a4958a7abbf5e0146e77f6295a07b671cdc1cc107cefd'
],
[
'146a778c04670c2f91b00af4680dfa8bce3490717d58ba889ddb5928366642be',
'b318e0ec3354028add669827f9d4b2870aaa971d2f7e5ed1d0b297483d83efd0'
],
[
'fa50c0f61d22e5f07e3acebb1aa07b128d0012209a28b9776d76a8793180eef9',
'6b84c6922397eba9b72cd2872281a68a5e683293a57a213b38cd8d7d3f4f2811'
],
[
'da1d61d0ca721a11b1a5bf6b7d88e8421a288ab5d5bba5220e53d32b5f067ec2',
'8157f55a7c99306c79c0766161c91e2966a73899d279b48a655fba0f1ad836f1'
],
[
'a8e282ff0c9706907215ff98e8fd416615311de0446f1e062a73b0610d064e13',
'7f97355b8db81c09abfb7f3c5b2515888b679a3e50dd6bd6cef7c73111f4cc0c'
],
[
'174a53b9c9a285872d39e56e6913cab15d59b1fa512508c022f382de8319497c',
'ccc9dc37abfc9c1657b4155f2c47f9e6646b3a1d8cb9854383da13ac079afa73'
],
[
'959396981943785c3d3e57edf5018cdbe039e730e4918b3d884fdff09475b7ba',
'2e7e552888c331dd8ba0386a4b9cd6849c653f64c8709385e9b8abf87524f2fd'
],
[
'd2a63a50ae401e56d645a1153b109a8fcca0a43d561fba2dbb51340c9d82b151',
'e82d86fb6443fcb7565aee58b2948220a70f750af484ca52d4142174dcf89405'
],
[
'64587e2335471eb890ee7896d7cfdc866bacbdbd3839317b3436f9b45617e073',
'd99fcdd5bf6902e2ae96dd6447c299a185b90a39133aeab358299e5e9faf6589'
],
[
'8481bde0e4e4d885b3a546d3e549de042f0aa6cea250e7fd358d6c86dd45e458',
'38ee7b8cba5404dd84a25bf39cecb2ca900a79c42b262e556d64b1b59779057e'
],
[
'13464a57a78102aa62b6979ae817f4637ffcfed3c4b1ce30bcd6303f6caf666b',
'69be159004614580ef7e433453ccb0ca48f300a81d0942e13f495a907f6ecc27'
],
[
'bc4a9df5b713fe2e9aef430bcc1dc97a0cd9ccede2f28588cada3a0d2d83f366',
'd3a81ca6e785c06383937adf4b798caa6e8a9fbfa547b16d758d666581f33c1'
],
[
'8c28a97bf8298bc0d23d8c749452a32e694b65e30a9472a3954ab30fe5324caa',
'40a30463a3305193378fedf31f7cc0eb7ae784f0451cb9459e71dc73cbef9482'
],
[
'8ea9666139527a8c1dd94ce4f071fd23c8b350c5a4bb33748c4ba111faccae0',
'620efabbc8ee2782e24e7c0cfb95c5d735b783be9cf0f8e955af34a30e62b945'
],
[
'dd3625faef5ba06074669716bbd3788d89bdde815959968092f76cc4eb9a9787',
'7a188fa3520e30d461da2501045731ca941461982883395937f68d00c644a573'
],
[
'f710d79d9eb962297e4f6232b40e8f7feb2bc63814614d692c12de752408221e',
'ea98e67232d3b3295d3b535532115ccac8612c721851617526ae47a9c77bfc82'
]
]
},
naf: {
wnd: 7,
points: [
[
'f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9',
'388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672'
],
[
'2f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4',
'd8ac222636e5e3d6d4dba9dda6c9c426f788271bab0d6840dca87d3aa6ac62d6'
],
[
'5cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc',
'6aebca40ba255960a3178d6d861a54dba813d0b813fde7b5a5082628087264da'
],
[
'acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbe',
'cc338921b0a7d9fd64380971763b61e9add888a4375f8e0f05cc262ac64f9c37'
],
[
'774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb',
'd984a032eb6b5e190243dd56d7b7b365372db1e2dff9d6a8301d74c9c953c61b'
],
[
'f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8',
'ab0902e8d880a89758212eb65cdaf473a1a06da521fa91f29b5cb52db03ed81'
],
[
'd7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e',
'581e2872a86c72a683842ec228cc6defea40af2bd896d3a5c504dc9ff6a26b58'
],
[
'defdea4cdb677750a420fee807eacf21eb9898ae79b9768766e4faa04a2d4a34',
'4211ab0694635168e997b0ead2a93daeced1f4a04a95c0f6cfb199f69e56eb77'
],
[
'2b4ea0a797a443d293ef5cff444f4979f06acfebd7e86d277475656138385b6c',
'85e89bc037945d93b343083b5a1c86131a01f60c50269763b570c854e5c09b7a'
],
[
'352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d5',
'321eb4075348f534d59c18259dda3e1f4a1b3b2e71b1039c67bd3d8bcf81998c'
],
[
'2fa2104d6b38d11b0230010559879124e42ab8dfeff5ff29dc9cdadd4ecacc3f',
'2de1068295dd865b64569335bd5dd80181d70ecfc882648423ba76b532b7d67'
],
[
'9248279b09b4d68dab21a9b066edda83263c3d84e09572e269ca0cd7f5453714',
'73016f7bf234aade5d1aa71bdea2b1ff3fc0de2a887912ffe54a32ce97cb3402'
],
[
'daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729',
'a69dce4a7d6c98e8d4a1aca87ef8d7003f83c230f3afa726ab40e52290be1c55'
],
[
'c44d12c7065d812e8acf28d7cbb19f9011ecd9e9fdf281b0e6a3b5e87d22e7db',
'2119a460ce326cdc76c45926c982fdac0e106e861edf61c5a039063f0e0e6482'
],
[
'6a245bf6dc698504c89a20cfded60853152b695336c28063b61c65cbd269e6b4',
'e022cf42c2bd4a708b3f5126f16a24ad8b33ba48d0423b6efd5e6348100d8a82'
],
[
'1697ffa6fd9de627c077e3d2fe541084ce13300b0bec1146f95ae57f0d0bd6a5',
'b9c398f186806f5d27561506e4557433a2cf15009e498ae7adee9d63d01b2396'
],
[
'605bdb019981718b986d0f07e834cb0d9deb8360ffb7f61df982345ef27a7479',
'2972d2de4f8d20681a78d93ec96fe23c26bfae84fb14db43b01e1e9056b8c49'
],
[
'62d14dab4150bf497402fdc45a215e10dcb01c354959b10cfe31c7e9d87ff33d',
'80fc06bd8cc5b01098088a1950eed0db01aa132967ab472235f5642483b25eaf'
],
[
'80c60ad0040f27dade5b4b06c408e56b2c50e9f56b9b8b425e555c2f86308b6f',
'1c38303f1cc5c30f26e66bad7fe72f70a65eed4cbe7024eb1aa01f56430bd57a'
],
[
'7a9375ad6167ad54aa74c6348cc54d344cc5dc9487d847049d5eabb0fa03c8fb',
'd0e3fa9eca8726909559e0d79269046bdc59ea10c70ce2b02d499ec224dc7f7'
],
[
'd528ecd9b696b54c907a9ed045447a79bb408ec39b68df504bb51f459bc3ffc9',
'eecf41253136e5f99966f21881fd656ebc4345405c520dbc063465b521409933'
],
[
'49370a4b5f43412ea25f514e8ecdad05266115e4a7ecb1387231808f8b45963',
'758f3f41afd6ed428b3081b0512fd62a54c3f3afbb5b6764b653052a12949c9a'
],
[
'77f230936ee88cbbd73df930d64702ef881d811e0e1498e2f1c13eb1fc345d74',
'958ef42a7886b6400a08266e9ba1b37896c95330d97077cbbe8eb3c7671c60d6'
],
[
'f2dac991cc4ce4b9ea44887e5c7c0bce58c80074ab9d4dbaeb28531b7739f530',
'e0dedc9b3b2f8dad4da1f32dec2531df9eb5fbeb0598e4fd1a117dba703a3c37'
],
[
'463b3d9f662621fb1b4be8fbbe2520125a216cdfc9dae3debcba4850c690d45b',
'5ed430d78c296c3543114306dd8622d7c622e27c970a1de31cb377b01af7307e'
],
[
'f16f804244e46e2a09232d4aff3b59976b98fac14328a2d1a32496b49998f247',
'cedabd9b82203f7e13d206fcdf4e33d92a6c53c26e5cce26d6579962c4e31df6'
],
[
'caf754272dc84563b0352b7a14311af55d245315ace27c65369e15f7151d41d1',
'cb474660ef35f5f2a41b643fa5e460575f4fa9b7962232a5c32f908318a04476'
],
[
'2600ca4b282cb986f85d0f1709979d8b44a09c07cb86d7c124497bc86f082120',
'4119b88753c15bd6a693b03fcddbb45d5ac6be74ab5f0ef44b0be9475a7e4b40'
],
[
'7635ca72d7e8432c338ec53cd12220bc01c48685e24f7dc8c602a7746998e435',
'91b649609489d613d1d5e590f78e6d74ecfc061d57048bad9e76f302c5b9c61'
],
[
'754e3239f325570cdbbf4a87deee8a66b7f2b33479d468fbc1a50743bf56cc18',
'673fb86e5bda30fb3cd0ed304ea49a023ee33d0197a695d0c5d98093c536683'
],
[
'e3e6bd1071a1e96aff57859c82d570f0330800661d1c952f9fe2694691d9b9e8',
'59c9e0bba394e76f40c0aa58379a3cb6a5a2283993e90c4167002af4920e37f5'
],
[
'186b483d056a033826ae73d88f732985c4ccb1f32ba35f4b4cc47fdcf04aa6eb',
'3b952d32c67cf77e2e17446e204180ab21fb8090895138b4a4a797f86e80888b'
],
[
'df9d70a6b9876ce544c98561f4be4f725442e6d2b737d9c91a8321724ce0963f',
'55eb2dafd84d6ccd5f862b785dc39d4ab157222720ef9da217b8c45cf2ba2417'
],
[
'5edd5cc23c51e87a497ca815d5dce0f8ab52554f849ed8995de64c5f34ce7143',
'efae9c8dbc14130661e8cec030c89ad0c13c66c0d17a2905cdc706ab7399a868'
],
[
'290798c2b6476830da12fe02287e9e777aa3fba1c355b17a722d362f84614fba',
'e38da76dcd440621988d00bcf79af25d5b29c094db2a23146d003afd41943e7a'
],
[
'af3c423a95d9f5b3054754efa150ac39cd29552fe360257362dfdecef4053b45',
'f98a3fd831eb2b749a93b0e6f35cfb40c8cd5aa667a15581bc2feded498fd9c6'
],
[
'766dbb24d134e745cccaa28c99bf274906bb66b26dcf98df8d2fed50d884249a',
'744b1152eacbe5e38dcc887980da38b897584a65fa06cedd2c924f97cbac5996'
],
[
'59dbf46f8c94759ba21277c33784f41645f7b44f6c596a58ce92e666191abe3e',
'c534ad44175fbc300f4ea6ce648309a042ce739a7919798cd85e216c4a307f6e'
],
[
'f13ada95103c4537305e691e74e9a4a8dd647e711a95e73cb62dc6018cfd87b8',
'e13817b44ee14de663bf4bc808341f326949e21a6a75c2570778419bdaf5733d'
],
[
'7754b4fa0e8aced06d4167a2c59cca4cda1869c06ebadfb6488550015a88522c',
'30e93e864e669d82224b967c3020b8fa8d1e4e350b6cbcc537a48b57841163a2'
],
[
'948dcadf5990e048aa3874d46abef9d701858f95de8041d2a6828c99e2262519',
'e491a42537f6e597d5d28a3224b1bc25df9154efbd2ef1d2cbba2cae5347d57e'
],
[
'7962414450c76c1689c7b48f8202ec37fb224cf5ac0bfa1570328a8a3d7c77ab',
'100b610ec4ffb4760d5c1fc133ef6f6b12507a051f04ac5760afa5b29db83437'
],
[
'3514087834964b54b15b160644d915485a16977225b8847bb0dd085137ec47ca',
'ef0afbb2056205448e1652c48e8127fc6039e77c15c2378b7e7d15a0de293311'
],
[
'd3cc30ad6b483e4bc79ce2c9dd8bc54993e947eb8df787b442943d3f7b527eaf',
'8b378a22d827278d89c5e9be8f9508ae3c2ad46290358630afb34db04eede0a4'
],
[
'1624d84780732860ce1c78fcbfefe08b2b29823db913f6493975ba0ff4847610',
'68651cf9b6da903e0914448c6cd9d4ca896878f5282be4c8cc06e2a404078575'
],
[
'733ce80da955a8a26902c95633e62a985192474b5af207da6df7b4fd5fc61cd4',
'f5435a2bd2badf7d485a4d8b8db9fcce3e1ef8e0201e4578c54673bc1dc5ea1d'
],
[
'15d9441254945064cf1a1c33bbd3b49f8966c5092171e699ef258dfab81c045c',
'd56eb30b69463e7234f5137b73b84177434800bacebfc685fc37bbe9efe4070d'
],
[
'a1d0fcf2ec9de675b612136e5ce70d271c21417c9d2b8aaaac138599d0717940',
'edd77f50bcb5a3cab2e90737309667f2641462a54070f3d519212d39c197a629'
],
[
'e22fbe15c0af8ccc5780c0735f84dbe9a790badee8245c06c7ca37331cb36980',
'a855babad5cd60c88b430a69f53a1a7a38289154964799be43d06d77d31da06'
],
[
'311091dd9860e8e20ee13473c1155f5f69635e394704eaa74009452246cfa9b3',
'66db656f87d1f04fffd1f04788c06830871ec5a64feee685bd80f0b1286d8374'
],
[
'34c1fd04d301be89b31c0442d3e6ac24883928b45a9340781867d4232ec2dbdf',
'9414685e97b1b5954bd46f730174136d57f1ceeb487443dc5321857ba73abee'
],
[
'f219ea5d6b54701c1c14de5b557eb42a8d13f3abbcd08affcc2a5e6b049b8d63',
'4cb95957e83d40b0f73af4544cccf6b1f4b08d3c07b27fb8d8c2962a400766d1'
],
[
'd7b8740f74a8fbaab1f683db8f45de26543a5490bca627087236912469a0b448',
'fa77968128d9c92ee1010f337ad4717eff15db5ed3c049b3411e0315eaa4593b'
],
[
'32d31c222f8f6f0ef86f7c98d3a3335ead5bcd32abdd94289fe4d3091aa824bf',
'5f3032f5892156e39ccd3d7915b9e1da2e6dac9e6f26e961118d14b8462e1661'
],
[
'7461f371914ab32671045a155d9831ea8793d77cd59592c4340f86cbc18347b5',
'8ec0ba238b96bec0cbdddcae0aa442542eee1ff50c986ea6b39847b3cc092ff6'
],
[
'ee079adb1df1860074356a25aa38206a6d716b2c3e67453d287698bad7b2b2d6',
'8dc2412aafe3be5c4c5f37e0ecc5f9f6a446989af04c4e25ebaac479ec1c8c1e'
],
[
'16ec93e447ec83f0467b18302ee620f7e65de331874c9dc72bfd8616ba9da6b5',
'5e4631150e62fb40d0e8c2a7ca5804a39d58186a50e497139626778e25b0674d'
],
[
'eaa5f980c245f6f038978290afa70b6bd8855897f98b6aa485b96065d537bd99',
'f65f5d3e292c2e0819a528391c994624d784869d7e6ea67fb18041024edc07dc'
],
[
'78c9407544ac132692ee1910a02439958ae04877151342ea96c4b6b35a49f51',
'f3e0319169eb9b85d5404795539a5e68fa1fbd583c064d2462b675f194a3ddb4'
],
[
'494f4be219a1a77016dcd838431aea0001cdc8ae7a6fc688726578d9702857a5',
'42242a969283a5f339ba7f075e36ba2af925ce30d767ed6e55f4b031880d562c'
],
[
'a598a8030da6d86c6bc7f2f5144ea549d28211ea58faa70ebf4c1e665c1fe9b5',
'204b5d6f84822c307e4b4a7140737aec23fc63b65b35f86a10026dbd2d864e6b'
],
[
'c41916365abb2b5d09192f5f2dbeafec208f020f12570a184dbadc3e58595997',
'4f14351d0087efa49d245b328984989d5caf9450f34bfc0ed16e96b58fa9913'
],
[
'841d6063a586fa475a724604da03bc5b92a2e0d2e0a36acfe4c73a5514742881',
'73867f59c0659e81904f9a1c7543698e62562d6744c169ce7a36de01a8d6154'
],
[
'5e95bb399a6971d376026947f89bde2f282b33810928be4ded112ac4d70e20d5',
'39f23f366809085beebfc71181313775a99c9aed7d8ba38b161384c746012865'
],
[
'36e4641a53948fd476c39f8a99fd974e5ec07564b5315d8bf99471bca0ef2f66',
'd2424b1b1abe4eb8164227b085c9aa9456ea13493fd563e06fd51cf5694c78fc'
],
[
'336581ea7bfbbb290c191a2f507a41cf5643842170e914faeab27c2c579f726',
'ead12168595fe1be99252129b6e56b3391f7ab1410cd1e0ef3dcdcabd2fda224'
],
[
'8ab89816dadfd6b6a1f2634fcf00ec8403781025ed6890c4849742706bd43ede',
'6fdcef09f2f6d0a044e654aef624136f503d459c3e89845858a47a9129cdd24e'
],
[
'1e33f1a746c9c5778133344d9299fcaa20b0938e8acff2544bb40284b8c5fb94',
'60660257dd11b3aa9c8ed618d24edff2306d320f1d03010e33a7d2057f3b3b6'
],
[
'85b7c1dcb3cec1b7ee7f30ded79dd20a0ed1f4cc18cbcfcfa410361fd8f08f31',
'3d98a9cdd026dd43f39048f25a8847f4fcafad1895d7a633c6fed3c35e999511'
],
[
'29df9fbd8d9e46509275f4b125d6d45d7fbe9a3b878a7af872a2800661ac5f51',
'b4c4fe99c775a606e2d8862179139ffda61dc861c019e55cd2876eb2a27d84b'
],
[
'a0b1cae06b0a847a3fea6e671aaf8adfdfe58ca2f768105c8082b2e449fce252',
'ae434102edde0958ec4b19d917a6a28e6b72da1834aff0e650f049503a296cf2'
],
[
'4e8ceafb9b3e9a136dc7ff67e840295b499dfb3b2133e4ba113f2e4c0e121e5',
'cf2174118c8b6d7a4b48f6d534ce5c79422c086a63460502b827ce62a326683c'
],
[
'd24a44e047e19b6f5afb81c7ca2f69080a5076689a010919f42725c2b789a33b',
'6fb8d5591b466f8fc63db50f1c0f1c69013f996887b8244d2cdec417afea8fa3'
],
[
'ea01606a7a6c9cdd249fdfcfacb99584001edd28abbab77b5104e98e8e3b35d4',
'322af4908c7312b0cfbfe369f7a7b3cdb7d4494bc2823700cfd652188a3ea98d'
],
[
'af8addbf2b661c8a6c6328655eb96651252007d8c5ea31be4ad196de8ce2131f',
'6749e67c029b85f52a034eafd096836b2520818680e26ac8f3dfbcdb71749700'
],
[
'e3ae1974566ca06cc516d47e0fb165a674a3dabcfca15e722f0e3450f45889',
'2aeabe7e4531510116217f07bf4d07300de97e4874f81f533420a72eeb0bd6a4'
],
[
'591ee355313d99721cf6993ffed1e3e301993ff3ed258802075ea8ced397e246',
'b0ea558a113c30bea60fc4775460c7901ff0b053d25ca2bdeee98f1a4be5d196'
],
[
'11396d55fda54c49f19aa97318d8da61fa8584e47b084945077cf03255b52984',
'998c74a8cd45ac01289d5833a7beb4744ff536b01b257be4c5767bea93ea57a4'
],
[
'3c5d2a1ba39c5a1790000738c9e0c40b8dcdfd5468754b6405540157e017aa7a',
'b2284279995a34e2f9d4de7396fc18b80f9b8b9fdd270f6661f79ca4c81bd257'
],
[
'cc8704b8a60a0defa3a99a7299f2e9c3fbc395afb04ac078425ef8a1793cc030',
'bdd46039feed17881d1e0862db347f8cf395b74fc4bcdc4e940b74e3ac1f1b13'
],
[
'c533e4f7ea8555aacd9777ac5cad29b97dd4defccc53ee7ea204119b2889b197',
'6f0a256bc5efdf429a2fb6242f1a43a2d9b925bb4a4b3a26bb8e0f45eb596096'
],
[
'c14f8f2ccb27d6f109f6d08d03cc96a69ba8c34eec07bbcf566d48e33da6593',
'c359d6923bb398f7fd4473e16fe1c28475b740dd098075e6c0e8649113dc3a38'
],
[
'a6cbc3046bc6a450bac24789fa17115a4c9739ed75f8f21ce441f72e0b90e6ef',
'21ae7f4680e889bb130619e2c0f95a360ceb573c70603139862afd617fa9b9f'
],
[
'347d6d9a02c48927ebfb86c1359b1caf130a3c0267d11ce6344b39f99d43cc38',
'60ea7f61a353524d1c987f6ecec92f086d565ab687870cb12689ff1e31c74448'
],
[
'da6545d2181db8d983f7dcb375ef5866d47c67b1bf31c8cf855ef7437b72656a',
'49b96715ab6878a79e78f07ce5680c5d6673051b4935bd897fea824b77dc208a'
],
[
'c40747cc9d012cb1a13b8148309c6de7ec25d6945d657146b9d5994b8feb1111',
'5ca560753be2a12fc6de6caf2cb489565db936156b9514e1bb5e83037e0fa2d4'
],
[
'4e42c8ec82c99798ccf3a610be870e78338c7f713348bd34c8203ef4037f3502',
'7571d74ee5e0fb92a7a8b33a07783341a5492144cc54bcc40a94473693606437'
],
[
'3775ab7089bc6af823aba2e1af70b236d251cadb0c86743287522a1b3b0dedea',
'be52d107bcfa09d8bcb9736a828cfa7fac8db17bf7a76a2c42ad961409018cf7'
],
[
'cee31cbf7e34ec379d94fb814d3d775ad954595d1314ba8846959e3e82f74e26',
'8fd64a14c06b589c26b947ae2bcf6bfa0149ef0be14ed4d80f448a01c43b1c6d'
],
[
'b4f9eaea09b6917619f6ea6a4eb5464efddb58fd45b1ebefcdc1a01d08b47986',
'39e5c9925b5a54b07433a4f18c61726f8bb131c012ca542eb24a8ac07200682a'
],
[
'd4263dfc3d2df923a0179a48966d30ce84e2515afc3dccc1b77907792ebcc60e',
'62dfaf07a0f78feb30e30d6295853ce189e127760ad6cf7fae164e122a208d54'
],
[
'48457524820fa65a4f8d35eb6930857c0032acc0a4a2de422233eeda897612c4',
'25a748ab367979d98733c38a1fa1c2e7dc6cc07db2d60a9ae7a76aaa49bd0f77'
],
[
'dfeeef1881101f2cb11644f3a2afdfc2045e19919152923f367a1767c11cceda',
'ecfb7056cf1de042f9420bab396793c0c390bde74b4bbdff16a83ae09a9a7517'
],
[
'6d7ef6b17543f8373c573f44e1f389835d89bcbc6062ced36c82df83b8fae859',
'cd450ec335438986dfefa10c57fea9bcc521a0959b2d80bbf74b190dca712d10'
],
[
'e75605d59102a5a2684500d3b991f2e3f3c88b93225547035af25af66e04541f',
'f5c54754a8f71ee540b9b48728473e314f729ac5308b06938360990e2bfad125'
],
[
'eb98660f4c4dfaa06a2be453d5020bc99a0c2e60abe388457dd43fefb1ed620c',
'6cb9a8876d9cb8520609af3add26cd20a0a7cd8a9411131ce85f44100099223e'
],
[
'13e87b027d8514d35939f2e6892b19922154596941888336dc3563e3b8dba942',
'fef5a3c68059a6dec5d624114bf1e91aac2b9da568d6abeb2570d55646b8adf1'
],
[
'ee163026e9fd6fe017c38f06a5be6fc125424b371ce2708e7bf4491691e5764a',
'1acb250f255dd61c43d94ccc670d0f58f49ae3fa15b96623e5430da0ad6c62b2'
],
[
'b268f5ef9ad51e4d78de3a750c2dc89b1e626d43505867999932e5db33af3d80',
'5f310d4b3c99b9ebb19f77d41c1dee018cf0d34fd4191614003e945a1216e423'
],
[
'ff07f3118a9df035e9fad85eb6c7bfe42b02f01ca99ceea3bf7ffdba93c4750d',
'438136d603e858a3a5c440c38eccbaddc1d2942114e2eddd4740d098ced1f0d8'
],
[
'8d8b9855c7c052a34146fd20ffb658bea4b9f69e0d825ebec16e8c3ce2b526a1',
'cdb559eedc2d79f926baf44fb84ea4d44bcf50fee51d7ceb30e2e7f463036758'
],
[
'52db0b5384dfbf05bfa9d472d7ae26dfe4b851ceca91b1eba54263180da32b63',
'c3b997d050ee5d423ebaf66a6db9f57b3180c902875679de924b69d84a7b375'
],
[
'e62f9490d3d51da6395efd24e80919cc7d0f29c3f3fa48c6fff543becbd43352',
'6d89ad7ba4876b0b22c2ca280c682862f342c8591f1daf5170e07bfd9ccafa7d'
],
[
'7f30ea2476b399b4957509c88f77d0191afa2ff5cb7b14fd6d8e7d65aaab1193',
'ca5ef7d4b231c94c3b15389a5f6311e9daff7bb67b103e9880ef4bff637acaec'
],
[
'5098ff1e1d9f14fb46a210fada6c903fef0fb7b4a1dd1d9ac60a0361800b7a00',
'9731141d81fc8f8084d37c6e7542006b3ee1b40d60dfe5362a5b132fd17ddc0'
],
[
'32b78c7de9ee512a72895be6b9cbefa6e2f3c4ccce445c96b9f2c81e2778ad58',
'ee1849f513df71e32efc3896ee28260c73bb80547ae2275ba497237794c8753c'
],
[
'e2cb74fddc8e9fbcd076eef2a7c72b0ce37d50f08269dfc074b581550547a4f7',
'd3aa2ed71c9dd2247a62df062736eb0baddea9e36122d2be8641abcb005cc4a4'
],
[
'8438447566d4d7bedadc299496ab357426009a35f235cb141be0d99cd10ae3a8',
'c4e1020916980a4da5d01ac5e6ad330734ef0d7906631c4f2390426b2edd791f'
],
[
'4162d488b89402039b584c6fc6c308870587d9c46f660b878ab65c82c711d67e',
'67163e903236289f776f22c25fb8a3afc1732f2b84b4e95dbda47ae5a0852649'
],
[
'3fad3fa84caf0f34f0f89bfd2dcf54fc175d767aec3e50684f3ba4a4bf5f683d',
'cd1bc7cb6cc407bb2f0ca647c718a730cf71872e7d0d2a53fa20efcdfe61826'
],
[
'674f2600a3007a00568c1a7ce05d0816c1fb84bf1370798f1c69532faeb1a86b',
'299d21f9413f33b3edf43b257004580b70db57da0b182259e09eecc69e0d38a5'
],
[
'd32f4da54ade74abb81b815ad1fb3b263d82d6c692714bcff87d29bd5ee9f08f',
'f9429e738b8e53b968e99016c059707782e14f4535359d582fc416910b3eea87'
],
[
'30e4e670435385556e593657135845d36fbb6931f72b08cb1ed954f1e3ce3ff6',
'462f9bce619898638499350113bbc9b10a878d35da70740dc695a559eb88db7b'
],
[
'be2062003c51cc3004682904330e4dee7f3dcd10b01e580bf1971b04d4cad297',
'62188bc49d61e5428573d48a74e1c655b1c61090905682a0d5558ed72dccb9bc'
],
[
'93144423ace3451ed29e0fb9ac2af211cb6e84a601df5993c419859fff5df04a',
'7c10dfb164c3425f5c71a3f9d7992038f1065224f72bb9d1d902a6d13037b47c'
],
[
'b015f8044f5fcbdcf21ca26d6c34fb8197829205c7b7d2a7cb66418c157b112c',
'ab8c1e086d04e813744a655b2df8d5f83b3cdc6faa3088c1d3aea1454e3a1d5f'
],
[
'd5e9e1da649d97d89e4868117a465a3a4f8a18de57a140d36b3f2af341a21b52',
'4cb04437f391ed73111a13cc1d4dd0db1693465c2240480d8955e8592f27447a'
],
[
'd3ae41047dd7ca065dbf8ed77b992439983005cd72e16d6f996a5316d36966bb',
'bd1aeb21ad22ebb22a10f0303417c6d964f8cdd7df0aca614b10dc14d125ac46'
],
[
'463e2763d885f958fc66cdd22800f0a487197d0a82e377b49f80af87c897b065',
'bfefacdb0e5d0fd7df3a311a94de062b26b80c61fbc97508b79992671ef7ca7f'
],
[
'7985fdfd127c0567c6f53ec1bb63ec3158e597c40bfe747c83cddfc910641917',
'603c12daf3d9862ef2b25fe1de289aed24ed291e0ec6708703a5bd567f32ed03'
],
[
'74a1ad6b5f76e39db2dd249410eac7f99e74c59cb83d2d0ed5ff1543da7703e9',
'cc6157ef18c9c63cd6193d83631bbea0093e0968942e8c33d5737fd790e0db08'
],
[
'30682a50703375f602d416664ba19b7fc9bab42c72747463a71d0896b22f6da3',
'553e04f6b018b4fa6c8f39e7f311d3176290d0e0f19ca73f17714d9977a22ff8'
],
[
'9e2158f0d7c0d5f26c3791efefa79597654e7a2b2464f52b1ee6c1347769ef57',
'712fcdd1b9053f09003a3481fa7762e9ffd7c8ef35a38509e2fbf2629008373'
],
[
'176e26989a43c9cfeba4029c202538c28172e566e3c4fce7322857f3be327d66',
'ed8cc9d04b29eb877d270b4878dc43c19aefd31f4eee09ee7b47834c1fa4b1c3'
],
[
'75d46efea3771e6e68abb89a13ad747ecf1892393dfc4f1b7004788c50374da8',
'9852390a99507679fd0b86fd2b39a868d7efc22151346e1a3ca4726586a6bed8'
],
[
'809a20c67d64900ffb698c4c825f6d5f2310fb0451c869345b7319f645605721',
'9e994980d9917e22b76b061927fa04143d096ccc54963e6a5ebfa5f3f8e286c1'
],
[
'1b38903a43f7f114ed4500b4eac7083fdefece1cf29c63528d563446f972c180',
'4036edc931a60ae889353f77fd53de4a2708b26b6f5da72ad3394119daf408f9'
]
]
}
};
},{}],116:[function(require,module,exports){
'use strict';
var utils = exports;
utils.assert = function assert(val, msg) {
if (!val)
throw new Error(msg || 'Assertion failed');
};
function toArray(msg, enc) {
if (Array.isArray(msg))
return msg.slice();
if (!msg)
return [];
var res = [];
if (typeof msg !== 'string') {
for (var i = 0; i < msg.length; i++)
res[i] = msg[i] | 0;
return res;
}
if (!enc) {
for (var i = 0; i < msg.length; i++) {
var c = msg.charCodeAt(i);
var hi = c >> 8;
var lo = c & 0xff;
if (hi)
res.push(hi, lo);
else
res.push(lo);
}
} else if (enc === 'hex') {
msg = msg.replace(/[^a-z0-9]+/ig, '');
if (msg.length % 2 !== 0)
msg = '0' + msg;
for (var i = 0; i < msg.length; i += 2)
res.push(parseInt(msg[i] + msg[i + 1], 16));
}
return res;
}
utils.toArray = toArray;
function zero2(word) {
if (word.length === 1)
return '0' + word;
else
return word;
}
utils.zero2 = zero2;
function toHex(msg) {
var res = '';
for (var i = 0; i < msg.length; i++)
res += zero2(msg[i].toString(16));
return res;
}
utils.toHex = toHex;
utils.encode = function encode(arr, enc) {
if (enc === 'hex')
return toHex(arr);
else
return arr;
};
// Represent num in a w-NAF form
function getNAF(num, w) {
var naf = [];
var ws = 1 << (w + 1);
var k = num.clone();
while (k.cmpn(1) >= 0) {
var z;
if (k.isOdd()) {
var mod = k.andln(ws - 1);
if (mod > (ws >> 1) - 1)
z = (ws >> 1) - mod;
else
z = mod;
k.isubn(z);
} else {
z = 0;
}
naf.push(z);
// Optimization, shift by word if possible
var shift = (k.cmpn(0) !== 0 && k.andln(ws - 1) === 0) ? (w + 1) : 1;
for (var i = 1; i < shift; i++)
naf.push(0);
k.ishrn(shift);
}
return naf;
}
utils.getNAF = getNAF;
// Represent k1, k2 in a Joint Sparse Form
function getJSF(k1, k2) {
var jsf = [
[],
[]
];
k1 = k1.clone();
k2 = k2.clone();
var d1 = 0;
var d2 = 0;
while (k1.cmpn(-d1) > 0 || k2.cmpn(-d2) > 0) {
// First phase
var m14 = (k1.andln(3) + d1) & 3;
var m24 = (k2.andln(3) + d2) & 3;
if (m14 === 3)
m14 = -1;
if (m24 === 3)
m24 = -1;
var u1;
if ((m14 & 1) === 0) {
u1 = 0;
} else {
var m8 = (k1.andln(7) + d1) & 7;
if ((m8 === 3 || m8 === 5) && m24 === 2)
u1 = -m14;
else
u1 = m14;
}
jsf[0].push(u1);
var u2;
if ((m24 & 1) === 0) {
u2 = 0;
} else {
var m8 = (k2.andln(7) + d2) & 7;
if ((m8 === 3 || m8 === 5) && m14 === 2)
u2 = -m24;
else
u2 = m24;
}
jsf[1].push(u2);
// Second phase
if (2 * d1 === u1 + 1)
d1 = 1 - d1;
if (2 * d2 === u2 + 1)
d2 = 1 - d2;
k1.ishrn(1);
k2.ishrn(1);
}
return jsf;
}
utils.getJSF = getJSF;
},{}],117:[function(require,module,exports){
var r;
module.exports = function rand(len) {
if (!r)
r = new Rand(null);
return r.generate(len);
};
function Rand(rand) {
this.rand = rand;
}
module.exports.Rand = Rand;
Rand.prototype.generate = function generate(len) {
return this._rand(len);
};
if (typeof window === 'object') {
if (window.crypto && window.crypto.getRandomValues) {
// Modern browsers
Rand.prototype._rand = function _rand(n) {
var arr = new Uint8Array(n);
window.crypto.getRandomValues(arr);
return arr;
};
} else if (window.msCrypto && window.msCrypto.getRandomValues) {
// IE
Rand.prototype._rand = function _rand(n) {
var arr = new Uint8Array(n);
window.msCrypto.getRandomValues(arr);
return arr;
};
} else {
// Old junk
Rand.prototype._rand = function() {
throw new Error('Not implemented yet');
};
}
} else {
// Node.js or Web worker
try {
var crypto = require('cry' + 'pto');
Rand.prototype._rand = function _rand(n) {
return crypto.randomBytes(n);
};
} catch (e) {
// Emulate crypto API using randy
Rand.prototype._rand = function _rand(n) {
var res = new Uint8Array(n);
for (var i = 0; i < res.length; i++)
res[i] = this.rand.getByte();
return res;
};
}
}
},{}],118:[function(require,module,exports){
var hash = exports;
hash.utils = require('./hash/utils');
hash.common = require('./hash/common');
hash.sha = require('./hash/sha');
hash.ripemd = require('./hash/ripemd');
hash.hmac = require('./hash/hmac');
// Proxy hash functions to the main object
hash.sha1 = hash.sha.sha1;
hash.sha256 = hash.sha.sha256;
hash.sha224 = hash.sha.sha224;
hash.sha384 = hash.sha.sha384;
hash.sha512 = hash.sha.sha512;
hash.ripemd160 = hash.ripemd.ripemd160;
},{"./hash/common":119,"./hash/hmac":120,"./hash/ripemd":121,"./hash/sha":122,"./hash/utils":123}],119:[function(require,module,exports){
var hash = require('../hash');
var utils = hash.utils;
var assert = utils.assert;
function BlockHash() {
this.pending = null;
this.pendingTotal = 0;
this.blockSize = this.constructor.blockSize;
this.outSize = this.constructor.outSize;
this.hmacStrength = this.constructor.hmacStrength;
this.padLength = this.constructor.padLength / 8;
this.endian = 'big';
this._delta8 = this.blockSize / 8;
this._delta32 = this.blockSize / 32;
}
exports.BlockHash = BlockHash;
BlockHash.prototype.update = function update(msg, enc) {
// Convert message to array, pad it, and join into 32bit blocks
msg = utils.toArray(msg, enc);
if (!this.pending)
this.pending = msg;
else
this.pending = this.pending.concat(msg);
this.pendingTotal += msg.length;
// Enough data, try updating
if (this.pending.length >= this._delta8) {
msg = this.pending;
// Process pending data in blocks
var r = msg.length % this._delta8;
this.pending = msg.slice(msg.length - r, msg.length);
if (this.pending.length === 0)
this.pending = null;
msg = utils.join32(msg, 0, msg.length - r, this.endian);
for (var i = 0; i < msg.length; i += this._delta32)
this._update(msg, i, i + this._delta32);
}
return this;
};
BlockHash.prototype.digest = function digest(enc) {
this.update(this._pad());
assert(this.pending === null);
return this._digest(enc);
};
BlockHash.prototype._pad = function pad() {
var len = this.pendingTotal;
var bytes = this._delta8;
var k = bytes - ((len + this.padLength) % bytes);
var res = new Array(k + this.padLength);
res[0] = 0x80;
for (var i = 1; i < k; i++)
res[i] = 0;
// Append length
len <<= 3;
if (this.endian === 'big') {
for (var t = 8; t < this.padLength; t++)
res[i++] = 0;
res[i++] = 0;
res[i++] = 0;
res[i++] = 0;
res[i++] = 0;
res[i++] = (len >>> 24) & 0xff;
res[i++] = (len >>> 16) & 0xff;
res[i++] = (len >>> 8) & 0xff;
res[i++] = len & 0xff;
} else {
res[i++] = len & 0xff;
res[i++] = (len >>> 8) & 0xff;
res[i++] = (len >>> 16) & 0xff;
res[i++] = (len >>> 24) & 0xff;
res[i++] = 0;
res[i++] = 0;
res[i++] = 0;
res[i++] = 0;
for (var t = 8; t < this.padLength; t++)
res[i++] = 0;
}
return res;
};
},{"../hash":118}],120:[function(require,module,exports){
var hmac = exports;
var hash = require('../hash');
var utils = hash.utils;
var assert = utils.assert;
function Hmac(hash, key, enc) {
if (!(this instanceof Hmac))
return new Hmac(hash, key, enc);
this.Hash = hash;
this.blockSize = hash.blockSize / 8;
this.outSize = hash.outSize / 8;
this.inner = null;
this.outer = null;
this._init(utils.toArray(key, enc));
}
module.exports = Hmac;
Hmac.prototype._init = function init(key) {
// Shorten key, if needed
if (key.length > this.blockSize)
key = new this.Hash().update(key).digest();
assert(key.length <= this.blockSize);
// Add padding to key
for (var i = key.length; i < this.blockSize; i++)
key.push(0);
for (var i = 0; i < key.length; i++)
key[i] ^= 0x36;
this.inner = new this.Hash().update(key);
// 0x36 ^ 0x5c = 0x6a
for (var i = 0; i < key.length; i++)
key[i] ^= 0x6a;
this.outer = new this.Hash().update(key);
};
Hmac.prototype.update = function update(msg, enc) {
this.inner.update(msg, enc);
return this;
};
Hmac.prototype.digest = function digest(enc) {
this.outer.update(this.inner.digest());
return this.outer.digest(enc);
};
},{"../hash":118}],121:[function(require,module,exports){
var hash = require('../hash');
var utils = hash.utils;
var rotl32 = utils.rotl32;
var sum32 = utils.sum32;
var sum32_3 = utils.sum32_3;
var sum32_4 = utils.sum32_4;
var BlockHash = hash.common.BlockHash;
function RIPEMD160() {
if (!(this instanceof RIPEMD160))
return new RIPEMD160();
BlockHash.call(this);
this.h = [ 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0 ];
this.endian = 'little';
}
utils.inherits(RIPEMD160, BlockHash);
exports.ripemd160 = RIPEMD160;
RIPEMD160.blockSize = 512;
RIPEMD160.outSize = 160;
RIPEMD160.hmacStrength = 192;
RIPEMD160.padLength = 64;
RIPEMD160.prototype._update = function update(msg, start) {
var A = this.h[0];
var B = this.h[1];
var C = this.h[2];
var D = this.h[3];
var E = this.h[4];
var Ah = A;
var Bh = B;
var Ch = C;
var Dh = D;
var Eh = E;
for (var j = 0; j < 80; j++) {
var T = sum32(
rotl32(
sum32_4(A, f(j, B, C, D), msg[r[j] + start], K(j)),
s[j]),
E);
A = E;
E = D;
D = rotl32(C, 10);
C = B;
B = T;
T = sum32(
rotl32(
sum32_4(Ah, f(79 - j, Bh, Ch, Dh), msg[rh[j] + start], Kh(j)),
sh[j]),
Eh);
Ah = Eh;
Eh = Dh;
Dh = rotl32(Ch, 10);
Ch = Bh;
Bh = T;
}
T = sum32_3(this.h[1], C, Dh);
this.h[1] = sum32_3(this.h[2], D, Eh);
this.h[2] = sum32_3(this.h[3], E, Ah);
this.h[3] = sum32_3(this.h[4], A, Bh);
this.h[4] = sum32_3(this.h[0], B, Ch);
this.h[0] = T;
};
RIPEMD160.prototype._digest = function digest(enc) {
if (enc === 'hex')
return utils.toHex32(this.h, 'little');
else
return utils.split32(this.h, 'little');
};
function f(j, x, y, z) {
if (j <= 15)
return x ^ y ^ z;
else if (j <= 31)
return (x & y) | ((~x) & z);
else if (j <= 47)
return (x | (~y)) ^ z;
else if (j <= 63)
return (x & z) | (y & (~z));
else
return x ^ (y | (~z));
}
function K(j) {
if (j <= 15)
return 0x00000000;
else if (j <= 31)
return 0x5a827999;
else if (j <= 47)
return 0x6ed9eba1;
else if (j <= 63)
return 0x8f1bbcdc;
else
return 0xa953fd4e;
}
function Kh(j) {
if (j <= 15)
return 0x50a28be6;
else if (j <= 31)
return 0x5c4dd124;
else if (j <= 47)
return 0x6d703ef3;
else if (j <= 63)
return 0x7a6d76e9;
else
return 0x00000000;
}
var r = [
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8,
3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12,
1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2,
4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13
];
var rh = [
5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12,
6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2,
15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13,
8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14,
12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11
];
var s = [
11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8,
7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12,
11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5,
11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12,
9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6
];
var sh = [
8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6,
9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11,
9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5,
15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8,
8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11
];
},{"../hash":118}],122:[function(require,module,exports){
var hash = require('../hash');
var utils = hash.utils;
var assert = utils.assert;
var rotr32 = utils.rotr32;
var rotl32 = utils.rotl32;
var sum32 = utils.sum32;
var sum32_4 = utils.sum32_4;
var sum32_5 = utils.sum32_5;
var rotr64_hi = utils.rotr64_hi;
var rotr64_lo = utils.rotr64_lo;
var shr64_hi = utils.shr64_hi;
var shr64_lo = utils.shr64_lo;
var sum64 = utils.sum64;
var sum64_hi = utils.sum64_hi;
var sum64_lo = utils.sum64_lo;
var sum64_4_hi = utils.sum64_4_hi;
var sum64_4_lo = utils.sum64_4_lo;
var sum64_5_hi = utils.sum64_5_hi;
var sum64_5_lo = utils.sum64_5_lo;
var BlockHash = hash.common.BlockHash;
var sha256_K = [
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 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 sha512_K = [
0x428a2f98, 0xd728ae22, 0x71374491, 0x23ef65cd,
0xb5c0fbcf, 0xec4d3b2f, 0xe9b5dba5, 0x8189dbbc,
0x3956c25b, 0xf348b538, 0x59f111f1, 0xb605d019,
0x923f82a4, 0xaf194f9b, 0xab1c5ed5, 0xda6d8118,
0xd807aa98, 0xa3030242, 0x12835b01, 0x45706fbe,
0x243185be, 0x4ee4b28c, 0x550c7dc3, 0xd5ffb4e2,
0x72be5d74, 0xf27b896f, 0x80deb1fe, 0x3b1696b1,
0x9bdc06a7, 0x25c71235, 0xc19bf174, 0xcf692694,
0xe49b69c1, 0x9ef14ad2, 0xefbe4786, 0x384f25e3,
0x0fc19dc6, 0x8b8cd5b5, 0x240ca1cc, 0x77ac9c65,
0x2de92c6f, 0x592b0275, 0x4a7484aa, 0x6ea6e483,
0x5cb0a9dc, 0xbd41fbd4, 0x76f988da, 0x831153b5,
0x983e5152, 0xee66dfab, 0xa831c66d, 0x2db43210,
0xb00327c8, 0x98fb213f, 0xbf597fc7, 0xbeef0ee4,
0xc6e00bf3, 0x3da88fc2, 0xd5a79147, 0x930aa725,
0x06ca6351, 0xe003826f, 0x14292967, 0x0a0e6e70,
0x27b70a85, 0x46d22ffc, 0x2e1b2138, 0x5c26c926,
0x4d2c6dfc, 0x5ac42aed, 0x53380d13, 0x9d95b3df,
0x650a7354, 0x8baf63de, 0x766a0abb, 0x3c77b2a8,
0x81c2c92e, 0x47edaee6, 0x92722c85, 0x1482353b,
0xa2bfe8a1, 0x4cf10364, 0xa81a664b, 0xbc423001,
0xc24b8b70, 0xd0f89791, 0xc76c51a3, 0x0654be30,
0xd192e819, 0xd6ef5218, 0xd6990624, 0x5565a910,
0xf40e3585, 0x5771202a, 0x106aa070, 0x32bbd1b8,
0x19a4c116, 0xb8d2d0c8, 0x1e376c08, 0x5141ab53,
0x2748774c, 0xdf8eeb99, 0x34b0bcb5, 0xe19b48a8,
0x391c0cb3, 0xc5c95a63, 0x4ed8aa4a, 0xe3418acb,
0x5b9cca4f, 0x7763e373, 0x682e6ff3, 0xd6b2b8a3,
0x748f82ee, 0x5defb2fc, 0x78a5636f, 0x43172f60,
0x84c87814, 0xa1f0ab72, 0x8cc70208, 0x1a6439ec,
0x90befffa, 0x23631e28, 0xa4506ceb, 0xde82bde9,
0xbef9a3f7, 0xb2c67915, 0xc67178f2, 0xe372532b,
0xca273ece, 0xea26619c, 0xd186b8c7, 0x21c0c207,
0xeada7dd6, 0xcde0eb1e, 0xf57d4f7f, 0xee6ed178,
0x06f067aa, 0x72176fba, 0x0a637dc5, 0xa2c898a6,
0x113f9804, 0xbef90dae, 0x1b710b35, 0x131c471b,
0x28db77f5, 0x23047d84, 0x32caab7b, 0x40c72493,
0x3c9ebe0a, 0x15c9bebc, 0x431d67c4, 0x9c100d4c,
0x4cc5d4be, 0xcb3e42b6, 0x597f299c, 0xfc657e2a,
0x5fcb6fab, 0x3ad6faec, 0x6c44198c, 0x4a475817
];
var sha1_K = [
0x5A827999, 0x6ED9EBA1,
0x8F1BBCDC, 0xCA62C1D6
];
function SHA256() {
if (!(this instanceof SHA256))
return new SHA256();
BlockHash.call(this);
this.h = [ 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 ];
this.k = sha256_K;
this.W = new Array(64);
}
utils.inherits(SHA256, BlockHash);
exports.sha256 = SHA256;
SHA256.blockSize = 512;
SHA256.outSize = 256;
SHA256.hmacStrength = 192;
SHA256.padLength = 64;
SHA256.prototype._update = function _update(msg, start) {
var W = this.W;
for (var i = 0; i < 16; i++)
W[i] = msg[start + i];
for (; i < W.length; i++)
W[i] = sum32_4(g1_256(W[i - 2]), W[i - 7], g0_256(W[i - 15]), W[i - 16]);
var a = this.h[0];
var b = this.h[1];
var c = this.h[2];
var d = this.h[3];
var e = this.h[4];
var f = this.h[5];
var g = this.h[6];
var h = this.h[7];
assert(this.k.length === W.length);
for (var i = 0; i < W.length; i++) {
var T1 = sum32_5(h, s1_256(e), ch32(e, f, g), this.k[i], W[i]);
var T2 = sum32(s0_256(a), maj32(a, b, c));
h = g;
g = f;
f = e;
e = sum32(d, T1);
d = c;
c = b;
b = a;
a = sum32(T1, T2);
}
this.h[0] = sum32(this.h[0], a);
this.h[1] = sum32(this.h[1], b);
this.h[2] = sum32(this.h[2], c);
this.h[3] = sum32(this.h[3], d);
this.h[4] = sum32(this.h[4], e);
this.h[5] = sum32(this.h[5], f);
this.h[6] = sum32(this.h[6], g);
this.h[7] = sum32(this.h[7], h);
};
SHA256.prototype._digest = function digest(enc) {
if (enc === 'hex')
return utils.toHex32(this.h, 'big');
else
return utils.split32(this.h, 'big');
};
function SHA224() {
if (!(this instanceof SHA224))
return new SHA224();
SHA256.call(this);
this.h = [ 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939,
0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4 ];
}
utils.inherits(SHA224, SHA256);
exports.sha224 = SHA224;
SHA224.blockSize = 512;
SHA224.outSize = 224;
SHA224.hmacStrength = 192;
SHA224.padLength = 64;
SHA224.prototype._digest = function digest(enc) {
// Just truncate output
if (enc === 'hex')
return utils.toHex32(this.h.slice(0, 7), 'big');
else
return utils.split32(this.h.slice(0, 7), 'big');
};
function SHA512() {
if (!(this instanceof SHA512))
return new SHA512();
BlockHash.call(this);
this.h = [ 0x6a09e667, 0xf3bcc908,
0xbb67ae85, 0x84caa73b,
0x3c6ef372, 0xfe94f82b,
0xa54ff53a, 0x5f1d36f1,
0x510e527f, 0xade682d1,
0x9b05688c, 0x2b3e6c1f,
0x1f83d9ab, 0xfb41bd6b,
0x5be0cd19, 0x137e2179 ];
this.k = sha512_K;
this.W = new Array(160);
}
utils.inherits(SHA512, BlockHash);
exports.sha512 = SHA512;
SHA512.blockSize = 1024;
SHA512.outSize = 512;
SHA512.hmacStrength = 192;
SHA512.padLength = 128;
SHA512.prototype._prepareBlock = function _prepareBlock(msg, start) {
var W = this.W;
// 32 x 32bit words
for (var i = 0; i < 32; i++)
W[i] = msg[start + i];
for (; i < W.length; i += 2) {
var c0_hi = g1_512_hi(W[i - 4], W[i - 3]); // i - 2
var c0_lo = g1_512_lo(W[i - 4], W[i - 3]);
var c1_hi = W[i - 14]; // i - 7
var c1_lo = W[i - 13];
var c2_hi = g0_512_hi(W[i - 30], W[i - 29]); // i - 15
var c2_lo = g0_512_lo(W[i - 30], W[i - 29]);
var c3_hi = W[i - 32]; // i - 16
var c3_lo = W[i - 31];
W[i] = sum64_4_hi(c0_hi, c0_lo,
c1_hi, c1_lo,
c2_hi, c2_lo,
c3_hi, c3_lo);
W[i + 1] = sum64_4_lo(c0_hi, c0_lo,
c1_hi, c1_lo,
c2_hi, c2_lo,
c3_hi, c3_lo);
}
};
SHA512.prototype._update = function _update(msg, start) {
this._prepareBlock(msg, start);
var W = this.W;
var ah = this.h[0];
var al = this.h[1];
var bh = this.h[2];
var bl = this.h[3];
var ch = this.h[4];
var cl = this.h[5];
var dh = this.h[6];
var dl = this.h[7];
var eh = this.h[8];
var el = this.h[9];
var fh = this.h[10];
var fl = this.h[11];
var gh = this.h[12];
var gl = this.h[13];
var hh = this.h[14];
var hl = this.h[15];
assert(this.k.length === W.length);
for (var i = 0; i < W.length; i += 2) {
var c0_hi = hh;
var c0_lo = hl;
var c1_hi = s1_512_hi(eh, el);
var c1_lo = s1_512_lo(eh, el);
var c2_hi = ch64_hi(eh, el, fh, fl, gh, gl);
var c2_lo = ch64_lo(eh, el, fh, fl, gh, gl);
var c3_hi = this.k[i];
var c3_lo = this.k[i + 1];
var c4_hi = W[i];
var c4_lo = W[i + 1];
var T1_hi = sum64_5_hi(c0_hi, c0_lo,
c1_hi, c1_lo,
c2_hi, c2_lo,
c3_hi, c3_lo,
c4_hi, c4_lo);
var T1_lo = sum64_5_lo(c0_hi, c0_lo,
c1_hi, c1_lo,
c2_hi, c2_lo,
c3_hi, c3_lo,
c4_hi, c4_lo);
var c0_hi = s0_512_hi(ah, al);
var c0_lo = s0_512_lo(ah, al);
var c1_hi = maj64_hi(ah, al, bh, bl, ch, cl);
var c1_lo = maj64_lo(ah, al, bh, bl, ch, cl);
var T2_hi = sum64_hi(c0_hi, c0_lo, c1_hi, c1_lo);
var T2_lo = sum64_lo(c0_hi, c0_lo, c1_hi, c1_lo);
hh = gh;
hl = gl;
gh = fh;
gl = fl;
fh = eh;
fl = el;
eh = sum64_hi(dh, dl, T1_hi, T1_lo);
el = sum64_lo(dl, dl, T1_hi, T1_lo);
dh = ch;
dl = cl;
ch = bh;
cl = bl;
bh = ah;
bl = al;
ah = sum64_hi(T1_hi, T1_lo, T2_hi, T2_lo);
al = sum64_lo(T1_hi, T1_lo, T2_hi, T2_lo);
}
sum64(this.h, 0, ah, al);
sum64(this.h, 2, bh, bl);
sum64(this.h, 4, ch, cl);
sum64(this.h, 6, dh, dl);
sum64(this.h, 8, eh, el);
sum64(this.h, 10, fh, fl);
sum64(this.h, 12, gh, gl);
sum64(this.h, 14, hh, hl);
};
SHA512.prototype._digest = function digest(enc) {
if (enc === 'hex')
return utils.toHex32(this.h, 'big');
else
return utils.split32(this.h, 'big');
};
function SHA384() {
if (!(this instanceof SHA384))
return new SHA384();
SHA512.call(this);
this.h = [ 0xcbbb9d5d, 0xc1059ed8,
0x629a292a, 0x367cd507,
0x9159015a, 0x3070dd17,
0x152fecd8, 0xf70e5939,
0x67332667, 0xffc00b31,
0x8eb44a87, 0x68581511,
0xdb0c2e0d, 0x64f98fa7,
0x47b5481d, 0xbefa4fa4 ];
}
utils.inherits(SHA384, SHA512);
exports.sha384 = SHA384;
SHA384.blockSize = 1024;
SHA384.outSize = 384;
SHA384.hmacStrength = 192;
SHA384.padLength = 128;
SHA384.prototype._digest = function digest(enc) {
if (enc === 'hex')
return utils.toHex32(this.h.slice(0, 12), 'big');
else
return utils.split32(this.h.slice(0, 12), 'big');
};
function SHA1() {
if (!(this instanceof SHA1))
return new SHA1();
BlockHash.call(this);
this.h = [ 0x67452301, 0xefcdab89, 0x98badcfe,
0x10325476, 0xc3d2e1f0 ];
this.W = new Array(80);
}
utils.inherits(SHA1, BlockHash);
exports.sha1 = SHA1;
SHA1.blockSize = 512;
SHA1.outSize = 160;
SHA1.hmacStrength = 80;
SHA1.padLength = 64;
SHA1.prototype._update = function _update(msg, start) {
var W = this.W;
for (var i = 0; i < 16; i++)
W[i] = msg[start + i];
for(; i < W.length; i++)
W[i] = rotl32(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1);
var a = this.h[0];
var b = this.h[1];
var c = this.h[2];
var d = this.h[3];
var e = this.h[4];
for (var i = 0; i < W.length; i++) {
var s = ~~(i / 20);
var t = sum32_5(rotl32(a, 5), ft_1(s, b, c, d), e, W[i], sha1_K[s]);
e = d;
d = c;
c = rotl32(b, 30);
b = a;
a = t;
}
this.h[0] = sum32(this.h[0], a);
this.h[1] = sum32(this.h[1], b);
this.h[2] = sum32(this.h[2], c);
this.h[3] = sum32(this.h[3], d);
this.h[4] = sum32(this.h[4], e);
};
SHA1.prototype._digest = function digest(enc) {
if (enc === 'hex')
return utils.toHex32(this.h, 'big');
else
return utils.split32(this.h, 'big');
};
function ch32(x, y, z) {
return (x & y) ^ ((~x) & z);
}
function maj32(x, y, z) {
return (x & y) ^ (x & z) ^ (y & z);
}
function p32(x, y, z) {
return x ^ y ^ z;
}
function s0_256(x) {
return rotr32(x, 2) ^ rotr32(x, 13) ^ rotr32(x, 22);
}
function s1_256(x) {
return rotr32(x, 6) ^ rotr32(x, 11) ^ rotr32(x, 25);
}
function g0_256(x) {
return rotr32(x, 7) ^ rotr32(x, 18) ^ (x >>> 3);
}
function g1_256(x) {
return rotr32(x, 17) ^ rotr32(x, 19) ^ (x >>> 10);
}
function ft_1(s, x, y, z) {
if (s === 0)
return ch32(x, y, z);
if (s === 1 || s === 3)
return p32(x, y, z);
if (s === 2)
return maj32(x, y, z);
}
function ch64_hi(xh, xl, yh, yl, zh, zl) {
var r = (xh & yh) ^ ((~xh) & zh);
if (r < 0)
r += 0x100000000;
return r;
}
function ch64_lo(xh, xl, yh, yl, zh, zl) {
var r = (xl & yl) ^ ((~xl) & zl);
if (r < 0)
r += 0x100000000;
return r;
}
function maj64_hi(xh, xl, yh, yl, zh, zl) {
var r = (xh & yh) ^ (xh & zh) ^ (yh & zh);
if (r < 0)
r += 0x100000000;
return r;
}
function maj64_lo(xh, xl, yh, yl, zh, zl) {
var r = (xl & yl) ^ (xl & zl) ^ (yl & zl);
if (r < 0)
r += 0x100000000;
return r;
}
function s0_512_hi(xh, xl) {
var c0_hi = rotr64_hi(xh, xl, 28);
var c1_hi = rotr64_hi(xl, xh, 2); // 34
var c2_hi = rotr64_hi(xl, xh, 7); // 39
var r = c0_hi ^ c1_hi ^ c2_hi;
if (r < 0)
r += 0x100000000;
return r;
}
function s0_512_lo(xh, xl) {
var c0_lo = rotr64_lo(xh, xl, 28);
var c1_lo = rotr64_lo(xl, xh, 2); // 34
var c2_lo = rotr64_lo(xl, xh, 7); // 39
var r = c0_lo ^ c1_lo ^ c2_lo;
if (r < 0)
r += 0x100000000;
return r;
}
function s1_512_hi(xh, xl) {
var c0_hi = rotr64_hi(xh, xl, 14);
var c1_hi = rotr64_hi(xh, xl, 18);
var c2_hi = rotr64_hi(xl, xh, 9); // 41
var r = c0_hi ^ c1_hi ^ c2_hi;
if (r < 0)
r += 0x100000000;
return r;
}
function s1_512_lo(xh, xl) {
var c0_lo = rotr64_lo(xh, xl, 14);
var c1_lo = rotr64_lo(xh, xl, 18);
var c2_lo = rotr64_lo(xl, xh, 9); // 41
var r = c0_lo ^ c1_lo ^ c2_lo;
if (r < 0)
r += 0x100000000;
return r;
}
function g0_512_hi(xh, xl) {
var c0_hi = rotr64_hi(xh, xl, 1);
var c1_hi = rotr64_hi(xh, xl, 8);
var c2_hi = shr64_hi(xh, xl, 7);
var r = c0_hi ^ c1_hi ^ c2_hi;
if (r < 0)
r += 0x100000000;
return r;
}
function g0_512_lo(xh, xl) {
var c0_lo = rotr64_lo(xh, xl, 1);
var c1_lo = rotr64_lo(xh, xl, 8);
var c2_lo = shr64_lo(xh, xl, 7);
var r = c0_lo ^ c1_lo ^ c2_lo;
if (r < 0)
r += 0x100000000;
return r;
}
function g1_512_hi(xh, xl) {
var c0_hi = rotr64_hi(xh, xl, 19);
var c1_hi = rotr64_hi(xl, xh, 29); // 61
var c2_hi = shr64_hi(xh, xl, 6);
var r = c0_hi ^ c1_hi ^ c2_hi;
if (r < 0)
r += 0x100000000;
return r;
}
function g1_512_lo(xh, xl) {
var c0_lo = rotr64_lo(xh, xl, 19);
var c1_lo = rotr64_lo(xl, xh, 29); // 61
var c2_lo = shr64_lo(xh, xl, 6);
var r = c0_lo ^ c1_lo ^ c2_lo;
if (r < 0)
r += 0x100000000;
return r;
}
},{"../hash":118}],123:[function(require,module,exports){
var utils = exports;
var inherits = require('inherits');
function toArray(msg, enc) {
if (Array.isArray(msg))
return msg.slice();
if (!msg)
return [];
var res = [];
if (typeof msg === 'string') {
if (!enc) {
for (var i = 0; i < msg.length; i++) {
var c = msg.charCodeAt(i);
var hi = c >> 8;
var lo = c & 0xff;
if (hi)
res.push(hi, lo);
else
res.push(lo);
}
} else if (enc === 'hex') {
msg = msg.replace(/[^a-z0-9]+/ig, '');
if (msg.length % 2 !== 0)
msg = '0' + msg;
for (var i = 0; i < msg.length; i += 2)
res.push(parseInt(msg[i] + msg[i + 1], 16));
}
} else {
for (var i = 0; i < msg.length; i++)
res[i] = msg[i] | 0;
}
return res;
}
utils.toArray = toArray;
function toHex(msg) {
var res = '';
for (var i = 0; i < msg.length; i++)
res += zero2(msg[i].toString(16));
return res;
}
utils.toHex = toHex;
function htonl(w) {
var res = (w >>> 24) |
((w >>> 8) & 0xff00) |
((w << 8) & 0xff0000) |
((w & 0xff) << 24);
return res >>> 0;
}
utils.htonl = htonl;
function toHex32(msg, endian) {
var res = '';
for (var i = 0; i < msg.length; i++) {
var w = msg[i];
if (endian === 'little')
w = htonl(w);
res += zero8(w.toString(16));
}
return res;
}
utils.toHex32 = toHex32;
function zero2(word) {
if (word.length === 1)
return '0' + word;
else
return word;
}
utils.zero2 = zero2;
function zero8(word) {
if (word.length === 7)
return '0' + word;
else if (word.length === 6)
return '00' + word;
else if (word.length === 5)
return '000' + word;
else if (word.length === 4)
return '0000' + word;
else if (word.length === 3)
return '00000' + word;
else if (word.length === 2)
return '000000' + word;
else if (word.length === 1)
return '0000000' + word;
else
return word;
}
utils.zero8 = zero8;
function join32(msg, start, end, endian) {
var len = end - start;
assert(len % 4 === 0);
var res = new Array(len / 4);
for (var i = 0, k = start; i < res.length; i++, k += 4) {
var w;
if (endian === 'big')
w = (msg[k] << 24) | (msg[k + 1] << 16) | (msg[k + 2] << 8) | msg[k + 3];
else
w = (msg[k + 3] << 24) | (msg[k + 2] << 16) | (msg[k + 1] << 8) | msg[k];
res[i] = w >>> 0;
}
return res;
}
utils.join32 = join32;
function split32(msg, endian) {
var res = new Array(msg.length * 4);
for (var i = 0, k = 0; i < msg.length; i++, k += 4) {
var m = msg[i];
if (endian === 'big') {
res[k] = m >>> 24;
res[k + 1] = (m >>> 16) & 0xff;
res[k + 2] = (m >>> 8) & 0xff;
res[k + 3] = m & 0xff;
} else {
res[k + 3] = m >>> 24;
res[k + 2] = (m >>> 16) & 0xff;
res[k + 1] = (m >>> 8) & 0xff;
res[k] = m & 0xff;
}
}
return res;
}
utils.split32 = split32;
function rotr32(w, b) {
return (w >>> b) | (w << (32 - b));
}
utils.rotr32 = rotr32;
function rotl32(w, b) {
return (w << b) | (w >>> (32 - b));
}
utils.rotl32 = rotl32;
function sum32(a, b) {
return (a + b) >>> 0;
}
utils.sum32 = sum32;
function sum32_3(a, b, c) {
return (a + b + c) >>> 0;
}
utils.sum32_3 = sum32_3;
function sum32_4(a, b, c, d) {
return (a + b + c + d) >>> 0;
}
utils.sum32_4 = sum32_4;
function sum32_5(a, b, c, d, e) {
return (a + b + c + d + e) >>> 0;
}
utils.sum32_5 = sum32_5;
function assert(cond, msg) {
if (!cond)
throw new Error(msg || 'Assertion failed');
}
utils.assert = assert;
utils.inherits = inherits;
function sum64(buf, pos, ah, al) {
var bh = buf[pos];
var bl = buf[pos + 1];
var lo = (al + bl) >>> 0;
var hi = (lo < al ? 1 : 0) + ah + bh;
buf[pos] = hi >>> 0;
buf[pos + 1] = lo;
}
exports.sum64 = sum64;
function sum64_hi(ah, al, bh, bl) {
var lo = (al + bl) >>> 0;
var hi = (lo < al ? 1 : 0) + ah + bh;
return hi >>> 0;
};
exports.sum64_hi = sum64_hi;
function sum64_lo(ah, al, bh, bl) {
var lo = al + bl;
return lo >>> 0;
};
exports.sum64_lo = sum64_lo;
function sum64_4_hi(ah, al, bh, bl, ch, cl, dh, dl) {
var carry = 0;
var lo = al;
lo = (lo + bl) >>> 0;
carry += lo < al ? 1 : 0;
lo = (lo + cl) >>> 0;
carry += lo < cl ? 1 : 0;
lo = (lo + dl) >>> 0;
carry += lo < dl ? 1 : 0;
var hi = ah + bh + ch + dh + carry;
return hi >>> 0;
};
exports.sum64_4_hi = sum64_4_hi;
function sum64_4_lo(ah, al, bh, bl, ch, cl, dh, dl) {
var lo = al + bl + cl + dl;
return lo >>> 0;
};
exports.sum64_4_lo = sum64_4_lo;
function sum64_5_hi(ah, al, bh, bl, ch, cl, dh, dl, eh, el) {
var carry = 0;
var lo = al;
lo = (lo + bl) >>> 0;
carry += lo < al ? 1 : 0;
lo = (lo + cl) >>> 0;
carry += lo < cl ? 1 : 0;
lo = (lo + dl) >>> 0;
carry += lo < dl ? 1 : 0;
lo = (lo + el) >>> 0;
carry += lo < el ? 1 : 0;
var hi = ah + bh + ch + dh + eh + carry;
return hi >>> 0;
};
exports.sum64_5_hi = sum64_5_hi;
function sum64_5_lo(ah, al, bh, bl, ch, cl, dh, dl, eh, el) {
var lo = al + bl + cl + dl + el;
return lo >>> 0;
};
exports.sum64_5_lo = sum64_5_lo;
function rotr64_hi(ah, al, num) {
var r = (al << (32 - num)) | (ah >>> num);
return r >>> 0;
};
exports.rotr64_hi = rotr64_hi;
function rotr64_lo(ah, al, num) {
var r = (ah << (32 - num)) | (al >>> num);
return r >>> 0;
};
exports.rotr64_lo = rotr64_lo;
function shr64_hi(ah, al, num) {
return ah >>> num;
};
exports.shr64_hi = shr64_hi;
function shr64_lo(ah, al, num) {
var r = (ah << (32 - num)) | (al >>> num);
return r >>> 0;
};
exports.shr64_lo = shr64_lo;
},{"inherits":223}],124:[function(require,module,exports){
module.exports={
"name": "elliptic",
"version": "3.1.0",
"description": "EC cryptography",
"main": "lib/elliptic.js",
"scripts": {
"test": "make lint && mocha --reporter=spec test/*-test.js"
},
"repository": {
"type": "git",
"url": "git+ssh://git@github.com/indutny/elliptic.git"
},
"keywords": [
"EC",
"Elliptic",
"curve",
"Cryptography"
],
"author": {
"name": "Fedor Indutny",
"email": "fedor@indutny.com"
},
"license": "MIT",
"bugs": {
"url": "https://github.com/indutny/elliptic/issues"
},
"homepage": "https://github.com/indutny/elliptic",
"devDependencies": {
"browserify": "^3.44.2",
"jscs": "^1.11.3",
"jshint": "^2.6.0",
"mocha": "^2.1.0",
"uglify-js": "^2.4.13"
},
"dependencies": {
"bn.js": "^2.0.3",
"brorand": "^1.0.1",
"hash.js": "^1.0.0",
"inherits": "^2.0.1"
},
"gitHead": "d86cd2a8178f7e7cecbd6dd92eea084e2ab44c13",
"_id": "elliptic@3.1.0",
"_shasum": "c21682ef762769b56a74201609105da11d5f60cc",
"_from": "elliptic@>=3.0.0 <4.0.0",
"_npmVersion": "2.11.0",
"_nodeVersion": "2.2.1",
"_npmUser": {
"name": "indutny",
"email": "fedor@indutny.com"
},
"maintainers": [
{
"name": "indutny",
"email": "fedor@indutny.com"
}
],
"dist": {
"shasum": "c21682ef762769b56a74201609105da11d5f60cc",
"tarball": "http://registry.npmjs.org/elliptic/-/elliptic-3.1.0.tgz"
},
"directories": {},
"_resolved": "https://registry.npmjs.org/elliptic/-/elliptic-3.1.0.tgz",
"readme": "ERROR: No README data found!"
}
},{}],125:[function(require,module,exports){
(function (Buffer){
var createHash = require('create-hash');
module.exports = function evp(password, salt, keyLen) {
keyLen = keyLen/8;
var ki = 0;
var ii = 0;
var key = new Buffer(keyLen);
var addmd = 0;
var md, md_buf;
var i;
while (true) {
md = createHash('md5');
if(addmd++ > 0) {
md.update(md_buf);
}
md.update(password);
md.update(salt);
md_buf = md.digest();
i = 0;
if(keyLen > 0) {
while(true) {
if(keyLen === 0) {
break;
}
if(i === md_buf.length) {
break;
}
key[ki++] = md_buf[i++];
keyLen--;
}
}
if(keyLen === 0) {
break;
}
}
for(i=0;i> 6];
var primitive = (tag & 0x20) === 0;
// Multi-octet tag - load
if ((tag & 0x1f) === 0x1f) {
var oct = tag;
tag = 0;
while ((oct & 0x80) === 0x80) {
oct = buf.readUInt8(fail);
if (buf.isError(oct))
return oct;
tag <<= 7;
tag |= oct & 0x7f;
}
} else {
tag &= 0x1f;
}
var tagStr = der.tag[tag];
return {
cls: cls,
primitive: primitive,
tag: tag,
tagStr: tagStr
};
}
function derDecodeLen(buf, primitive, fail) {
var len = buf.readUInt8(fail);
if (buf.isError(len))
return len;
// Indefinite form
if (!primitive && len === 0x80)
return null;
// Definite form
if ((len & 0x80) === 0) {
// Short form
return len;
}
// Long form
var num = len & 0x7f;
if (num >= 4)
return buf.error('length octect is too long');
len = 0;
for (var i = 0; i < num; i++) {
len <<= 8;
var j = buf.readUInt8(fail);
if (buf.isError(j))
return j;
len |= j;
}
return len;
}
},{"../../asn1":130,"inherits":223}],139:[function(require,module,exports){
var decoders = exports;
decoders.der = require('./der');
decoders.pem = require('./pem');
},{"./der":138,"./pem":140}],140:[function(require,module,exports){
var inherits = require('inherits');
var Buffer = require('buffer').Buffer;
var asn1 = require('../../asn1');
var DERDecoder = require('./der');
function PEMDecoder(entity) {
DERDecoder.call(this, entity);
this.enc = 'pem';
};
inherits(PEMDecoder, DERDecoder);
module.exports = PEMDecoder;
PEMDecoder.prototype.decode = function decode(data, options) {
var lines = data.toString().split(/[\r\n]+/g);
var label = options.label.toUpperCase();
var re = /^-----(BEGIN|END) ([^-]+)-----$/;
var start = -1;
var end = -1;
for (var i = 0; i < lines.length; i++) {
var match = lines[i].match(re);
if (match === null)
continue;
if (match[2] !== label)
continue;
if (start === -1) {
if (match[1] !== 'BEGIN')
break;
start = i;
} else {
if (match[1] !== 'END')
break;
end = i;
break;
}
}
if (start === -1 || end === -1)
throw new Error('PEM section not found for: ' + label);
var base64 = lines.slice(start + 1, end).join('');
// Remove excessive symbols
base64.replace(/[^a-z0-9\+\/=]+/gi, '');
var input = new Buffer(base64, 'base64');
return DERDecoder.prototype.decode.call(this, input, options);
};
},{"../../asn1":130,"./der":138,"buffer":76,"inherits":223}],141:[function(require,module,exports){
var inherits = require('inherits');
var Buffer = require('buffer').Buffer;
var asn1 = require('../../asn1');
var base = asn1.base;
var bignum = asn1.bignum;
// Import DER constants
var der = asn1.constants.der;
function DEREncoder(entity) {
this.enc = 'der';
this.name = entity.name;
this.entity = entity;
// Construct base tree
this.tree = new DERNode();
this.tree._init(entity.body);
};
module.exports = DEREncoder;
DEREncoder.prototype.encode = function encode(data, reporter) {
return this.tree._encode(data, reporter).join();
};
// Tree methods
function DERNode(parent) {
base.Node.call(this, 'der', parent);
}
inherits(DERNode, base.Node);
DERNode.prototype._encodeComposite = function encodeComposite(tag,
primitive,
cls,
content) {
var encodedTag = encodeTag(tag, primitive, cls, this.reporter);
// Short form
if (content.length < 0x80) {
var header = new Buffer(2);
header[0] = encodedTag;
header[1] = content.length;
return this._createEncoderBuffer([ header, content ]);
}
// Long form
// Count octets required to store length
var lenOctets = 1;
for (var i = content.length; i >= 0x100; i >>= 8)
lenOctets++;
var header = new Buffer(1 + 1 + lenOctets);
header[0] = encodedTag;
header[1] = 0x80 | lenOctets;
for (var i = 1 + lenOctets, j = content.length; j > 0; i--, j >>= 8)
header[i] = j & 0xff;
return this._createEncoderBuffer([ header, content ]);
};
DERNode.prototype._encodeStr = function encodeStr(str, tag) {
if (tag === 'octstr')
return this._createEncoderBuffer(str);
else if (tag === 'bitstr')
return this._createEncoderBuffer([ str.unused | 0, str.data ]);
else if (tag === 'ia5str')
return this._createEncoderBuffer(str);
return this.reporter.error('Encoding of string type: ' + tag +
' unsupported');
};
DERNode.prototype._encodeObjid = function encodeObjid(id, values, relative) {
if (typeof id === 'string') {
if (!values)
return this.reporter.error('string objid given, but no values map found');
if (!values.hasOwnProperty(id))
return this.reporter.error('objid not found in values map');
id = values[id].split(/[\s\.]+/g);
for (var i = 0; i < id.length; i++)
id[i] |= 0;
} else if (Array.isArray(id)) {
id = id.slice();
for (var i = 0; i < id.length; i++)
id[i] |= 0;
}
if (!Array.isArray(id)) {
return this.reporter.error('objid() should be either array or string, ' +
'got: ' + JSON.stringify(id));
}
if (!relative) {
if (id[1] >= 40)
return this.reporter.error('Second objid identifier OOB');
id.splice(0, 2, id[0] * 40 + id[1]);
}
// Count number of octets
var size = 0;
for (var i = 0; i < id.length; i++) {
var ident = id[i];
for (size++; ident >= 0x80; ident >>= 7)
size++;
}
var objid = new Buffer(size);
var offset = objid.length - 1;
for (var i = id.length - 1; i >= 0; i--) {
var ident = id[i];
objid[offset--] = ident & 0x7f;
while ((ident >>= 7) > 0)
objid[offset--] = 0x80 | (ident & 0x7f);
}
return this._createEncoderBuffer(objid);
};
function two(num) {
if (num < 10)
return '0' + num;
else
return num;
}
DERNode.prototype._encodeTime = function encodeTime(time, tag) {
var str;
var date = new Date(time);
if (tag === 'gentime') {
str = [
two(date.getFullYear()),
two(date.getUTCMonth() + 1),
two(date.getUTCDate()),
two(date.getUTCHours()),
two(date.getUTCMinutes()),
two(date.getUTCSeconds()),
'Z'
].join('');
} else if (tag === 'utctime') {
str = [
two(date.getFullYear() % 100),
two(date.getUTCMonth() + 1),
two(date.getUTCDate()),
two(date.getUTCHours()),
two(date.getUTCMinutes()),
two(date.getUTCSeconds()),
'Z'
].join('');
} else {
this.reporter.error('Encoding ' + tag + ' time is not supported yet');
}
return this._encodeStr(str, 'octstr');
};
DERNode.prototype._encodeNull = function encodeNull() {
return this._createEncoderBuffer('');
};
DERNode.prototype._encodeInt = function encodeInt(num, values) {
if (typeof num === 'string') {
if (!values)
return this.reporter.error('String int or enum given, but no values map');
if (!values.hasOwnProperty(num)) {
return this.reporter.error('Values map doesn\'t contain: ' +
JSON.stringify(num));
}
num = values[num];
}
// Bignum, assume big endian
if (typeof num !== 'number' && !Buffer.isBuffer(num)) {
var numArray = num.toArray();
if (num.sign === false && numArray[0] & 0x80) {
numArray.unshift(0);
}
num = new Buffer(numArray);
}
if (Buffer.isBuffer(num)) {
var size = num.length;
if (num.length === 0)
size++;
var out = new Buffer(size);
num.copy(out);
if (num.length === 0)
out[0] = 0
return this._createEncoderBuffer(out);
}
if (num < 0x80)
return this._createEncoderBuffer(num);
if (num < 0x100)
return this._createEncoderBuffer([0, num]);
var size = 1;
for (var i = num; i >= 0x100; i >>= 8)
size++;
var out = new Array(size);
for (var i = out.length - 1; i >= 0; i--) {
out[i] = num & 0xff;
num >>= 8;
}
if(out[0] & 0x80) {
out.unshift(0);
}
return this._createEncoderBuffer(new Buffer(out));
};
DERNode.prototype._encodeBool = function encodeBool(value) {
return this._createEncoderBuffer(value ? 0xff : 0);
};
DERNode.prototype._use = function use(entity, obj) {
if (typeof entity === 'function')
entity = entity(obj);
return entity._getEncoder('der').tree;
};
DERNode.prototype._skipDefault = function skipDefault(dataBuffer, reporter, parent) {
var state = this._baseState;
var i;
if (state['default'] === null)
return false;
var data = dataBuffer.join();
if (state.defaultBuffer === undefined)
state.defaultBuffer = this._encodeValue(state['default'], reporter, parent).join();
if (data.length !== state.defaultBuffer.length)
return false;
for (i=0; i < data.length; i++)
if (data[i] !== state.defaultBuffer[i])
return false;
return true;
};
// Utility methods
function encodeTag(tag, primitive, cls, reporter) {
var res;
if (tag === 'seqof')
tag = 'seq';
else if (tag === 'setof')
tag = 'set';
if (der.tagByName.hasOwnProperty(tag))
res = der.tagByName[tag];
else if (typeof tag === 'number' && (tag | 0) === tag)
res = tag;
else
return reporter.error('Unknown tag: ' + tag);
if (res >= 0x1f)
return reporter.error('Multi-octet tag encoding unsupported');
if (!primitive)
res |= 0x20;
res |= (der.tagClassByName[cls || 'universal'] << 6);
return res;
}
},{"../../asn1":130,"buffer":76,"inherits":223}],142:[function(require,module,exports){
var encoders = exports;
encoders.der = require('./der');
encoders.pem = require('./pem');
},{"./der":141,"./pem":143}],143:[function(require,module,exports){
var inherits = require('inherits');
var Buffer = require('buffer').Buffer;
var asn1 = require('../../asn1');
var DEREncoder = require('./der');
function PEMEncoder(entity) {
DEREncoder.call(this, entity);
this.enc = 'pem';
};
inherits(PEMEncoder, DEREncoder);
module.exports = PEMEncoder;
PEMEncoder.prototype.encode = function encode(data, options) {
var buf = DEREncoder.prototype.encode.call(this, data);
var p = buf.toString('base64');
var out = [ '-----BEGIN ' + options.label + '-----' ];
for (var i = 0; i < p.length; i += 64)
out.push(p.slice(i, i + 64));
out.push('-----END ' + options.label + '-----');
return out.join('\n');
};
},{"../../asn1":130,"./der":141,"buffer":76,"inherits":223}],144:[function(require,module,exports){
module.exports = assert;
function assert(val, msg) {
if (!val)
throw new Error(msg || 'Assertion failed');
}
assert.equal = function assertEqual(l, r, msg) {
if (l != r)
throw new Error(msg || ('Assertion failed: ' + l + ' != ' + r));
};
},{}],145:[function(require,module,exports){
(function (Buffer){
// much of this based on https://github.com/indutny/self-signed/blob/gh-pages/lib/rsa.js
var parseKeys = require('parse-asn1')
var BN = require('bn.js')
var elliptic = require('elliptic')
var crt = require('browserify-rsa')
var createHmac = require('create-hmac')
var curves = require('./curves')
module.exports = sign
function sign (hash, key, hashType, signType) {
var priv = parseKeys(key)
if (priv.curve) {
if (signType !== 'ecdsa') {
throw new Error('wrong private key type')
}
return ecSign(hash, priv)
} else if (priv.type === 'dsa') {
return dsaSign(hash, priv, hashType)
if (signType !== 'dsa') {
throw new Error('wrong private key type')
}
} else {
if (signType !== 'rsa') {
throw new Error('wrong private key type')
}
}
var len = priv.modulus.byteLength()
var pad = [ 0, 1 ]
while (hash.length + pad.length + 1 < len) {
pad.push(0xff)
}
pad.push(0x00)
var i = -1
while (++i < hash.length) {
pad.push(hash[i])
}
var out = crt(pad, priv)
return out
}
function ecSign (hash, priv) {
var curveId = curves[priv.curve.join('.')]
if (!curveId)
throw new Error('unknown curve ' + priv.curve.join('.'))
var curve = new elliptic.ec(curveId)
var key = curve.genKeyPair()
key._importPrivate(priv.privateKey)
var out = key.sign(hash)
return new Buffer(out.toDER())
}
function dsaSign (hash, priv, algo) {
var x = priv.params.priv_key
var p = priv.params.p
var q = priv.params.q
var montq = BN.mont(q)
var g = priv.params.g
var r = new BN(0)
var k
var H = bits2int(hash, q).mod(q)
var s = false
var kv = getKey(x, q, hash, algo)
while (s === false) {
k = makeKey(q, kv, algo)
r = makeR(g, k, p, q)
s = k.invm(q).imul(H.add(x.mul(r))).mod(q)
if (!s.cmpn(0)) {
s = false
r = new BN(0)
}
}
return toDER(r, s)
}
function toDER (r, s) {
r = r.toArray()
s = s.toArray()
// Pad values
if (r[0] & 0x80)
r = [ 0 ].concat(r)
// Pad values
if (s[0] & 0x80)
s = [0].concat(s)
var total = r.length + s.length + 4
var res = [ 0x30, total, 0x02, r.length ]
res = res.concat(r, [ 0x02, s.length ], s)
return new Buffer(res)
}
module.exports.getKey = getKey
function getKey (x, q, hash, algo) {
x = new Buffer(x.toArray())
if (x.length < q.byteLength()) {
var zeros = new Buffer(q.byteLength() - x.length)
zeros.fill(0)
x = Buffer.concat([zeros, x])
}
var hlen = hash.length
var hbits = bits2octets(hash, q)
var v = new Buffer(hlen)
v.fill(1)
var k = new Buffer(hlen)
k.fill(0)
k = createHmac(algo, k)
.update(v)
.update(new Buffer([0]))
.update(x)
.update(hbits)
.digest()
v = createHmac(algo, k)
.update(v)
.digest()
k = createHmac(algo, k)
.update(v)
.update(new Buffer([1]))
.update(x)
.update(hbits)
.digest()
v = createHmac(algo, k)
.update(v)
.digest()
return {
k: k,
v: v
}
}
function bits2int (obits, q) {
var bits = new BN(obits)
var shift = (obits.length << 3) - q.bitLength()
if (shift > 0) {
bits.ishrn(shift)
}
return bits
}
function bits2octets (bits, q) {
bits = bits2int(bits, q)
bits = bits.mod(q)
var out = new Buffer(bits.toArray())
if (out.length < q.byteLength()) {
var zeros = new Buffer(q.byteLength() - out.length)
zeros.fill(0)
out = Buffer.concat([zeros, out])
}
return out
}
module.exports.makeKey = makeKey
function makeKey (q, kv, algo) {
var t
var k
while (true) {
t = new Buffer('')
while (t.length * 8 < q.bitLength()) {
kv.v = createHmac(algo, kv.k)
.update(kv.v)
.digest()
t = Buffer.concat([t, kv.v])
}
k = bits2int(t, q)
kv.k = createHmac(algo, kv.k)
.update(kv.v)
.update(new Buffer([0]))
.digest()
kv.v = createHmac(algo, kv.k)
.update(kv.v)
.digest()
if (k.cmp(q) === -1) {
return k
}
}
}
function makeR (g, k, p, q) {
return g.toRed(BN.mont(p)).redPow(k).fromRed().mod(q)
}
}).call(this,require("buffer").Buffer)
},{"./curves":101,"bn.js":102,"browserify-rsa":103,"buffer":76,"create-hmac":183,"elliptic":104,"parse-asn1":129}],146:[function(require,module,exports){
(function (Buffer){
'use strict'
// much of this based on https://github.com/indutny/self-signed/blob/gh-pages/lib/rsa.js
var parseKeys = require('parse-asn1')
var elliptic = require('elliptic')
var curves = require('./curves')
var BN = require('bn.js')
module.exports = verify
function verify (sig, hash, key, signType) {
var pub = parseKeys(key)
if (pub.type === 'ec') {
if (signType !== 'ecdsa') {
throw new Error('wrong public key type')
}
return ecVerify(sig, hash, pub)
} else if (pub.type === 'dsa') {
if (signType !== 'dsa') {
throw new Error('wrong public key type')
}
return dsaVerify(sig, hash, pub)
} else {
if (signType !== 'rsa') {
throw new Error('wrong public key type')
}
}
var len = pub.modulus.byteLength()
var pad = [ 1 ]
var padNum = 0
while (hash.length + pad.length + 2 < len) {
pad.push(0xff)
padNum++
}
pad.push(0x00)
var i = -1
while (++i < hash.length) {
pad.push(hash[i])
}
pad = new Buffer(pad)
var red = BN.mont(pub.modulus)
sig = new BN(sig).toRed(red)
sig = sig.redPow(new BN(pub.publicExponent))
sig = new Buffer(sig.fromRed().toArray())
var out = 0
if (padNum < 8) {
out = 1
}
len = Math.min(sig.length, pad.length)
if (sig.length !== pad.length) {
out = 1
}
i = -1
while (++i < len) {
out |= (sig[i] ^ pad[i])
}
return out === 0
}
function ecVerify (sig, hash, pub) {
var curveId = curves[pub.data.algorithm.curve.join('.')]
if (!curveId)
throw new Error('unknown curve ' + pub.data.algorithm.curve.join('.'))
var curve = new elliptic.ec(curveId)
var pubkey = pub.data.subjectPrivateKey.data
return curve.verify(hash, sig, pubkey)
}
function dsaVerify (sig, hash, pub) {
var p = pub.data.p
var q = pub.data.q
var g = pub.data.g
var y = pub.data.pub_key
var unpacked = parseKeys.signature.decode(sig, 'der')
var s = unpacked.s
var r = unpacked.r
checkValue(s, q)
checkValue(r, q)
var montq = BN.mont(q)
var montp = BN.mont(p)
var w = s.invm(q)
var v = g.toRed(montp)
.redPow(new BN(hash).mul(w).mod(q))
.fromRed()
.mul(
y.toRed(montp)
.redPow(r.mul(w).mod(q))
.fromRed()
).mod(p).mod(q)
return !v.cmp(r)
}
function checkValue (b, q) {
if (b.cmpn(0) <= 0) {
throw new Error('invalid sig')
}
if (b.cmp(q) >= q) {
throw new Error('invalid sig')
}
}
}).call(this,require("buffer").Buffer)
},{"./curves":101,"bn.js":102,"buffer":76,"elliptic":104,"parse-asn1":129}],147:[function(require,module,exports){
(function (Buffer){
var elliptic = require('elliptic');
var BN = require('bn.js');
module.exports = function createECDH(curve) {
return new ECDH(curve);
};
var aliases = {
secp256k1: {
name: 'secp256k1',
byteLength: 32
},
secp224r1: {
name: 'p224',
byteLength: 28
},
prime256v1: {
name: 'p256',
byteLength: 32
},
prime192v1: {
name: 'p192',
byteLength: 24
},
ed25519: {
name: 'ed25519',
byteLength: 32
}
};
aliases.p224 = aliases.secp224r1;
aliases.p256 = aliases.secp256r1 = aliases.prime256v1;
aliases.p192 = aliases.secp192r1 = aliases.prime192v1;
function ECDH(curve) {
this.curveType = aliases[curve];
if (!this.curveType ) {
this.curveType = {
name: curve
};
}
this.curve = new elliptic.ec(this.curveType.name);
this.keys = void 0;
}
ECDH.prototype.generateKeys = function (enc, format) {
this.keys = this.curve.genKeyPair();
return this.getPublicKey(enc, format);
};
ECDH.prototype.computeSecret = function (other, inenc, enc) {
inenc = inenc || 'utf8';
if (!Buffer.isBuffer(other)) {
other = new Buffer(other, inenc);
}
var otherPub = this.curve.keyFromPublic(other).getPublic();
var out = otherPub.mul(this.keys.getPrivate()).getX();
return formatReturnValue(out, enc, this.curveType.byteLength);
};
ECDH.prototype.getPublicKey = function (enc, format) {
var key = this.keys.getPublic(format === 'compressed', true);
if (format === 'hybrid') {
if (key[key.length - 1] % 2) {
key[0] = 7;
} else {
key [0] = 6;
}
}
return formatReturnValue(key, enc);
};
ECDH.prototype.getPrivateKey = function (enc) {
return formatReturnValue(this.keys.getPrivate(), enc);
};
ECDH.prototype.setPublicKey = function (pub, enc) {
enc = enc || 'utf8';
if (!Buffer.isBuffer(pub)) {
pub = new Buffer(pub, enc);
}
this.keys._importPublic(pub);
return this;
};
ECDH.prototype.setPrivateKey = function (priv, enc) {
enc = enc || 'utf8';
if (!Buffer.isBuffer(priv)) {
priv = new Buffer(priv, enc);
}
var _priv = new BN(priv);
_priv = _priv.toString(16);
this.keys._importPrivate(_priv);
return this;
};
function formatReturnValue(bn, enc, len) {
if (!Array.isArray(bn)) {
bn = bn.toArray();
}
var buf = new Buffer(bn);
if (len && buf.length < len) {
var zeros = new Buffer(len - buf.length);
zeros.fill(0);
buf = Buffer.concat([zeros, buf]);
}
if (!enc) {
return buf;
} else {
return buf.toString(enc);
}
}
}).call(this,require("buffer").Buffer)
},{"bn.js":149,"buffer":76,"elliptic":150}],148:[function(require,module,exports){
var createECDH = require('crypto').createECDH;
module.exports = createECDH || require('./browser');
},{"./browser":147,"crypto":80}],149:[function(require,module,exports){
arguments[4][102][0].apply(exports,arguments)
},{"dup":102}],150:[function(require,module,exports){
arguments[4][104][0].apply(exports,arguments)
},{"../package.json":170,"./elliptic/curve":153,"./elliptic/curves":156,"./elliptic/ec":157,"./elliptic/hmac-drbg":160,"./elliptic/utils":162,"brorand":163,"dup":104}],151:[function(require,module,exports){
arguments[4][105][0].apply(exports,arguments)
},{"../../elliptic":150,"bn.js":149,"dup":105}],152:[function(require,module,exports){
arguments[4][106][0].apply(exports,arguments)
},{"../../elliptic":150,"../curve":153,"bn.js":149,"dup":106,"inherits":223}],153:[function(require,module,exports){
arguments[4][107][0].apply(exports,arguments)
},{"./base":151,"./edwards":152,"./mont":154,"./short":155,"dup":107}],154:[function(require,module,exports){
arguments[4][108][0].apply(exports,arguments)
},{"../curve":153,"bn.js":149,"dup":108,"inherits":223}],155:[function(require,module,exports){
arguments[4][109][0].apply(exports,arguments)
},{"../../elliptic":150,"../curve":153,"bn.js":149,"dup":109,"inherits":223}],156:[function(require,module,exports){
arguments[4][110][0].apply(exports,arguments)
},{"../elliptic":150,"./precomputed/secp256k1":161,"dup":110,"hash.js":164}],157:[function(require,module,exports){
arguments[4][111][0].apply(exports,arguments)
},{"../../elliptic":150,"./key":158,"./signature":159,"bn.js":149,"dup":111}],158:[function(require,module,exports){
arguments[4][112][0].apply(exports,arguments)
},{"../../elliptic":150,"bn.js":149,"dup":112}],159:[function(require,module,exports){
arguments[4][113][0].apply(exports,arguments)
},{"../../elliptic":150,"bn.js":149,"dup":113}],160:[function(require,module,exports){
arguments[4][114][0].apply(exports,arguments)
},{"../elliptic":150,"dup":114,"hash.js":164}],161:[function(require,module,exports){
arguments[4][115][0].apply(exports,arguments)
},{"dup":115}],162:[function(require,module,exports){
arguments[4][116][0].apply(exports,arguments)
},{"dup":116}],163:[function(require,module,exports){
arguments[4][117][0].apply(exports,arguments)
},{"dup":117}],164:[function(require,module,exports){
arguments[4][118][0].apply(exports,arguments)
},{"./hash/common":165,"./hash/hmac":166,"./hash/ripemd":167,"./hash/sha":168,"./hash/utils":169,"dup":118}],165:[function(require,module,exports){
arguments[4][119][0].apply(exports,arguments)
},{"../hash":164,"dup":119}],166:[function(require,module,exports){
arguments[4][120][0].apply(exports,arguments)
},{"../hash":164,"dup":120}],167:[function(require,module,exports){
arguments[4][121][0].apply(exports,arguments)
},{"../hash":164,"dup":121}],168:[function(require,module,exports){
arguments[4][122][0].apply(exports,arguments)
},{"../hash":164,"dup":122}],169:[function(require,module,exports){
arguments[4][123][0].apply(exports,arguments)
},{"dup":123,"inherits":223}],170:[function(require,module,exports){
arguments[4][124][0].apply(exports,arguments)
},{"dup":124}],171:[function(require,module,exports){
(function (Buffer){
'use strict';
var inherits = require('inherits')
var md5 = require('./md5')
var rmd160 = require('ripemd160')
var sha = require('sha.js')
var Transform = require('stream').Transform
function HashNoConstructor(hash) {
Transform.call(this)
this._hash = hash
this.buffers = []
}
inherits(HashNoConstructor, Transform)
HashNoConstructor.prototype._transform = function (data, _, next) {
this.buffers.push(data)
next()
}
HashNoConstructor.prototype._flush = function (next) {
this.push(this.digest())
next()
}
HashNoConstructor.prototype.update = function (data, enc) {
if (typeof data === 'string') {
data = new Buffer(data, enc)
}
this.buffers.push(data)
return this
}
HashNoConstructor.prototype.digest = function (enc) {
var buf = Buffer.concat(this.buffers)
var r = this._hash(buf)
this.buffers = null
return enc ? r.toString(enc) : r
}
function Hash(hash) {
Transform.call(this)
this._hash = hash
}
inherits(Hash, Transform)
Hash.prototype._transform = function (data, enc, next) {
if (enc) data = new Buffer(data, enc)
this._hash.update(data)
next()
}
Hash.prototype._flush = function (next) {
this.push(this._hash.digest())
this._hash = null
next()
}
Hash.prototype.update = function (data, enc) {
if (typeof data === 'string') {
data = new Buffer(data, enc)
}
this._hash.update(data)
return this
}
Hash.prototype.digest = function (enc) {
var outData = this._hash.digest()
return enc ? outData.toString(enc) : outData
}
module.exports = function createHash (alg) {
if ('md5' === alg) return new HashNoConstructor(md5)
if ('rmd160' === alg) return new HashNoConstructor(rmd160)
return new Hash(sha(alg))
}
}).call(this,require("buffer").Buffer)
},{"./md5":173,"buffer":76,"inherits":223,"ripemd160":174,"sha.js":176,"stream":241}],172:[function(require,module,exports){
(function (Buffer){
'use strict';
var intSize = 4;
var zeroBuffer = new Buffer(intSize); zeroBuffer.fill(0);
var chrsz = 8;
function toArray(buf, bigEndian) {
if ((buf.length % intSize) !== 0) {
var len = buf.length + (intSize - (buf.length % intSize));
buf = Buffer.concat([buf, zeroBuffer], len);
}
var arr = [];
var fn = bigEndian ? buf.readInt32BE : buf.readInt32LE;
for (var i = 0; i < buf.length; i += intSize) {
arr.push(fn.call(buf, i));
}
return arr;
}
function toBuffer(arr, size, bigEndian) {
var buf = new Buffer(size);
var fn = bigEndian ? buf.writeInt32BE : buf.writeInt32LE;
for (var i = 0; i < arr.length; i++) {
fn.call(buf, arr[i], i * 4, true);
}
return buf;
}
function hash(buf, fn, hashSize, bigEndian) {
if (!Buffer.isBuffer(buf)) buf = new Buffer(buf);
var arr = fn(toArray(buf, bigEndian), buf.length * chrsz);
return toBuffer(arr, hashSize, bigEndian);
}
exports.hash = hash;
}).call(this,require("buffer").Buffer)
},{"buffer":76}],173:[function(require,module,exports){
'use strict';
/*
* 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.
*/
var helpers = require('./helpers');
/*
* 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);
}
/*
* 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));
}
module.exports = function md5(buf) {
return helpers.hash(buf, core_md5, 16);
};
},{"./helpers":172}],174:[function(require,module,exports){
(function (Buffer){
/*
CryptoJS v3.1.2
code.google.com/p/crypto-js
(c) 2009-2013 by Jeff Mott. All rights reserved.
code.google.com/p/crypto-js/wiki/License
*/
/** @preserve
(c) 2012 by Cédric Mesnil. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// constants table
var zl = [
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8,
3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12,
1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2,
4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13
]
var zr = [
5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12,
6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2,
15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13,
8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14,
12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11
]
var sl = [
11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8,
7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12,
11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5,
11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12,
9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6
]
var sr = [
8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6,
9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11,
9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5,
15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8,
8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11
]
var hl = [0x00000000, 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xA953FD4E]
var hr = [0x50A28BE6, 0x5C4DD124, 0x6D703EF3, 0x7A6D76E9, 0x00000000]
function bytesToWords (bytes) {
var words = []
for (var i = 0, b = 0; i < bytes.length; i++, b += 8) {
words[b >>> 5] |= bytes[i] << (24 - b % 32)
}
return words
}
function wordsToBytes (words) {
var bytes = []
for (var b = 0; b < words.length * 32; b += 8) {
bytes.push((words[b >>> 5] >>> (24 - b % 32)) & 0xFF)
}
return bytes
}
function processBlock (H, M, offset) {
// swap endian
for (var i = 0; i < 16; i++) {
var offset_i = offset + i
var M_offset_i = M[offset_i]
// Swap
M[offset_i] = (
(((M_offset_i << 8) | (M_offset_i >>> 24)) & 0x00ff00ff) |
(((M_offset_i << 24) | (M_offset_i >>> 8)) & 0xff00ff00)
)
}
// Working variables
var al, bl, cl, dl, el
var ar, br, cr, dr, er
ar = al = H[0]
br = bl = H[1]
cr = cl = H[2]
dr = dl = H[3]
er = el = H[4]
// computation
var t
for (i = 0; i < 80; i += 1) {
t = (al + M[offset + zl[i]]) | 0
if (i < 16) {
t += f1(bl, cl, dl) + hl[0]
} else if (i < 32) {
t += f2(bl, cl, dl) + hl[1]
} else if (i < 48) {
t += f3(bl, cl, dl) + hl[2]
} else if (i < 64) {
t += f4(bl, cl, dl) + hl[3]
} else {// if (i<80) {
t += f5(bl, cl, dl) + hl[4]
}
t = t | 0
t = rotl(t, sl[i])
t = (t + el) | 0
al = el
el = dl
dl = rotl(cl, 10)
cl = bl
bl = t
t = (ar + M[offset + zr[i]]) | 0
if (i < 16) {
t += f5(br, cr, dr) + hr[0]
} else if (i < 32) {
t += f4(br, cr, dr) + hr[1]
} else if (i < 48) {
t += f3(br, cr, dr) + hr[2]
} else if (i < 64) {
t += f2(br, cr, dr) + hr[3]
} else {// if (i<80) {
t += f1(br, cr, dr) + hr[4]
}
t = t | 0
t = rotl(t, sr[i])
t = (t + er) | 0
ar = er
er = dr
dr = rotl(cr, 10)
cr = br
br = t
}
// intermediate hash value
t = (H[1] + cl + dr) | 0
H[1] = (H[2] + dl + er) | 0
H[2] = (H[3] + el + ar) | 0
H[3] = (H[4] + al + br) | 0
H[4] = (H[0] + bl + cr) | 0
H[0] = t
}
function f1 (x, y, z) {
return ((x) ^ (y) ^ (z))
}
function f2 (x, y, z) {
return (((x) & (y)) | ((~x) & (z)))
}
function f3 (x, y, z) {
return (((x) | (~(y))) ^ (z))
}
function f4 (x, y, z) {
return (((x) & (z)) | ((y) & (~(z))))
}
function f5 (x, y, z) {
return ((x) ^ ((y) | (~(z))))
}
function rotl (x, n) {
return (x << n) | (x >>> (32 - n))
}
function ripemd160 (message) {
var H = [0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0]
if (typeof message === 'string') {
message = new Buffer(message, 'utf8')
}
var m = bytesToWords(message)
var nBitsLeft = message.length * 8
var nBitsTotal = message.length * 8
// Add padding
m[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32)
m[(((nBitsLeft + 64) >>> 9) << 4) + 14] = (
(((nBitsTotal << 8) | (nBitsTotal >>> 24)) & 0x00ff00ff) |
(((nBitsTotal << 24) | (nBitsTotal >>> 8)) & 0xff00ff00)
)
for (var i = 0; i < m.length; i += 16) {
processBlock(H, m, i)
}
// swap endian
for (i = 0; i < 5; i++) {
// shortcut
var H_i = H[i]
// Swap
H[i] = (((H_i << 8) | (H_i >>> 24)) & 0x00ff00ff) |
(((H_i << 24) | (H_i >>> 8)) & 0xff00ff00)
}
var digestbytes = wordsToBytes(H)
return new Buffer(digestbytes)
}
module.exports = ripemd160
}).call(this,require("buffer").Buffer)
},{"buffer":76}],175:[function(require,module,exports){
(function (Buffer){
// prototype class for hash functions
function Hash (blockSize, finalSize) {
this._block = new Buffer(blockSize)
this._finalSize = finalSize
this._blockSize = blockSize
this._len = 0
this._s = 0
}
Hash.prototype.update = function (data, enc) {
if (typeof data === 'string') {
enc = enc || 'utf8'
data = new Buffer(data, enc)
}
var l = this._len += data.length
var s = this._s || 0
var f = 0
var buffer = this._block
while (s < l) {
var t = Math.min(data.length, f + this._blockSize - (s % this._blockSize))
var ch = (t - f)
for (var i = 0; i < ch; i++) {
buffer[(s % this._blockSize) + i] = data[i + f]
}
s += ch
f += ch
if ((s % this._blockSize) === 0) {
this._update(buffer)
}
}
this._s = s
return this
}
Hash.prototype.digest = function (enc) {
// Suppose the length of the message M, in bits, is l
var l = this._len * 8
// Append the bit 1 to the end of the message
this._block[this._len % this._blockSize] = 0x80
// and then k zero bits, where k is the smallest non-negative solution to the equation (l + 1 + k) === finalSize mod blockSize
this._block.fill(0, this._len % this._blockSize + 1)
if (l % (this._blockSize * 8) >= this._finalSize * 8) {
this._update(this._block)
this._block.fill(0)
}
// to this append the block which is equal to the number l written in binary
// TODO: handle case where l is > Math.pow(2, 29)
this._block.writeInt32BE(l, this._blockSize - 4)
var hash = this._update(this._block) || this._hash()
return enc ? hash.toString(enc) : hash
}
Hash.prototype._update = function () {
throw new Error('_update must be implemented by subclass')
}
module.exports = Hash
}).call(this,require("buffer").Buffer)
},{"buffer":76}],176:[function(require,module,exports){
var exports = module.exports = function SHA (algorithm) {
algorithm = algorithm.toLowerCase()
var Algorithm = exports[algorithm]
if (!Algorithm) throw new Error(algorithm + ' is not supported (we accept pull requests)')
return new Algorithm()
}
exports.sha = require('./sha')
exports.sha1 = require('./sha1')
exports.sha224 = require('./sha224')
exports.sha256 = require('./sha256')
exports.sha384 = require('./sha384')
exports.sha512 = require('./sha512')
},{"./sha":177,"./sha1":178,"./sha224":179,"./sha256":180,"./sha384":181,"./sha512":182}],177:[function(require,module,exports){
(function (Buffer){
/*
* A JavaScript implementation of the Secure Hash Algorithm, SHA-0, as defined
* in FIPS PUB 180-1
* This source code is derived from sha1.js of the same repository.
* The difference between SHA-0 and SHA-1 is just a bitwise rotate left
* operation was added.
*/
var inherits = require('inherits')
var Hash = require('./hash')
var W = new Array(80)
function Sha () {
this.init()
this._w = W
Hash.call(this, 64, 56)
}
inherits(Sha, Hash)
Sha.prototype.init = function () {
this._a = 0x67452301 | 0
this._b = 0xefcdab89 | 0
this._c = 0x98badcfe | 0
this._d = 0x10325476 | 0
this._e = 0xc3d2e1f0 | 0
return this
}
/*
* Bitwise rotate a 32-bit number to the left.
*/
function rol (num, cnt) {
return (num << cnt) | (num >>> (32 - cnt))
}
Sha.prototype._update = function (M) {
var W = this._w
var a = this._a
var b = this._b
var c = this._c
var d = this._d
var e = this._e
var j = 0, k
/*
* SHA-1 has a bitwise rotate left operation. But, SHA is not
* function calcW() { return rol(W[j - 3] ^ W[j - 8] ^ W[j - 14] ^ W[j - 16], 1) }
*/
function calcW () { return W[j - 3] ^ W[j - 8] ^ W[j - 14] ^ W[j - 16] }
function loop (w, f) {
W[j] = w
var t = rol(a, 5) + f + e + w + k
e = d
d = c
c = rol(b, 30)
b = a
a = t
j++
}
k = 1518500249
while (j < 16) loop(M.readInt32BE(j * 4), (b & c) | ((~b) & d))
while (j < 20) loop(calcW(), (b & c) | ((~b) & d))
k = 1859775393
while (j < 40) loop(calcW(), b ^ c ^ d)
k = -1894007588
while (j < 60) loop(calcW(), (b & c) | (b & d) | (c & d))
k = -899497514
while (j < 80) loop(calcW(), b ^ c ^ d)
this._a = (a + this._a) | 0
this._b = (b + this._b) | 0
this._c = (c + this._c) | 0
this._d = (d + this._d) | 0
this._e = (e + this._e) | 0
}
Sha.prototype._hash = function () {
var H = new Buffer(20)
H.writeInt32BE(this._a | 0, 0)
H.writeInt32BE(this._b | 0, 4)
H.writeInt32BE(this._c | 0, 8)
H.writeInt32BE(this._d | 0, 12)
H.writeInt32BE(this._e | 0, 16)
return H
}
module.exports = Sha
}).call(this,require("buffer").Buffer)
},{"./hash":175,"buffer":76,"inherits":223}],178:[function(require,module,exports){
(function (Buffer){
/*
* 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.
*/
var inherits = require('inherits')
var Hash = require('./hash')
var W = new Array(80)
function Sha1 () {
this.init()
this._w = W
Hash.call(this, 64, 56)
}
inherits(Sha1, Hash)
Sha1.prototype.init = function () {
this._a = 0x67452301 | 0
this._b = 0xefcdab89 | 0
this._c = 0x98badcfe | 0
this._d = 0x10325476 | 0
this._e = 0xc3d2e1f0 | 0
return this
}
/*
* Bitwise rotate a 32-bit number to the left.
*/
function rol (num, cnt) {
return (num << cnt) | (num >>> (32 - cnt))
}
Sha1.prototype._update = function (M) {
var W = this._w
var a = this._a
var b = this._b
var c = this._c
var d = this._d
var e = this._e
var j = 0, k
function calcW () { return rol(W[j - 3] ^ W[j - 8] ^ W[j - 14] ^ W[j - 16], 1) }
function loop (w, f) {
W[j] = w
var t = rol(a, 5) + f + e + w + k
e = d
d = c
c = rol(b, 30)
b = a
a = t
j++
}
k = 1518500249
while (j < 16) loop(M.readInt32BE(j * 4), (b & c) | ((~b) & d))
while (j < 20) loop(calcW(), (b & c) | ((~b) & d))
k = 1859775393
while (j < 40) loop(calcW(), b ^ c ^ d)
k = -1894007588
while (j < 60) loop(calcW(), (b & c) | (b & d) | (c & d))
k = -899497514
while (j < 80) loop(calcW(), b ^ c ^ d)
this._a = (a + this._a) | 0
this._b = (b + this._b) | 0
this._c = (c + this._c) | 0
this._d = (d + this._d) | 0
this._e = (e + this._e) | 0
}
Sha1.prototype._hash = function () {
var H = new Buffer(20)
H.writeInt32BE(this._a | 0, 0)
H.writeInt32BE(this._b | 0, 4)
H.writeInt32BE(this._c | 0, 8)
H.writeInt32BE(this._d | 0, 12)
H.writeInt32BE(this._e | 0, 16)
return H
}
module.exports = Sha1
}).call(this,require("buffer").Buffer)
},{"./hash":175,"buffer":76,"inherits":223}],179:[function(require,module,exports){
(function (Buffer){
/**
* 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
*
*/
var inherits = require('inherits')
var Sha256 = require('./sha256')
var Hash = require('./hash')
var W = new Array(64)
function Sha224 () {
this.init()
this._w = W // new Array(64)
Hash.call(this, 64, 56)
}
inherits(Sha224, Sha256)
Sha224.prototype.init = function () {
this._a = 0xc1059ed8 | 0
this._b = 0x367cd507 | 0
this._c = 0x3070dd17 | 0
this._d = 0xf70e5939 | 0
this._e = 0xffc00b31 | 0
this._f = 0x68581511 | 0
this._g = 0x64f98fa7 | 0
this._h = 0xbefa4fa4 | 0
return this
}
Sha224.prototype._hash = function () {
var H = new Buffer(28)
H.writeInt32BE(this._a, 0)
H.writeInt32BE(this._b, 4)
H.writeInt32BE(this._c, 8)
H.writeInt32BE(this._d, 12)
H.writeInt32BE(this._e, 16)
H.writeInt32BE(this._f, 20)
H.writeInt32BE(this._g, 24)
return H
}
module.exports = Sha224
}).call(this,require("buffer").Buffer)
},{"./hash":175,"./sha256":180,"buffer":76,"inherits":223}],180:[function(require,module,exports){
(function (Buffer){
/**
* 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
*
*/
var inherits = require('inherits')
var Hash = require('./hash')
var K = [
0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,
0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC,
0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7,
0xC6E00BF3, 0xD5A79147, 0x06CA6351, 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 W = new Array(64)
function Sha256 () {
this.init()
this._w = W // new Array(64)
Hash.call(this, 64, 56)
}
inherits(Sha256, Hash)
Sha256.prototype.init = function () {
this._a = 0x6a09e667 | 0
this._b = 0xbb67ae85 | 0
this._c = 0x3c6ef372 | 0
this._d = 0xa54ff53a | 0
this._e = 0x510e527f | 0
this._f = 0x9b05688c | 0
this._g = 0x1f83d9ab | 0
this._h = 0x5be0cd19 | 0
return this
}
function S (X, n) {
return (X >>> n) | (X << (32 - n))
}
function R (X, n) {
return (X >>> n)
}
function Ch (x, y, z) {
return ((x & y) ^ ((~x) & z))
}
function Maj (x, y, z) {
return ((x & y) ^ (x & z) ^ (y & z))
}
function Sigma0256 (x) {
return (S(x, 2) ^ S(x, 13) ^ S(x, 22))
}
function Sigma1256 (x) {
return (S(x, 6) ^ S(x, 11) ^ S(x, 25))
}
function Gamma0256 (x) {
return (S(x, 7) ^ S(x, 18) ^ R(x, 3))
}
function Gamma1256 (x) {
return (S(x, 17) ^ S(x, 19) ^ R(x, 10))
}
Sha256.prototype._update = function (M) {
var W = this._w
var a = this._a | 0
var b = this._b | 0
var c = this._c | 0
var d = this._d | 0
var e = this._e | 0
var f = this._f | 0
var g = this._g | 0
var h = this._h | 0
var j = 0
function calcW () { return Gamma1256(W[j - 2]) + W[j - 7] + Gamma0256(W[j - 15]) + W[j - 16] }
function loop (w) {
W[j] = w
var T1 = h + Sigma1256(e) + Ch(e, f, g) + K[j] + w
var T2 = Sigma0256(a) + Maj(a, b, c)
h = g
g = f
f = e
e = d + T1
d = c
c = b
b = a
a = T1 + T2
j++
}
while (j < 16) loop(M.readInt32BE(j * 4))
while (j < 64) loop(calcW())
this._a = (a + this._a) | 0
this._b = (b + this._b) | 0
this._c = (c + this._c) | 0
this._d = (d + this._d) | 0
this._e = (e + this._e) | 0
this._f = (f + this._f) | 0
this._g = (g + this._g) | 0
this._h = (h + this._h) | 0
}
Sha256.prototype._hash = function () {
var H = new Buffer(32)
H.writeInt32BE(this._a, 0)
H.writeInt32BE(this._b, 4)
H.writeInt32BE(this._c, 8)
H.writeInt32BE(this._d, 12)
H.writeInt32BE(this._e, 16)
H.writeInt32BE(this._f, 20)
H.writeInt32BE(this._g, 24)
H.writeInt32BE(this._h, 28)
return H
}
module.exports = Sha256
}).call(this,require("buffer").Buffer)
},{"./hash":175,"buffer":76,"inherits":223}],181:[function(require,module,exports){
(function (Buffer){
var inherits = require('inherits')
var SHA512 = require('./sha512')
var Hash = require('./hash')
var W = new Array(160)
function Sha384 () {
this.init()
this._w = W
Hash.call(this, 128, 112)
}
inherits(Sha384, SHA512)
Sha384.prototype.init = function () {
this._a = 0xcbbb9d5d | 0
this._b = 0x629a292a | 0
this._c = 0x9159015a | 0
this._d = 0x152fecd8 | 0
this._e = 0x67332667 | 0
this._f = 0x8eb44a87 | 0
this._g = 0xdb0c2e0d | 0
this._h = 0x47b5481d | 0
this._al = 0xc1059ed8 | 0
this._bl = 0x367cd507 | 0
this._cl = 0x3070dd17 | 0
this._dl = 0xf70e5939 | 0
this._el = 0xffc00b31 | 0
this._fl = 0x68581511 | 0
this._gl = 0x64f98fa7 | 0
this._hl = 0xbefa4fa4 | 0
return this
}
Sha384.prototype._hash = function () {
var H = new Buffer(48)
function writeInt64BE (h, l, offset) {
H.writeInt32BE(h, offset)
H.writeInt32BE(l, offset + 4)
}
writeInt64BE(this._a, this._al, 0)
writeInt64BE(this._b, this._bl, 8)
writeInt64BE(this._c, this._cl, 16)
writeInt64BE(this._d, this._dl, 24)
writeInt64BE(this._e, this._el, 32)
writeInt64BE(this._f, this._fl, 40)
return H
}
module.exports = Sha384
}).call(this,require("buffer").Buffer)
},{"./hash":175,"./sha512":182,"buffer":76,"inherits":223}],182:[function(require,module,exports){
(function (Buffer){
var inherits = require('inherits')
var Hash = require('./hash')
var K = [
0x428a2f98, 0xd728ae22, 0x71374491, 0x23ef65cd,
0xb5c0fbcf, 0xec4d3b2f, 0xe9b5dba5, 0x8189dbbc,
0x3956c25b, 0xf348b538, 0x59f111f1, 0xb605d019,
0x923f82a4, 0xaf194f9b, 0xab1c5ed5, 0xda6d8118,
0xd807aa98, 0xa3030242, 0x12835b01, 0x45706fbe,
0x243185be, 0x4ee4b28c, 0x550c7dc3, 0xd5ffb4e2,
0x72be5d74, 0xf27b896f, 0x80deb1fe, 0x3b1696b1,
0x9bdc06a7, 0x25c71235, 0xc19bf174, 0xcf692694,
0xe49b69c1, 0x9ef14ad2, 0xefbe4786, 0x384f25e3,
0x0fc19dc6, 0x8b8cd5b5, 0x240ca1cc, 0x77ac9c65,
0x2de92c6f, 0x592b0275, 0x4a7484aa, 0x6ea6e483,
0x5cb0a9dc, 0xbd41fbd4, 0x76f988da, 0x831153b5,
0x983e5152, 0xee66dfab, 0xa831c66d, 0x2db43210,
0xb00327c8, 0x98fb213f, 0xbf597fc7, 0xbeef0ee4,
0xc6e00bf3, 0x3da88fc2, 0xd5a79147, 0x930aa725,
0x06ca6351, 0xe003826f, 0x14292967, 0x0a0e6e70,
0x27b70a85, 0x46d22ffc, 0x2e1b2138, 0x5c26c926,
0x4d2c6dfc, 0x5ac42aed, 0x53380d13, 0x9d95b3df,
0x650a7354, 0x8baf63de, 0x766a0abb, 0x3c77b2a8,
0x81c2c92e, 0x47edaee6, 0x92722c85, 0x1482353b,
0xa2bfe8a1, 0x4cf10364, 0xa81a664b, 0xbc423001,
0xc24b8b70, 0xd0f89791, 0xc76c51a3, 0x0654be30,
0xd192e819, 0xd6ef5218, 0xd6990624, 0x5565a910,
0xf40e3585, 0x5771202a, 0x106aa070, 0x32bbd1b8,
0x19a4c116, 0xb8d2d0c8, 0x1e376c08, 0x5141ab53,
0x2748774c, 0xdf8eeb99, 0x34b0bcb5, 0xe19b48a8,
0x391c0cb3, 0xc5c95a63, 0x4ed8aa4a, 0xe3418acb,
0x5b9cca4f, 0x7763e373, 0x682e6ff3, 0xd6b2b8a3,
0x748f82ee, 0x5defb2fc, 0x78a5636f, 0x43172f60,
0x84c87814, 0xa1f0ab72, 0x8cc70208, 0x1a6439ec,
0x90befffa, 0x23631e28, 0xa4506ceb, 0xde82bde9,
0xbef9a3f7, 0xb2c67915, 0xc67178f2, 0xe372532b,
0xca273ece, 0xea26619c, 0xd186b8c7, 0x21c0c207,
0xeada7dd6, 0xcde0eb1e, 0xf57d4f7f, 0xee6ed178,
0x06f067aa, 0x72176fba, 0x0a637dc5, 0xa2c898a6,
0x113f9804, 0xbef90dae, 0x1b710b35, 0x131c471b,
0x28db77f5, 0x23047d84, 0x32caab7b, 0x40c72493,
0x3c9ebe0a, 0x15c9bebc, 0x431d67c4, 0x9c100d4c,
0x4cc5d4be, 0xcb3e42b6, 0x597f299c, 0xfc657e2a,
0x5fcb6fab, 0x3ad6faec, 0x6c44198c, 0x4a475817
]
var W = new Array(160)
function Sha512 () {
this.init()
this._w = W
Hash.call(this, 128, 112)
}
inherits(Sha512, Hash)
Sha512.prototype.init = function () {
this._a = 0x6a09e667 | 0
this._b = 0xbb67ae85 | 0
this._c = 0x3c6ef372 | 0
this._d = 0xa54ff53a | 0
this._e = 0x510e527f | 0
this._f = 0x9b05688c | 0
this._g = 0x1f83d9ab | 0
this._h = 0x5be0cd19 | 0
this._al = 0xf3bcc908 | 0
this._bl = 0x84caa73b | 0
this._cl = 0xfe94f82b | 0
this._dl = 0x5f1d36f1 | 0
this._el = 0xade682d1 | 0
this._fl = 0x2b3e6c1f | 0
this._gl = 0xfb41bd6b | 0
this._hl = 0x137e2179 | 0
return this
}
function S (X, Xl, n) {
return (X >>> n) | (Xl << (32 - n))
}
function Ch (x, y, z) {
return ((x & y) ^ ((~x) & z))
}
function Maj (x, y, z) {
return ((x & y) ^ (x & z) ^ (y & z))
}
Sha512.prototype._update = function (M) {
var W = this._w
var a = this._a | 0
var b = this._b | 0
var c = this._c | 0
var d = this._d | 0
var e = this._e | 0
var f = this._f | 0
var g = this._g | 0
var h = this._h | 0
var al = this._al | 0
var bl = this._bl | 0
var cl = this._cl | 0
var dl = this._dl | 0
var el = this._el | 0
var fl = this._fl | 0
var gl = this._gl | 0
var hl = this._hl | 0
var i = 0, j = 0
var Wi, Wil
function calcW () {
var x = W[j - 15 * 2]
var xl = W[j - 15 * 2 + 1]
var gamma0 = S(x, xl, 1) ^ S(x, xl, 8) ^ (x >>> 7)
var gamma0l = S(xl, x, 1) ^ S(xl, x, 8) ^ S(xl, x, 7)
x = W[j - 2 * 2]
xl = W[j - 2 * 2 + 1]
var gamma1 = S(x, xl, 19) ^ S(xl, x, 29) ^ (x >>> 6)
var gamma1l = S(xl, x, 19) ^ S(x, xl, 29) ^ S(xl, x, 6)
// W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16]
var Wi7 = W[j - 7 * 2]
var Wi7l = W[j - 7 * 2 + 1]
var Wi16 = W[j - 16 * 2]
var Wi16l = W[j - 16 * 2 + 1]
Wil = gamma0l + Wi7l
Wi = gamma0 + Wi7 + ((Wil >>> 0) < (gamma0l >>> 0) ? 1 : 0)
Wil = Wil + gamma1l
Wi = Wi + gamma1 + ((Wil >>> 0) < (gamma1l >>> 0) ? 1 : 0)
Wil = Wil + Wi16l
Wi = Wi + Wi16 + ((Wil >>> 0) < (Wi16l >>> 0) ? 1 : 0)
}
function loop () {
W[j] = Wi
W[j + 1] = Wil
var maj = Maj(a, b, c)
var majl = Maj(al, bl, cl)
var sigma0h = S(a, al, 28) ^ S(al, a, 2) ^ S(al, a, 7)
var sigma0l = S(al, a, 28) ^ S(a, al, 2) ^ S(a, al, 7)
var sigma1h = S(e, el, 14) ^ S(e, el, 18) ^ S(el, e, 9)
var sigma1l = S(el, e, 14) ^ S(el, e, 18) ^ S(e, el, 9)
// t1 = h + sigma1 + ch + K[i] + W[i]
var Ki = K[j]
var Kil = K[j + 1]
var ch = Ch(e, f, g)
var chl = Ch(el, fl, gl)
var t1l = hl + sigma1l
var t1 = h + sigma1h + ((t1l >>> 0) < (hl >>> 0) ? 1 : 0)
t1l = t1l + chl
t1 = t1 + ch + ((t1l >>> 0) < (chl >>> 0) ? 1 : 0)
t1l = t1l + Kil
t1 = t1 + Ki + ((t1l >>> 0) < (Kil >>> 0) ? 1 : 0)
t1l = t1l + Wil
t1 = t1 + Wi + ((t1l >>> 0) < (Wil >>> 0) ? 1 : 0)
// t2 = sigma0 + maj
var t2l = sigma0l + majl
var t2 = sigma0h + maj + ((t2l >>> 0) < (sigma0l >>> 0) ? 1 : 0)
h = g
hl = gl
g = f
gl = fl
f = e
fl = el
el = (dl + t1l) | 0
e = (d + t1 + ((el >>> 0) < (dl >>> 0) ? 1 : 0)) | 0
d = c
dl = cl
c = b
cl = bl
b = a
bl = al
al = (t1l + t2l) | 0
a = (t1 + t2 + ((al >>> 0) < (t1l >>> 0) ? 1 : 0)) | 0
i++
j += 2
}
while (i < 16) {
Wi = M.readInt32BE(j * 4)
Wil = M.readInt32BE(j * 4 + 4)
loop()
}
while (i < 80) {
calcW()
loop()
}
this._al = (this._al + al) | 0
this._bl = (this._bl + bl) | 0
this._cl = (this._cl + cl) | 0
this._dl = (this._dl + dl) | 0
this._el = (this._el + el) | 0
this._fl = (this._fl + fl) | 0
this._gl = (this._gl + gl) | 0
this._hl = (this._hl + hl) | 0
this._a = (this._a + a + ((this._al >>> 0) < (al >>> 0) ? 1 : 0)) | 0
this._b = (this._b + b + ((this._bl >>> 0) < (bl >>> 0) ? 1 : 0)) | 0
this._c = (this._c + c + ((this._cl >>> 0) < (cl >>> 0) ? 1 : 0)) | 0
this._d = (this._d + d + ((this._dl >>> 0) < (dl >>> 0) ? 1 : 0)) | 0
this._e = (this._e + e + ((this._el >>> 0) < (el >>> 0) ? 1 : 0)) | 0
this._f = (this._f + f + ((this._fl >>> 0) < (fl >>> 0) ? 1 : 0)) | 0
this._g = (this._g + g + ((this._gl >>> 0) < (gl >>> 0) ? 1 : 0)) | 0
this._h = (this._h + h + ((this._hl >>> 0) < (hl >>> 0) ? 1 : 0)) | 0
}
Sha512.prototype._hash = function () {
var H = new Buffer(64)
function writeInt64BE (h, l, offset) {
H.writeInt32BE(h, offset)
H.writeInt32BE(l, offset + 4)
}
writeInt64BE(this._a, this._al, 0)
writeInt64BE(this._b, this._bl, 8)
writeInt64BE(this._c, this._cl, 16)
writeInt64BE(this._d, this._dl, 24)
writeInt64BE(this._e, this._el, 32)
writeInt64BE(this._f, this._fl, 40)
writeInt64BE(this._g, this._gl, 48)
writeInt64BE(this._h, this._hl, 56)
return H
}
module.exports = Sha512
}).call(this,require("buffer").Buffer)
},{"./hash":175,"buffer":76,"inherits":223}],183:[function(require,module,exports){
(function (Buffer){
'use strict';
var createHash = require('create-hash/browser');
var inherits = require('inherits')
var Transform = require('stream').Transform
var ZEROS = new Buffer(128)
ZEROS.fill(0)
function Hmac(alg, key) {
Transform.call(this)
if (typeof key === 'string') {
key = new Buffer(key)
}
var blocksize = (alg === 'sha512' || alg === 'sha384') ? 128 : 64
this._alg = alg
this._key = key
if (key.length > blocksize) {
key = createHash(alg).update(key).digest()
} else if (key.length < blocksize) {
key = Buffer.concat([key, ZEROS], blocksize)
}
var ipad = this._ipad = new Buffer(blocksize)
var opad = this._opad = new Buffer(blocksize)
for (var i = 0; i < blocksize; i++) {
ipad[i] = key[i] ^ 0x36
opad[i] = key[i] ^ 0x5C
}
this._hash = createHash(alg).update(ipad)
}
inherits(Hmac, Transform)
Hmac.prototype.update = function (data, enc) {
this._hash.update(data, enc)
return this
}
Hmac.prototype._transform = function (data, _, next) {
this._hash.update(data)
next()
}
Hmac.prototype._flush = function (next) {
this.push(this.digest())
next()
}
Hmac.prototype.digest = function (enc) {
var h = this._hash.digest()
return createHash(this._alg).update(this._opad).update(h).digest(enc)
}
module.exports = function createHmac(alg, key) {
return new Hmac(alg, key)
}
}).call(this,require("buffer").Buffer)
},{"buffer":76,"create-hash/browser":171,"inherits":223,"stream":241}],184:[function(require,module,exports){
(function (Buffer){
var generatePrime = require('./lib/generatePrime');
var primes = require('./lib/primes');
var DH = require('./lib/dh');
function getDiffieHellman(mod) {
var prime = new Buffer(primes[mod].prime, 'hex');
var gen = new Buffer(primes[mod].gen, 'hex');
return new DH(prime, gen);
}
function createDiffieHellman(prime, enc, generator, genc) {
if (Buffer.isBuffer(enc) || (typeof enc === 'string' && ['hex', 'binary', 'base64'].indexOf(enc) === -1)) {
genc = generator;
generator = enc;
enc = undefined;
}
enc = enc || 'binary';
genc = genc || 'binary';
generator = generator || new Buffer([2]);
if (!Buffer.isBuffer(generator)) {
generator = new Buffer(generator, genc);
}
if (typeof prime === 'number') {
return new DH(generatePrime(prime, generator), generator, true);
}
if (!Buffer.isBuffer(prime)) {
prime = new Buffer(prime, enc);
}
return new DH(prime, generator, true);
}
exports.DiffieHellmanGroup = exports.createDiffieHellmanGroup = exports.getDiffieHellman = getDiffieHellman;
exports.createDiffieHellman = exports.DiffieHellman = createDiffieHellman;
}).call(this,require("buffer").Buffer)
},{"./lib/dh":185,"./lib/generatePrime":186,"./lib/primes":187,"buffer":76}],185:[function(require,module,exports){
(function (Buffer){
var BN = require('bn.js');
var MillerRabin = require('miller-rabin');
var millerRabin = new MillerRabin();
var TWENTYFOUR = new BN(24);
var ELEVEN = new BN(11);
var TEN = new BN(10);
var THREE = new BN(3);
var SEVEN = new BN(7);
var primes = require('./generatePrime');
var randomBytes = require('randombytes');
module.exports = DH;
function setPublicKey(pub, enc) {
enc = enc || 'utf8';
if (!Buffer.isBuffer(pub)) {
pub = new Buffer(pub, enc);
}
this._pub = new BN(pub);
return this;
}
function setPrivateKey(priv, enc) {
enc = enc || 'utf8';
if (!Buffer.isBuffer(priv)) {
priv = new Buffer(priv, enc);
}
this._priv = new BN(priv);
return this;
}
var primeCache = {};
function checkPrime(prime, generator) {
var gen = generator.toString('hex');
var hex = [gen, prime.toString(16)].join('_');
if (hex in primeCache) {
return primeCache[hex];
}
var error = 0;
if (prime.isEven() ||
!primes.simpleSieve ||
!primes.fermatTest(prime) ||
!millerRabin.test(prime)) {
//not a prime so +1
error += 1;
if (gen === '02' || gen === '05') {
// we'd be able to check the generator
// it would fail so +8
error += 8;
} else {
//we wouldn't be able to test the generator
// so +4
error += 4;
}
primeCache[hex] = error;
return error;
}
if (!millerRabin.test(prime.shrn(1))) {
//not a safe prime
error += 2;
}
var rem;
switch (gen) {
case '02':
if (prime.mod(TWENTYFOUR).cmp(ELEVEN)) {
// unsuidable generator
error += 8;
}
break;
case '05':
rem = prime.mod(TEN);
if (rem.cmp(THREE) && rem.cmp(SEVEN)) {
// prime mod 10 needs to equal 3 or 7
error += 8;
}
break;
default:
error += 4;
}
primeCache[hex] = error;
return error;
}
function defineError (self, error) {
try {
Object.defineProperty(self, 'verifyError', {
enumerable: true,
value: error,
writable: false
});
} catch(e) {
self.verifyError = error;
}
}
function DH(prime, generator, malleable) {
this.setGenerator(generator);
this.__prime = new BN(prime);
this._prime = BN.mont(this.__prime);
this._primeLen = prime.length;
this._pub = void 0;
this._priv = void 0;
if (malleable) {
this.setPublicKey = setPublicKey;
this.setPrivateKey = setPrivateKey;
defineError(this, checkPrime(this.__prime, generator));
} else {
defineError(this, 8);
}
}
DH.prototype.generateKeys = function () {
if (!this._priv) {
this._priv = new BN(randomBytes(this._primeLen));
}
this._pub = this._gen.toRed(this._prime).redPow(this._priv).fromRed();
return this.getPublicKey();
};
DH.prototype.computeSecret = function (other) {
other = new BN(other);
other = other.toRed(this._prime);
var secret = other.redPow(this._priv).fromRed();
var out = new Buffer(secret.toArray());
var prime = this.getPrime();
if (out.length < prime.length) {
var front = new Buffer(prime.length - out.length);
front.fill(0);
out = Buffer.concat([front, out]);
}
return out;
};
DH.prototype.getPublicKey = function getPublicKey(enc) {
return formatReturnValue(this._pub, enc);
};
DH.prototype.getPrivateKey = function getPrivateKey(enc) {
return formatReturnValue(this._priv, enc);
};
DH.prototype.getPrime = function (enc) {
return formatReturnValue(this.__prime, enc);
};
DH.prototype.getGenerator = function (enc) {
return formatReturnValue(this._gen, enc);
};
DH.prototype.setGenerator = function (gen, enc) {
enc = enc || 'utf8';
if (!Buffer.isBuffer(gen)) {
gen = new Buffer(gen, enc);
}
this._gen = new BN(gen);
return this;
};
function formatReturnValue(bn, enc) {
var buf = new Buffer(bn.toArray());
if (!enc) {
return buf;
} else {
return buf.toString(enc);
}
}
}).call(this,require("buffer").Buffer)
},{"./generatePrime":186,"bn.js":188,"buffer":76,"miller-rabin":189,"randombytes":221}],186:[function(require,module,exports){
var randomBytes = require('randombytes');
module.exports = findPrime;
findPrime.simpleSieve = simpleSieve;
findPrime.fermatTest = fermatTest;
var BN = require('bn.js');
var TWENTYFOUR = new BN(24);
var MillerRabin = require('miller-rabin');
var millerRabin = new MillerRabin();
var ONE = new BN(1);
var TWO = new BN(2);
var FIVE = new BN(5);
var SIXTEEN = new BN(16);
var EIGHT = new BN(8);
var TEN = new BN(10);
var THREE = new BN(3);
var SEVEN = new BN(7);
var ELEVEN = new BN(11);
var FOUR = new BN(4);
var TWELVE = new BN(12);
var primes = null;
function _getPrimes() {
if (primes !== null)
return primes;
var limit = 0x100000;
var res = [];
res[0] = 2;
for (var i = 1, k = 3; k < limit; k += 2) {
var sqrt = Math.ceil(Math.sqrt(k));
for (var j = 0; j < i && res[j] <= sqrt; j++)
if (k % res[j] === 0)
break;
if (i !== j && res[j] <= sqrt)
continue;
res[i++] = k;
}
primes = res;
return res;
}
function simpleSieve(p) {
var primes = _getPrimes();
for (var i = 0; i < primes.length; i++)
if (p.modn(primes[i]) === 0) {
if (p.cmpn(primes[i]) === 0) {
return true;
} else {
return false;
}
}
return true;
}
function fermatTest(p) {
var red = BN.mont(p);
return TWO.toRed(red).redPow(p.subn(1)).fromRed().cmpn(1) === 0;
}
function findPrime(bits, gen) {
if (bits < 16) {
// this is what openssl does
if (gen === 2 || gen === 5) {
return new BN([0x8c, 0x7b]);
} else {
return new BN([0x8c, 0x27]);
}
}
gen = new BN(gen);
var runs, comp;
function generateRandom(bits) {
runs = -1;
var out = new BN(randomBytes(Math.ceil(bits / 8)));
while (out.bitLength() > bits) {
out.ishrn(1);
}
if (out.isEven()) {
out.iadd(ONE);
}
if (!out.testn(1)) {
out.iadd(TWO);
}
if (!gen.cmp(TWO)) {
while (out.mod(TWENTYFOUR).cmp(ELEVEN)) {
out.iadd(FOUR);
}
comp = {
major: [TWENTYFOUR],
minor: [TWELVE]
};
} else if (!gen.cmp(FIVE)) {
rem = out.mod(TEN);
while (rem.cmp(THREE)) {
out.iadd(FOUR);
rem = out.mod(TEN);
}
comp = {
major: [FOUR, SIXTEEN],
minor: [TWO, EIGHT]
};
} else {
comp = {
major: [FOUR],
minor: [TWO]
};
}
return out;
}
var num = generateRandom(bits);
var n2 = num.shrn(1);
while (true) {
while (num.bitLength() > bits) {
num = generateRandom(bits);
n2 = num.shrn(1);
}
runs++;
if (simpleSieve(n2) && simpleSieve(num) &&
fermatTest(n2) && fermatTest(num) &&
millerRabin.test(n2) && millerRabin.test(num)) {
return num;
}
num.iadd(comp.major[runs%comp.major.length]);
n2.iadd(comp.minor[runs%comp.minor.length]);
}
}
},{"bn.js":188,"miller-rabin":189,"randombytes":221}],187:[function(require,module,exports){
module.exports={
"modp1": {
"gen": "02",
"prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a63a3620ffffffffffffffff"
},
"modp2": {
"gen": "02",
"prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece65381ffffffffffffffff"
},
"modp5": {
"gen": "02",
"prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca237327ffffffffffffffff"
},
"modp14": {
"gen": "02",
"prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aacaa68ffffffffffffffff"
},
"modp15": {
"gen": "02",
"prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a93ad2caffffffffffffffff"
},
"modp16": {
"gen": "02",
"prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c934063199ffffffffffffffff"
},
"modp17": {
"gen": "02",
"prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c93402849236c3fab4d27c7026c1d4dcb2602646dec9751e763dba37bdf8ff9406ad9e530ee5db382f413001aeb06a53ed9027d831179727b0865a8918da3edbebcf9b14ed44ce6cbaced4bb1bdb7f1447e6cc254b332051512bd7af426fb8f401378cd2bf5983ca01c64b92ecf032ea15d1721d03f482d7ce6e74fef6d55e702f46980c82b5a84031900b1c9e59e7c97fbec7e8f323a97a7e36cc88be0f1d45b7ff585ac54bd407b22b4154aacc8f6d7ebf48e1d814cc5ed20f8037e0a79715eef29be32806a1d58bb7c5da76f550aa3d8a1fbff0eb19ccb1a313d55cda56c9ec2ef29632387fe8d76e3c0468043e8f663f4860ee12bf2d5b0b7474d6e694f91e6dcc4024ffffffffffffffff"
},
"modp18": {
"gen": "02",
"prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c93402849236c3fab4d27c7026c1d4dcb2602646dec9751e763dba37bdf8ff9406ad9e530ee5db382f413001aeb06a53ed9027d831179727b0865a8918da3edbebcf9b14ed44ce6cbaced4bb1bdb7f1447e6cc254b332051512bd7af426fb8f401378cd2bf5983ca01c64b92ecf032ea15d1721d03f482d7ce6e74fef6d55e702f46980c82b5a84031900b1c9e59e7c97fbec7e8f323a97a7e36cc88be0f1d45b7ff585ac54bd407b22b4154aacc8f6d7ebf48e1d814cc5ed20f8037e0a79715eef29be32806a1d58bb7c5da76f550aa3d8a1fbff0eb19ccb1a313d55cda56c9ec2ef29632387fe8d76e3c0468043e8f663f4860ee12bf2d5b0b7474d6e694f91e6dbe115974a3926f12fee5e438777cb6a932df8cd8bec4d073b931ba3bc832b68d9dd300741fa7bf8afc47ed2576f6936ba424663aab639c5ae4f5683423b4742bf1c978238f16cbe39d652de3fdb8befc848ad922222e04a4037c0713eb57a81a23f0c73473fc646cea306b4bcbc8862f8385ddfa9d4b7fa2c087e879683303ed5bdd3a062b3cf5b3a278a66d2a13f83f44f82ddf310ee074ab6a364597e899a0255dc164f31cc50846851df9ab48195ded7ea1b1d510bd7ee74d73faf36bc31ecfa268359046f4eb879f924009438b481c6cd7889a002ed5ee382bc9190da6fc026e479558e4475677e9aa9e3050e2765694dfc81f56e880b96e7160c980dd98edd3dfffffffffffffffff"
}
}
},{}],188:[function(require,module,exports){
arguments[4][102][0].apply(exports,arguments)
},{"dup":102}],189:[function(require,module,exports){
var bn = require('bn.js');
var brorand = require('brorand');
function MillerRabin(rand) {
this.rand = rand || new brorand.Rand();
}
module.exports = MillerRabin;
MillerRabin.create = function create(rand) {
return new MillerRabin(rand);
};
MillerRabin.prototype._rand = function _rand(n) {
var len = n.bitLength();
var buf = this.rand.generate(Math.ceil(len / 8));
// Set low bits
buf[0] |= 3;
// Mask high bits
var mask = len & 0x7;
if (mask !== 0)
buf[buf.length - 1] >>= 7 - mask;
return new bn(buf);
}
MillerRabin.prototype.test = function test(n, k, cb) {
var len = n.bitLength();
var red = bn.mont(n);
var rone = new bn(1).toRed(red);
if (!k)
k = Math.max(1, (len / 48) | 0);
// Find d and s, (n - 1) = (2 ^ s) * d;
var n1 = n.subn(1);
var n2 = n1.subn(1);
for (var s = 0; !n1.testn(s); s++) {}
var d = n.shrn(s);
var rn1 = n1.toRed(red);
var prime = true;
for (; k > 0; k--) {
var a = this._rand(n2);
if (cb)
cb(a);
var x = a.toRed(red).redPow(d);
if (x.cmp(rone) === 0 || x.cmp(rn1) === 0)
continue;
for (var i = 1; i < s; i++) {
x = x.redSqr();
if (x.cmp(rone) === 0)
return false;
if (x.cmp(rn1) === 0)
break;
}
if (i === s)
return false;
}
return prime;
};
MillerRabin.prototype.getDivisor = function getDivisor(n, k) {
var len = n.bitLength();
var red = bn.mont(n);
var rone = new bn(1).toRed(red);
if (!k)
k = Math.max(1, (len / 48) | 0);
// Find d and s, (n - 1) = (2 ^ s) * d;
var n1 = n.subn(1);
var n2 = n1.subn(1);
for (var s = 0; !n1.testn(s); s++) {}
var d = n.shrn(s);
var rn1 = n1.toRed(red);
for (; k > 0; k--) {
var a = this._rand(n2);
var g = n.gcd(a);
if (g.cmpn(1) !== 0)
return g;
var x = a.toRed(red).redPow(d);
if (x.cmp(rone) === 0 || x.cmp(rn1) === 0)
continue;
for (var i = 1; i < s; i++) {
x = x.redSqr();
if (x.cmp(rone) === 0)
return x.fromRed().subn(1).gcd(n);
if (x.cmp(rn1) === 0)
break;
}
if (i === s) {
x = x.redSqr();
return x.fromRed().subn(1).gcd(n);
}
}
return false;
};
},{"bn.js":190,"brorand":191}],190:[function(require,module,exports){
(function (module, exports) {
'use strict';
// Utils
function assert(val, msg) {
if (!val)
throw new Error(msg || 'Assertion failed');
}
// Could use `inherits` module, but don't want to move from single file
// architecture yet.
function inherits(ctor, superCtor) {
ctor.super_ = superCtor;
var TempCtor = function () {};
TempCtor.prototype = superCtor.prototype;
ctor.prototype = new TempCtor();
ctor.prototype.constructor = ctor;
}
// BN
function BN(number, base, endian) {
// May be `new BN(bn)` ?
if (number !== null &&
typeof number === 'object' &&
Array.isArray(number.words)) {
return number;
}
this.sign = false;
this.words = null;
this.length = 0;
// Reduction context
this.red = null;
if (base === 'le' || base === 'be') {
endian = base;
base = 10;
}
if (number !== null)
this._init(number || 0, base || 10, endian || 'be');
}
if (typeof module === 'object')
module.exports = BN;
else
exports.BN = BN;
BN.BN = BN;
BN.wordSize = 26;
BN.prototype._init = function init(number, base, endian) {
if (typeof number === 'number') {
return this._initNumber(number, base, endian);
} else if (typeof number === 'object') {
return this._initArray(number, base, endian);
}
if (base === 'hex')
base = 16;
assert(base === (base | 0) && base >= 2 && base <= 36);
number = number.toString().replace(/\s+/g, '');
var start = 0;
if (number[0] === '-')
start++;
if (base === 16)
this._parseHex(number, start);
else
this._parseBase(number, base, start);
if (number[0] === '-')
this.sign = true;
this.strip();
if (endian !== 'le')
return;
this._initArray(this.toArray(), base, endian);
};
BN.prototype._initNumber = function _initNumber(number, base, endian) {
if (number < 0) {
this.sign = true;
number = -number;
}
if (number < 0x4000000) {
this.words = [ number & 0x3ffffff ];
this.length = 1;
} else if (number < 0x10000000000000) {
this.words = [
number & 0x3ffffff,
(number / 0x4000000) & 0x3ffffff
];
this.length = 2;
} else {
assert(number < 0x20000000000000); // 2 ^ 53 (unsafe)
this.words = [
number & 0x3ffffff,
(number / 0x4000000) & 0x3ffffff,
1
];
this.length = 3;
}
if (endian !== 'le')
return;
// Reverse the bytes
this._initArray(this.toArray(), base, endian);
};
BN.prototype._initArray = function _initArray(number, base, endian) {
// Perhaps a Uint8Array
assert(typeof number.length === 'number');
if (number.length <= 0) {
this.words = [ 0 ];
this.length = 1;
return this;
}
this.length = Math.ceil(number.length / 3);
this.words = new Array(this.length);
for (var i = 0; i < this.length; i++)
this.words[i] = 0;
var off = 0;
if (endian === 'be') {
for (var i = number.length - 1, j = 0; i >= 0; i -= 3) {
var w = number[i] | (number[i - 1] << 8) | (number[i - 2] << 16);
this.words[j] |= (w << off) & 0x3ffffff;
this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff;
off += 24;
if (off >= 26) {
off -= 26;
j++;
}
}
} else if (endian === 'le') {
for (var i = 0, j = 0; i < number.length; i += 3) {
var w = number[i] | (number[i + 1] << 8) | (number[i + 2] << 16);
this.words[j] |= (w << off) & 0x3ffffff;
this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff;
off += 24;
if (off >= 26) {
off -= 26;
j++;
}
}
}
return this.strip();
};
function parseHex(str, start, end) {
var r = 0;
var len = Math.min(str.length, end);
for (var i = start; i < len; i++) {
var c = str.charCodeAt(i) - 48;
r <<= 4;
// 'a' - 'f'
if (c >= 49 && c <= 54)
r |= c - 49 + 0xa;
// 'A' - 'F'
else if (c >= 17 && c <= 22)
r |= c - 17 + 0xa;
// '0' - '9'
else
r |= c & 0xf;
}
return r;
}
BN.prototype._parseHex = function _parseHex(number, start) {
// Create possibly bigger array to ensure that it fits the number
this.length = Math.ceil((number.length - start) / 6);
this.words = new Array(this.length);
for (var i = 0; i < this.length; i++)
this.words[i] = 0;
// Scan 24-bit chunks and add them to the number
var off = 0;
for (var i = number.length - 6, j = 0; i >= start; i -= 6) {
var w = parseHex(number, i, i + 6);
this.words[j] |= (w << off) & 0x3ffffff;
this.words[j + 1] |= w >>> (26 - off) & 0x3fffff;
off += 24;
if (off >= 26) {
off -= 26;
j++;
}
}
if (i + 6 !== start) {
var w = parseHex(number, start, i + 6);
this.words[j] |= (w << off) & 0x3ffffff;
this.words[j + 1] |= w >>> (26 - off) & 0x3fffff;
}
this.strip();
};
function parseBase(str, start, end, mul) {
var r = 0;
var len = Math.min(str.length, end);
for (var i = start; i < len; i++) {
var c = str.charCodeAt(i) - 48;
r *= mul;
// 'a'
if (c >= 49)
r += c - 49 + 0xa;
// 'A'
else if (c >= 17)
r += c - 17 + 0xa;
// '0' - '9'
else
r += c;
}
return r;
}
BN.prototype._parseBase = function _parseBase(number, base, start) {
// Initialize as zero
this.words = [ 0 ];
this.length = 1;
// Find length of limb in base
for (var limbLen = 0, limbPow = 1; limbPow <= 0x3ffffff; limbPow *= base)
limbLen++;
limbLen--;
limbPow = (limbPow / base) | 0;
var total = number.length - start;
var mod = total % limbLen;
var end = Math.min(total, total - mod) + start;
var word = 0;
for (var i = start; i < end; i += limbLen) {
word = parseBase(number, i, i + limbLen, base);
this.imuln(limbPow);
if (this.words[0] + word < 0x4000000)
this.words[0] += word;
else
this._iaddn(word);
}
if (mod !== 0) {
var pow = 1;
var word = parseBase(number, i, number.length, base);
for (var i = 0; i < mod; i++)
pow *= base;
this.imuln(pow);
if (this.words[0] + word < 0x4000000)
this.words[0] += word;
else
this._iaddn(word);
}
};
BN.prototype.copy = function copy(dest) {
dest.words = new Array(this.length);
for (var i = 0; i < this.length; i++)
dest.words[i] = this.words[i];
dest.length = this.length;
dest.sign = this.sign;
dest.red = this.red;
};
BN.prototype.clone = function clone() {
var r = new BN(null);
this.copy(r);
return r;
};
// Remove leading `0` from `this`
BN.prototype.strip = function strip() {
while (this.length > 1 && this.words[this.length - 1] === 0)
this.length--;
return this._normSign();
};
BN.prototype._normSign = function _normSign() {
// -0 = 0
if (this.length === 1 && this.words[0] === 0)
this.sign = false;
return this;
};
BN.prototype.inspect = function inspect() {
return (this.red ? '';
};
/*
var zeros = [];
var groupSizes = [];
var groupBases = [];
var s = '';
var i = -1;
while (++i < BN.wordSize) {
zeros[i] = s;
s += '0';
}
groupSizes[0] = 0;
groupSizes[1] = 0;
groupBases[0] = 0;
groupBases[1] = 0;
var base = 2 - 1;
while (++base < 36 + 1) {
var groupSize = 0;
var groupBase = 1;
while (groupBase < (1 << BN.wordSize) / base) {
groupBase *= base;
groupSize += 1;
}
groupSizes[base] = groupSize;
groupBases[base] = groupBase;
}
*/
var zeros = [
'',
'0',
'00',
'000',
'0000',
'00000',
'000000',
'0000000',
'00000000',
'000000000',
'0000000000',
'00000000000',
'000000000000',
'0000000000000',
'00000000000000',
'000000000000000',
'0000000000000000',
'00000000000000000',
'000000000000000000',
'0000000000000000000',
'00000000000000000000',
'000000000000000000000',
'0000000000000000000000',
'00000000000000000000000',
'000000000000000000000000',
'0000000000000000000000000'
];
var groupSizes = [
0, 0,
25, 16, 12, 11, 10, 9, 8,
8, 7, 7, 7, 7, 6, 6,
6, 6, 6, 6, 6, 5, 5,
5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5
];
var groupBases = [
0, 0,
33554432, 43046721, 16777216, 48828125, 60466176, 40353607, 16777216,
43046721, 10000000, 19487171, 35831808, 62748517, 7529536, 11390625,
16777216, 24137569, 34012224, 47045881, 64000000, 4084101, 5153632,
6436343, 7962624, 9765625, 11881376, 14348907, 17210368, 20511149,
24300000, 28629151, 33554432, 39135393, 45435424, 52521875, 60466176
];
BN.prototype.toString = function toString(base, padding) {
base = base || 10;
if (base === 16 || base === 'hex') {
var out = '';
var off = 0;
var padding = padding | 0 || 1;
var carry = 0;
for (var i = 0; i < this.length; i++) {
var w = this.words[i];
var word = (((w << off) | carry) & 0xffffff).toString(16);
carry = (w >>> (24 - off)) & 0xffffff;
if (carry !== 0 || i !== this.length - 1)
out = zeros[6 - word.length] + word + out;
else
out = word + out;
off += 2;
if (off >= 26) {
off -= 26;
i--;
}
}
if (carry !== 0)
out = carry.toString(16) + out;
while (out.length % padding !== 0)
out = '0' + out;
if (this.sign)
out = '-' + out;
return out;
} else if (base === (base | 0) && base >= 2 && base <= 36) {
// var groupSize = Math.floor(BN.wordSize * Math.LN2 / Math.log(base));
var groupSize = groupSizes[base];
// var groupBase = Math.pow(base, groupSize);
var groupBase = groupBases[base];
var out = '';
var c = this.clone();
c.sign = false;
while (c.cmpn(0) !== 0) {
var r = c.modn(groupBase).toString(base);
c = c.idivn(groupBase);
if (c.cmpn(0) !== 0)
out = zeros[groupSize - r.length] + r + out;
else
out = r + out;
}
if (this.cmpn(0) === 0)
out = '0' + out;
if (this.sign)
out = '-' + out;
return out;
} else {
assert(false, 'Base should be between 2 and 36');
}
};
BN.prototype.toJSON = function toJSON() {
return this.toString(16);
};
BN.prototype.toArray = function toArray(endian, length) {
this.strip();
var littleEndian = endian === 'le';
var res = new Array(this.byteLength());
res[0] = 0;
var q = this.clone();
if (!littleEndian) {
// Assume big-endian
for (var i = 0; q.cmpn(0) !== 0; i++) {
var b = q.andln(0xff);
q.iushrn(8);
res[res.length - i - 1] = b;
}
} else {
for (var i = 0; q.cmpn(0) !== 0; i++) {
var b = q.andln(0xff);
q.iushrn(8);
res[i] = b;
}
}
if (length) {
assert(res.length <= length, 'byte array longer than desired length');
while (res.length < length) {
if (littleEndian)
res.push(0);
else
res.unshift(0);
}
}
return res;
};
if (Math.clz32) {
BN.prototype._countBits = function _countBits(w) {
return 32 - Math.clz32(w);
};
} else {
BN.prototype._countBits = function _countBits(w) {
var t = w;
var r = 0;
if (t >= 0x1000) {
r += 13;
t >>>= 13;
}
if (t >= 0x40) {
r += 7;
t >>>= 7;
}
if (t >= 0x8) {
r += 4;
t >>>= 4;
}
if (t >= 0x02) {
r += 2;
t >>>= 2;
}
return r + t;
};
}
BN.prototype._zeroBits = function _zeroBits(w) {
// Short-cut
if (w === 0)
return 26;
var t = w;
var r = 0;
if ((t & 0x1fff) === 0) {
r += 13;
t >>>= 13;
}
if ((t & 0x7f) === 0) {
r += 7;
t >>>= 7;
}
if ((t & 0xf) === 0) {
r += 4;
t >>>= 4;
}
if ((t & 0x3) === 0) {
r += 2;
t >>>= 2;
}
if ((t & 0x1) === 0)
r++;
return r;
};
// Return number of used bits in a BN
BN.prototype.bitLength = function bitLength() {
var hi = 0;
var w = this.words[this.length - 1];
var hi = this._countBits(w);
return (this.length - 1) * 26 + hi;
};
// Number of trailing zero bits
BN.prototype.zeroBits = function zeroBits() {
if (this.cmpn(0) === 0)
return 0;
var r = 0;
for (var i = 0; i < this.length; i++) {
var b = this._zeroBits(this.words[i]);
r += b;
if (b !== 26)
break;
}
return r;
};
BN.prototype.byteLength = function byteLength() {
return Math.ceil(this.bitLength() / 8);
};
// Return negative clone of `this`
BN.prototype.neg = function neg() {
if (this.cmpn(0) === 0)
return this.clone();
var r = this.clone();
r.sign = !this.sign;
return r;
};
// Or `num` with `this` in-place
BN.prototype.iuor = function iuor(num) {
while (this.length < num.length)
this.words[this.length++] = 0;
for (var i = 0; i < num.length; i++)
this.words[i] = this.words[i] | num.words[i];
return this.strip();
};
BN.prototype.ior = function ior(num) {
assert(!this.sign && !num.sign);
return this.iuor(num);
};
// Or `num` with `this`
BN.prototype.or = function or(num) {
if (this.length > num.length)
return this.clone().ior(num);
else
return num.clone().ior(this);
};
BN.prototype.uor = function uor(num) {
if (this.length > num.length)
return this.clone().iuor(num);
else
return num.clone().iuor(this);
};
// And `num` with `this` in-place
BN.prototype.iuand = function iuand(num) {
// b = min-length(num, this)
var b;
if (this.length > num.length)
b = num;
else
b = this;
for (var i = 0; i < b.length; i++)
this.words[i] = this.words[i] & num.words[i];
this.length = b.length;
return this.strip();
};
BN.prototype.iand = function iand(num) {
assert(!this.sign && !num.sign);
return this.iuand(num);
};
// And `num` with `this`
BN.prototype.and = function and(num) {
if (this.length > num.length)
return this.clone().iand(num);
else
return num.clone().iand(this);
};
BN.prototype.uand = function uand(num) {
if (this.length > num.length)
return this.clone().iuand(num);
else
return num.clone().iuand(this);
};
// Xor `num` with `this` in-place
BN.prototype.iuxor = function iuxor(num) {
// a.length > b.length
var a;
var b;
if (this.length > num.length) {
a = this;
b = num;
} else {
a = num;
b = this;
}
for (var i = 0; i < b.length; i++)
this.words[i] = a.words[i] ^ b.words[i];
if (this !== a)
for (; i < a.length; i++)
this.words[i] = a.words[i];
this.length = a.length;
return this.strip();
};
BN.prototype.ixor = function ixor(num) {
assert(!this.sign && !num.sign);
return this.iuxor(num);
};
// Xor `num` with `this`
BN.prototype.xor = function xor(num) {
if (this.length > num.length)
return this.clone().ixor(num);
else
return num.clone().ixor(this);
};
BN.prototype.uxor = function uxor(num) {
if (this.length > num.length)
return this.clone().iuxor(num);
else
return num.clone().iuxor(this);
};
// Set `bit` of `this`
BN.prototype.setn = function setn(bit, val) {
assert(typeof bit === 'number' && bit >= 0);
var off = (bit / 26) | 0;
var wbit = bit % 26;
while (this.length <= off)
this.words[this.length++] = 0;
if (val)
this.words[off] = this.words[off] | (1 << wbit);
else
this.words[off] = this.words[off] & ~(1 << wbit);
return this.strip();
};
// Add `num` to `this` in-place
BN.prototype.iadd = function iadd(num) {
// negative + positive
if (this.sign && !num.sign) {
this.sign = false;
var r = this.isub(num);
this.sign = !this.sign;
return this._normSign();
// positive + negative
} else if (!this.sign && num.sign) {
num.sign = false;
var r = this.isub(num);
num.sign = true;
return r._normSign();
}
// a.length > b.length
var a;
var b;
if (this.length > num.length) {
a = this;
b = num;
} else {
a = num;
b = this;
}
var carry = 0;
for (var i = 0; i < b.length; i++) {
var r = a.words[i] + b.words[i] + carry;
this.words[i] = r & 0x3ffffff;
carry = r >>> 26;
}
for (; carry !== 0 && i < a.length; i++) {
var r = a.words[i] + carry;
this.words[i] = r & 0x3ffffff;
carry = r >>> 26;
}
this.length = a.length;
if (carry !== 0) {
this.words[this.length] = carry;
this.length++;
// Copy the rest of the words
} else if (a !== this) {
for (; i < a.length; i++)
this.words[i] = a.words[i];
}
return this;
};
// Add `num` to `this`
BN.prototype.add = function add(num) {
if (num.sign && !this.sign) {
num.sign = false;
var res = this.sub(num);
num.sign = true;
return res;
} else if (!num.sign && this.sign) {
this.sign = false;
var res = num.sub(this);
this.sign = true;
return res;
}
if (this.length > num.length)
return this.clone().iadd(num);
else
return num.clone().iadd(this);
};
// Subtract `num` from `this` in-place
BN.prototype.isub = function isub(num) {
// this - (-num) = this + num
if (num.sign) {
num.sign = false;
var r = this.iadd(num);
num.sign = true;
return r._normSign();
// -this - num = -(this + num)
} else if (this.sign) {
this.sign = false;
this.iadd(num);
this.sign = true;
return this._normSign();
}
// At this point both numbers are positive
var cmp = this.cmp(num);
// Optimization - zeroify
if (cmp === 0) {
this.sign = false;
this.length = 1;
this.words[0] = 0;
return this;
}
// a > b
var a;
var b;
if (cmp > 0) {
a = this;
b = num;
} else {
a = num;
b = this;
}
var carry = 0;
for (var i = 0; i < b.length; i++) {
var r = a.words[i] - b.words[i] + carry;
carry = r >> 26;
this.words[i] = r & 0x3ffffff;
}
for (; carry !== 0 && i < a.length; i++) {
var r = a.words[i] + carry;
carry = r >> 26;
this.words[i] = r & 0x3ffffff;
}
// Copy rest of the words
if (carry === 0 && i < a.length && a !== this)
for (; i < a.length; i++)
this.words[i] = a.words[i];
this.length = Math.max(this.length, i);
if (a !== this)
this.sign = true;
return this.strip();
};
// Subtract `num` from `this`
BN.prototype.sub = function sub(num) {
return this.clone().isub(num);
};
/*
// NOTE: This could be potentionally used to generate loop-less multiplications
function _genCombMulTo(alen, blen) {
var len = alen + blen - 1;
var src = [
'var a = this.words, b = num.words, o = out.words, c = 0, w, ' +
'mask = 0x3ffffff, shift = 0x4000000;',
'out.length = ' + len + ';'
];
for (var k = 0; k < len; k++) {
var minJ = Math.max(0, k - alen + 1);
var maxJ = Math.min(k, blen - 1);
for (var j = minJ; j <= maxJ; j++) {
var i = k - j;
var mul = 'a[' + i + '] * b[' + j + ']';
if (j === minJ) {
src.push('w = ' + mul + ' + c;');
src.push('c = (w / shift) | 0;');
} else {
src.push('w += ' + mul + ';');
src.push('c += (w / shift) | 0;');
}
src.push('w &= mask;');
}
src.push('o[' + k + '] = w;');
}
src.push('if (c !== 0) {',
' o[' + k + '] = c;',
' out.length++;',
'}',
'return out;');
return src.join('\n');
}
*/
BN.prototype._smallMulTo = function _smallMulTo(num, out) {
out.sign = num.sign !== this.sign;
out.length = this.length + num.length;
var carry = 0;
for (var k = 0; k < out.length - 1; k++) {
// Sum all words with the same `i + j = k` and accumulate `ncarry`,
// note that ncarry could be >= 0x3ffffff
var ncarry = carry >>> 26;
var rword = carry & 0x3ffffff;
var maxJ = Math.min(k, num.length - 1);
for (var j = Math.max(0, k - this.length + 1); j <= maxJ; j++) {
var i = k - j;
var a = this.words[i] | 0;
var b = num.words[j] | 0;
var r = a * b;
var lo = r & 0x3ffffff;
ncarry = (ncarry + ((r / 0x4000000) | 0)) | 0;
lo = (lo + rword) | 0;
rword = lo & 0x3ffffff;
ncarry = (ncarry + (lo >>> 26)) | 0;
}
out.words[k] = rword;
carry = ncarry;
}
if (carry !== 0) {
out.words[k] = carry;
} else {
out.length--;
}
return out.strip();
};
BN.prototype._bigMulTo = function _bigMulTo(num, out) {
out.sign = num.sign !== this.sign;
out.length = this.length + num.length;
var carry = 0;
var hncarry = 0;
for (var k = 0; k < out.length - 1; k++) {
// Sum all words with the same `i + j = k` and accumulate `ncarry`,
// note that ncarry could be >= 0x3ffffff
var ncarry = hncarry;
hncarry = 0;
var rword = carry & 0x3ffffff;
var maxJ = Math.min(k, num.length - 1);
for (var j = Math.max(0, k - this.length + 1); j <= maxJ; j++) {
var i = k - j;
var a = this.words[i] | 0;
var b = num.words[j] | 0;
var r = a * b;
var lo = r & 0x3ffffff;
ncarry = (ncarry + ((r / 0x4000000) | 0)) | 0;
lo = (lo + rword) | 0;
rword = lo & 0x3ffffff;
ncarry = (ncarry + (lo >>> 26)) | 0;
hncarry += ncarry >>> 26;
ncarry &= 0x3ffffff;
}
out.words[k] = rword;
carry = ncarry;
ncarry = hncarry;
}
if (carry !== 0) {
out.words[k] = carry;
} else {
out.length--;
}
return out.strip();
};
BN.prototype.mulTo = function mulTo(num, out) {
var res;
if (this.length + num.length < 63)
res = this._smallMulTo(num, out);
else
res = this._bigMulTo(num, out);
return res;
};
// Multiply `this` by `num`
BN.prototype.mul = function mul(num) {
var out = new BN(null);
out.words = new Array(this.length + num.length);
return this.mulTo(num, out);
};
// In-place Multiplication
BN.prototype.imul = function imul(num) {
if (this.cmpn(0) === 0 || num.cmpn(0) === 0) {
this.words[0] = 0;
this.length = 1;
return this;
}
var tlen = this.length;
var nlen = num.length;
this.sign = num.sign !== this.sign;
this.length = this.length + num.length;
this.words[this.length - 1] = 0;
for (var k = this.length - 2; k >= 0; k--) {
// Sum all words with the same `i + j = k` and accumulate `carry`,
// note that carry could be >= 0x3ffffff
var carry = 0;
var rword = 0;
var maxJ = Math.min(k, nlen - 1);
for (var j = Math.max(0, k - tlen + 1); j <= maxJ; j++) {
var i = k - j;
var a = this.words[i];
var b = num.words[j];
var r = a * b;
var lo = r & 0x3ffffff;
carry += (r / 0x4000000) | 0;
lo += rword;
rword = lo & 0x3ffffff;
carry += lo >>> 26;
}
this.words[k] = rword;
this.words[k + 1] += carry;
carry = 0;
}
// Propagate overflows
var carry = 0;
for (var i = 1; i < this.length; i++) {
var w = this.words[i] + carry;
this.words[i] = w & 0x3ffffff;
carry = w >>> 26;
}
return this.strip();
};
BN.prototype.imuln = function imuln(num) {
assert(typeof num === 'number');
// Carry
var carry = 0;
for (var i = 0; i < this.length; i++) {
var w = this.words[i] * num;
var lo = (w & 0x3ffffff) + (carry & 0x3ffffff);
carry >>= 26;
carry += (w / 0x4000000) | 0;
// NOTE: lo is 27bit maximum
carry += lo >>> 26;
this.words[i] = lo & 0x3ffffff;
}
if (carry !== 0) {
this.words[i] = carry;
this.length++;
}
return this;
};
BN.prototype.muln = function muln(num) {
return this.clone().imuln(num);
};
// `this` * `this`
BN.prototype.sqr = function sqr() {
return this.mul(this);
};
// `this` * `this` in-place
BN.prototype.isqr = function isqr() {
return this.mul(this);
};
// Shift-left in-place
BN.prototype.iushln = function iushln(bits) {
assert(typeof bits === 'number' && bits >= 0);
var r = bits % 26;
var s = (bits - r) / 26;
var carryMask = (0x3ffffff >>> (26 - r)) << (26 - r);
if (r !== 0) {
var carry = 0;
for (var i = 0; i < this.length; i++) {
var newCarry = this.words[i] & carryMask;
var c = (this.words[i] - newCarry) << r;
this.words[i] = c | carry;
carry = newCarry >>> (26 - r);
}
if (carry) {
this.words[i] = carry;
this.length++;
}
}
if (s !== 0) {
for (var i = this.length - 1; i >= 0; i--)
this.words[i + s] = this.words[i];
for (var i = 0; i < s; i++)
this.words[i] = 0;
this.length += s;
}
return this.strip();
};
BN.prototype.ishln = function ishln(bits) {
// TODO(indutny): implement me
assert(!this.sign);
return this.iushln(bits);
};
// Shift-right in-place
// NOTE: `hint` is a lowest bit before trailing zeroes
// NOTE: if `extended` is present - it will be filled with destroyed bits
BN.prototype.iushrn = function iushrn(bits, hint, extended) {
assert(typeof bits === 'number' && bits >= 0);
var h;
if (hint)
h = (hint - (hint % 26)) / 26;
else
h = 0;
var r = bits % 26;
var s = Math.min((bits - r) / 26, this.length);
var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r);
var maskedWords = extended;
h -= s;
h = Math.max(0, h);
// Extended mode, copy masked part
if (maskedWords) {
for (var i = 0; i < s; i++)
maskedWords.words[i] = this.words[i];
maskedWords.length = s;
}
if (s === 0) {
// No-op, we should not move anything at all
} else if (this.length > s) {
this.length -= s;
for (var i = 0; i < this.length; i++)
this.words[i] = this.words[i + s];
} else {
this.words[0] = 0;
this.length = 1;
}
var carry = 0;
for (var i = this.length - 1; i >= 0 && (carry !== 0 || i >= h); i--) {
var word = this.words[i];
this.words[i] = (carry << (26 - r)) | (word >>> r);
carry = word & mask;
}
// Push carried bits as a mask
if (maskedWords && carry !== 0)
maskedWords.words[maskedWords.length++] = carry;
if (this.length === 0) {
this.words[0] = 0;
this.length = 1;
}
this.strip();
return this;
};
BN.prototype.ishrn = function ishrn(bits, hint, extended) {
// TODO(indutny): implement me
assert(!this.sign);
return this.iushrn(bits, hint, extended);
};
// Shift-left
BN.prototype.shln = function shln(bits) {
return this.clone().ishln(bits);
};
BN.prototype.ushln = function ushln(bits) {
return this.clone().iushln(bits);
};
// Shift-right
BN.prototype.shrn = function shrn(bits) {
return this.clone().ishrn(bits);
};
BN.prototype.ushrn = function ushrn(bits) {
return this.clone().iushrn(bits);
};
// Test if n bit is set
BN.prototype.testn = function testn(bit) {
assert(typeof bit === 'number' && bit >= 0);
var r = bit % 26;
var s = (bit - r) / 26;
var q = 1 << r;
// Fast case: bit is much higher than all existing words
if (this.length <= s) {
return false;
}
// Check bit and return
var w = this.words[s];
return !!(w & q);
};
// Return only lowers bits of number (in-place)
BN.prototype.imaskn = function imaskn(bits) {
assert(typeof bits === 'number' && bits >= 0);
var r = bits % 26;
var s = (bits - r) / 26;
assert(!this.sign, 'imaskn works only with positive numbers');
if (r !== 0)
s++;
this.length = Math.min(s, this.length);
if (r !== 0) {
var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r);
this.words[this.length - 1] &= mask;
}
return this.strip();
};
// Return only lowers bits of number
BN.prototype.maskn = function maskn(bits) {
return this.clone().imaskn(bits);
};
// Add plain number `num` to `this`
BN.prototype.iaddn = function iaddn(num) {
assert(typeof num === 'number');
if (num < 0)
return this.isubn(-num);
// Possible sign change
if (this.sign) {
if (this.length === 1 && this.words[0] < num) {
this.words[0] = num - this.words[0];
this.sign = false;
return this;
}
this.sign = false;
this.isubn(num);
this.sign = true;
return this;
}
// Add without checks
return this._iaddn(num);
};
BN.prototype._iaddn = function _iaddn(num) {
this.words[0] += num;
// Carry
for (var i = 0; i < this.length && this.words[i] >= 0x4000000; i++) {
this.words[i] -= 0x4000000;
if (i === this.length - 1)
this.words[i + 1] = 1;
else
this.words[i + 1]++;
}
this.length = Math.max(this.length, i + 1);
return this;
};
// Subtract plain number `num` from `this`
BN.prototype.isubn = function isubn(num) {
assert(typeof num === 'number');
if (num < 0)
return this.iaddn(-num);
if (this.sign) {
this.sign = false;
this.iaddn(num);
this.sign = true;
return this;
}
this.words[0] -= num;
// Carry
for (var i = 0; i < this.length && this.words[i] < 0; i++) {
this.words[i] += 0x4000000;
this.words[i + 1] -= 1;
}
return this.strip();
};
BN.prototype.addn = function addn(num) {
return this.clone().iaddn(num);
};
BN.prototype.subn = function subn(num) {
return this.clone().isubn(num);
};
BN.prototype.iabs = function iabs() {
this.sign = false;
return this;
};
BN.prototype.abs = function abs() {
return this.clone().iabs();
};
BN.prototype._ishlnsubmul = function _ishlnsubmul(num, mul, shift) {
// Bigger storage is needed
var len = num.length + shift;
var i;
if (this.words.length < len) {
var t = new Array(len);
for (var i = 0; i < this.length; i++)
t[i] = this.words[i];
this.words = t;
} else {
i = this.length;
}
// Zeroify rest
this.length = Math.max(this.length, len);
for (; i < this.length; i++)
this.words[i] = 0;
var carry = 0;
for (var i = 0; i < num.length; i++) {
var w = this.words[i + shift] + carry;
var right = num.words[i] * mul;
w -= right & 0x3ffffff;
carry = (w >> 26) - ((right / 0x4000000) | 0);
this.words[i + shift] = w & 0x3ffffff;
}
for (; i < this.length - shift; i++) {
var w = this.words[i + shift] + carry;
carry = w >> 26;
this.words[i + shift] = w & 0x3ffffff;
}
if (carry === 0)
return this.strip();
// Subtraction overflow
assert(carry === -1);
carry = 0;
for (var i = 0; i < this.length; i++) {
var w = -this.words[i] + carry;
carry = w >> 26;
this.words[i] = w & 0x3ffffff;
}
this.sign = true;
return this.strip();
};
BN.prototype._wordDiv = function _wordDiv(num, mode) {
var shift = this.length - num.length;
var a = this.clone();
var b = num;
// Normalize
var bhi = b.words[b.length - 1];
var bhiBits = this._countBits(bhi);
shift = 26 - bhiBits;
if (shift !== 0) {
b = b.ushln(shift);
a.iushln(shift);
bhi = b.words[b.length - 1];
}
// Initialize quotient
var m = a.length - b.length;
var q;
if (mode !== 'mod') {
q = new BN(null);
q.length = m + 1;
q.words = new Array(q.length);
for (var i = 0; i < q.length; i++)
q.words[i] = 0;
}
var diff = a.clone()._ishlnsubmul(b, 1, m);
if (!diff.sign) {
a = diff;
if (q)
q.words[m] = 1;
}
for (var j = m - 1; j >= 0; j--) {
var qj = a.words[b.length + j] * 0x4000000 + a.words[b.length + j - 1];
// NOTE: (qj / bhi) is (0x3ffffff * 0x4000000 + 0x3ffffff) / 0x2000000 max
// (0x7ffffff)
qj = Math.min((qj / bhi) | 0, 0x3ffffff);
a._ishlnsubmul(b, qj, j);
while (a.sign) {
qj--;
a.sign = false;
a._ishlnsubmul(b, 1, j);
if (a.cmpn(0) !== 0)
a.sign = !a.sign;
}
if (q)
q.words[j] = qj;
}
if (q)
q.strip();
a.strip();
// Denormalize
if (mode !== 'div' && shift !== 0)
a.iushrn(shift);
return { div: q ? q : null, mod: a };
};
BN.prototype.divmod = function divmod(num, mode, positive) {
assert(num.cmpn(0) !== 0);
if (this.sign && !num.sign) {
var res = this.neg().divmod(num, mode);
var div;
var mod;
if (mode !== 'mod')
div = res.div.neg();
if (mode !== 'div') {
mod = res.mod.neg();
if (positive && mod.neg)
mod = mod.add(num);
}
return {
div: div,
mod: mod
};
} else if (!this.sign && num.sign) {
var res = this.divmod(num.neg(), mode);
var div;
if (mode !== 'mod')
div = res.div.neg();
return { div: div, mod: res.mod };
} else if (this.sign && num.sign) {
var res = this.neg().divmod(num.neg(), mode);
var mod;
if (mode !== 'div') {
mod = res.mod.neg();
if (positive && mod.neg)
mod = mod.isub(num);
}
return {
div: res.div,
mod: mod
};
}
// Both numbers are positive at this point
// Strip both numbers to approximate shift value
if (num.length > this.length || this.cmp(num) < 0)
return { div: new BN(0), mod: this };
// Very short reduction
if (num.length === 1) {
if (mode === 'div')
return { div: this.divn(num.words[0]), mod: null };
else if (mode === 'mod')
return { div: null, mod: new BN(this.modn(num.words[0])) };
return {
div: this.divn(num.words[0]),
mod: new BN(this.modn(num.words[0]))
};
}
return this._wordDiv(num, mode);
};
// Find `this` / `num`
BN.prototype.div = function div(num) {
return this.divmod(num, 'div', false).div;
};
// Find `this` % `num`
BN.prototype.mod = function mod(num) {
return this.divmod(num, 'mod', false).mod;
};
BN.prototype.umod = function umod(num) {
return this.divmod(num, 'mod', true).mod;
};
// Find Round(`this` / `num`)
BN.prototype.divRound = function divRound(num) {
var dm = this.divmod(num);
// Fast case - exact division
if (dm.mod.cmpn(0) === 0)
return dm.div;
var mod = dm.div.sign ? dm.mod.isub(num) : dm.mod;
var half = num.ushrn(1);
var r2 = num.andln(1);
var cmp = mod.cmp(half);
// Round down
if (cmp < 0 || r2 === 1 && cmp === 0)
return dm.div;
// Round up
return dm.div.sign ? dm.div.isubn(1) : dm.div.iaddn(1);
};
BN.prototype.modn = function modn(num) {
assert(num <= 0x3ffffff);
var p = (1 << 26) % num;
var acc = 0;
for (var i = this.length - 1; i >= 0; i--)
acc = (p * acc + this.words[i]) % num;
return acc;
};
// In-place division by number
BN.prototype.idivn = function idivn(num) {
assert(num <= 0x3ffffff);
var carry = 0;
for (var i = this.length - 1; i >= 0; i--) {
var w = this.words[i] + carry * 0x4000000;
this.words[i] = (w / num) | 0;
carry = w % num;
}
return this.strip();
};
BN.prototype.divn = function divn(num) {
return this.clone().idivn(num);
};
BN.prototype.egcd = function egcd(p) {
assert(!p.sign);
assert(p.cmpn(0) !== 0);
var x = this;
var y = p.clone();
if (x.sign)
x = x.umod(p);
else
x = x.clone();
// A * x + B * y = x
var A = new BN(1);
var B = new BN(0);
// C * x + D * y = y
var C = new BN(0);
var D = new BN(1);
var g = 0;
while (x.isEven() && y.isEven()) {
x.iushrn(1);
y.iushrn(1);
++g;
}
var yp = y.clone();
var xp = x.clone();
while (x.cmpn(0) !== 0) {
while (x.isEven()) {
x.iushrn(1);
if (A.isEven() && B.isEven()) {
A.iushrn(1);
B.iushrn(1);
} else {
A.iadd(yp).iushrn(1);
B.isub(xp).iushrn(1);
}
}
while (y.isEven()) {
y.iushrn(1);
if (C.isEven() && D.isEven()) {
C.iushrn(1);
D.iushrn(1);
} else {
C.iadd(yp).iushrn(1);
D.isub(xp).iushrn(1);
}
}
if (x.cmp(y) >= 0) {
x.isub(y);
A.isub(C);
B.isub(D);
} else {
y.isub(x);
C.isub(A);
D.isub(B);
}
}
return {
a: C,
b: D,
gcd: y.iushln(g)
};
};
// This is reduced incarnation of the binary EEA
// above, designated to invert members of the
// _prime_ fields F(p) at a maximal speed
BN.prototype._invmp = function _invmp(p) {
assert(!p.sign);
assert(p.cmpn(0) !== 0);
var a = this;
var b = p.clone();
if (a.sign)
a = a.umod(p);
else
a = a.clone();
var x1 = new BN(1);
var x2 = new BN(0);
var delta = b.clone();
while (a.cmpn(1) > 0 && b.cmpn(1) > 0) {
while (a.isEven()) {
a.iushrn(1);
if (x1.isEven())
x1.iushrn(1);
else
x1.iadd(delta).iushrn(1);
}
while (b.isEven()) {
b.iushrn(1);
if (x2.isEven())
x2.iushrn(1);
else
x2.iadd(delta).iushrn(1);
}
if (a.cmp(b) >= 0) {
a.isub(b);
x1.isub(x2);
} else {
b.isub(a);
x2.isub(x1);
}
}
var res;
if (a.cmpn(1) === 0)
res = x1;
else
res = x2;
if (res.cmpn(0) < 0)
res.iadd(p);
return res;
};
BN.prototype.gcd = function gcd(num) {
if (this.cmpn(0) === 0)
return num.clone();
if (num.cmpn(0) === 0)
return this.clone();
var a = this.clone();
var b = num.clone();
a.sign = false;
b.sign = false;
// Remove common factor of two
for (var shift = 0; a.isEven() && b.isEven(); shift++) {
a.iushrn(1);
b.iushrn(1);
}
do {
while (a.isEven())
a.iushrn(1);
while (b.isEven())
b.iushrn(1);
var r = a.cmp(b);
if (r < 0) {
// Swap `a` and `b` to make `a` always bigger than `b`
var t = a;
a = b;
b = t;
} else if (r === 0 || b.cmpn(1) === 0) {
break;
}
a.isub(b);
} while (true);
return b.iushln(shift);
};
// Invert number in the field F(num)
BN.prototype.invm = function invm(num) {
return this.egcd(num).a.umod(num);
};
BN.prototype.isEven = function isEven() {
return (this.words[0] & 1) === 0;
};
BN.prototype.isOdd = function isOdd() {
return (this.words[0] & 1) === 1;
};
// And first word and num
BN.prototype.andln = function andln(num) {
return this.words[0] & num;
};
// Increment at the bit position in-line
BN.prototype.bincn = function bincn(bit) {
assert(typeof bit === 'number');
var r = bit % 26;
var s = (bit - r) / 26;
var q = 1 << r;
// Fast case: bit is much higher than all existing words
if (this.length <= s) {
for (var i = this.length; i < s + 1; i++)
this.words[i] = 0;
this.words[s] |= q;
this.length = s + 1;
return this;
}
// Add bit and propagate, if needed
var carry = q;
for (var i = s; carry !== 0 && i < this.length; i++) {
var w = this.words[i];
w += carry;
carry = w >>> 26;
w &= 0x3ffffff;
this.words[i] = w;
}
if (carry !== 0) {
this.words[i] = carry;
this.length++;
}
return this;
};
BN.prototype.cmpn = function cmpn(num) {
var sign = num < 0;
if (sign)
num = -num;
if (this.sign && !sign)
return -1;
else if (!this.sign && sign)
return 1;
num &= 0x3ffffff;
this.strip();
var res;
if (this.length > 1) {
res = 1;
} else {
var w = this.words[0];
res = w === num ? 0 : w < num ? -1 : 1;
}
if (this.sign)
res = -res;
return res;
};
// Compare two numbers and return:
// 1 - if `this` > `num`
// 0 - if `this` == `num`
// -1 - if `this` < `num`
BN.prototype.cmp = function cmp(num) {
if (this.sign && !num.sign)
return -1;
else if (!this.sign && num.sign)
return 1;
var res = this.ucmp(num);
if (this.sign)
return -res;
else
return res;
};
// Unsigned comparison
BN.prototype.ucmp = function ucmp(num) {
// At this point both numbers have the same sign
if (this.length > num.length)
return 1;
else if (this.length < num.length)
return -1;
var res = 0;
for (var i = this.length - 1; i >= 0; i--) {
var a = this.words[i];
var b = num.words[i];
if (a === b)
continue;
if (a < b)
res = -1;
else if (a > b)
res = 1;
break;
}
return res;
};
//
// A reduce context, could be using montgomery or something better, depending
// on the `m` itself.
//
BN.red = function red(num) {
return new Red(num);
};
BN.prototype.toRed = function toRed(ctx) {
assert(!this.red, 'Already a number in reduction context');
assert(!this.sign, 'red works only with positives');
return ctx.convertTo(this)._forceRed(ctx);
};
BN.prototype.fromRed = function fromRed() {
assert(this.red, 'fromRed works only with numbers in reduction context');
return this.red.convertFrom(this);
};
BN.prototype._forceRed = function _forceRed(ctx) {
this.red = ctx;
return this;
};
BN.prototype.forceRed = function forceRed(ctx) {
assert(!this.red, 'Already a number in reduction context');
return this._forceRed(ctx);
};
BN.prototype.redAdd = function redAdd(num) {
assert(this.red, 'redAdd works only with red numbers');
return this.red.add(this, num);
};
BN.prototype.redIAdd = function redIAdd(num) {
assert(this.red, 'redIAdd works only with red numbers');
return this.red.iadd(this, num);
};
BN.prototype.redSub = function redSub(num) {
assert(this.red, 'redSub works only with red numbers');
return this.red.sub(this, num);
};
BN.prototype.redISub = function redISub(num) {
assert(this.red, 'redISub works only with red numbers');
return this.red.isub(this, num);
};
BN.prototype.redShl = function redShl(num) {
assert(this.red, 'redShl works only with red numbers');
return this.red.ushl(this, num);
};
BN.prototype.redMul = function redMul(num) {
assert(this.red, 'redMul works only with red numbers');
this.red._verify2(this, num);
return this.red.mul(this, num);
};
BN.prototype.redIMul = function redIMul(num) {
assert(this.red, 'redMul works only with red numbers');
this.red._verify2(this, num);
return this.red.imul(this, num);
};
BN.prototype.redSqr = function redSqr() {
assert(this.red, 'redSqr works only with red numbers');
this.red._verify1(this);
return this.red.sqr(this);
};
BN.prototype.redISqr = function redISqr() {
assert(this.red, 'redISqr works only with red numbers');
this.red._verify1(this);
return this.red.isqr(this);
};
// Square root over p
BN.prototype.redSqrt = function redSqrt() {
assert(this.red, 'redSqrt works only with red numbers');
this.red._verify1(this);
return this.red.sqrt(this);
};
BN.prototype.redInvm = function redInvm() {
assert(this.red, 'redInvm works only with red numbers');
this.red._verify1(this);
return this.red.invm(this);
};
// Return negative clone of `this` % `red modulo`
BN.prototype.redNeg = function redNeg() {
assert(this.red, 'redNeg works only with red numbers');
this.red._verify1(this);
return this.red.neg(this);
};
BN.prototype.redPow = function redPow(num) {
assert(this.red && !num.red, 'redPow(normalNum)');
this.red._verify1(this);
return this.red.pow(this, num);
};
// Prime numbers with efficient reduction
var primes = {
k256: null,
p224: null,
p192: null,
p25519: null
};
// Pseudo-Mersenne prime
function MPrime(name, p) {
// P = 2 ^ N - K
this.name = name;
this.p = new BN(p, 16);
this.n = this.p.bitLength();
this.k = new BN(1).iushln(this.n).isub(this.p);
this.tmp = this._tmp();
}
MPrime.prototype._tmp = function _tmp() {
var tmp = new BN(null);
tmp.words = new Array(Math.ceil(this.n / 13));
return tmp;
};
MPrime.prototype.ireduce = function ireduce(num) {
// Assumes that `num` is less than `P^2`
// num = HI * (2 ^ N - K) + HI * K + LO = HI * K + LO (mod P)
var r = num;
var rlen;
do {
this.split(r, this.tmp);
r = this.imulK(r);
r = r.iadd(this.tmp);
rlen = r.bitLength();
} while (rlen > this.n);
var cmp = rlen < this.n ? -1 : r.ucmp(this.p);
if (cmp === 0) {
r.words[0] = 0;
r.length = 1;
} else if (cmp > 0) {
r.isub(this.p);
} else {
r.strip();
}
return r;
};
MPrime.prototype.split = function split(input, out) {
input.iushrn(this.n, 0, out);
};
MPrime.prototype.imulK = function imulK(num) {
return num.imul(this.k);
};
function K256() {
MPrime.call(
this,
'k256',
'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f');
}
inherits(K256, MPrime);
K256.prototype.split = function split(input, output) {
// 256 = 9 * 26 + 22
var mask = 0x3fffff;
var outLen = Math.min(input.length, 9);
for (var i = 0; i < outLen; i++)
output.words[i] = input.words[i];
output.length = outLen;
if (input.length <= 9) {
input.words[0] = 0;
input.length = 1;
return;
}
// Shift by 9 limbs
var prev = input.words[9];
output.words[output.length++] = prev & mask;
for (var i = 10; i < input.length; i++) {
var next = input.words[i];
input.words[i - 10] = ((next & mask) << 4) | (prev >>> 22);
prev = next;
}
input.words[i - 10] = prev >>> 22;
input.length -= 9;
};
K256.prototype.imulK = function imulK(num) {
// K = 0x1000003d1 = [ 0x40, 0x3d1 ]
num.words[num.length] = 0;
num.words[num.length + 1] = 0;
num.length += 2;
// bounded at: 0x40 * 0x3ffffff + 0x3d0 = 0x100000390
var hi;
var lo = 0;
for (var i = 0; i < num.length; i++) {
var w = num.words[i];
hi = w * 0x40;
lo += w * 0x3d1;
hi += (lo / 0x4000000) | 0;
lo &= 0x3ffffff;
num.words[i] = lo;
lo = hi;
}
// Fast length reduction
if (num.words[num.length - 1] === 0) {
num.length--;
if (num.words[num.length - 1] === 0)
num.length--;
}
return num;
};
function P224() {
MPrime.call(
this,
'p224',
'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001');
}
inherits(P224, MPrime);
function P192() {
MPrime.call(
this,
'p192',
'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff');
}
inherits(P192, MPrime);
function P25519() {
// 2 ^ 255 - 19
MPrime.call(
this,
'25519',
'7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed');
}
inherits(P25519, MPrime);
P25519.prototype.imulK = function imulK(num) {
// K = 0x13
var carry = 0;
for (var i = 0; i < num.length; i++) {
var hi = num.words[i] * 0x13 + carry;
var lo = hi & 0x3ffffff;
hi >>>= 26;
num.words[i] = lo;
carry = hi;
}
if (carry !== 0)
num.words[num.length++] = carry;
return num;
};
// Exported mostly for testing purposes, use plain name instead
BN._prime = function prime(name) {
// Cached version of prime
if (primes[name])
return primes[name];
var prime;
if (name === 'k256')
prime = new K256();
else if (name === 'p224')
prime = new P224();
else if (name === 'p192')
prime = new P192();
else if (name === 'p25519')
prime = new P25519();
else
throw new Error('Unknown prime ' + name);
primes[name] = prime;
return prime;
};
//
// Base reduction engine
//
function Red(m) {
if (typeof m === 'string') {
var prime = BN._prime(m);
this.m = prime.p;
this.prime = prime;
} else {
this.m = m;
this.prime = null;
}
}
Red.prototype._verify1 = function _verify1(a) {
assert(!a.sign, 'red works only with positives');
assert(a.red, 'red works only with red numbers');
};
Red.prototype._verify2 = function _verify2(a, b) {
assert(!a.sign && !b.sign, 'red works only with positives');
assert(a.red && a.red === b.red,
'red works only with red numbers');
};
Red.prototype.imod = function imod(a) {
if (this.prime)
return this.prime.ireduce(a)._forceRed(this);
return a.umod(this.m)._forceRed(this);
};
Red.prototype.neg = function neg(a) {
var r = a.clone();
r.sign = !r.sign;
return r.iadd(this.m)._forceRed(this);
};
Red.prototype.add = function add(a, b) {
this._verify2(a, b);
var res = a.add(b);
if (res.cmp(this.m) >= 0)
res.isub(this.m);
return res._forceRed(this);
};
Red.prototype.iadd = function iadd(a, b) {
this._verify2(a, b);
var res = a.iadd(b);
if (res.cmp(this.m) >= 0)
res.isub(this.m);
return res;
};
Red.prototype.sub = function sub(a, b) {
this._verify2(a, b);
var res = a.sub(b);
if (res.cmpn(0) < 0)
res.iadd(this.m);
return res._forceRed(this);
};
Red.prototype.isub = function isub(a, b) {
this._verify2(a, b);
var res = a.isub(b);
if (res.cmpn(0) < 0)
res.iadd(this.m);
return res;
};
Red.prototype.shl = function shl(a, num) {
this._verify1(a);
return this.imod(a.ushln(num));
};
Red.prototype.imul = function imul(a, b) {
this._verify2(a, b);
return this.imod(a.imul(b));
};
Red.prototype.mul = function mul(a, b) {
this._verify2(a, b);
return this.imod(a.mul(b));
};
Red.prototype.isqr = function isqr(a) {
return this.imul(a, a);
};
Red.prototype.sqr = function sqr(a) {
return this.mul(a, a);
};
Red.prototype.sqrt = function sqrt(a) {
if (a.cmpn(0) === 0)
return a.clone();
var mod3 = this.m.andln(3);
assert(mod3 % 2 === 1);
// Fast case
if (mod3 === 3) {
var pow = this.m.add(new BN(1)).iushrn(2);
var r = this.pow(a, pow);
return r;
}
// Tonelli-Shanks algorithm (Totally unoptimized and slow)
//
// Find Q and S, that Q * 2 ^ S = (P - 1)
var q = this.m.subn(1);
var s = 0;
while (q.cmpn(0) !== 0 && q.andln(1) === 0) {
s++;
q.iushrn(1);
}
assert(q.cmpn(0) !== 0);
var one = new BN(1).toRed(this);
var nOne = one.redNeg();
// Find quadratic non-residue
// NOTE: Max is such because of generalized Riemann hypothesis.
var lpow = this.m.subn(1).iushrn(1);
var z = this.m.bitLength();
z = new BN(2 * z * z).toRed(this);
while (this.pow(z, lpow).cmp(nOne) !== 0)
z.redIAdd(nOne);
var c = this.pow(z, q);
var r = this.pow(a, q.addn(1).iushrn(1));
var t = this.pow(a, q);
var m = s;
while (t.cmp(one) !== 0) {
var tmp = t;
for (var i = 0; tmp.cmp(one) !== 0; i++)
tmp = tmp.redSqr();
assert(i < m);
var b = this.pow(c, new BN(1).iushln(m - i - 1));
r = r.redMul(b);
c = b.redSqr();
t = t.redMul(c);
m = i;
}
return r;
};
Red.prototype.invm = function invm(a) {
var inv = a._invmp(this.m);
if (inv.sign) {
inv.sign = false;
return this.imod(inv).redNeg();
} else {
return this.imod(inv);
}
};
Red.prototype.pow = function pow(a, num) {
var w = [];
if (num.cmpn(0) === 0)
return new BN(1);
var q = num.clone();
while (q.cmpn(0) !== 0) {
w.push(q.andln(1));
q.iushrn(1);
}
// Skip leading zeroes
var res = a;
for (var i = 0; i < w.length; i++, res = this.sqr(res))
if (w[i] !== 0)
break;
if (++i < w.length) {
for (var q = this.sqr(res); i < w.length; i++, q = this.sqr(q)) {
if (w[i] === 0)
continue;
res = this.mul(res, q);
}
}
return res;
};
Red.prototype.convertTo = function convertTo(num) {
var r = num.umod(this.m);
if (r === num)
return r.clone();
else
return r;
};
Red.prototype.convertFrom = function convertFrom(num) {
var res = num.clone();
res.red = null;
return res;
};
//
// Montgomery method engine
//
BN.mont = function mont(num) {
return new Mont(num);
};
function Mont(m) {
Red.call(this, m);
this.shift = this.m.bitLength();
if (this.shift % 26 !== 0)
this.shift += 26 - (this.shift % 26);
this.r = new BN(1).iushln(this.shift);
this.r2 = this.imod(this.r.sqr());
this.rinv = this.r._invmp(this.m);
this.minv = this.rinv.mul(this.r).isubn(1).div(this.m);
this.minv = this.minv.umod(this.r);
this.minv = this.r.sub(this.minv);
}
inherits(Mont, Red);
Mont.prototype.convertTo = function convertTo(num) {
return this.imod(num.ushln(this.shift));
};
Mont.prototype.convertFrom = function convertFrom(num) {
var r = this.imod(num.mul(this.rinv));
r.red = null;
return r;
};
Mont.prototype.imul = function imul(a, b) {
if (a.cmpn(0) === 0 || b.cmpn(0) === 0) {
a.words[0] = 0;
a.length = 1;
return a;
}
var t = a.imul(b);
var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m);
var u = t.isub(c).iushrn(this.shift);
var res = u;
if (u.cmp(this.m) >= 0)
res = u.isub(this.m);
else if (u.cmpn(0) < 0)
res = u.iadd(this.m);
return res._forceRed(this);
};
Mont.prototype.mul = function mul(a, b) {
if (a.cmpn(0) === 0 || b.cmpn(0) === 0)
return new BN(0)._forceRed(this);
var t = a.mul(b);
var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m);
var u = t.isub(c).iushrn(this.shift);
var res = u;
if (u.cmp(this.m) >= 0)
res = u.isub(this.m);
else if (u.cmpn(0) < 0)
res = u.iadd(this.m);
return res._forceRed(this);
};
Mont.prototype.invm = function invm(a) {
// (AR)^-1 * R^2 = (A^-1 * R^-1) * R^2 = A^-1 * R
var res = this.imod(a._invmp(this.m).mul(this.r2));
return res._forceRed(this);
};
})(typeof module === 'undefined' || module, this);
},{}],191:[function(require,module,exports){
arguments[4][117][0].apply(exports,arguments)
},{"dup":117}],192:[function(require,module,exports){
(function (Buffer){
var createHmac = require('create-hmac')
var MAX_ALLOC = Math.pow(2, 30) - 1 // default in iojs
exports.pbkdf2 = pbkdf2
function pbkdf2 (password, salt, iterations, keylen, digest, callback) {
if (typeof digest === 'function') {
callback = digest
digest = undefined
}
if (typeof callback !== 'function') {
throw new Error('No callback provided to pbkdf2')
}
var result = pbkdf2Sync(password, salt, iterations, keylen, digest)
setTimeout(function () {
callback(undefined, result)
})
}
exports.pbkdf2Sync = pbkdf2Sync
function pbkdf2Sync (password, salt, iterations, keylen, digest) {
if (typeof iterations !== 'number') {
throw new TypeError('Iterations not a number')
}
if (iterations < 0) {
throw new TypeError('Bad iterations')
}
if (typeof keylen !== 'number') {
throw new TypeError('Key length not a number')
}
if (keylen < 0 || keylen > MAX_ALLOC) {
throw new TypeError('Bad key length')
}
digest = digest || 'sha1'
if (!Buffer.isBuffer(password)) password = new Buffer(password, 'binary')
if (!Buffer.isBuffer(salt)) salt = new Buffer(salt, 'binary')
var hLen
var l = 1
var DK = new Buffer(keylen)
var block1 = new Buffer(salt.length + 4)
salt.copy(block1, 0, 0, salt.length)
var r
var T
for (var i = 1; i <= l; i++) {
block1.writeUInt32BE(i, salt.length)
var U = createHmac(digest, password).update(block1).digest()
if (!hLen) {
hLen = U.length
T = new Buffer(hLen)
l = Math.ceil(keylen / hLen)
r = keylen - (l - 1) * hLen
}
U.copy(T, 0, 0, hLen)
for (var j = 1; j < iterations; j++) {
U = createHmac(digest, password).update(U).digest()
for (var k = 0; k < hLen; k++) {
T[k] ^= U[k]
}
}
var destPos = (i - 1) * hLen
var len = (i === l ? r : hLen)
T.copy(DK, destPos, 0, len)
}
return DK
}
}).call(this,require("buffer").Buffer)
},{"buffer":76,"create-hmac":183}],193:[function(require,module,exports){
exports.publicEncrypt = require('./publicEncrypt');
exports.privateDecrypt = require('./privateDecrypt');
exports.privateEncrypt = function privateEncrypt(key, buf) {
return exports.publicEncrypt(key, buf, true);
};
exports.publicDecrypt = function publicDecrypt(key, buf) {
return exports.privateDecrypt(key, buf, true);
};
},{"./privateDecrypt":217,"./publicEncrypt":218}],194:[function(require,module,exports){
(function (Buffer){
var createHash = require('create-hash');
module.exports = function (seed, len) {
var t = new Buffer('');
var i = 0, c;
while (t.length < len) {
c = i2ops(i++);
t = Buffer.concat([t, createHash('sha1').update(seed).update(c).digest()]);
}
return t.slice(0, len);
};
function i2ops(c) {
var out = new Buffer(4);
out.writeUInt32BE(c,0);
return out;
}
}).call(this,require("buffer").Buffer)
},{"buffer":76,"create-hash":171}],195:[function(require,module,exports){
arguments[4][102][0].apply(exports,arguments)
},{"dup":102}],196:[function(require,module,exports){
arguments[4][103][0].apply(exports,arguments)
},{"bn.js":195,"buffer":76,"dup":103,"randombytes":221}],197:[function(require,module,exports){
arguments[4][125][0].apply(exports,arguments)
},{"buffer":76,"create-hash":171,"dup":125}],198:[function(require,module,exports){
arguments[4][126][0].apply(exports,arguments)
},{"dup":126}],199:[function(require,module,exports){
arguments[4][127][0].apply(exports,arguments)
},{"asn1.js":202,"dup":127}],200:[function(require,module,exports){
arguments[4][128][0].apply(exports,arguments)
},{"./EVP_BytesToKey":197,"browserify-aes":84,"buffer":76,"dup":128}],201:[function(require,module,exports){
arguments[4][129][0].apply(exports,arguments)
},{"./aesid.json":198,"./asn1":199,"./fixProc":200,"browserify-aes":84,"buffer":76,"dup":129,"pbkdf2":192}],202:[function(require,module,exports){
arguments[4][130][0].apply(exports,arguments)
},{"./asn1/api":203,"./asn1/base":205,"./asn1/constants":209,"./asn1/decoders":211,"./asn1/encoders":214,"bn.js":195,"dup":130}],203:[function(require,module,exports){
arguments[4][131][0].apply(exports,arguments)
},{"../asn1":202,"dup":131,"inherits":223,"vm":244}],204:[function(require,module,exports){
arguments[4][132][0].apply(exports,arguments)
},{"../base":205,"buffer":76,"dup":132,"inherits":223}],205:[function(require,module,exports){
arguments[4][133][0].apply(exports,arguments)
},{"./buffer":204,"./node":206,"./reporter":207,"dup":133}],206:[function(require,module,exports){
arguments[4][134][0].apply(exports,arguments)
},{"../base":205,"dup":134,"minimalistic-assert":216}],207:[function(require,module,exports){
arguments[4][135][0].apply(exports,arguments)
},{"dup":135,"inherits":223}],208:[function(require,module,exports){
arguments[4][136][0].apply(exports,arguments)
},{"../constants":209,"dup":136}],209:[function(require,module,exports){
arguments[4][137][0].apply(exports,arguments)
},{"./der":208,"dup":137}],210:[function(require,module,exports){
arguments[4][138][0].apply(exports,arguments)
},{"../../asn1":202,"dup":138,"inherits":223}],211:[function(require,module,exports){
arguments[4][139][0].apply(exports,arguments)
},{"./der":210,"./pem":212,"dup":139}],212:[function(require,module,exports){
arguments[4][140][0].apply(exports,arguments)
},{"../../asn1":202,"./der":210,"buffer":76,"dup":140,"inherits":223}],213:[function(require,module,exports){
arguments[4][141][0].apply(exports,arguments)
},{"../../asn1":202,"buffer":76,"dup":141,"inherits":223}],214:[function(require,module,exports){
arguments[4][142][0].apply(exports,arguments)
},{"./der":213,"./pem":215,"dup":142}],215:[function(require,module,exports){
arguments[4][143][0].apply(exports,arguments)
},{"../../asn1":202,"./der":213,"buffer":76,"dup":143,"inherits":223}],216:[function(require,module,exports){
arguments[4][144][0].apply(exports,arguments)
},{"dup":144}],217:[function(require,module,exports){
(function (Buffer){
var parseKeys = require('parse-asn1');
var mgf = require('./mgf');
var xor = require('./xor');
var bn = require('bn.js');
var crt = require('browserify-rsa');
var createHash = require('create-hash');
var withPublic = require('./withPublic');
module.exports = function privateDecrypt(private_key, enc, reverse) {
var padding;
if (private_key.padding) {
padding = private_key.padding;
} else if (reverse) {
padding = 1;
} else {
padding = 4;
}
var key = parseKeys(private_key);
var k = key.modulus.byteLength();
if (enc.length > k || new bn(enc).cmp(key.modulus) >= 0) {
throw new Error('decryption error');
}
var msg;
if (reverse) {
msg = withPublic(new bn(enc), key);
} else {
msg = crt(enc, key);
}
var zBuffer = new Buffer(k - msg.length);
zBuffer.fill(0);
msg = Buffer.concat([zBuffer, msg], k);
if (padding === 4) {
return oaep(key, msg);
} else if (padding === 1) {
return pkcs1(key, msg, reverse);
} else if (padding === 3) {
return msg;
} else {
throw new Error('unknown padding');
}
};
function oaep(key, msg){
var n = key.modulus;
var k = key.modulus.byteLength();
var mLen = msg.length;
var iHash = createHash('sha1').update(new Buffer('')).digest();
var hLen = iHash.length;
var hLen2 = 2 * hLen;
if (msg[0] !== 0) {
throw new Error('decryption error');
}
var maskedSeed = msg.slice(1, hLen + 1);
var maskedDb = msg.slice(hLen + 1);
var seed = xor(maskedSeed, mgf(maskedDb, hLen));
var db = xor(maskedDb, mgf(seed, k - hLen - 1));
if (compare(iHash, db.slice(0, hLen))) {
throw new Error('decryption error');
}
var i = hLen;
while (db[i] === 0) {
i++;
}
if (db[i++] !== 1) {
throw new Error('decryption error');
}
return db.slice(i);
}
function pkcs1(key, msg, reverse){
var p1 = msg.slice(0, 2);
var i = 2;
var status = 0;
while (msg[i++] !== 0) {
if (i >= msg.length) {
status++;
break;
}
}
var ps = msg.slice(2, i - 1);
var p2 = msg.slice(i - 1, i);
if ((p1.toString('hex') !== '0002' && !reverse) || (p1.toString('hex') !== '0001' && reverse)){
status++;
}
if (ps.length < 8) {
status++;
}
if (status) {
throw new Error('decryption error');
}
return msg.slice(i);
}
function compare(a, b){
a = new Buffer(a);
b = new Buffer(b);
var dif = 0;
var len = a.length;
if (a.length !== b.length) {
dif++;
len = Math.min(a.length, b.length);
}
var i = -1;
while (++i < len) {
dif += (a[i] ^ b[i]);
}
return dif;
}
}).call(this,require("buffer").Buffer)
},{"./mgf":194,"./withPublic":219,"./xor":220,"bn.js":195,"browserify-rsa":196,"buffer":76,"create-hash":171,"parse-asn1":201}],218:[function(require,module,exports){
(function (Buffer){
var parseKeys = require('parse-asn1');
var randomBytes = require('randombytes');
var createHash = require('create-hash');
var mgf = require('./mgf');
var xor = require('./xor');
var bn = require('bn.js');
var withPublic = require('./withPublic');
var crt = require('browserify-rsa');
var constants = {
RSA_PKCS1_OAEP_PADDING: 4,
RSA_PKCS1_PADDIN: 1,
RSA_NO_PADDING: 3
};
module.exports = function publicEncrypt(public_key, msg, reverse) {
var padding;
if (public_key.padding) {
padding = public_key.padding;
} else if (reverse) {
padding = 1;
} else {
padding = 4;
}
var key = parseKeys(public_key);
var paddedMsg;
if (padding === 4) {
paddedMsg = oaep(key, msg);
} else if (padding === 1) {
paddedMsg = pkcs1(key, msg, reverse);
} else if (padding === 3) {
paddedMsg = new bn(msg);
if (paddedMsg.cmp(key.modulus) >= 0) {
throw new Error('data too long for modulus');
}
} else {
throw new Error('unknown padding');
}
if (reverse) {
return crt(paddedMsg, key);
} else {
return withPublic(paddedMsg, key);
}
};
function oaep(key, msg){
var k = key.modulus.byteLength();
var mLen = msg.length;
var iHash = createHash('sha1').update(new Buffer('')).digest();
var hLen = iHash.length;
var hLen2 = 2 * hLen;
if (mLen > k - hLen2 - 2) {
throw new Error('message too long');
}
var ps = new Buffer(k - mLen - hLen2 - 2);
ps.fill(0);
var dblen = k - hLen - 1;
var seed = randomBytes(hLen);
var maskedDb = xor(Buffer.concat([iHash, ps, new Buffer([1]), msg], dblen), mgf(seed, dblen));
var maskedSeed = xor(seed, mgf(maskedDb, hLen));
return new bn(Buffer.concat([new Buffer([0]), maskedSeed, maskedDb], k));
}
function pkcs1(key, msg, reverse){
var mLen = msg.length;
var k = key.modulus.byteLength();
if (mLen > k - 11) {
throw new Error('message too long');
}
var ps;
if (reverse) {
ps = new Buffer(k - mLen - 3);
ps.fill(0xff);
} else {
ps = nonZero(k - mLen - 3);
}
return new bn(Buffer.concat([new Buffer([0, reverse?1:2]), ps, new Buffer([0]), msg], k));
}
function nonZero(len, crypto) {
var out = new Buffer(len);
var i = 0;
var cache = randomBytes(len*2);
var cur = 0;
var num;
while (i < len) {
if (cur === cache.length) {
cache = randomBytes(len*2);
cur = 0;
}
num = cache[cur++];
if (num) {
out[i++] = num;
}
}
return out;
}
}).call(this,require("buffer").Buffer)
},{"./mgf":194,"./withPublic":219,"./xor":220,"bn.js":195,"browserify-rsa":196,"buffer":76,"create-hash":171,"parse-asn1":201,"randombytes":221}],219:[function(require,module,exports){
(function (Buffer){
var bn = require('bn.js');
function withPublic(paddedMsg, key) {
return new Buffer(paddedMsg
.toRed(bn.mont(key.modulus))
.redPow(new bn(key.publicExponent))
.fromRed()
.toArray());
}
module.exports = withPublic;
}).call(this,require("buffer").Buffer)
},{"bn.js":195,"buffer":76}],220:[function(require,module,exports){
module.exports = function xor(a, b) {
var len = a.length;
var i = -1;
while (++i < len) {
a[i] ^= b[i];
}
return a
};
},{}],221:[function(require,module,exports){
(function (process,global,Buffer){
'use strict';
var crypto = global.crypto || global.msCrypto
if(crypto && crypto.getRandomValues) {
module.exports = randomBytes;
} else {
module.exports = oldBrowser;
}
function randomBytes(size, cb) {
var bytes = new Buffer(size); //in browserify, this is an extended Uint8Array
/* This will not work in older browsers.
* See https://developer.mozilla.org/en-US/docs/Web/API/window.crypto.getRandomValues
*/
crypto.getRandomValues(bytes);
if (typeof cb === 'function') {
return process.nextTick(function () {
cb(null, bytes);
});
}
return bytes;
}
function oldBrowser() {
throw new Error(
'secure random number generation not supported by this browser\n'+
'use chrome, FireFox or Internet Explorer 11'
)
}
}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("buffer").Buffer)
},{"_process":225,"buffer":76}],222:[function(require,module,exports){
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
function EventEmitter() {
this._events = this._events || {};
this._maxListeners = this._maxListeners || undefined;
}
module.exports = EventEmitter;
// Backwards-compat with node 0.10.x
EventEmitter.EventEmitter = EventEmitter;
EventEmitter.prototype._events = undefined;
EventEmitter.prototype._maxListeners = undefined;
// 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.
EventEmitter.defaultMaxListeners = 10;
// Obviously not all Emitters should be limited to 10. This function allows
// that to be increased. Set to zero for unlimited.
EventEmitter.prototype.setMaxListeners = function(n) {
if (!isNumber(n) || n < 0 || isNaN(n))
throw TypeError('n must be a positive number');
this._maxListeners = n;
return this;
};
EventEmitter.prototype.emit = function(type) {
var er, handler, len, args, i, listeners;
if (!this._events)
this._events = {};
// If there is no 'error' event listener then throw.
if (type === 'error') {
if (!this._events.error ||
(isObject(this._events.error) && !this._events.error.length)) {
er = arguments[1];
if (er instanceof Error) {
throw er; // Unhandled 'error' event
}
throw TypeError('Uncaught, unspecified "error" event.');
}
}
handler = this._events[type];
if (isUndefined(handler))
return false;
if (isFunction(handler)) {
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:
len = arguments.length;
args = new Array(len - 1);
for (i = 1; i < len; i++)
args[i - 1] = arguments[i];
handler.apply(this, args);
}
} else if (isObject(handler)) {
len = arguments.length;
args = new Array(len - 1);
for (i = 1; i < len; i++)
args[i - 1] = arguments[i];
listeners = handler.slice();
len = listeners.length;
for (i = 0; i < len; i++)
listeners[i].apply(this, args);
}
return true;
};
EventEmitter.prototype.addListener = function(type, listener) {
var m;
if (!isFunction(listener))
throw TypeError('listener must be a function');
if (!this._events)
this._events = {};
// To avoid recursion in the case that type === "newListener"! Before
// adding it to the listeners, first emit "newListener".
if (this._events.newListener)
this.emit('newListener', type,
isFunction(listener.listener) ?
listener.listener : listener);
if (!this._events[type])
// Optimize the case of one listener. Don't need the extra array object.
this._events[type] = listener;
else if (isObject(this._events[type]))
// 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];
// Check for listener leak
if (isObject(this._events[type]) && !this._events[type].warned) {
var m;
if (!isUndefined(this._maxListeners)) {
m = this._maxListeners;
} else {
m = EventEmitter.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);
if (typeof console.trace === 'function') {
// not supported in IE 10
console.trace();
}
}
}
return this;
};
EventEmitter.prototype.on = EventEmitter.prototype.addListener;
EventEmitter.prototype.once = function(type, listener) {
if (!isFunction(listener))
throw TypeError('listener must be a function');
var fired = false;
function g() {
this.removeListener(type, g);
if (!fired) {
fired = true;
listener.apply(this, arguments);
}
}
g.listener = listener;
this.on(type, g);
return this;
};
// emits a 'removeListener' event iff the listener was removed
EventEmitter.prototype.removeListener = function(type, listener) {
var list, position, length, i;
if (!isFunction(listener))
throw TypeError('listener must be a function');
if (!this._events || !this._events[type])
return this;
list = this._events[type];
length = list.length;
position = -1;
if (list === listener ||
(isFunction(list.listener) && list.listener === listener)) {
delete this._events[type];
if (this._events.removeListener)
this.emit('removeListener', type, listener);
} else if (isObject(list)) {
for (i = length; i-- > 0;) {
if (list[i] === listener ||
(list[i].listener && list[i].listener === listener)) {
position = i;
break;
}
}
if (position < 0)
return this;
if (list.length === 1) {
list.length = 0;
delete this._events[type];
} else {
list.splice(position, 1);
}
if (this._events.removeListener)
this.emit('removeListener', type, listener);
}
return this;
};
EventEmitter.prototype.removeAllListeners = function(type) {
var key, listeners;
if (!this._events)
return this;
// not listening for removeListener, no need to emit
if (!this._events.removeListener) {
if (arguments.length === 0)
this._events = {};
else if (this._events[type])
delete this._events[type];
return this;
}
// emit removeListener for all listeners on all events
if (arguments.length === 0) {
for (key in this._events) {
if (key === 'removeListener') continue;
this.removeAllListeners(key);
}
this.removeAllListeners('removeListener');
this._events = {};
return this;
}
listeners = this._events[type];
if (isFunction(listeners)) {
this.removeListener(type, listeners);
} else {
// LIFO order
while (listeners.length)
this.removeListener(type, listeners[listeners.length - 1]);
}
delete this._events[type];
return this;
};
EventEmitter.prototype.listeners = function(type) {
var ret;
if (!this._events || !this._events[type])
ret = [];
else if (isFunction(this._events[type]))
ret = [this._events[type]];
else
ret = this._events[type].slice();
return ret;
};
EventEmitter.listenerCount = function(emitter, type) {
var ret;
if (!emitter._events || !emitter._events[type])
ret = 0;
else if (isFunction(emitter._events[type]))
ret = 1;
else
ret = emitter._events[type].length;
return ret;
};
function isFunction(arg) {
return typeof arg === 'function';
}
function isNumber(arg) {
return typeof arg === 'number';
}
function isObject(arg) {
return typeof arg === 'object' && arg !== null;
}
function isUndefined(arg) {
return arg === void 0;
}
},{}],223:[function(require,module,exports){
if (typeof Object.create === 'function') {
// implementation from standard node.js 'util' module
module.exports = function inherits(ctor, superCtor) {
ctor.super_ = superCtor
ctor.prototype = Object.create(superCtor.prototype, {
constructor: {
value: ctor,
enumerable: false,
writable: true,
configurable: true
}
});
};
} else {
// old school shim for old browsers
module.exports = function inherits(ctor, superCtor) {
ctor.super_ = superCtor
var TempCtor = function () {}
TempCtor.prototype = superCtor.prototype
ctor.prototype = new TempCtor()
ctor.prototype.constructor = ctor
}
}
},{}],224:[function(require,module,exports){
module.exports = Array.isArray || function (arr) {
return Object.prototype.toString.call(arr) == '[object Array]';
};
},{}],225:[function(require,module,exports){
// shim for using process in browser
var process = module.exports = {};
var queue = [];
var draining = false;
function drainQueue() {
if (draining) {
return;
}
draining = true;
var currentQueue;
var len = queue.length;
while(len) {
currentQueue = queue;
queue = [];
var i = -1;
while (++i < len) {
currentQueue[i]();
}
len = queue.length;
}
draining = false;
}
process.nextTick = function (fun) {
queue.push(fun);
if (!draining) {
setTimeout(drainQueue, 0);
}
};
process.title = 'browser';
process.browser = true;
process.env = {};
process.argv = [];
process.version = ''; // empty string to avoid regexp issues
process.versions = {};
function noop() {}
process.on = noop;
process.addListener = noop;
process.once = noop;
process.off = noop;
process.removeListener = noop;
process.removeAllListeners = noop;
process.emit = noop;
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');
};
process.umask = function() { return 0; };
},{}],226:[function(require,module,exports){
(function (global){
/*! http://mths.be/punycode v1.2.4 by @mathias */
;(function(root) {
/** Detect free variables */
var freeExports = typeof exports == 'object' && exports;
var freeModule = typeof module == 'object' && module &&
module.exports == freeExports && module;
var freeGlobal = typeof global == 'object' && global;
if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) {
root = freeGlobal;
}
/**
* The `punycode` object.
* @name punycode
* @type Object
*/
var punycode,
/** Highest positive signed 32-bit float value */
maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1
/** Bootstring parameters */
base = 36,
tMin = 1,
tMax = 26,
skew = 38,
damp = 700,
initialBias = 72,
initialN = 128, // 0x80
delimiter = '-', // '\x2D'
/** Regular expressions */
regexPunycode = /^xn--/,
regexNonASCII = /[^ -~]/, // unprintable ASCII chars + non-ASCII chars
regexSeparators = /\x2E|\u3002|\uFF0E|\uFF61/g, // RFC 3490 separators
/** Error messages */
errors = {
'overflow': 'Overflow: input needs wider integers to process',
'not-basic': 'Illegal input >= 0x80 (not a basic code point)',
'invalid-input': 'Invalid input'
},
/** Convenience shortcuts */
baseMinusTMin = base - tMin,
floor = Math.floor,
stringFromCharCode = String.fromCharCode,
/** Temporary variable */
key;
/*--------------------------------------------------------------------------*/
/**
* A generic error utility function.
* @private
* @param {String} type The error type.
* @returns {Error} Throws a `RangeError` with the applicable error message.
*/
function error(type) {
throw RangeError(errors[type]);
}
/**
* A generic `Array#map` utility function.
* @private
* @param {Array} array The array to iterate over.
* @param {Function} callback The function that gets called for every array
* item.
* @returns {Array} A new array of values returned by the callback function.
*/
function map(array, fn) {
var length = array.length;
while (length--) {
array[length] = fn(array[length]);
}
return array;
}
/**
* A simple `Array#map`-like wrapper to work with domain name strings.
* @private
* @param {String} domain The domain name.
* @param {Function} callback The function that gets called for every
* character.
* @returns {Array} A new string of characters returned by the callback
* function.
*/
function mapDomain(string, fn) {
return map(string.split(regexSeparators), fn).join('.');
}
/**
* Creates an array containing the numeric code points of each Unicode
* character in the string. While JavaScript uses UCS-2 internally,
* this function will convert a pair of surrogate halves (each of which
* UCS-2 exposes as separate characters) into a single code point,
* matching UTF-16.
* @see `punycode.ucs2.encode`
* @see
* @memberOf punycode.ucs2
* @name decode
* @param {String} string The Unicode input string (UCS-2).
* @returns {Array} The new array of code points.
*/
function ucs2decode(string) {
var output = [],
counter = 0,
length = string.length,
value,
extra;
while (counter < length) {
value = string.charCodeAt(counter++);
if (value >= 0xD800 && value <= 0xDBFF && counter < length) {
// high surrogate, and there is a next character
extra = string.charCodeAt(counter++);
if ((extra & 0xFC00) == 0xDC00) { // low surrogate
output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
} else {
// unmatched surrogate; only append this code unit, in case the next
// code unit is the high surrogate of a surrogate pair
output.push(value);
counter--;
}
} else {
output.push(value);
}
}
return output;
}
/**
* Creates a string based on an array of numeric code points.
* @see `punycode.ucs2.decode`
* @memberOf punycode.ucs2
* @name encode
* @param {Array} codePoints The array of numeric code points.
* @returns {String} The new Unicode string (UCS-2).
*/
function ucs2encode(array) {
return map(array, function(value) {
var output = '';
if (value > 0xFFFF) {
value -= 0x10000;
output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
value = 0xDC00 | value & 0x3FF;
}
output += stringFromCharCode(value);
return output;
}).join('');
}
/**
* Converts a basic code point into a digit/integer.
* @see `digitToBasic()`
* @private
* @param {Number} codePoint The basic numeric code point value.
* @returns {Number} The numeric value of a basic code point (for use in
* representing integers) in the range `0` to `base - 1`, or `base` if
* the code point does not represent a value.
*/
function basicToDigit(codePoint) {
if (codePoint - 48 < 10) {
return codePoint - 22;
}
if (codePoint - 65 < 26) {
return codePoint - 65;
}
if (codePoint - 97 < 26) {
return codePoint - 97;
}
return base;
}
/**
* Converts a digit/integer into a basic code point.
* @see `basicToDigit()`
* @private
* @param {Number} digit The numeric value of a basic code point.
* @returns {Number} The basic code point whose value (when used for
* representing integers) is `digit`, which needs to be in the range
* `0` to `base - 1`. If `flag` is non-zero, the uppercase form is
* used; else, the lowercase form is used. The behavior is undefined
* if `flag` is non-zero and `digit` has no uppercase form.
*/
function digitToBasic(digit, flag) {
// 0..25 map to ASCII a..z or A..Z
// 26..35 map to ASCII 0..9
return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);
}
/**
* Bias adaptation function as per section 3.4 of RFC 3492.
* http://tools.ietf.org/html/rfc3492#section-3.4
* @private
*/
function adapt(delta, numPoints, firstTime) {
var k = 0;
delta = firstTime ? floor(delta / damp) : delta >> 1;
delta += floor(delta / numPoints);
for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) {
delta = floor(delta / baseMinusTMin);
}
return floor(k + (baseMinusTMin + 1) * delta / (delta + skew));
}
/**
* Converts a Punycode string of ASCII-only symbols to a string of Unicode
* symbols.
* @memberOf punycode
* @param {String} input The Punycode string of ASCII-only symbols.
* @returns {String} The resulting string of Unicode symbols.
*/
function decode(input) {
// Don't use UCS-2
var output = [],
inputLength = input.length,
out,
i = 0,
n = initialN,
bias = initialBias,
basic,
j,
index,
oldi,
w,
k,
digit,
t,
/** Cached calculation results */
baseMinusT;
// Handle the basic code points: let `basic` be the number of input code
// points before the last delimiter, or `0` if there is none, then copy
// the first basic code points to the output.
basic = input.lastIndexOf(delimiter);
if (basic < 0) {
basic = 0;
}
for (j = 0; j < basic; ++j) {
// if it's not a basic code point
if (input.charCodeAt(j) >= 0x80) {
error('not-basic');
}
output.push(input.charCodeAt(j));
}
// Main decoding loop: start just after the last delimiter if any basic code
// points were copied; start at the beginning otherwise.
for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) {
// `index` is the index of the next character to be consumed.
// Decode a generalized variable-length integer into `delta`,
// which gets added to `i`. The overflow checking is easier
// if we increase `i` as we go, then subtract off its starting
// value at the end to obtain `delta`.
for (oldi = i, w = 1, k = base; /* no condition */; k += base) {
if (index >= inputLength) {
error('invalid-input');
}
digit = basicToDigit(input.charCodeAt(index++));
if (digit >= base || digit > floor((maxInt - i) / w)) {
error('overflow');
}
i += digit * w;
t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
if (digit < t) {
break;
}
baseMinusT = base - t;
if (w > floor(maxInt / baseMinusT)) {
error('overflow');
}
w *= baseMinusT;
}
out = output.length + 1;
bias = adapt(i - oldi, out, oldi == 0);
// `i` was supposed to wrap around from `out` to `0`,
// incrementing `n` each time, so we'll fix that now:
if (floor(i / out) > maxInt - n) {
error('overflow');
}
n += floor(i / out);
i %= out;
// Insert `n` at position `i` of the output
output.splice(i++, 0, n);
}
return ucs2encode(output);
}
/**
* Converts a string of Unicode symbols to a Punycode string of ASCII-only
* symbols.
* @memberOf punycode
* @param {String} input The string of Unicode symbols.
* @returns {String} The resulting Punycode string of ASCII-only symbols.
*/
function encode(input) {
var n,
delta,
handledCPCount,
basicLength,
bias,
j,
m,
q,
k,
t,
currentValue,
output = [],
/** `inputLength` will hold the number of code points in `input`. */
inputLength,
/** Cached calculation results */
handledCPCountPlusOne,
baseMinusT,
qMinusT;
// Convert the input in UCS-2 to Unicode
input = ucs2decode(input);
// Cache the length
inputLength = input.length;
// Initialize the state
n = initialN;
delta = 0;
bias = initialBias;
// Handle the basic code points
for (j = 0; j < inputLength; ++j) {
currentValue = input[j];
if (currentValue < 0x80) {
output.push(stringFromCharCode(currentValue));
}
}
handledCPCount = basicLength = output.length;
// `handledCPCount` is the number of code points that have been handled;
// `basicLength` is the number of basic code points.
// Finish the basic string - if it is not empty - with a delimiter
if (basicLength) {
output.push(delimiter);
}
// Main encoding loop:
while (handledCPCount < inputLength) {
// All non-basic code points < n have been handled already. Find the next
// larger one:
for (m = maxInt, j = 0; j < inputLength; ++j) {
currentValue = input[j];
if (currentValue >= n && currentValue < m) {
m = currentValue;
}
}
// Increase `delta` enough to advance the decoder's state to ,
// but guard against overflow
handledCPCountPlusOne = handledCPCount + 1;
if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {
error('overflow');
}
delta += (m - n) * handledCPCountPlusOne;
n = m;
for (j = 0; j < inputLength; ++j) {
currentValue = input[j];
if (currentValue < n && ++delta > maxInt) {
error('overflow');
}
if (currentValue == n) {
// Represent delta as a generalized variable-length integer
for (q = delta, k = base; /* no condition */; k += base) {
t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
if (q < t) {
break;
}
qMinusT = q - t;
baseMinusT = base - t;
output.push(
stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0))
);
q = floor(qMinusT / baseMinusT);
}
output.push(stringFromCharCode(digitToBasic(q, 0)));
bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);
delta = 0;
++handledCPCount;
}
}
++delta;
++n;
}
return output.join('');
}
/**
* Converts a Punycode string representing a domain name to Unicode. Only the
* Punycoded parts of the domain name will be converted, i.e. it doesn't
* matter if you call it on a string that has already been converted to
* Unicode.
* @memberOf punycode
* @param {String} domain The Punycode domain name to convert to Unicode.
* @returns {String} The Unicode representation of the given Punycode
* string.
*/
function toUnicode(domain) {
return mapDomain(domain, function(string) {
return regexPunycode.test(string)
? decode(string.slice(4).toLowerCase())
: string;
});
}
/**
* Converts a Unicode string representing a domain name to Punycode. Only the
* non-ASCII parts of the domain name will be converted, i.e. it doesn't
* matter if you call it with a domain that's already in ASCII.
* @memberOf punycode
* @param {String} domain The domain name to convert, as a Unicode string.
* @returns {String} The Punycode representation of the given domain name.
*/
function toASCII(domain) {
return mapDomain(domain, function(string) {
return regexNonASCII.test(string)
? 'xn--' + encode(string)
: string;
});
}
/*--------------------------------------------------------------------------*/
/** Define the public API */
punycode = {
/**
* A string representing the current Punycode.js version number.
* @memberOf punycode
* @type String
*/
'version': '1.2.4',
/**
* An object of methods to convert from JavaScript's internal character
* representation (UCS-2) to Unicode code points, and back.
* @see
* @memberOf punycode
* @type Object
*/
'ucs2': {
'decode': ucs2decode,
'encode': ucs2encode
},
'decode': decode,
'encode': encode,
'toASCII': toASCII,
'toUnicode': toUnicode
};
/** Expose `punycode` */
// 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
) {
define('punycode', function() {
return punycode;
});
} else if (freeExports && !freeExports.nodeType) {
if (freeModule) { // in Node.js or RingoJS v0.8.0+
freeModule.exports = punycode;
} else { // in Narwhal or RingoJS v0.7.0-
for (key in punycode) {
punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]);
}
}
} else { // in Rhino or a web browser
root.punycode = punycode;
}
}(this));
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{}],227:[function(require,module,exports){
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
'use strict';
// If obj.hasOwnProperty has been overridden, then calling
// obj.hasOwnProperty(prop) will break.
// See: https://github.com/joyent/node/issues/1707
function hasOwnProperty(obj, prop) {
return Object.prototype.hasOwnProperty.call(obj, prop);
}
module.exports = function(qs, sep, eq, options) {
sep = sep || '&';
eq = eq || '=';
var obj = {};
if (typeof qs !== 'string' || qs.length === 0) {
return obj;
}
var regexp = /\+/g;
qs = qs.split(sep);
var maxKeys = 1000;
if (options && typeof options.maxKeys === 'number') {
maxKeys = options.maxKeys;
}
var len = qs.length;
// maxKeys <= 0 means that we should not limit keys count
if (maxKeys > 0 && len > maxKeys) {
len = maxKeys;
}
for (var i = 0; i < len; ++i) {
var x = qs[i].replace(regexp, '%20'),
idx = x.indexOf(eq),
kstr, vstr, k, v;
if (idx >= 0) {
kstr = x.substr(0, idx);
vstr = x.substr(idx + 1);
} else {
kstr = x;
vstr = '';
}
k = decodeURIComponent(kstr);
v = decodeURIComponent(vstr);
if (!hasOwnProperty(obj, k)) {
obj[k] = v;
} else if (isArray(obj[k])) {
obj[k].push(v);
} else {
obj[k] = [obj[k], v];
}
}
return obj;
};
var isArray = Array.isArray || function (xs) {
return Object.prototype.toString.call(xs) === '[object Array]';
};
},{}],228:[function(require,module,exports){
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
'use strict';
var stringifyPrimitive = function(v) {
switch (typeof v) {
case 'string':
return v;
case 'boolean':
return v ? 'true' : 'false';
case 'number':
return isFinite(v) ? v : '';
default:
return '';
}
};
module.exports = function(obj, sep, eq, name) {
sep = sep || '&';
eq = eq || '=';
if (obj === null) {
obj = undefined;
}
if (typeof obj === 'object') {
return map(objectKeys(obj), function(k) {
var ks = encodeURIComponent(stringifyPrimitive(k)) + eq;
if (isArray(obj[k])) {
return map(obj[k], function(v) {
return ks + encodeURIComponent(stringifyPrimitive(v));
}).join(sep);
} else {
return ks + encodeURIComponent(stringifyPrimitive(obj[k]));
}
}).join(sep);
}
if (!name) return '';
return encodeURIComponent(stringifyPrimitive(name)) + eq +
encodeURIComponent(stringifyPrimitive(obj));
};
var isArray = Array.isArray || function (xs) {
return Object.prototype.toString.call(xs) === '[object Array]';
};
function map (xs, f) {
if (xs.map) return xs.map(f);
var res = [];
for (var i = 0; i < xs.length; i++) {
res.push(f(xs[i], i));
}
return res;
}
var objectKeys = Object.keys || function (obj) {
var res = [];
for (var key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) res.push(key);
}
return res;
};
},{}],229:[function(require,module,exports){
'use strict';
exports.decode = exports.parse = require('./decode');
exports.encode = exports.stringify = require('./encode');
},{"./decode":227,"./encode":228}],230:[function(require,module,exports){
module.exports = require("./lib/_stream_duplex.js")
},{"./lib/_stream_duplex.js":231}],231:[function(require,module,exports){
(function (process){
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
// a duplex stream is just a stream that is both readable and writable.
// Since JS doesn't have multiple prototypal inheritance, this class
// prototypally inherits from Readable, and then parasitically from
// Writable.
module.exports = Duplex;
/**/
var objectKeys = Object.keys || function (obj) {
var keys = [];
for (var key in obj) keys.push(key);
return keys;
}
/**/
/**/
var util = require('core-util-is');
util.inherits = require('inherits');
/**/
var Readable = require('./_stream_readable');
var Writable = require('./_stream_writable');
util.inherits(Duplex, Readable);
forEach(objectKeys(Writable.prototype), function(method) {
if (!Duplex.prototype[method])
Duplex.prototype[method] = Writable.prototype[method];
});
function Duplex(options) {
if (!(this instanceof Duplex))
return new Duplex(options);
Readable.call(this, options);
Writable.call(this, options);
if (options && options.readable === false)
this.readable = false;
if (options && options.writable === false)
this.writable = false;
this.allowHalfOpen = true;
if (options && options.allowHalfOpen === false)
this.allowHalfOpen = false;
this.once('end', onend);
}
// the no-half-open enforcer
function onend() {
// if we allow half-open state, or if the writable side ended,
// then we're ok.
if (this.allowHalfOpen || this._writableState.ended)
return;
// no more data can be written.
// But allow more writes to happen in this tick.
process.nextTick(this.end.bind(this));
}
function forEach (xs, f) {
for (var i = 0, l = xs.length; i < l; i++) {
f(xs[i], i);
}
}
}).call(this,require('_process'))
},{"./_stream_readable":233,"./_stream_writable":235,"_process":225,"core-util-is":236,"inherits":223}],232:[function(require,module,exports){
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
// a passthrough stream.
// basically just the most minimal sort of Transform stream.
// Every written chunk gets output as-is.
module.exports = PassThrough;
var Transform = require('./_stream_transform');
/**/
var util = require('core-util-is');
util.inherits = require('inherits');
/**/
util.inherits(PassThrough, Transform);
function PassThrough(options) {
if (!(this instanceof PassThrough))
return new PassThrough(options);
Transform.call(this, options);
}
PassThrough.prototype._transform = function(chunk, encoding, cb) {
cb(null, chunk);
};
},{"./_stream_transform":234,"core-util-is":236,"inherits":223}],233:[function(require,module,exports){
(function (process){
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
module.exports = Readable;
/**/
var isArray = require('isarray');
/**/
/**/
var Buffer = require('buffer').Buffer;
/**/
Readable.ReadableState = ReadableState;
var EE = require('events').EventEmitter;
/**/
if (!EE.listenerCount) EE.listenerCount = function(emitter, type) {
return emitter.listeners(type).length;
};
/**/
var Stream = require('stream');
/**/
var util = require('core-util-is');
util.inherits = require('inherits');
/**/
var StringDecoder;
/**/
var debug = require('util');
if (debug && debug.debuglog) {
debug = debug.debuglog('stream');
} else {
debug = function () {};
}
/**/
util.inherits(Readable, Stream);
function ReadableState(options, stream) {
var Duplex = require('./_stream_duplex');
options = options || {};
// the point at which it stops calling _read() to fill the buffer
// Note: 0 is a valid value, means "don't call _read preemptively ever"
var hwm = options.highWaterMark;
var defaultHwm = options.objectMode ? 16 : 16 * 1024;
this.highWaterMark = (hwm || hwm === 0) ? hwm : defaultHwm;
// cast to ints.
this.highWaterMark = ~~this.highWaterMark;
this.buffer = [];
this.length = 0;
this.pipes = null;
this.pipesCount = 0;
this.flowing = null;
this.ended = false;
this.endEmitted = false;
this.reading = false;
// a flag to be able to tell if the onwrite cb is called immediately,
// or on a later tick. We set this to true at first, because any
// actions that shouldn't happen until "later" should generally also
// not happen before the first write call.
this.sync = true;
// whenever we return null, then we set a flag to say
// that we're awaiting a 'readable' event emission.
this.needReadable = false;
this.emittedReadable = false;
this.readableListening = false;
// object stream flag. Used to make read(n) ignore n and to
// make all the buffer merging and length checks go away
this.objectMode = !!options.objectMode;
if (stream instanceof Duplex)
this.objectMode = this.objectMode || !!options.readableObjectMode;
// Crypto is kind of old and crusty. Historically, its default string
// encoding is 'binary' so we have to make this configurable.
// Everything else in the universe uses 'utf8', though.
this.defaultEncoding = options.defaultEncoding || 'utf8';
// when piping, we only care about 'readable' events that happen
// after read()ing all the bytes and not getting any pushback.
this.ranOut = false;
// the number of writers that are awaiting a drain event in .pipe()s
this.awaitDrain = 0;
// if true, a maybeReadMore has been scheduled
this.readingMore = false;
this.decoder = null;
this.encoding = null;
if (options.encoding) {
if (!StringDecoder)
StringDecoder = require('string_decoder/').StringDecoder;
this.decoder = new StringDecoder(options.encoding);
this.encoding = options.encoding;
}
}
function Readable(options) {
var Duplex = require('./_stream_duplex');
if (!(this instanceof Readable))
return new Readable(options);
this._readableState = new ReadableState(options, this);
// legacy
this.readable = true;
Stream.call(this);
}
// Manually shove something into the read() buffer.
// This returns true if the highWaterMark has not been hit yet,
// similar to how Writable.write() returns true if you should
// write() some more.
Readable.prototype.push = function(chunk, encoding) {
var state = this._readableState;
if (util.isString(chunk) && !state.objectMode) {
encoding = encoding || state.defaultEncoding;
if (encoding !== state.encoding) {
chunk = new Buffer(chunk, encoding);
encoding = '';
}
}
return readableAddChunk(this, state, chunk, encoding, false);
};
// Unshift should *always* be something directly out of read()
Readable.prototype.unshift = function(chunk) {
var state = this._readableState;
return readableAddChunk(this, state, chunk, '', true);
};
function readableAddChunk(stream, state, chunk, encoding, addToFront) {
var er = chunkInvalid(state, chunk);
if (er) {
stream.emit('error', er);
} else if (util.isNullOrUndefined(chunk)) {
state.reading = false;
if (!state.ended)
onEofChunk(stream, state);
} else if (state.objectMode || chunk && chunk.length > 0) {
if (state.ended && !addToFront) {
var e = new Error('stream.push() after EOF');
stream.emit('error', e);
} else if (state.endEmitted && addToFront) {
var e = new Error('stream.unshift() after end event');
stream.emit('error', e);
} else {
if (state.decoder && !addToFront && !encoding)
chunk = state.decoder.write(chunk);
if (!addToFront)
state.reading = false;
// if we want the data now, just emit it.
if (state.flowing && state.length === 0 && !state.sync) {
stream.emit('data', chunk);
stream.read(0);
} else {
// update the buffer info.
state.length += state.objectMode ? 1 : chunk.length;
if (addToFront)
state.buffer.unshift(chunk);
else
state.buffer.push(chunk);
if (state.needReadable)
emitReadable(stream);
}
maybeReadMore(stream, state);
}
} else if (!addToFront) {
state.reading = false;
}
return needMoreData(state);
}
// if it's past the high water mark, we can push in some more.
// Also, if we have no data yet, we can stand some
// more bytes. This is to work around cases where hwm=0,
// such as the repl. Also, if the push() triggered a
// readable event, and the user called read(largeNumber) such that
// needReadable was set, then we ought to push more, so that another
// 'readable' event will be triggered.
function needMoreData(state) {
return !state.ended &&
(state.needReadable ||
state.length < state.highWaterMark ||
state.length === 0);
}
// backwards compatibility.
Readable.prototype.setEncoding = function(enc) {
if (!StringDecoder)
StringDecoder = require('string_decoder/').StringDecoder;
this._readableState.decoder = new StringDecoder(enc);
this._readableState.encoding = enc;
return this;
};
// Don't raise the hwm > 128MB
var MAX_HWM = 0x800000;
function roundUpToNextPowerOf2(n) {
if (n >= MAX_HWM) {
n = MAX_HWM;
} else {
// Get the next highest power of 2
n--;
for (var p = 1; p < 32; p <<= 1) n |= n >> p;
n++;
}
return n;
}
function howMuchToRead(n, state) {
if (state.length === 0 && state.ended)
return 0;
if (state.objectMode)
return n === 0 ? 0 : 1;
if (isNaN(n) || util.isNull(n)) {
// only flow one buffer at a time
if (state.flowing && state.buffer.length)
return state.buffer[0].length;
else
return state.length;
}
if (n <= 0)
return 0;
// If we're asking for more than the target buffer level,
// then raise the water mark. Bump up to the next highest
// power of 2, to prevent increasing it excessively in tiny
// amounts.
if (n > state.highWaterMark)
state.highWaterMark = roundUpToNextPowerOf2(n);
// don't have that much. return null, unless we've ended.
if (n > state.length) {
if (!state.ended) {
state.needReadable = true;
return 0;
} else
return state.length;
}
return n;
}
// you can override either this method, or the async _read(n) below.
Readable.prototype.read = function(n) {
debug('read', n);
var state = this._readableState;
var nOrig = n;
if (!util.isNumber(n) || n > 0)
state.emittedReadable = false;
// if we're doing read(0) to trigger a readable event, but we
// already have a bunch of data in the buffer, then just trigger
// the 'readable' event and move on.
if (n === 0 &&
state.needReadable &&
(state.length >= state.highWaterMark || state.ended)) {
debug('read: emitReadable', state.length, state.ended);
if (state.length === 0 && state.ended)
endReadable(this);
else
emitReadable(this);
return null;
}
n = howMuchToRead(n, state);
// if we've ended, and we're now clear, then finish it up.
if (n === 0 && state.ended) {
if (state.length === 0)
endReadable(this);
return null;
}
// All the actual chunk generation logic needs to be
// *below* the call to _read. The reason is that in certain
// synthetic stream cases, such as passthrough streams, _read
// may be a completely synchronous operation which may change
// the state of the read buffer, providing enough data when
// before there was *not* enough.
//
// So, the steps are:
// 1. Figure out what the state of things will be after we do
// a read from the buffer.
//
// 2. If that resulting state will trigger a _read, then call _read.
// Note that this may be asynchronous, or synchronous. Yes, it is
// deeply ugly to write APIs this way, but that still doesn't mean
// that the Readable class should behave improperly, as streams are
// designed to be sync/async agnostic.
// Take note if the _read call is sync or async (ie, if the read call
// has returned yet), so that we know whether or not it's safe to emit
// 'readable' etc.
//
// 3. Actually pull the requested chunks out of the buffer and return.
// if we need a readable event, then we need to do some reading.
var doRead = state.needReadable;
debug('need readable', doRead);
// if we currently have less than the highWaterMark, then also read some
if (state.length === 0 || state.length - n < state.highWaterMark) {
doRead = true;
debug('length less than watermark', doRead);
}
// however, if we've ended, then there's no point, and if we're already
// reading, then it's unnecessary.
if (state.ended || state.reading) {
doRead = false;
debug('reading or ended', doRead);
}
if (doRead) {
debug('do read');
state.reading = true;
state.sync = true;
// if the length is currently zero, then we *need* a readable event.
if (state.length === 0)
state.needReadable = true;
// call internal read method
this._read(state.highWaterMark);
state.sync = false;
}
// If _read pushed data synchronously, then `reading` will be false,
// and we need to re-evaluate how much data we can return to the user.
if (doRead && !state.reading)
n = howMuchToRead(nOrig, state);
var ret;
if (n > 0)
ret = fromList(n, state);
else
ret = null;
if (util.isNull(ret)) {
state.needReadable = true;
n = 0;
}
state.length -= n;
// If we have nothing in the buffer, then we want to know
// as soon as we *do* get something into the buffer.
if (state.length === 0 && !state.ended)
state.needReadable = true;
// If we tried to read() past the EOF, then emit end on the next tick.
if (nOrig !== n && state.ended && state.length === 0)
endReadable(this);
if (!util.isNull(ret))
this.emit('data', ret);
return ret;
};
function chunkInvalid(state, chunk) {
var er = null;
if (!util.isBuffer(chunk) &&
!util.isString(chunk) &&
!util.isNullOrUndefined(chunk) &&
!state.objectMode) {
er = new TypeError('Invalid non-string/buffer chunk');
}
return er;
}
function onEofChunk(stream, state) {
if (state.decoder && !state.ended) {
var chunk = state.decoder.end();
if (chunk && chunk.length) {
state.buffer.push(chunk);
state.length += state.objectMode ? 1 : chunk.length;
}
}
state.ended = true;
// emit 'readable' now to make sure it gets picked up.
emitReadable(stream);
}
// Don't emit readable right away in sync mode, because this can trigger
// another read() call => stack overflow. This way, it might trigger
// a nextTick recursion warning, but that's not so bad.
function emitReadable(stream) {
var state = stream._readableState;
state.needReadable = false;
if (!state.emittedReadable) {
debug('emitReadable', state.flowing);
state.emittedReadable = true;
if (state.sync)
process.nextTick(function() {
emitReadable_(stream);
});
else
emitReadable_(stream);
}
}
function emitReadable_(stream) {
debug('emit readable');
stream.emit('readable');
flow(stream);
}
// at this point, the user has presumably seen the 'readable' event,
// and called read() to consume some data. that may have triggered
// in turn another _read(n) call, in which case reading = true if
// it's in progress.
// However, if we're not ended, or reading, and the length < hwm,
// then go ahead and try to read some more preemptively.
function maybeReadMore(stream, state) {
if (!state.readingMore) {
state.readingMore = true;
process.nextTick(function() {
maybeReadMore_(stream, state);
});
}
}
function maybeReadMore_(stream, state) {
var len = state.length;
while (!state.reading && !state.flowing && !state.ended &&
state.length < state.highWaterMark) {
debug('maybeReadMore read 0');
stream.read(0);
if (len === state.length)
// didn't get any data, stop spinning.
break;
else
len = state.length;
}
state.readingMore = false;
}
// abstract method. to be overridden in specific implementation classes.
// call cb(er, data) where data is <= n in length.
// for virtual (non-string, non-buffer) streams, "length" is somewhat
// arbitrary, and perhaps not very meaningful.
Readable.prototype._read = function(n) {
this.emit('error', new Error('not implemented'));
};
Readable.prototype.pipe = function(dest, pipeOpts) {
var src = this;
var state = this._readableState;
switch (state.pipesCount) {
case 0:
state.pipes = dest;
break;
case 1:
state.pipes = [state.pipes, dest];
break;
default:
state.pipes.push(dest);
break;
}
state.pipesCount += 1;
debug('pipe count=%d opts=%j', state.pipesCount, pipeOpts);
var doEnd = (!pipeOpts || pipeOpts.end !== false) &&
dest !== process.stdout &&
dest !== process.stderr;
var endFn = doEnd ? onend : cleanup;
if (state.endEmitted)
process.nextTick(endFn);
else
src.once('end', endFn);
dest.on('unpipe', onunpipe);
function onunpipe(readable) {
debug('onunpipe');
if (readable === src) {
cleanup();
}
}
function onend() {
debug('onend');
dest.end();
}
// when the dest drains, it reduces the awaitDrain counter
// on the source. This would be more elegant with a .once()
// handler in flow(), but adding and removing repeatedly is
// too slow.
var ondrain = pipeOnDrain(src);
dest.on('drain', ondrain);
function cleanup() {
debug('cleanup');
// cleanup event handlers once the pipe is broken
dest.removeListener('close', onclose);
dest.removeListener('finish', onfinish);
dest.removeListener('drain', ondrain);
dest.removeListener('error', onerror);
dest.removeListener('unpipe', onunpipe);
src.removeListener('end', onend);
src.removeListener('end', cleanup);
src.removeListener('data', ondata);
// if the reader is waiting for a drain event from this
// specific writer, then it would cause it to never start
// flowing again.
// So, if this is awaiting a drain, then we just call it now.
// If we don't know, then assume that we are waiting for one.
if (state.awaitDrain &&
(!dest._writableState || dest._writableState.needDrain))
ondrain();
}
src.on('data', ondata);
function ondata(chunk) {
debug('ondata');
var ret = dest.write(chunk);
if (false === ret) {
debug('false write response, pause',
src._readableState.awaitDrain);
src._readableState.awaitDrain++;
src.pause();
}
}
// if the dest has an error, then stop piping into it.
// however, don't suppress the throwing behavior for this.
function onerror(er) {
debug('onerror', er);
unpipe();
dest.removeListener('error', onerror);
if (EE.listenerCount(dest, 'error') === 0)
dest.emit('error', er);
}
// This is a brutally ugly hack to make sure that our error handler
// is attached before any userland ones. NEVER DO THIS.
if (!dest._events || !dest._events.error)
dest.on('error', onerror);
else if (isArray(dest._events.error))
dest._events.error.unshift(onerror);
else
dest._events.error = [onerror, dest._events.error];
// Both close and finish should trigger unpipe, but only once.
function onclose() {
dest.removeListener('finish', onfinish);
unpipe();
}
dest.once('close', onclose);
function onfinish() {
debug('onfinish');
dest.removeListener('close', onclose);
unpipe();
}
dest.once('finish', onfinish);
function unpipe() {
debug('unpipe');
src.unpipe(dest);
}
// tell the dest that it's being piped to
dest.emit('pipe', src);
// start the flow if it hasn't been started already.
if (!state.flowing) {
debug('pipe resume');
src.resume();
}
return dest;
};
function pipeOnDrain(src) {
return function() {
var state = src._readableState;
debug('pipeOnDrain', state.awaitDrain);
if (state.awaitDrain)
state.awaitDrain--;
if (state.awaitDrain === 0 && EE.listenerCount(src, 'data')) {
state.flowing = true;
flow(src);
}
};
}
Readable.prototype.unpipe = function(dest) {
var state = this._readableState;
// if we're not piping anywhere, then do nothing.
if (state.pipesCount === 0)
return this;
// just one destination. most common case.
if (state.pipesCount === 1) {
// passed in one, but it's not the right one.
if (dest && dest !== state.pipes)
return this;
if (!dest)
dest = state.pipes;
// got a match.
state.pipes = null;
state.pipesCount = 0;
state.flowing = false;
if (dest)
dest.emit('unpipe', this);
return this;
}
// slow case. multiple pipe destinations.
if (!dest) {
// remove all.
var dests = state.pipes;
var len = state.pipesCount;
state.pipes = null;
state.pipesCount = 0;
state.flowing = false;
for (var i = 0; i < len; i++)
dests[i].emit('unpipe', this);
return this;
}
// try to find the right one.
var i = indexOf(state.pipes, dest);
if (i === -1)
return this;
state.pipes.splice(i, 1);
state.pipesCount -= 1;
if (state.pipesCount === 1)
state.pipes = state.pipes[0];
dest.emit('unpipe', this);
return this;
};
// set up data events if they are asked for
// Ensure readable listeners eventually get something
Readable.prototype.on = function(ev, fn) {
var res = Stream.prototype.on.call(this, ev, fn);
// If listening to data, and it has not explicitly been paused,
// then call resume to start the flow of data on the next tick.
if (ev === 'data' && false !== this._readableState.flowing) {
this.resume();
}
if (ev === 'readable' && this.readable) {
var state = this._readableState;
if (!state.readableListening) {
state.readableListening = true;
state.emittedReadable = false;
state.needReadable = true;
if (!state.reading) {
var self = this;
process.nextTick(function() {
debug('readable nexttick read 0');
self.read(0);
});
} else if (state.length) {
emitReadable(this, state);
}
}
}
return res;
};
Readable.prototype.addListener = Readable.prototype.on;
// pause() and resume() are remnants of the legacy readable stream API
// If the user uses them, then switch into old mode.
Readable.prototype.resume = function() {
var state = this._readableState;
if (!state.flowing) {
debug('resume');
state.flowing = true;
if (!state.reading) {
debug('resume read 0');
this.read(0);
}
resume(this, state);
}
return this;
};
function resume(stream, state) {
if (!state.resumeScheduled) {
state.resumeScheduled = true;
process.nextTick(function() {
resume_(stream, state);
});
}
}
function resume_(stream, state) {
state.resumeScheduled = false;
stream.emit('resume');
flow(stream);
if (state.flowing && !state.reading)
stream.read(0);
}
Readable.prototype.pause = function() {
debug('call pause flowing=%j', this._readableState.flowing);
if (false !== this._readableState.flowing) {
debug('pause');
this._readableState.flowing = false;
this.emit('pause');
}
return this;
};
function flow(stream) {
var state = stream._readableState;
debug('flow', state.flowing);
if (state.flowing) {
do {
var chunk = stream.read();
} while (null !== chunk && state.flowing);
}
}
// wrap an old-style stream as the async data source.
// This is *not* part of the readable stream interface.
// It is an ugly unfortunate mess of history.
Readable.prototype.wrap = function(stream) {
var state = this._readableState;
var paused = false;
var self = this;
stream.on('end', function() {
debug('wrapped end');
if (state.decoder && !state.ended) {
var chunk = state.decoder.end();
if (chunk && chunk.length)
self.push(chunk);
}
self.push(null);
});
stream.on('data', function(chunk) {
debug('wrapped data');
if (state.decoder)
chunk = state.decoder.write(chunk);
if (!chunk || !state.objectMode && !chunk.length)
return;
var ret = self.push(chunk);
if (!ret) {
paused = true;
stream.pause();
}
});
// proxy all the other methods.
// important when wrapping filters and duplexes.
for (var i in stream) {
if (util.isFunction(stream[i]) && util.isUndefined(this[i])) {
this[i] = function(method) { return function() {
return stream[method].apply(stream, arguments);
}}(i);
}
}
// proxy certain important events.
var events = ['error', 'close', 'destroy', 'pause', 'resume'];
forEach(events, function(ev) {
stream.on(ev, self.emit.bind(self, ev));
});
// when we try to consume some more bytes, simply unpause the
// underlying stream.
self._read = function(n) {
debug('wrapped _read', n);
if (paused) {
paused = false;
stream.resume();
}
};
return self;
};
// exposed for testing purposes only.
Readable._fromList = fromList;
// Pluck off n bytes from an array of buffers.
// Length is the combined lengths of all the buffers in the list.
function fromList(n, state) {
var list = state.buffer;
var length = state.length;
var stringMode = !!state.decoder;
var objectMode = !!state.objectMode;
var ret;
// nothing in the list, definitely empty.
if (list.length === 0)
return null;
if (length === 0)
ret = null;
else if (objectMode)
ret = list.shift();
else if (!n || n >= length) {
// read it all, truncate the array.
if (stringMode)
ret = list.join('');
else
ret = Buffer.concat(list, length);
list.length = 0;
} else {
// read just some of it.
if (n < list[0].length) {
// just take a part of the first list item.
// slice is the same for buffers and strings.
var buf = list[0];
ret = buf.slice(0, n);
list[0] = buf.slice(n);
} else if (n === list[0].length) {
// first list is a perfect match
ret = list.shift();
} else {
// complex case.
// we have enough to cover it, but it spans past the first buffer.
if (stringMode)
ret = '';
else
ret = new Buffer(n);
var c = 0;
for (var i = 0, l = list.length; i < l && c < n; i++) {
var buf = list[0];
var cpy = Math.min(n - c, buf.length);
if (stringMode)
ret += buf.slice(0, cpy);
else
buf.copy(ret, c, 0, cpy);
if (cpy < buf.length)
list[0] = buf.slice(cpy);
else
list.shift();
c += cpy;
}
}
}
return ret;
}
function endReadable(stream) {
var state = stream._readableState;
// If we get here before consuming all the bytes, then that is a
// bug in node. Should never happen.
if (state.length > 0)
throw new Error('endReadable called on non-empty stream');
if (!state.endEmitted) {
state.ended = true;
process.nextTick(function() {
// Check that we didn't get one last unshift.
if (!state.endEmitted && state.length === 0) {
state.endEmitted = true;
stream.readable = false;
stream.emit('end');
}
});
}
}
function forEach (xs, f) {
for (var i = 0, l = xs.length; i < l; i++) {
f(xs[i], i);
}
}
function indexOf (xs, x) {
for (var i = 0, l = xs.length; i < l; i++) {
if (xs[i] === x) return i;
}
return -1;
}
}).call(this,require('_process'))
},{"./_stream_duplex":231,"_process":225,"buffer":76,"core-util-is":236,"events":222,"inherits":223,"isarray":224,"stream":241,"string_decoder/":242,"util":75}],234:[function(require,module,exports){
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
// a transform stream is a readable/writable stream where you do
// something with the data. Sometimes it's called a "filter",
// but that's not a great name for it, since that implies a thing where
// some bits pass through, and others are simply ignored. (That would
// be a valid example of a transform, of course.)
//
// While the output is causally related to the input, it's not a
// necessarily symmetric or synchronous transformation. For example,
// a zlib stream might take multiple plain-text writes(), and then
// emit a single compressed chunk some time in the future.
//
// Here's how this works:
//
// The Transform stream has all the aspects of the readable and writable
// stream classes. When you write(chunk), that calls _write(chunk,cb)
// internally, and returns false if there's a lot of pending writes
// buffered up. When you call read(), that calls _read(n) until
// there's enough pending readable data buffered up.
//
// In a transform stream, the written data is placed in a buffer. When
// _read(n) is called, it transforms the queued up data, calling the
// buffered _write cb's as it consumes chunks. If consuming a single
// written chunk would result in multiple output chunks, then the first
// outputted bit calls the readcb, and subsequent chunks just go into
// the read buffer, and will cause it to emit 'readable' if necessary.
//
// This way, back-pressure is actually determined by the reading side,
// since _read has to be called to start processing a new chunk. However,
// a pathological inflate type of transform can cause excessive buffering
// here. For example, imagine a stream where every byte of input is
// interpreted as an integer from 0-255, and then results in that many
// bytes of output. Writing the 4 bytes {ff,ff,ff,ff} would result in
// 1kb of data being output. In this case, you could write a very small
// amount of input, and end up with a very large amount of output. In
// such a pathological inflating mechanism, there'd be no way to tell
// the system to stop doing the transform. A single 4MB write could
// cause the system to run out of memory.
//
// However, even in such a pathological case, only a single written chunk
// would be consumed, and then the rest would wait (un-transformed) until
// the results of the previous transformed chunk were consumed.
module.exports = Transform;
var Duplex = require('./_stream_duplex');
/**/
var util = require('core-util-is');
util.inherits = require('inherits');
/**/
util.inherits(Transform, Duplex);
function TransformState(options, stream) {
this.afterTransform = function(er, data) {
return afterTransform(stream, er, data);
};
this.needTransform = false;
this.transforming = false;
this.writecb = null;
this.writechunk = null;
}
function afterTransform(stream, er, data) {
var ts = stream._transformState;
ts.transforming = false;
var cb = ts.writecb;
if (!cb)
return stream.emit('error', new Error('no writecb in Transform class'));
ts.writechunk = null;
ts.writecb = null;
if (!util.isNullOrUndefined(data))
stream.push(data);
if (cb)
cb(er);
var rs = stream._readableState;
rs.reading = false;
if (rs.needReadable || rs.length < rs.highWaterMark) {
stream._read(rs.highWaterMark);
}
}
function Transform(options) {
if (!(this instanceof Transform))
return new Transform(options);
Duplex.call(this, options);
this._transformState = new TransformState(options, this);
// when the writable side finishes, then flush out anything remaining.
var stream = this;
// start out asking for a readable event once data is transformed.
this._readableState.needReadable = true;
// we have implemented the _read method, and done the other things
// that Readable wants before the first _read call, so unset the
// sync guard flag.
this._readableState.sync = false;
this.once('prefinish', function() {
if (util.isFunction(this._flush))
this._flush(function(er) {
done(stream, er);
});
else
done(stream);
});
}
Transform.prototype.push = function(chunk, encoding) {
this._transformState.needTransform = false;
return Duplex.prototype.push.call(this, chunk, encoding);
};
// This is the part where you do stuff!
// override this function in implementation classes.
// 'chunk' is an input chunk.
//
// Call `push(newChunk)` to pass along transformed output
// to the readable side. You may call 'push' zero or more times.
//
// Call `cb(err)` when you are done with this chunk. If you pass
// an error, then that'll put the hurt on the whole operation. If you
// never call cb(), then you'll never get another chunk.
Transform.prototype._transform = function(chunk, encoding, cb) {
throw new Error('not implemented');
};
Transform.prototype._write = function(chunk, encoding, cb) {
var ts = this._transformState;
ts.writecb = cb;
ts.writechunk = chunk;
ts.writeencoding = encoding;
if (!ts.transforming) {
var rs = this._readableState;
if (ts.needTransform ||
rs.needReadable ||
rs.length < rs.highWaterMark)
this._read(rs.highWaterMark);
}
};
// Doesn't matter what the args are here.
// _transform does all the work.
// That we got here means that the readable side wants more data.
Transform.prototype._read = function(n) {
var ts = this._transformState;
if (!util.isNull(ts.writechunk) && ts.writecb && !ts.transforming) {
ts.transforming = true;
this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform);
} else {
// mark that we need a transform, so that any data that comes in
// will get processed, now that we've asked for it.
ts.needTransform = true;
}
};
function done(stream, er) {
if (er)
return stream.emit('error', er);
// if there's nothing in the write buffer, then that means
// that nothing more will ever be provided
var ws = stream._writableState;
var ts = stream._transformState;
if (ws.length)
throw new Error('calling transform done when ws.length != 0');
if (ts.transforming)
throw new Error('calling transform done when still transforming');
return stream.push(null);
}
},{"./_stream_duplex":231,"core-util-is":236,"inherits":223}],235:[function(require,module,exports){
(function (process){
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
// A bit simpler than readable streams.
// Implement an async ._write(chunk, cb), and it'll handle all
// the drain event emission and buffering.
module.exports = Writable;
/**/
var Buffer = require('buffer').Buffer;
/**/
Writable.WritableState = WritableState;
/**/
var util = require('core-util-is');
util.inherits = require('inherits');
/**/
var Stream = require('stream');
util.inherits(Writable, Stream);
function WriteReq(chunk, encoding, cb) {
this.chunk = chunk;
this.encoding = encoding;
this.callback = cb;
}
function WritableState(options, stream) {
var Duplex = require('./_stream_duplex');
options = options || {};
// the point at which write() starts returning false
// Note: 0 is a valid value, means that we always return false if
// the entire buffer is not flushed immediately on write()
var hwm = options.highWaterMark;
var defaultHwm = options.objectMode ? 16 : 16 * 1024;
this.highWaterMark = (hwm || hwm === 0) ? hwm : defaultHwm;
// object stream flag to indicate whether or not this stream
// contains buffers or objects.
this.objectMode = !!options.objectMode;
if (stream instanceof Duplex)
this.objectMode = this.objectMode || !!options.writableObjectMode;
// cast to ints.
this.highWaterMark = ~~this.highWaterMark;
this.needDrain = false;
// at the start of calling end()
this.ending = false;
// when end() has been called, and returned
this.ended = false;
// when 'finish' is emitted
this.finished = false;
// should we decode strings into buffers before passing to _write?
// this is here so that some node-core streams can optimize string
// handling at a lower level.
var noDecode = options.decodeStrings === false;
this.decodeStrings = !noDecode;
// Crypto is kind of old and crusty. Historically, its default string
// encoding is 'binary' so we have to make this configurable.
// Everything else in the universe uses 'utf8', though.
this.defaultEncoding = options.defaultEncoding || 'utf8';
// not an actual buffer we keep track of, but a measurement
// of how much we're waiting to get pushed to some underlying
// socket or file.
this.length = 0;
// a flag to see when we're in the middle of a write.
this.writing = false;
// when true all writes will be buffered until .uncork() call
this.corked = 0;
// a flag to be able to tell if the onwrite cb is called immediately,
// or on a later tick. We set this to true at first, because any
// actions that shouldn't happen until "later" should generally also
// not happen before the first write call.
this.sync = true;
// a flag to know if we're processing previously buffered items, which
// may call the _write() callback in the same tick, so that we don't
// end up in an overlapped onwrite situation.
this.bufferProcessing = false;
// the callback that's passed to _write(chunk,cb)
this.onwrite = function(er) {
onwrite(stream, er);
};
// the callback that the user supplies to write(chunk,encoding,cb)
this.writecb = null;
// the amount that is being written when _write is called.
this.writelen = 0;
this.buffer = [];
// number of pending user-supplied write callbacks
// this must be 0 before 'finish' can be emitted
this.pendingcb = 0;
// emit prefinish if the only thing we're waiting for is _write cbs
// This is relevant for synchronous Transform streams
this.prefinished = false;
// True if the error was already emitted and should not be thrown again
this.errorEmitted = false;
}
function Writable(options) {
var Duplex = require('./_stream_duplex');
// Writable ctor is applied to Duplexes, though they're not
// instanceof Writable, they're instanceof Readable.
if (!(this instanceof Writable) && !(this instanceof Duplex))
return new Writable(options);
this._writableState = new WritableState(options, this);
// legacy.
this.writable = true;
Stream.call(this);
}
// Otherwise people can pipe Writable streams, which is just wrong.
Writable.prototype.pipe = function() {
this.emit('error', new Error('Cannot pipe. Not readable.'));
};
function writeAfterEnd(stream, state, cb) {
var er = new Error('write after end');
// TODO: defer error events consistently everywhere, not just the cb
stream.emit('error', er);
process.nextTick(function() {
cb(er);
});
}
// If we get something that is not a buffer, string, null, or undefined,
// and we're not in objectMode, then that's an error.
// Otherwise stream chunks are all considered to be of length=1, and the
// watermarks determine how many objects to keep in the buffer, rather than
// how many bytes or characters.
function validChunk(stream, state, chunk, cb) {
var valid = true;
if (!util.isBuffer(chunk) &&
!util.isString(chunk) &&
!util.isNullOrUndefined(chunk) &&
!state.objectMode) {
var er = new TypeError('Invalid non-string/buffer chunk');
stream.emit('error', er);
process.nextTick(function() {
cb(er);
});
valid = false;
}
return valid;
}
Writable.prototype.write = function(chunk, encoding, cb) {
var state = this._writableState;
var ret = false;
if (util.isFunction(encoding)) {
cb = encoding;
encoding = null;
}
if (util.isBuffer(chunk))
encoding = 'buffer';
else if (!encoding)
encoding = state.defaultEncoding;
if (!util.isFunction(cb))
cb = function() {};
if (state.ended)
writeAfterEnd(this, state, cb);
else if (validChunk(this, state, chunk, cb)) {
state.pendingcb++;
ret = writeOrBuffer(this, state, chunk, encoding, cb);
}
return ret;
};
Writable.prototype.cork = function() {
var state = this._writableState;
state.corked++;
};
Writable.prototype.uncork = function() {
var state = this._writableState;
if (state.corked) {
state.corked--;
if (!state.writing &&
!state.corked &&
!state.finished &&
!state.bufferProcessing &&
state.buffer.length)
clearBuffer(this, state);
}
};
function decodeChunk(state, chunk, encoding) {
if (!state.objectMode &&
state.decodeStrings !== false &&
util.isString(chunk)) {
chunk = new Buffer(chunk, encoding);
}
return chunk;
}
// if we're already writing something, then just put this
// in the queue, and wait our turn. Otherwise, call _write
// If we return false, then we need a drain event, so set that flag.
function writeOrBuffer(stream, state, chunk, encoding, cb) {
chunk = decodeChunk(state, chunk, encoding);
if (util.isBuffer(chunk))
encoding = 'buffer';
var len = state.objectMode ? 1 : chunk.length;
state.length += len;
var ret = state.length < state.highWaterMark;
// we must ensure that previous needDrain will not be reset to false.
if (!ret)
state.needDrain = true;
if (state.writing || state.corked)
state.buffer.push(new WriteReq(chunk, encoding, cb));
else
doWrite(stream, state, false, len, chunk, encoding, cb);
return ret;
}
function doWrite(stream, state, writev, len, chunk, encoding, cb) {
state.writelen = len;
state.writecb = cb;
state.writing = true;
state.sync = true;
if (writev)
stream._writev(chunk, state.onwrite);
else
stream._write(chunk, encoding, state.onwrite);
state.sync = false;
}
function onwriteError(stream, state, sync, er, cb) {
if (sync)
process.nextTick(function() {
state.pendingcb--;
cb(er);
});
else {
state.pendingcb--;
cb(er);
}
stream._writableState.errorEmitted = true;
stream.emit('error', er);
}
function onwriteStateUpdate(state) {
state.writing = false;
state.writecb = null;
state.length -= state.writelen;
state.writelen = 0;
}
function onwrite(stream, er) {
var state = stream._writableState;
var sync = state.sync;
var cb = state.writecb;
onwriteStateUpdate(state);
if (er)
onwriteError(stream, state, sync, er, cb);
else {
// Check if we're actually ready to finish, but don't emit yet
var finished = needFinish(stream, state);
if (!finished &&
!state.corked &&
!state.bufferProcessing &&
state.buffer.length) {
clearBuffer(stream, state);
}
if (sync) {
process.nextTick(function() {
afterWrite(stream, state, finished, cb);
});
} else {
afterWrite(stream, state, finished, cb);
}
}
}
function afterWrite(stream, state, finished, cb) {
if (!finished)
onwriteDrain(stream, state);
state.pendingcb--;
cb();
finishMaybe(stream, state);
}
// Must force callback to be called on nextTick, so that we don't
// emit 'drain' before the write() consumer gets the 'false' return
// value, and has a chance to attach a 'drain' listener.
function onwriteDrain(stream, state) {
if (state.length === 0 && state.needDrain) {
state.needDrain = false;
stream.emit('drain');
}
}
// if there's something in the buffer waiting, then process it
function clearBuffer(stream, state) {
state.bufferProcessing = true;
if (stream._writev && state.buffer.length > 1) {
// Fast case, write everything using _writev()
var cbs = [];
for (var c = 0; c < state.buffer.length; c++)
cbs.push(state.buffer[c].callback);
// count the one we are adding, as well.
// TODO(isaacs) clean this up
state.pendingcb++;
doWrite(stream, state, true, state.length, state.buffer, '', function(err) {
for (var i = 0; i < cbs.length; i++) {
state.pendingcb--;
cbs[i](err);
}
});
// Clear buffer
state.buffer = [];
} else {
// Slow case, write chunks one-by-one
for (var c = 0; c < state.buffer.length; c++) {
var entry = state.buffer[c];
var chunk = entry.chunk;
var encoding = entry.encoding;
var cb = entry.callback;
var len = state.objectMode ? 1 : chunk.length;
doWrite(stream, state, false, len, chunk, encoding, cb);
// if we didn't call the onwrite immediately, then
// it means that we need to wait until it does.
// also, that means that the chunk and cb are currently
// being processed, so move the buffer counter past them.
if (state.writing) {
c++;
break;
}
}
if (c < state.buffer.length)
state.buffer = state.buffer.slice(c);
else
state.buffer.length = 0;
}
state.bufferProcessing = false;
}
Writable.prototype._write = function(chunk, encoding, cb) {
cb(new Error('not implemented'));
};
Writable.prototype._writev = null;
Writable.prototype.end = function(chunk, encoding, cb) {
var state = this._writableState;
if (util.isFunction(chunk)) {
cb = chunk;
chunk = null;
encoding = null;
} else if (util.isFunction(encoding)) {
cb = encoding;
encoding = null;
}
if (!util.isNullOrUndefined(chunk))
this.write(chunk, encoding);
// .end() fully uncorks
if (state.corked) {
state.corked = 1;
this.uncork();
}
// ignore unnecessary end() calls.
if (!state.ending && !state.finished)
endWritable(this, state, cb);
};
function needFinish(stream, state) {
return (state.ending &&
state.length === 0 &&
!state.finished &&
!state.writing);
}
function prefinish(stream, state) {
if (!state.prefinished) {
state.prefinished = true;
stream.emit('prefinish');
}
}
function finishMaybe(stream, state) {
var need = needFinish(stream, state);
if (need) {
if (state.pendingcb === 0) {
prefinish(stream, state);
state.finished = true;
stream.emit('finish');
} else
prefinish(stream, state);
}
return need;
}
function endWritable(stream, state, cb) {
state.ending = true;
finishMaybe(stream, state);
if (cb) {
if (state.finished)
process.nextTick(cb);
else
stream.once('finish', cb);
}
state.ended = true;
}
}).call(this,require('_process'))
},{"./_stream_duplex":231,"_process":225,"buffer":76,"core-util-is":236,"inherits":223,"stream":241}],236:[function(require,module,exports){
(function (Buffer){
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
// NOTE: These type checking functions intentionally don't use `instanceof`
// because it is fragile and can be easily faked with `Object.create()`.
function isArray(ar) {
return Array.isArray(ar);
}
exports.isArray = isArray;
function isBoolean(arg) {
return typeof arg === 'boolean';
}
exports.isBoolean = isBoolean;
function isNull(arg) {
return arg === null;
}
exports.isNull = isNull;
function isNullOrUndefined(arg) {
return arg == null;
}
exports.isNullOrUndefined = isNullOrUndefined;
function isNumber(arg) {
return typeof arg === 'number';
}
exports.isNumber = isNumber;
function isString(arg) {
return typeof arg === 'string';
}
exports.isString = isString;
function isSymbol(arg) {
return typeof arg === 'symbol';
}
exports.isSymbol = isSymbol;
function isUndefined(arg) {
return arg === void 0;
}
exports.isUndefined = isUndefined;
function isRegExp(re) {
return isObject(re) && objectToString(re) === '[object RegExp]';
}
exports.isRegExp = isRegExp;
function isObject(arg) {
return typeof arg === 'object' && arg !== null;
}
exports.isObject = isObject;
function isDate(d) {
return isObject(d) && objectToString(d) === '[object Date]';
}
exports.isDate = isDate;
function isError(e) {
return isObject(e) &&
(objectToString(e) === '[object Error]' || e instanceof Error);
}
exports.isError = isError;
function isFunction(arg) {
return typeof arg === 'function';
}
exports.isFunction = isFunction;
function isPrimitive(arg) {
return arg === null ||
typeof arg === 'boolean' ||
typeof arg === 'number' ||
typeof arg === 'string' ||
typeof arg === 'symbol' || // ES6 symbol
typeof arg === 'undefined';
}
exports.isPrimitive = isPrimitive;
function isBuffer(arg) {
return Buffer.isBuffer(arg);
}
exports.isBuffer = isBuffer;
function objectToString(o) {
return Object.prototype.toString.call(o);
}
}).call(this,require("buffer").Buffer)
},{"buffer":76}],237:[function(require,module,exports){
module.exports = require("./lib/_stream_passthrough.js")
},{"./lib/_stream_passthrough.js":232}],238:[function(require,module,exports){
exports = module.exports = require('./lib/_stream_readable.js');
exports.Stream = require('stream');
exports.Readable = exports;
exports.Writable = require('./lib/_stream_writable.js');
exports.Duplex = require('./lib/_stream_duplex.js');
exports.Transform = require('./lib/_stream_transform.js');
exports.PassThrough = require('./lib/_stream_passthrough.js');
},{"./lib/_stream_duplex.js":231,"./lib/_stream_passthrough.js":232,"./lib/_stream_readable.js":233,"./lib/_stream_transform.js":234,"./lib/_stream_writable.js":235,"stream":241}],239:[function(require,module,exports){
module.exports = require("./lib/_stream_transform.js")
},{"./lib/_stream_transform.js":234}],240:[function(require,module,exports){
module.exports = require("./lib/_stream_writable.js")
},{"./lib/_stream_writable.js":235}],241:[function(require,module,exports){
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
module.exports = Stream;
var EE = require('events').EventEmitter;
var inherits = require('inherits');
inherits(Stream, EE);
Stream.Readable = require('readable-stream/readable.js');
Stream.Writable = require('readable-stream/writable.js');
Stream.Duplex = require('readable-stream/duplex.js');
Stream.Transform = require('readable-stream/transform.js');
Stream.PassThrough = require('readable-stream/passthrough.js');
// Backwards-compat with node 0.4.x
Stream.Stream = Stream;
// old-style streams. Note that the pipe method (the only relevant
// part of this class) is overridden in the Readable class.
function Stream() {
EE.call(this);
}
Stream.prototype.pipe = function(dest, options) {
var source = this;
function ondata(chunk) {
if (dest.writable) {
if (false === dest.write(chunk) && source.pause) {
source.pause();
}
}
}
source.on('data', ondata);
function ondrain() {
if (source.readable && source.resume) {
source.resume();
}
}
dest.on('drain', ondrain);
// If the 'end' option is not supplied, dest.end() will be called when
// source gets the 'end' or 'close' events. Only dest.end() once.
if (!dest._isStdio && (!options || options.end !== false)) {
source.on('end', onend);
source.on('close', onclose);
}
var didOnEnd = false;
function onend() {
if (didOnEnd) return;
didOnEnd = true;
dest.end();
}
function onclose() {
if (didOnEnd) return;
didOnEnd = true;
if (typeof dest.destroy === 'function') dest.destroy();
}
// don't leave dangling pipes when there are errors.
function onerror(er) {
cleanup();
if (EE.listenerCount(this, 'error') === 0) {
throw er; // Unhandled stream error in pipe.
}
}
source.on('error', onerror);
dest.on('error', onerror);
// remove all the event listeners that were added.
function cleanup() {
source.removeListener('data', ondata);
dest.removeListener('drain', ondrain);
source.removeListener('end', onend);
source.removeListener('close', onclose);
source.removeListener('error', onerror);
dest.removeListener('error', onerror);
source.removeListener('end', cleanup);
source.removeListener('close', cleanup);
dest.removeListener('close', cleanup);
}
source.on('end', cleanup);
source.on('close', cleanup);
dest.on('close', cleanup);
dest.emit('pipe', source);
// Allow for unix-like usage: A.pipe(B).pipe(C)
return dest;
};
},{"events":222,"inherits":223,"readable-stream/duplex.js":230,"readable-stream/passthrough.js":237,"readable-stream/readable.js":238,"readable-stream/transform.js":239,"readable-stream/writable.js":240}],242:[function(require,module,exports){
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
var Buffer = require('buffer').Buffer;
var isBufferEncoding = Buffer.isEncoding
|| function(encoding) {
switch (encoding && encoding.toLowerCase()) {
case 'hex': case 'utf8': case 'utf-8': case 'ascii': case 'binary': case 'base64': case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': case 'raw': return true;
default: return false;
}
}
function assertEncoding(encoding) {
if (encoding && !isBufferEncoding(encoding)) {
throw new Error('Unknown encoding: ' + encoding);
}
}
// StringDecoder provides an interface for efficiently splitting a series of
// buffers into a series of JS strings without breaking apart multi-byte
// characters. CESU-8 is handled as part of the UTF-8 encoding.
//
// @TODO Handling all encodings inside a single object makes it very difficult
// to reason about this code, so it should be split up in the future.
// @TODO There should be a utf8-strict encoding that rejects invalid UTF-8 code
// points as used by CESU-8.
var StringDecoder = exports.StringDecoder = function(encoding) {
this.encoding = (encoding || 'utf8').toLowerCase().replace(/[-_]/, '');
assertEncoding(encoding);
switch (this.encoding) {
case 'utf8':
// CESU-8 represents each of Surrogate Pair by 3-bytes
this.surrogateSize = 3;
break;
case 'ucs2':
case 'utf16le':
// UTF-16 represents each of Surrogate Pair by 2-bytes
this.surrogateSize = 2;
this.detectIncompleteChar = utf16DetectIncompleteChar;
break;
case 'base64':
// Base-64 stores 3 bytes in 4 chars, and pads the remainder.
this.surrogateSize = 3;
this.detectIncompleteChar = base64DetectIncompleteChar;
break;
default:
this.write = passThroughWrite;
return;
}
// Enough space to store all bytes of a single character. UTF-8 needs 4
// bytes, but CESU-8 may require up to 6 (3 bytes per surrogate).
this.charBuffer = new Buffer(6);
// Number of bytes received for the current incomplete multi-byte character.
this.charReceived = 0;
// Number of bytes expected for the current incomplete multi-byte character.
this.charLength = 0;
};
// write decodes the given buffer and returns it as JS string that is
// guaranteed to not contain any partial multi-byte characters. Any partial
// character found at the end of the buffer is buffered up, and will be
// returned when calling write again with the remaining bytes.
//
// Note: Converting a Buffer containing an orphan surrogate to a String
// currently works, but converting a String to a Buffer (via `new Buffer`, or
// Buffer#write) will replace incomplete surrogates with the unicode
// replacement character. See https://codereview.chromium.org/121173009/ .
StringDecoder.prototype.write = function(buffer) {
var charStr = '';
// if our last write ended with an incomplete multibyte character
while (this.charLength) {
// determine how many remaining bytes this buffer has to offer for this char
var available = (buffer.length >= this.charLength - this.charReceived) ?
this.charLength - this.charReceived :
buffer.length;
// add the new bytes to the char buffer
buffer.copy(this.charBuffer, this.charReceived, 0, available);
this.charReceived += available;
if (this.charReceived < this.charLength) {
// still not enough chars in this buffer? wait for more ...
return '';
}
// remove bytes belonging to the current character from the buffer
buffer = buffer.slice(available, buffer.length);
// get the character that was split
charStr = this.charBuffer.slice(0, this.charLength).toString(this.encoding);
// CESU-8: lead surrogate (D800-DBFF) is also the incomplete character
var charCode = charStr.charCodeAt(charStr.length - 1);
if (charCode >= 0xD800 && charCode <= 0xDBFF) {
this.charLength += this.surrogateSize;
charStr = '';
continue;
}
this.charReceived = this.charLength = 0;
// if there are no more bytes in this buffer, just emit our char
if (buffer.length === 0) {
return charStr;
}
break;
}
// determine and set charLength / charReceived
this.detectIncompleteChar(buffer);
var end = buffer.length;
if (this.charLength) {
// buffer the incomplete character bytes we got
buffer.copy(this.charBuffer, 0, buffer.length - this.charReceived, end);
end -= this.charReceived;
}
charStr += buffer.toString(this.encoding, 0, end);
var end = charStr.length - 1;
var charCode = charStr.charCodeAt(end);
// CESU-8: lead surrogate (D800-DBFF) is also the incomplete character
if (charCode >= 0xD800 && charCode <= 0xDBFF) {
var size = this.surrogateSize;
this.charLength += size;
this.charReceived += size;
this.charBuffer.copy(this.charBuffer, size, 0, size);
buffer.copy(this.charBuffer, 0, 0, size);
return charStr.substring(0, end);
}
// or just emit the charStr
return charStr;
};
// detectIncompleteChar determines if there is an incomplete UTF-8 character at
// the end of the given buffer. If so, it sets this.charLength to the byte
// length that character, and sets this.charReceived to the number of bytes
// that are available for this character.
StringDecoder.prototype.detectIncompleteChar = function(buffer) {
// determine how many bytes we have to check at the end of this buffer
var i = (buffer.length >= 3) ? 3 : buffer.length;
// Figure out if one of the last i bytes of our buffer announces an
// incomplete char.
for (; i > 0; i--) {
var c = buffer[buffer.length - i];
// See http://en.wikipedia.org/wiki/UTF-8#Description
// 110XXXXX
if (i == 1 && c >> 5 == 0x06) {
this.charLength = 2;
break;
}
// 1110XXXX
if (i <= 2 && c >> 4 == 0x0E) {
this.charLength = 3;
break;
}
// 11110XXX
if (i <= 3 && c >> 3 == 0x1E) {
this.charLength = 4;
break;
}
}
this.charReceived = i;
};
StringDecoder.prototype.end = function(buffer) {
var res = '';
if (buffer && buffer.length)
res = this.write(buffer);
if (this.charReceived) {
var cr = this.charReceived;
var buf = this.charBuffer;
var enc = this.encoding;
res += buf.slice(0, cr).toString(enc);
}
return res;
};
function passThroughWrite(buffer) {
return buffer.toString(this.encoding);
}
function utf16DetectIncompleteChar(buffer) {
this.charReceived = buffer.length % 2;
this.charLength = this.charReceived ? 2 : 0;
}
function base64DetectIncompleteChar(buffer) {
this.charReceived = buffer.length % 3;
this.charLength = this.charReceived ? 3 : 0;
}
},{"buffer":76}],243:[function(require,module,exports){
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
var punycode = require('punycode');
exports.parse = urlParse;
exports.resolve = urlResolve;
exports.resolveObject = urlResolveObject;
exports.format = urlFormat;
exports.Url = Url;
function Url() {
this.protocol = null;
this.slashes = null;
this.auth = null;
this.host = null;
this.port = null;
this.hostname = null;
this.hash = null;
this.search = null;
this.query = null;
this.pathname = null;
this.path = null;
this.href = null;
}
// Reference: RFC 3986, RFC 1808, RFC 2396
// define these here so at least they only have to be
// compiled once on the first module load.
var protocolPattern = /^([a-z0-9.+-]+:)/i,
portPattern = /:[0-9]*$/,
// RFC 2396: characters reserved for delimiting URLs.
// We actually just auto-escape these.
delims = ['<', '>', '"', '`', ' ', '\r', '\n', '\t'],
// RFC 2396: characters not allowed for various reasons.
unwise = ['{', '}', '|', '\\', '^', '`'].concat(delims),
// Allowed by RFCs, but cause of XSS attacks. Always escape these.
autoEscape = ['\''].concat(unwise),
// Characters that are never ever allowed in a hostname.
// Note that any invalid chars are also handled, but these
// are the ones that are *expected* to be seen, so we fast-path
// them.
nonHostChars = ['%', '/', '?', ';', '#'].concat(autoEscape),
hostEndingChars = ['/', '?', '#'],
hostnameMaxLen = 255,
hostnamePartPattern = /^[a-z0-9A-Z_-]{0,63}$/,
hostnamePartStart = /^([a-z0-9A-Z_-]{0,63})(.*)$/,
// protocols that can allow "unsafe" and "unwise" chars.
unsafeProtocol = {
'javascript': true,
'javascript:': true
},
// protocols that never have a hostname.
hostlessProtocol = {
'javascript': true,
'javascript:': true
},
// protocols that always contain a // bit.
slashedProtocol = {
'http': true,
'https': true,
'ftp': true,
'gopher': true,
'file': true,
'http:': true,
'https:': true,
'ftp:': true,
'gopher:': true,
'file:': true
},
querystring = require('querystring');
function urlParse(url, parseQueryString, slashesDenoteHost) {
if (url && isObject(url) && url instanceof Url) return url;
var u = new Url;
u.parse(url, parseQueryString, slashesDenoteHost);
return u;
}
Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) {
if (!isString(url)) {
throw new TypeError("Parameter 'url' must be a string, not " + typeof url);
}
var rest = url;
// trim before proceeding.
// This is to support parse stuff like " http://foo.com \n"
rest = rest.trim();
var proto = protocolPattern.exec(rest);
if (proto) {
proto = proto[0];
var lowerProto = proto.toLowerCase();
this.protocol = lowerProto;
rest = rest.substr(proto.length);
}
// figure out if it's got a host
// user@server is *always* interpreted as a hostname, and url
// resolution will treat //foo/bar as host=foo,path=bar because that's
// how the browser resolves relative URLs.
if (slashesDenoteHost || proto || rest.match(/^\/\/[^@\/]+@[^@\/]+/)) {
var slashes = rest.substr(0, 2) === '//';
if (slashes && !(proto && hostlessProtocol[proto])) {
rest = rest.substr(2);
this.slashes = true;
}
}
if (!hostlessProtocol[proto] &&
(slashes || (proto && !slashedProtocol[proto]))) {
// there's a hostname.
// the first instance of /, ?, ;, or # ends the host.
//
// If there is an @ in the hostname, then non-host chars *are* allowed
// to the left of the last @ sign, unless some host-ending character
// comes *before* the @-sign.
// URLs are obnoxious.
//
// ex:
// http://a@b@c/ => user:a@b host:c
// http://a@b?@c => user:a host:c path:/?@c
// v0.12 TODO(isaacs): This is not quite how Chrome does things.
// Review our test case against browsers more comprehensively.
// find the first instance of any hostEndingChars
var hostEnd = -1;
for (var i = 0; i < hostEndingChars.length; i++) {
var hec = rest.indexOf(hostEndingChars[i]);
if (hec !== -1 && (hostEnd === -1 || hec < hostEnd))
hostEnd = hec;
}
// at this point, either we have an explicit point where the
// auth portion cannot go past, or the last @ char is the decider.
var auth, atSign;
if (hostEnd === -1) {
// atSign can be anywhere.
atSign = rest.lastIndexOf('@');
} else {
// atSign must be in auth portion.
// http://a@b/c@d => host:b auth:a path:/c@d
atSign = rest.lastIndexOf('@', hostEnd);
}
// Now we have a portion which is definitely the auth.
// Pull that off.
if (atSign !== -1) {
auth = rest.slice(0, atSign);
rest = rest.slice(atSign + 1);
this.auth = decodeURIComponent(auth);
}
// the host is the remaining to the left of the first non-host char
hostEnd = -1;
for (var i = 0; i < nonHostChars.length; i++) {
var hec = rest.indexOf(nonHostChars[i]);
if (hec !== -1 && (hostEnd === -1 || hec < hostEnd))
hostEnd = hec;
}
// if we still have not hit it, then the entire thing is a host.
if (hostEnd === -1)
hostEnd = rest.length;
this.host = rest.slice(0, hostEnd);
rest = rest.slice(hostEnd);
// pull out port.
this.parseHost();
// we've indicated that there is a hostname,
// so even if it's empty, it has to be present.
this.hostname = this.hostname || '';
// if hostname begins with [ and ends with ]
// assume that it's an IPv6 address.
var ipv6Hostname = this.hostname[0] === '[' &&
this.hostname[this.hostname.length - 1] === ']';
// validate a little.
if (!ipv6Hostname) {
var hostparts = this.hostname.split(/\./);
for (var i = 0, l = hostparts.length; i < l; i++) {
var part = hostparts[i];
if (!part) continue;
if (!part.match(hostnamePartPattern)) {
var newpart = '';
for (var j = 0, k = part.length; j < k; j++) {
if (part.charCodeAt(j) > 127) {
// we replace non-ASCII char with a temporary placeholder
// we need this to make sure size of hostname is not
// broken by replacing non-ASCII by nothing
newpart += 'x';
} else {
newpart += part[j];
}
}
// we test again with ASCII char only
if (!newpart.match(hostnamePartPattern)) {
var validParts = hostparts.slice(0, i);
var notHost = hostparts.slice(i + 1);
var bit = part.match(hostnamePartStart);
if (bit) {
validParts.push(bit[1]);
notHost.unshift(bit[2]);
}
if (notHost.length) {
rest = '/' + notHost.join('.') + rest;
}
this.hostname = validParts.join('.');
break;
}
}
}
}
if (this.hostname.length > hostnameMaxLen) {
this.hostname = '';
} else {
// hostnames are always lower case.
this.hostname = this.hostname.toLowerCase();
}
if (!ipv6Hostname) {
// IDNA Support: Returns a puny coded representation of "domain".
// It only converts the part of the domain name that
// has non ASCII characters. I.e. it dosent matter if
// you call it with a domain that already is in ASCII.
var domainArray = this.hostname.split('.');
var newOut = [];
for (var i = 0; i < domainArray.length; ++i) {
var s = domainArray[i];
newOut.push(s.match(/[^A-Za-z0-9_-]/) ?
'xn--' + punycode.encode(s) : s);
}
this.hostname = newOut.join('.');
}
var p = this.port ? ':' + this.port : '';
var h = this.hostname || '';
this.host = h + p;
this.href += this.host;
// strip [ and ] from the hostname
// the host field still retains them, though
if (ipv6Hostname) {
this.hostname = this.hostname.substr(1, this.hostname.length - 2);
if (rest[0] !== '/') {
rest = '/' + rest;
}
}
}
// now rest is set to the post-host stuff.
// chop off any delim chars.
if (!unsafeProtocol[lowerProto]) {
// First, make 100% sure that any "autoEscape" chars get
// escaped, even if encodeURIComponent doesn't think they
// need to be.
for (var i = 0, l = autoEscape.length; i < l; i++) {
var ae = autoEscape[i];
var esc = encodeURIComponent(ae);
if (esc === ae) {
esc = escape(ae);
}
rest = rest.split(ae).join(esc);
}
}
// chop off from the tail first.
var hash = rest.indexOf('#');
if (hash !== -1) {
// got a fragment string.
this.hash = rest.substr(hash);
rest = rest.slice(0, hash);
}
var qm = rest.indexOf('?');
if (qm !== -1) {
this.search = rest.substr(qm);
this.query = rest.substr(qm + 1);
if (parseQueryString) {
this.query = querystring.parse(this.query);
}
rest = rest.slice(0, qm);
} else if (parseQueryString) {
// no query string, but parseQueryString still requested
this.search = '';
this.query = {};
}
if (rest) this.pathname = rest;
if (slashedProtocol[lowerProto] &&
this.hostname && !this.pathname) {
this.pathname = '/';
}
//to support http.request
if (this.pathname || this.search) {
var p = this.pathname || '';
var s = this.search || '';
this.path = p + s;
}
// finally, reconstruct the href based on what has been validated.
this.href = this.format();
return this;
};
// format a parsed object into a url string
function urlFormat(obj) {
// ensure it's an object, and not a string url.
// If it's an obj, this is a no-op.
// this way, you can call url_format() on strings
// to clean up potentially wonky urls.
if (isString(obj)) obj = urlParse(obj);
if (!(obj instanceof Url)) return Url.prototype.format.call(obj);
return obj.format();
}
Url.prototype.format = function() {
var auth = this.auth || '';
if (auth) {
auth = encodeURIComponent(auth);
auth = auth.replace(/%3A/i, ':');
auth += '@';
}
var protocol = this.protocol || '',
pathname = this.pathname || '',
hash = this.hash || '',
host = false,
query = '';
if (this.host) {
host = auth + this.host;
} else if (this.hostname) {
host = auth + (this.hostname.indexOf(':') === -1 ?
this.hostname :
'[' + this.hostname + ']');
if (this.port) {
host += ':' + this.port;
}
}
if (this.query &&
isObject(this.query) &&
Object.keys(this.query).length) {
query = querystring.stringify(this.query);
}
var search = this.search || (query && ('?' + query)) || '';
if (protocol && protocol.substr(-1) !== ':') protocol += ':';
// only the slashedProtocols get the //. Not mailto:, xmpp:, etc.
// unless they had them to begin with.
if (this.slashes ||
(!protocol || slashedProtocol[protocol]) && host !== false) {
host = '//' + (host || '');
if (pathname && pathname.charAt(0) !== '/') pathname = '/' + pathname;
} else if (!host) {
host = '';
}
if (hash && hash.charAt(0) !== '#') hash = '#' + hash;
if (search && search.charAt(0) !== '?') search = '?' + search;
pathname = pathname.replace(/[?#]/g, function(match) {
return encodeURIComponent(match);
});
search = search.replace('#', '%23');
return protocol + host + pathname + search + hash;
};
function urlResolve(source, relative) {
return urlParse(source, false, true).resolve(relative);
}
Url.prototype.resolve = function(relative) {
return this.resolveObject(urlParse(relative, false, true)).format();
};
function urlResolveObject(source, relative) {
if (!source) return relative;
return urlParse(source, false, true).resolveObject(relative);
}
Url.prototype.resolveObject = function(relative) {
if (isString(relative)) {
var rel = new Url();
rel.parse(relative, false, true);
relative = rel;
}
var result = new Url();
Object.keys(this).forEach(function(k) {
result[k] = this[k];
}, this);
// hash is always overridden, no matter what.
// even href="" will remove it.
result.hash = relative.hash;
// if the relative url is empty, then there's nothing left to do here.
if (relative.href === '') {
result.href = result.format();
return result;
}
// hrefs like //foo/bar always cut to the protocol.
if (relative.slashes && !relative.protocol) {
// take everything except the protocol from relative
Object.keys(relative).forEach(function(k) {
if (k !== 'protocol')
result[k] = relative[k];
});
//urlParse appends trailing / to urls like http://www.example.com
if (slashedProtocol[result.protocol] &&
result.hostname && !result.pathname) {
result.path = result.pathname = '/';
}
result.href = result.format();
return result;
}
if (relative.protocol && relative.protocol !== result.protocol) {
// if it's a known url protocol, then changing
// the protocol does weird things
// first, if it's not file:, then we MUST have a host,
// and if there was a path
// to begin with, then we MUST have a path.
// if it is file:, then the host is dropped,
// because that's known to be hostless.
// anything else is assumed to be absolute.
if (!slashedProtocol[relative.protocol]) {
Object.keys(relative).forEach(function(k) {
result[k] = relative[k];
});
result.href = result.format();
return result;
}
result.protocol = relative.protocol;
if (!relative.host && !hostlessProtocol[relative.protocol]) {
var relPath = (relative.pathname || '').split('/');
while (relPath.length && !(relative.host = relPath.shift()));
if (!relative.host) relative.host = '';
if (!relative.hostname) relative.hostname = '';
if (relPath[0] !== '') relPath.unshift('');
if (relPath.length < 2) relPath.unshift('');
result.pathname = relPath.join('/');
} else {
result.pathname = relative.pathname;
}
result.search = relative.search;
result.query = relative.query;
result.host = relative.host || '';
result.auth = relative.auth;
result.hostname = relative.hostname || relative.host;
result.port = relative.port;
// to support http.request
if (result.pathname || result.search) {
var p = result.pathname || '';
var s = result.search || '';
result.path = p + s;
}
result.slashes = result.slashes || relative.slashes;
result.href = result.format();
return result;
}
var isSourceAbs = (result.pathname && result.pathname.charAt(0) === '/'),
isRelAbs = (
relative.host ||
relative.pathname && relative.pathname.charAt(0) === '/'
),
mustEndAbs = (isRelAbs || isSourceAbs ||
(result.host && relative.pathname)),
removeAllDots = mustEndAbs,
srcPath = result.pathname && result.pathname.split('/') || [],
relPath = relative.pathname && relative.pathname.split('/') || [],
psychotic = result.protocol && !slashedProtocol[result.protocol];
// if the url is a non-slashed url, then relative
// links like ../.. should be able
// to crawl up to the hostname, as well. This is strange.
// result.protocol has already been set by now.
// Later on, put the first path part into the host field.
if (psychotic) {
result.hostname = '';
result.port = null;
if (result.host) {
if (srcPath[0] === '') srcPath[0] = result.host;
else srcPath.unshift(result.host);
}
result.host = '';
if (relative.protocol) {
relative.hostname = null;
relative.port = null;
if (relative.host) {
if (relPath[0] === '') relPath[0] = relative.host;
else relPath.unshift(relative.host);
}
relative.host = null;
}
mustEndAbs = mustEndAbs && (relPath[0] === '' || srcPath[0] === '');
}
if (isRelAbs) {
// it's absolute.
result.host = (relative.host || relative.host === '') ?
relative.host : result.host;
result.hostname = (relative.hostname || relative.hostname === '') ?
relative.hostname : result.hostname;
result.search = relative.search;
result.query = relative.query;
srcPath = relPath;
// fall through to the dot-handling below.
} else if (relPath.length) {
// it's relative
// throw away the existing file, and take the new path instead.
if (!srcPath) srcPath = [];
srcPath.pop();
srcPath = srcPath.concat(relPath);
result.search = relative.search;
result.query = relative.query;
} else if (!isNullOrUndefined(relative.search)) {
// just pull out the search.
// like href='?foo'.
// Put this after the other two cases because it simplifies the booleans
if (psychotic) {
result.hostname = result.host = srcPath.shift();
//occationaly the auth can get stuck only in host
//this especialy happens in cases like
//url.resolveObject('mailto:local1@domain1', 'local2@domain2')
var authInHost = result.host && result.host.indexOf('@') > 0 ?
result.host.split('@') : false;
if (authInHost) {
result.auth = authInHost.shift();
result.host = result.hostname = authInHost.shift();
}
}
result.search = relative.search;
result.query = relative.query;
//to support http.request
if (!isNull(result.pathname) || !isNull(result.search)) {
result.path = (result.pathname ? result.pathname : '') +
(result.search ? result.search : '');
}
result.href = result.format();
return result;
}
if (!srcPath.length) {
// no path at all. easy.
// we've already handled the other stuff above.
result.pathname = null;
//to support http.request
if (result.search) {
result.path = '/' + result.search;
} else {
result.path = null;
}
result.href = result.format();
return result;
}
// if a url ENDs in . or .., then it must get a trailing slash.
// however, if it ends in anything else non-slashy,
// then it must NOT get a trailing slash.
var last = srcPath.slice(-1)[0];
var hasTrailingSlash = (
(result.host || relative.host) && (last === '.' || last === '..') ||
last === '');
// strip single dots, resolve double dots to parent dir
// if the path tries to go above the root, `up` ends up > 0
var up = 0;
for (var i = srcPath.length; i >= 0; i--) {
last = srcPath[i];
if (last == '.') {
srcPath.splice(i, 1);
} else if (last === '..') {
srcPath.splice(i, 1);
up++;
} else if (up) {
srcPath.splice(i, 1);
up--;
}
}
// if the path is allowed to go above the root, restore leading ..s
if (!mustEndAbs && !removeAllDots) {
for (; up--; up) {
srcPath.unshift('..');
}
}
if (mustEndAbs && srcPath[0] !== '' &&
(!srcPath[0] || srcPath[0].charAt(0) !== '/')) {
srcPath.unshift('');
}
if (hasTrailingSlash && (srcPath.join('/').substr(-1) !== '/')) {
srcPath.push('');
}
var isAbsolute = srcPath[0] === '' ||
(srcPath[0] && srcPath[0].charAt(0) === '/');
// put the host back
if (psychotic) {
result.hostname = result.host = isAbsolute ? '' :
srcPath.length ? srcPath.shift() : '';
//occationaly the auth can get stuck only in host
//this especialy happens in cases like
//url.resolveObject('mailto:local1@domain1', 'local2@domain2')
var authInHost = result.host && result.host.indexOf('@') > 0 ?
result.host.split('@') : false;
if (authInHost) {
result.auth = authInHost.shift();
result.host = result.hostname = authInHost.shift();
}
}
mustEndAbs = mustEndAbs || (result.host && srcPath.length);
if (mustEndAbs && !isAbsolute) {
srcPath.unshift('');
}
if (!srcPath.length) {
result.pathname = null;
result.path = null;
} else {
result.pathname = srcPath.join('/');
}
//to support request.http
if (!isNull(result.pathname) || !isNull(result.search)) {
result.path = (result.pathname ? result.pathname : '') +
(result.search ? result.search : '');
}
result.auth = relative.auth || result.auth;
result.slashes = result.slashes || relative.slashes;
result.href = result.format();
return result;
};
Url.prototype.parseHost = function() {
var host = this.host;
var port = portPattern.exec(host);
if (port) {
port = port[0];
if (port !== ':') {
this.port = port.substr(1);
}
host = host.substr(0, host.length - port.length);
}
if (host) this.hostname = host;
};
function isString(arg) {
return typeof arg === "string";
}
function isObject(arg) {
return typeof arg === 'object' && arg !== null;
}
function isNull(arg) {
return arg === null;
}
function isNullOrUndefined(arg) {
return arg == null;
}
},{"punycode":226,"querystring":229}],244:[function(require,module,exports){
var indexOf = require('indexof');
var Object_keys = function (obj) {
if (Object.keys) return Object.keys(obj)
else {
var res = [];
for (var key in obj) res.push(key)
return res;
}
};
var forEach = function (xs, fn) {
if (xs.forEach) return xs.forEach(fn)
else for (var i = 0; i < xs.length; i++) {
fn(xs[i], i, xs);
}
};
var defineProp = (function() {
try {
Object.defineProperty({}, '_', {});
return function(obj, name, value) {
Object.defineProperty(obj, name, {
writable: true,
enumerable: false,
configurable: true,
value: value
})
};
} catch(e) {
return function(obj, name, value) {
obj[name] = value;
};
}
}());
var globals = ['Array', 'Boolean', 'Date', 'Error', 'EvalError', 'Function',
'Infinity', 'JSON', 'Math', 'NaN', 'Number', 'Object', 'RangeError',
'ReferenceError', 'RegExp', 'String', 'SyntaxError', 'TypeError', 'URIError',
'decodeURI', 'decodeURIComponent', 'encodeURI', 'encodeURIComponent', 'escape',
'eval', 'isFinite', 'isNaN', 'parseFloat', 'parseInt', 'undefined', 'unescape'];
function Context() {}
Context.prototype = {};
var Script = exports.Script = function NodeScript (code) {
if (!(this instanceof Script)) return new Script(code);
this.code = code;
};
Script.prototype.runInContext = function (context) {
if (!(context instanceof Context)) {
throw new TypeError("needs a 'context' argument.");
}
var iframe = document.createElement('iframe');
if (!iframe.style) iframe.style = {};
iframe.style.display = 'none';
document.body.appendChild(iframe);
var win = iframe.contentWindow;
var wEval = win.eval, wExecScript = win.execScript;
if (!wEval && wExecScript) {
// win.eval() magically appears when this is called in IE:
wExecScript.call(win, 'null');
wEval = win.eval;
}
forEach(Object_keys(context), function (key) {
win[key] = context[key];
});
forEach(globals, function (key) {
if (context[key]) {
win[key] = context[key];
}
});
var winKeys = Object_keys(win);
var res = wEval.call(win, this.code);
forEach(Object_keys(win), function (key) {
// Avoid copying circular objects like `top` and `window` by only
// updating existing context properties or new properties in the `win`
// that was only introduced after the eval.
if (key in context || indexOf(winKeys, key) === -1) {
context[key] = win[key];
}
});
forEach(globals, function (key) {
if (!(key in context)) {
defineProp(context, key, win[key]);
}
});
document.body.removeChild(iframe);
return res;
};
Script.prototype.runInThisContext = function () {
return eval(this.code); // maybe...
};
Script.prototype.runInNewContext = function (context) {
var ctx = Script.createContext(context);
var res = this.runInContext(ctx);
forEach(Object_keys(ctx), function (key) {
context[key] = ctx[key];
});
return res;
};
forEach(Object_keys(Script.prototype), function (name) {
exports[name] = Script[name] = function (code) {
var s = Script(code);
return s[name].apply(s, [].slice.call(arguments, 1));
};
});
exports.createScript = function (code) {
return exports.Script(code);
};
exports.createContext = Script.createContext = function (context) {
var copy = new Context();
if(typeof context === 'object') {
forEach(Object_keys(context), function (key) {
copy[key] = context[key];
});
}
return copy;
};
},{"indexof":245}],245:[function(require,module,exports){
var indexOf = [].indexOf;
module.exports = function(arr, obj){
if (indexOf) return arr.indexOf(obj);
for (var i = 0; i < arr.length; ++i) {
if (arr[i] === obj) return i;
}
return -1;
};
},{}],246:[function(require,module,exports){
(function (Buffer){
(function () {
"use strict";
function btoa(str) {
var buffer
;
if (str instanceof Buffer) {
buffer = str;
} else {
buffer = new Buffer(str.toString(), 'binary');
}
return buffer.toString('base64');
}
module.exports = btoa;
}());
}).call(this,require("buffer").Buffer)
},{"buffer":76}],247:[function(require,module,exports){
// Diacritics.js
//
// Started as something to be an equivalent of the Google Java Library diacritics library for JavaScript.
// Found this: http://jsperf.com/diacritics/6 and converted it into a reusable module.
//
// @author Nijiko Yonskai
// @license MIT
// @copyright Nijikokun 2013
(function (name, definition) {
if (typeof module != 'undefined' && module.exports) module.exports = definition()
else if (typeof define == 'function' && define.amd) define(definition)
else this[name] = definition()
})('Diacritics', function () {
// Create public object
var output = {
map: {}
};
// Create private reference map.
var reference = [
{'base':' ', 'letters':'\u00A0'},
{'base':'A', 'letters':'\u0041\u24B6\uFF21\u00C0\u00C1\u00C2\u1EA6\u1EA4\u1EAA\u1EA8\u00C3\u0100\u0102\u1EB0\u1EAE\u1EB4\u1EB2\u0226\u01E0\u00C4\u01DE\u1EA2\u00C5\u01FA\u01CD\u0200\u0202\u1EA0\u1EAC\u1EB6\u1E00\u0104\u023A\u2C6F'},
{'base':'AA', 'letters':'\uA732'},
{'base':'AE', 'letters':'\u00C6\u01FC\u01E2'},
{'base':'AO', 'letters':'\uA734'},
{'base':'AU', 'letters':'\uA736'},
{'base':'AV', 'letters':'\uA738\uA73A'},
{'base':'AY', 'letters':'\uA73C'},
{'base':'B', 'letters':'\u0042\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0182\u0181'},
{'base':'C', 'letters':'\u0043\u24B8\uFF23\u0106\u0108\u010A\u010C\u00C7\u1E08\u0187\u023B\uA73E'},
{'base':'D', 'letters':'\u0044\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018B\u018A\u0189\uA779'},
{'base':'DZ', 'letters':'\u01F1\u01C4'},
{'base':'Dz', 'letters':'\u01F2\u01C5'},
{'base':'E', 'letters':'\u0045\u24BA\uFF25\u00C8\u00C9\u00CA\u1EC0\u1EBE\u1EC4\u1EC2\u1EBC\u0112\u1E14\u1E16\u0114\u0116\u00CB\u1EBA\u011A\u0204\u0206\u1EB8\u1EC6\u0228\u1E1C\u0118\u1E18\u1E1A\u0190\u018E'},
{'base':'F', 'letters':'\u0046\u24BB\uFF26\u1E1E\u0191\uA77B'},
{'base':'G', 'letters':'\u0047\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4\u0193\uA7A0\uA77D\uA77E'},
{'base':'H', 'letters':'\u0048\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D'},
{'base':'I', 'letters':'\u0049\u24BE\uFF29\u00CC\u00CD\u00CE\u0128\u012A\u012C\u0130\u00CF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197'},
{'base':'J', 'letters':'\u004A\u24BF\uFF2A\u0134\u0248'},
{'base':'K', 'letters':'\u004B\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2'},
{'base':'L', 'letters':'\u004C\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u0141\u023D\u2C62\u2C60\uA748\uA746\uA780'},
{'base':'LJ', 'letters':'\u01C7'},
{'base':'Lj', 'letters':'\u01C8'},
{'base':'M', 'letters':'\u004D\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C'},
{'base':'N', 'letters':'\u004E\u24C3\uFF2E\u01F8\u0143\u00D1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u0220\u019D\uA790\uA7A4'},
{'base':'NJ', 'letters':'\u01CA'},
{'base':'Nj', 'letters':'\u01CB'},
{'base':'O', 'letters':'\u004F\u24C4\uFF2F\u00D2\u00D3\u00D4\u1ED2\u1ED0\u1ED6\u1ED4\u00D5\u1E4C\u022C\u1E4E\u014C\u1E50\u1E52\u014E\u022E\u0230\u00D6\u022A\u1ECE\u0150\u01D1\u020C\u020E\u01A0\u1EDC\u1EDA\u1EE0\u1EDE\u1EE2\u1ECC\u1ED8\u01EA\u01EC\u00D8\u01FE\u0186\u019F\uA74A\uA74C'},
{'base':'OI', 'letters':'\u01A2'},
{'base':'OO', 'letters':'\uA74E'},
{'base':'OU', 'letters':'\u0222'},
{'base':'P', 'letters':'\u0050\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754'},
{'base':'Q', 'letters':'\u0051\u24C6\uFF31\uA756\uA758\u024A'},
{'base':'R', 'letters':'\u0052\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782'},
{'base':'S', 'letters':'\u0053\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784'},
{'base':'T', 'letters':'\u0054\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786'},
{'base':'Th', 'letters':'\u00DE'},
{'base':'TZ', 'letters':'\uA728'},
{'base':'U', 'letters':'\u0055\u24CA\uFF35\u00D9\u00DA\u00DB\u0168\u1E78\u016A\u1E7A\u016C\u00DC\u01DB\u01D7\u01D5\u01D9\u1EE6\u016E\u0170\u01D3\u0214\u0216\u01AF\u1EEA\u1EE8\u1EEE\u1EEC\u1EF0\u1EE4\u1E72\u0172\u1E76\u1E74\u0244'},
{'base':'V', 'letters':'\u0056\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245'},
{'base':'VY', 'letters':'\uA760'},
{'base':'W', 'letters':'\u0057\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72'},
{'base':'X', 'letters':'\u0058\u24CD\uFF38\u1E8A\u1E8C'},
{'base':'Y', 'letters':'\u0059\u24CE\uFF39\u1EF2\u00DD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE'},
{'base':'Z', 'letters':'\u005A\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762'},
{'base':'a', 'letters':'\u0061\u24D0\uFF41\u1E9A\u00E0\u00E1\u00E2\u1EA7\u1EA5\u1EAB\u1EA9\u00E3\u0101\u0103\u1EB1\u1EAF\u1EB5\u1EB3\u0227\u01E1\u00E4\u01DF\u1EA3\u00E5\u01FB\u01CE\u0201\u0203\u1EA1\u1EAD\u1EB7\u1E01\u0105\u2C65\u0250\u0251'},
{'base':'aa', 'letters':'\uA733'},
{'base':'ae', 'letters':'\u00E6\u01FD\u01E3'},
{'base':'ao', 'letters':'\uA735'},
{'base':'au', 'letters':'\uA737'},
{'base':'av', 'letters':'\uA739\uA73B'},
{'base':'ay', 'letters':'\uA73D'},
{'base':'b', 'letters':'\u0062\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253'},
{'base':'c', 'letters':'\u0063\u24D2\uFF43\u0107\u0109\u010B\u010D\u00E7\u1E09\u0188\u023C\uA73F\u2184'},
{'base':'d', 'letters':'\u0064\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\uA77A'},
{'base':'dz', 'letters':'\u01F3\u01C6'},
{'base':'e', 'letters':'\u0065\u24D4\uFF45\u00E8\u00E9\u00EA\u1EC1\u1EBF\u1EC5\u1EC3\u1EBD\u0113\u1E15\u1E17\u0115\u0117\u00EB\u1EBB\u011B\u0205\u0207\u1EB9\u1EC7\u0229\u1E1D\u0119\u1E19\u1E1B\u0247\u025B\u01DD'},
{'base':'f', 'letters':'\u0066\u24D5\uFF46\u1E1F\u0192\uA77C'},
{'base':'ff', 'letters':'\uFB00'},
{'base':'fi', 'letters':'\uFB01'},
{'base':'fl', 'letters':'\uFB02'},
{'base':'ffi', 'letters':'\uFB03'},
{'base':'ffl', 'letters':'\uFB04'},
{'base':'g', 'letters':'\u0067\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\u1D79\uA77F'},
{'base':'h', 'letters':'\u0068\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265'},
{'base':'hv', 'letters':'\u0195'},
{'base':'i', 'letters':'\u0069\u24D8\uFF49\u00EC\u00ED\u00EE\u0129\u012B\u012D\u00EF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131'},
{'base':'j', 'letters':'\u006A\u24D9\uFF4A\u0135\u01F0\u0249'},
{'base':'k', 'letters':'\u006B\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3'},
{'base':'l', 'letters':'\u006C\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747'},
{'base':'lj', 'letters':'\u01C9'},
{'base':'m', 'letters':'\u006D\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F'},
{'base':'n', 'letters':'\x6E\xF1\u006E\u24DD\uFF4E\u01F9\u0144\u00F1\u1E45\u0148\u1E47\u0146\u1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5\u043B\u0509'},
{'base':'nj', 'letters':'\u01CC'},
{'base':'o', 'letters':'\u07C0\u006F\u24DE\uFF4F\u00F2\u00F3\u00F4\u1ED3\u1ED1\u1ED7\u1ED5\u00F5\u1E4D\u022D\u1E4F\u014D\u1E51\u1E53\u014F\u022F\u0231\u00F6\u022B\u1ECF\u0151\u01D2\u020D\u020F\u01A1\u1EDD\u1EDB\u1EE1\u1EDF\u1EE3\u1ECD\u1ED9\u01EB\u01ED\u00F8\u01FF\u0254\uA74B\uA74D\u0275'},
{'base':'oe', 'letters':'\u0152\u0153'},
{'base':'oi', 'letters':'\u01A3'},
{'base':'ou', 'letters':'\u0223'},
{'base':'oo', 'letters':'\uA74F'},
{'base':'p', 'letters':'\u0070\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755'},
{'base':'q', 'letters':'\u0071\u24E0\uFF51\u024B\uA757\uA759'},
{'base':'r', 'letters':'\u0072\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783'},
{'base':'s', 'letters':'\u0073\u24E2\uFF53\u00DF\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B'},
{'base':'ss', 'letters':'\xDF'},
{'base':'t', 'letters':'\u0074\u24E3\uFF54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787'},
{'base':'th', 'letters':'\u00FE'},
{'base':'tz', 'letters':'\uA729'},
{'base':'u', 'letters': '\u0075\u24E4\uFF55\u00F9\u00FA\u00FB\u0169\u1E79\u016B\u1E7B\u016D\u00FC\u01DC\u01D8\u01D6\u01DA\u1EE7\u016F\u0171\u01D4\u0215\u0217\u01B0\u1EEB\u1EE9\u1EEF\u1EED\u1EF1\u1EE5\u1E73\u0173\u1E77\u1E75\u0289'},
{'base':'v', 'letters':'\u0076\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C'},
{'base':'vy', 'letters':'\uA761'},
{'base':'w', 'letters':'\u0077\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73'},
{'base':'x', 'letters':'\u0078\u24E7\uFF58\u1E8B\u1E8D'},
{'base':'y', 'letters':'\u0079\u24E8\uFF59\u1EF3\u00FD\u0177\u1EF9\u0233\u1E8F\u00FF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF'},
{'base':'z', 'letters':'\u007A\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763'}
];
// Generate reference mapping
for (var i = 0, refLength = reference.length; i < refLength; i++){
var letters = reference[i].letters.split("");
for (var j = 0, letLength = letters.length; j < letLength; j++){
output.map[letters[j]] = reference[i].base;
}
}
/**
* Clean accents (diacritics) from string.
*
* @param {String} input String to be cleaned of diacritics.
* @return {String}
*/
output.clean = function (input) {
if (!input || !input.length || input.length < 1) {
return "";
}
var string = "";
var letters = input.split("");
var index = 0;
var length = letters.length;
var letter;
for (; index < length; index++) {
letter = letters[index];
string += letter in output.map ? output.map[letter] : letter;
}
return string;
};
return output;
});
},{}],248:[function(require,module,exports){
(function (process){
// vim:ts=4:sts=4:sw=4:
/*!
*
* Copyright 2009-2012 Kris Kowal under the terms of the MIT
* license found at http://github.com/kriskowal/q/raw/master/LICENSE
*
* With parts by Tyler Close
* Copyright 2007-2009 Tyler Close under the terms of the MIT X license found
* at http://www.opensource.org/licenses/mit-license.html
* Forked at ref_send.js version: 2009-05-11
*
* With parts by Mark Miller
* Copyright (C) 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
(function (definition) {
"use strict";
// This file will function properly as a