Reorganize core source and add Docker support to CLI.
This commit is contained in:
1
platform-independent/web/.gitignore
vendored
Normal file
1
platform-independent/web/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
js/es5
|
112
platform-independent/web/css/main.css
Normal file
112
platform-independent/web/css/main.css
Normal file
@@ -0,0 +1,112 @@
|
||||
@import url(//fonts.googleapis.com/css?family=Flamenco:300|Exo+2:400,100,900);
|
||||
|
||||
/**** BASE STYLE ****/
|
||||
html {
|
||||
background: radial-gradient(black 15%, transparent 16%) 0 0,
|
||||
radial-gradient(black 15%, transparent 16%) 8px 8px,
|
||||
radial-gradient(rgba(255,255,255,.05) 15%, transparent 20%) 0 1px,
|
||||
radial-gradient(rgba(255,255,255,.05) 15%, transparent 20%) 8px 9px;
|
||||
background-color: #161616;
|
||||
background-size: 16px 16px;
|
||||
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
body {
|
||||
background: radial-gradient(transparent 16%, black);
|
||||
|
||||
width: 100%;
|
||||
min-height: 100%;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
clear: both;
|
||||
|
||||
font-family: 'Exo 2',
|
||||
"HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica,
|
||||
Arial, "Lucida Grande", sans-serif;
|
||||
font-weight: 300;
|
||||
color: #DDD;
|
||||
text-align: center;
|
||||
}
|
||||
h1, h2, h3, h4 {
|
||||
margin: 0;
|
||||
}
|
||||
h1 {
|
||||
font-size: 5em;
|
||||
}
|
||||
a {
|
||||
font: inherit;
|
||||
color: inherit;
|
||||
}
|
||||
input, select {
|
||||
background: rgba(0, 0, 0, .3);
|
||||
border: 1px solid #000;
|
||||
border-radius: 4px;
|
||||
|
||||
width: 67%;
|
||||
height: 2em;
|
||||
margin: 1ex 0;
|
||||
|
||||
font: inherit;
|
||||
color: inherit;
|
||||
text-align: center;
|
||||
}
|
||||
input:focus, select:focus {
|
||||
outline: none;
|
||||
box-shadow: 0 0 50px #333;
|
||||
}
|
||||
input.half, select.half {
|
||||
width: 33%;
|
||||
}
|
||||
input.minimal, select.minimal {
|
||||
width: auto;
|
||||
}
|
||||
input[type="submit"], input[type="image"] {
|
||||
background: transparent;
|
||||
border: none;
|
||||
|
||||
width: auto;
|
||||
|
||||
font-size: 2em;
|
||||
}
|
||||
input[type="submit"] {
|
||||
display: inline;
|
||||
}
|
||||
#identity.working input[type="submit"] {
|
||||
display: none;
|
||||
}
|
||||
input[type="image"] {
|
||||
display: none;
|
||||
}
|
||||
#identity.working input[type="image"] {
|
||||
display: inline;
|
||||
}
|
||||
#error {
|
||||
color: red;
|
||||
}
|
||||
header, section, footer {
|
||||
overflow: hidden;
|
||||
clear: both;
|
||||
}
|
||||
header, footer {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
section {
|
||||
font-size: 2.5em;
|
||||
}
|
||||
|
||||
|
||||
/**** LAYOUT ****/
|
||||
section {
|
||||
display: none;
|
||||
|
||||
|
||||
}
|
||||
section.active {
|
||||
display: block;
|
||||
}
|
||||
.small {
|
||||
font-size: 0.5em;
|
||||
}
|
6
platform-independent/web/img/spinner.svg
Normal file
6
platform-independent/web/img/spinner.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="32" height="32" fill="white">
|
||||
<path opacity=".25" d="M16 0 A16 16 0 0 0 16 32 A16 16 0 0 0 16 0 M16 4 A12 12 0 0 1 16 28 A12 12 0 0 1 16 4"/>
|
||||
<path d="M16 0 A16 16 0 0 1 32 16 L28 16 A12 12 0 0 0 16 4z">
|
||||
<animateTransform attributeName="transform" type="rotate" from="0 16 16" to="360 16 16" dur="0.8s" repeatCount="indefinite" />
|
||||
</path>
|
||||
</svg>
|
After Width: | Height: | Size: 423 B |
70
platform-independent/web/index.html
Normal file
70
platform-independent/web/index.html
Normal file
@@ -0,0 +1,70 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<title>Master Password — Secure your life, forget your passwords.</title>
|
||||
<meta content="Master Password is an ingenious password solution that makes your passwords truly impossible to lose." />
|
||||
<meta name="apple-itunes-app" content="app-id=510296984" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="css/main.css?2">
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<p><strong>BETA</strong> - This site may not yet work on your browser.<br>
|
||||
Passwords are generated locally, your master password is not sent to any server. See <a href="https://github.com/Lyndir/MasterPassword/tree/master/platform-independent/web-js">the source</a>.</p>
|
||||
<span id="error"></span>
|
||||
</header>
|
||||
<section id="identity" class="active"><form action="#">
|
||||
<h1>Identity</h1>
|
||||
<p>
|
||||
<input id="userName" type="text" placeholder="Your Full Name" /><br>
|
||||
<input id="masterPassword" type="password" placeholder="Your Master Password" /><br>
|
||||
<input type="submit" value="⏎" /><br>
|
||||
<input type="image" src="img/spinner.svg" />
|
||||
<select id="version" class="minimal">
|
||||
<option value="0">V0</option>
|
||||
<option value="1">V1</option>
|
||||
<option value="2">V2</option>
|
||||
<option value="3" selected>V3</option>
|
||||
</select>
|
||||
</p>
|
||||
</form></section>
|
||||
|
||||
<section id="site">
|
||||
<h1>Site</h1>
|
||||
<p>
|
||||
<input id="siteName" type="text" placeholder="Site Name (eg. apple.com)" /><br>
|
||||
<span class="small">
|
||||
<input id="siteCounter" type="number" placeholder="Site Counter" min="1" max="100" value="1" class="half" />
|
||||
<select id="siteType" class="half">
|
||||
<option value="pin">PIN</option>
|
||||
<option value="short">Short</option>
|
||||
<option value="basic">Basic</option>
|
||||
<option value="medium">Medium</option>
|
||||
<option value="long" selected>Long</option>
|
||||
<option value="maximum">Maximum</option>
|
||||
<option value="name">Name</option>
|
||||
<option value="phrase">Phrase</option>
|
||||
</select>
|
||||
</span><br>
|
||||
<h2 id="sitePassword" title="Your password is ..."></h2><br>
|
||||
<input id="logout" type="submit" value="⎋" />
|
||||
<input type="image" src="img/spinner.svg" />
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<footer>
|
||||
<p>This page was made possible thanks to <a href="https://tomthorogood.co.uk/" title="Tom Thorogood">tmthrgd</a>'s <a href="https://github.com/tmthrgd/mpw-js">mpw-js</a>.<br>
|
||||
<em><a href="https://masterpassword.app">Master Password</a> is a security product and algorithm by <a href="http://www.lhunath.com" title="Maarten Billemont">Maarten Billemont</a>, <a href="http://www.lyndir.com">Lyndir</a> (© 2011-2014).</em><br>
|
||||
Usage implies agreement with our <a href="https://masterpassword.app/privacy.html">privacy policy and disclaimer</a>.</p>
|
||||
</footer>
|
||||
|
||||
<!-- Scripts -->
|
||||
<script>document.write('<script src="js/vendor/jquery-2.1.1.min.js"><\/script>')</script>
|
||||
<script>window.jQuery || document.write('<script src="js/vendor/jquery-2.1.1.js"><\/script>')</script>
|
||||
<script src="js/dependencies.js?4"></script>
|
||||
<script src="js/main.js?3"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
15
platform-independent/web/js/Makefile
Normal file
15
platform-independent/web/js/Makefile
Normal file
@@ -0,0 +1,15 @@
|
||||
build: mkdir-es5 es5/mpw-js/pbkdf2.js es5/mpw-js/scrypt.js es5/mpw-js/mpw.js es5/setImmediate-polyfill.js
|
||||
|
||||
mkdir-es5:
|
||||
mkdir -p es5
|
||||
mkdir -p es5/mpw-js
|
||||
|
||||
es5/%: $*
|
||||
babel $* -o $@ --presets es2015 --source-maps
|
||||
|
||||
clean:
|
||||
rm -rf es5 2>/dev/null
|
||||
|
||||
update:
|
||||
git submodule update --init --recursive
|
||||
git submodule foreach git pull origin master
|
8
platform-independent/web/js/README.md
Normal file
8
platform-independent/web/js/README.md
Normal file
@@ -0,0 +1,8 @@
|
||||
ES5
|
||||
===
|
||||
|
||||
If your browser does not support ECMAScript 6, you will need to run babel to compile an ES5-compatible version of the ES6 mpw-js code.
|
||||
|
||||
1. Install npm. On OS X, you can use `brew install npm`.
|
||||
2. Install babel. With npm installed, you can use `npm -g install babel-cli babel-preset-es2015`
|
||||
3. Build the ES5-translation of the ES6 code. From this directory, just run `make`.
|
49
platform-independent/web/js/dependencies.js
Normal file
49
platform-independent/web/js/dependencies.js
Normal file
@@ -0,0 +1,49 @@
|
||||
// Test for required ES6 features
|
||||
// Use an eval call to avoid a hard-fail on ES5 parsers.
|
||||
var ES6 = false;
|
||||
var esdir = "es5/";
|
||||
try {
|
||||
// Use ES6 code if the ES6 class, let, destructive assignment and rest arguments are supported.
|
||||
eval("class $ES6 { constructor() { let b = true; this.b = b; } } var [ES6, esdir] = ((...args) => args)(new $ES6().b, '')");
|
||||
} catch (e) {
|
||||
}
|
||||
|
||||
// If crypto.subtle is not supported, try crypto.webkitSubtle instead.
|
||||
if (window.crypto && !window.crypto.subtle && window.crypto.webkitSubtle)
|
||||
window.crypto.subtle = window.crypto.webkitSubtle;
|
||||
if ((!window.crypto || !window.crypto.subtle) && window.SubtleCrypto)
|
||||
window.crypto = { subtle: window.SubtleCrypto }
|
||||
|
||||
// If Web Crypto API is not supported we include a JS crypto library
|
||||
// https://code.google.com/p/crypto-js/
|
||||
/* Disabled by default. Enable manually if your browser requires this.
|
||||
if (!window.crypto || !window.crypto.subtle) {
|
||||
document.write("<script src=https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/rollups/hmac-sha256.js><\/script>");
|
||||
document.write("<script src=https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/rollups/pbkdf2.js><\/script>");
|
||||
document.write("<script src=https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/components/lib-typedarrays-min.js><\/script>");
|
||||
}/**/
|
||||
|
||||
if (!Number.MAX_SAFE_INTEGER)
|
||||
Number.MAX_SAFE_INTEGER = Math.pow(2, 53) - 1;
|
||||
|
||||
// If Typed Arrays are not supported we include the polyfill
|
||||
// https://github.com/inexorabletash/polyfill
|
||||
window.ArrayBuffer || document.write("<script src=js/typedarray-polyfill.js><\/script>");
|
||||
|
||||
// If TextEncoder is not supported we include the polyfill
|
||||
// https://github.com/inexorabletash/text-encoding
|
||||
window.TextEncoder || document.write("<script src=js/encoding-polyfill.js><\/script>");
|
||||
|
||||
// If Promise is not supported we include the polyfill
|
||||
// https://github.com/taylorhakes/promise-polyfill
|
||||
window.Promise || document.write("<script src=js/promise-polyfill.js><\/script>");
|
||||
|
||||
// If setImmediate is not implemented we include the polyfill
|
||||
window.setImmediate || document.write("<script src=js/" + esdir + "setImmediate-polyfill.js><\/script>");
|
||||
|
||||
// Include the scrypt implementation
|
||||
document.write("<script src=js/" + esdir + "mpw-js/pbkdf2.js><\/script>");
|
||||
document.write("<script src=js/" + esdir + "mpw-js/scrypt.js?1><\/script>");
|
||||
|
||||
// Include the MPW class
|
||||
document.write("<script src=js/" + esdir + "mpw-js/mpw.js?1><\/script>");
|
2408
platform-independent/web/js/encoding-polyfill.js
Normal file
2408
platform-independent/web/js/encoding-polyfill.js
Normal file
File diff suppressed because it is too large
Load Diff
114
platform-independent/web/js/main.js
Normal file
114
platform-independent/web/js/main.js
Normal file
@@ -0,0 +1,114 @@
|
||||
var mpw, error;
|
||||
|
||||
function updateMPW() {
|
||||
mpw = null;
|
||||
startWork();
|
||||
mpw = new MPW( $('#userName')[0].value, $('#masterPassword')[0].value, $('#version')[0].value );
|
||||
mpw.key.then(
|
||||
function() {
|
||||
doneWork();
|
||||
},
|
||||
function(reason) {
|
||||
error = reason;
|
||||
mpw = null;
|
||||
doneWork();
|
||||
}
|
||||
);
|
||||
}
|
||||
function startWork() {
|
||||
update(true);
|
||||
}
|
||||
function doneWork() {
|
||||
update(false);
|
||||
}
|
||||
function update(working) {
|
||||
var screen = mpw? 'site': 'identity';
|
||||
|
||||
// Screen Name
|
||||
if (screen == 'identity') {
|
||||
$('#identity').addClass('active');
|
||||
|
||||
if (!working)
|
||||
$('#userName').focus();
|
||||
}
|
||||
else {
|
||||
$('#identity').removeClass('active');
|
||||
$('#userName')[0].value = $('#masterPassword')[0].value = '';
|
||||
}
|
||||
|
||||
if (screen == 'site') {
|
||||
$('#site').addClass('active');
|
||||
|
||||
if (!working)
|
||||
$('#siteName').focus();
|
||||
}
|
||||
else {
|
||||
$('#site').removeClass('active');
|
||||
$('#siteName')[0].value = $('#sitePassword')[0].value = '';
|
||||
}
|
||||
|
||||
// Working
|
||||
if (working && screen == 'identity')
|
||||
$('#identity').addClass('working').find('input, select').attr('disabled', 'disabled');
|
||||
else
|
||||
$('#identity').removeClass('working').find('input, select').removeAttr('disabled');
|
||||
|
||||
if (working && screen == 'site')
|
||||
$('#site').addClass('working');
|
||||
else
|
||||
$('#site').removeClass('working');
|
||||
|
||||
// Error
|
||||
$('#error').text(error);
|
||||
}
|
||||
function updateSite() {
|
||||
if (!mpw) {
|
||||
doneWork();
|
||||
return
|
||||
}
|
||||
|
||||
startWork();
|
||||
mpw.generatePassword( $('#siteName')[0].value, $('#siteCounter')[0].valueAsNumber, $('#siteType')[0].value )
|
||||
.then( function (sitePassword) {
|
||||
$('#sitePassword').text(sitePassword);
|
||||
doneWork();
|
||||
}, function (reason) {
|
||||
error = reason;
|
||||
doneWork();
|
||||
});
|
||||
}
|
||||
function selectText(element) {
|
||||
var doc = document, range, selection;
|
||||
|
||||
if (doc.body.createTextRange) { //ms
|
||||
range = doc.body.createTextRange();
|
||||
range.moveToElementText(element);
|
||||
range.select();
|
||||
} else if (window.getSelection) { //all others
|
||||
selection = window.getSelection();
|
||||
range = doc.createRange();
|
||||
range.selectNodeContents(element);
|
||||
selection.removeAllRanges();
|
||||
selection.addRange(range);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$(function() {
|
||||
$('#identity form').on('submit', function() {
|
||||
updateMPW();
|
||||
return false;
|
||||
});
|
||||
$('#site input, #site select').on('change input keyup', function() {
|
||||
updateSite();
|
||||
});
|
||||
$('#logout').on('click', function() {
|
||||
mpw = null;
|
||||
doneWork();
|
||||
});
|
||||
$('#sitePassword').on('click', function() {
|
||||
selectText(this);
|
||||
});
|
||||
|
||||
doneWork();
|
||||
});
|
1
platform-independent/web/js/mpw-js
Submodule
1
platform-independent/web/js/mpw-js
Submodule
Submodule platform-independent/web/js/mpw-js added at 5972a1c80f
186
platform-independent/web/js/promise-polyfill.js
Normal file
186
platform-independent/web/js/promise-polyfill.js
Normal file
@@ -0,0 +1,186 @@
|
||||
(function() {
|
||||
var root;
|
||||
|
||||
if (typeof window === 'object' && window) {
|
||||
root = window;
|
||||
} else {
|
||||
root = global;
|
||||
}
|
||||
|
||||
if (typeof module !== 'undefined' && module.exports) {
|
||||
module.exports = root.Promise ? root.Promise : Promise;
|
||||
} else if (!root.Promise) {
|
||||
root.Promise = Promise;
|
||||
}
|
||||
|
||||
// Use polyfill for setImmediate for performance gains
|
||||
var asap = root.setImmediate || function(fn) { setTimeout(fn, 1); };
|
||||
|
||||
// Polyfill for Function.prototype.bind
|
||||
function bind(fn, thisArg) {
|
||||
return function() {
|
||||
fn.apply(thisArg, arguments);
|
||||
}
|
||||
}
|
||||
|
||||
var isArray = Array.isArray || function(value) { return Object.prototype.toString.call(value) === "[object Array]" };
|
||||
|
||||
function Promise(fn) {
|
||||
if (typeof this !== 'object') throw new TypeError('Promises must be constructed via new');
|
||||
if (typeof fn !== 'function') throw new TypeError('not a function');
|
||||
this._state = null;
|
||||
this._value = null;
|
||||
this._deferreds = []
|
||||
|
||||
doResolve(fn, bind(resolve, this), bind(reject, this))
|
||||
}
|
||||
|
||||
function handle(deferred) {
|
||||
var me = this;
|
||||
if (this._state === null) {
|
||||
this._deferreds.push(deferred);
|
||||
return
|
||||
}
|
||||
asap(function() {
|
||||
var cb = me._state ? deferred.onFulfilled : deferred.onRejected
|
||||
if (cb === null) {
|
||||
(me._state ? deferred.resolve : deferred.reject)(me._value);
|
||||
return;
|
||||
}
|
||||
var ret;
|
||||
try {
|
||||
ret = cb(me._value);
|
||||
}
|
||||
catch (e) {
|
||||
deferred.reject(e);
|
||||
return;
|
||||
}
|
||||
deferred.resolve(ret);
|
||||
})
|
||||
}
|
||||
|
||||
function resolve(newValue) {
|
||||
try { //Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
|
||||
if (newValue === this) throw new TypeError('A promise cannot be resolved with itself.');
|
||||
if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
|
||||
var then = newValue.then;
|
||||
if (typeof then === 'function') {
|
||||
doResolve(bind(then, newValue), bind(resolve, this), bind(reject, this));
|
||||
return;
|
||||
}
|
||||
}
|
||||
this._state = true;
|
||||
this._value = newValue;
|
||||
finale.call(this);
|
||||
} catch (e) { reject.call(this, e); }
|
||||
}
|
||||
|
||||
function reject(newValue) {
|
||||
this._state = false;
|
||||
this._value = newValue;
|
||||
finale.call(this);
|
||||
}
|
||||
|
||||
function finale() {
|
||||
for (var i = 0, len = this._deferreds.length; i < len; i++) {
|
||||
handle.call(this, this._deferreds[i]);
|
||||
}
|
||||
this._deferreds = null;
|
||||
}
|
||||
|
||||
function Handler(onFulfilled, onRejected, resolve, reject){
|
||||
this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;
|
||||
this.onRejected = typeof onRejected === 'function' ? onRejected : null;
|
||||
this.resolve = resolve;
|
||||
this.reject = reject;
|
||||
}
|
||||
|
||||
/**
|
||||
* Take a potentially misbehaving resolver function and make sure
|
||||
* onFulfilled and onRejected are only called once.
|
||||
*
|
||||
* Makes no guarantees about asynchrony.
|
||||
*/
|
||||
function doResolve(fn, onFulfilled, onRejected) {
|
||||
var done = false;
|
||||
try {
|
||||
fn(function (value) {
|
||||
if (done) return;
|
||||
done = true;
|
||||
onFulfilled(value);
|
||||
}, function (reason) {
|
||||
if (done) return;
|
||||
done = true;
|
||||
onRejected(reason);
|
||||
})
|
||||
} catch (ex) {
|
||||
if (done) return;
|
||||
done = true;
|
||||
onRejected(ex);
|
||||
}
|
||||
}
|
||||
|
||||
Promise.prototype['catch'] = function (onRejected) {
|
||||
return this.then(null, onRejected);
|
||||
};
|
||||
|
||||
Promise.prototype.then = function(onFulfilled, onRejected) {
|
||||
var me = this;
|
||||
return new Promise(function(resolve, reject) {
|
||||
handle.call(me, new Handler(onFulfilled, onRejected, resolve, reject));
|
||||
})
|
||||
};
|
||||
|
||||
Promise.all = function () {
|
||||
var args = Array.prototype.slice.call(arguments.length === 1 && isArray(arguments[0]) ? arguments[0] : arguments);
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
if (args.length === 0) return resolve([]);
|
||||
var remaining = args.length;
|
||||
function res(i, val) {
|
||||
try {
|
||||
if (val && (typeof val === 'object' || typeof val === 'function')) {
|
||||
var then = val.then;
|
||||
if (typeof then === 'function') {
|
||||
then.call(val, function (val) { res(i, val) }, reject);
|
||||
return;
|
||||
}
|
||||
}
|
||||
args[i] = val;
|
||||
if (--remaining === 0) {
|
||||
resolve(args);
|
||||
}
|
||||
} catch (ex) {
|
||||
reject(ex);
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < args.length; i++) {
|
||||
res(i, args[i]);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
Promise.resolve = function (value) {
|
||||
if (value && typeof value === 'object' && value.constructor === Promise) {
|
||||
return value;
|
||||
}
|
||||
|
||||
return new Promise(function (resolve) {
|
||||
resolve(value);
|
||||
});
|
||||
};
|
||||
|
||||
Promise.reject = function (value) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
reject(value);
|
||||
});
|
||||
};
|
||||
|
||||
Promise.race = function (values) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
for(var i = 0, len = values.length; i < len; i++) {
|
||||
values[i].then(resolve, reject);
|
||||
}
|
||||
});
|
||||
};
|
||||
})();
|
211
platform-independent/web/js/setImmediate-polyfill.js
Normal file
211
platform-independent/web/js/setImmediate-polyfill.js
Normal file
@@ -0,0 +1,211 @@
|
||||
/*! by Tom Thorogood <me@tomthorogood.co.uk> */
|
||||
/*! This work is licensed under the Creative Commons Attribution 4.0
|
||||
International License. To view a copy of this license, visit
|
||||
http://creativecommons.org/licenses/by/4.0/ or see LICENSE. */
|
||||
|
||||
// setImmediate is a 0-delay setTimeout of sorts introduced
|
||||
// by MS and wrongly held back by other browsers
|
||||
window.setImmediate || !function (global) {
|
||||
// Get the global prototype to attach setImmediate to
|
||||
let attachTo = Object.getPrototypeOf && Object.getPrototypeOf(global);
|
||||
|
||||
// If we couldn't get the prototype or setTimeout wasn't attached
|
||||
// to the prototype we just attach to global
|
||||
attachTo && attachTo.setTimeout || (attachTo = global);
|
||||
|
||||
// If the MS prefixed implementation exists, use it
|
||||
if (global.msSetImmediate) {
|
||||
return attachTo.setImmediate = global.msSetImmediate, attachTo.clearImmediate = global.msClearImmediate;
|
||||
}
|
||||
|
||||
// https://github.com/YuzuJS/setImmediate/blob/master/setImmediate.js
|
||||
// This checks if the current environment is Node.js
|
||||
if (global.process && Object.prototype.toString(global.process) === "[object process]") {
|
||||
// If it is we might be able to use timers
|
||||
let timers = global.require("timers");
|
||||
|
||||
// If it implements setImmediate we use it
|
||||
if (timers && timers.setImmediate) {
|
||||
return attachTo.setImmediate = timers.setImmediate, attachTo.clearImmediate = timers.clearImmediate;
|
||||
}
|
||||
|
||||
// If it isn't we polyfill with nextTick which is
|
||||
// sufficiently similar
|
||||
if (global.process.nextTick) {
|
||||
return attachTo.setImmediate = function (func, ...params) {
|
||||
// Invoke func with the params as passed into setImmediate
|
||||
global.process.nextTick(() => func(...params));
|
||||
}, attachTo.clearImmediate = function (immediateID) {
|
||||
// There is no id or way to stop nextTick
|
||||
throw new Error("clearImmediate not implemented");
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// http://dbaron.org/log/20100309-faster-timeouts
|
||||
// https://github.com/YuzuJS/setImmediate/blob/master/setImmediate.js
|
||||
// https://github.com/kriskowal/q/blob/0428c15d2ffc8e874b4be3a50e92884ef8701a6f/q.js#L125-141
|
||||
// If we have messaging channels, or we have postMessage and this
|
||||
// isn't a WebWorker, we can use messaging
|
||||
if (global.MessageChannel || global.postMessage && !global.importScripts && (function () {
|
||||
// This checks if global.postMessage is asynchronous,
|
||||
// it has been known to be buggy and synchronous in
|
||||
// some browsers
|
||||
let postMessageIsAsynchronous = true;
|
||||
let oldOnMessage = global.onmessage;
|
||||
global.onmessage = function () { postMessageIsAsynchronous = false; };
|
||||
global.postMessage("", "*");
|
||||
global.onmessage = oldOnMessage;
|
||||
return postMessageIsAsynchronous;
|
||||
})()) {
|
||||
// A unique id prefix to ensure that ONLY valid messages are accepted
|
||||
let messageName = `setImmediate-polyfill-${Math.random()}`.replace("0.", "");
|
||||
|
||||
// The numeric identifier of the next dispatched scrypt call
|
||||
let immediateID = 1;
|
||||
|
||||
// The timeout function and arguments, indexed by numeric identifier
|
||||
let timeouts = { };
|
||||
|
||||
// If a MessageChannel exists we can use it to avoid sending
|
||||
// messages to the browser which could cause interoperability
|
||||
// issues
|
||||
let channel = global.MessageChannel && new global.MessageChannel();
|
||||
|
||||
// We need to start port1 in order to receive messages sent
|
||||
// from port2
|
||||
channel && channel.port1.start();
|
||||
|
||||
// Add a handler to the message event of either the message
|
||||
// channel, if it exists, or global if it does not
|
||||
(channel && channel.port1 || global).addEventListener("message", function (event) {
|
||||
// If event data is not a string, i.e. doesn't implement split,
|
||||
// we didn't send it
|
||||
if (!event.data || !event.data.split) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Split the identifier into the name and numeric id
|
||||
let [name, immediateID] = event.data.split("$");
|
||||
|
||||
// If we are not using a MessageChannel check that the source
|
||||
// of the event was this window, also check the name is valid,
|
||||
// if either of these are not true, we didn't send it
|
||||
if (!channel && event.source !== global || name !== messageName) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Prevent the event from propagating further
|
||||
event.stopPropagation();
|
||||
|
||||
// Retrieve the function and the arguments we will invoke
|
||||
// leaving func and params as null if the immediateID
|
||||
// does not exist in timeouts (because clearImmediate has
|
||||
// been called before we got here)
|
||||
let [func, params] = timeouts[immediateID] || [ ];
|
||||
|
||||
// Invoke the func with the appropriate parameters
|
||||
func && func(...params);
|
||||
|
||||
// Clear func and params for GC
|
||||
func = params = null;
|
||||
|
||||
// Remove key:immediateID from timeouts to ensure it's only
|
||||
// called once and to allow for GC
|
||||
delete timeouts[immediateID];
|
||||
}, false);
|
||||
|
||||
return attachTo.setImmediate = function (func, ...params) {
|
||||
// Store the function and it's arguments in timeouts
|
||||
timeouts[immediateID] = [func, params];
|
||||
|
||||
// Post the message either using port2 of the MessageChannel
|
||||
// or on global if it's not available w/ the unique id
|
||||
// If the message is sent on global we dispatch it w/ a
|
||||
// targetOrigin of "*" (indicating no preference)
|
||||
(channel && channel.port2 || global).postMessage([messageName, immediateID].join("$"), ...(channel ? [ ] : ["*"]));
|
||||
|
||||
// We return a unique numeric id to identify the call
|
||||
// to setImmediate, this allows it to be cancelled
|
||||
return immediateID++;
|
||||
}, attachTo.clearImmediate = function (immediateID) {
|
||||
// Delete the function and arguments associated
|
||||
// w/ identifier of immediateID
|
||||
delete timeouts[immediateID];
|
||||
};
|
||||
}
|
||||
|
||||
// Set setImmediate to prefixed or non-prefixed requestAnimationFrame
|
||||
// requestAnimationFrame dispatches at a later point in the event cycle
|
||||
attachTo.setImmediate = global.requestAnimationFrame || global.mozRequestAnimationFrame || global.webkitRequestAnimationFrame || global.msRequestAnimationFrame;
|
||||
|
||||
// If requestAnimationFrame existed we end, setting clearImmediate
|
||||
// to cancelAnimationFrame
|
||||
if (attachTo.setImmediate) {
|
||||
return attachTo.clearImmediate = global.cancelAnimationFrame || global.mozCancelAnimationFrame || global.webkitCancelAnimationFrame || global.msCancelAnimationFrame || global.webkitCancelRequestAnimationFrame;
|
||||
}
|
||||
|
||||
// https://github.com/YuzuJS/setImmediate/blob/master/setImmediate.js
|
||||
// We can use a script tag and the readystatechange event on IE(?)
|
||||
if (global.document && "onreadystatechange" in global.document.getElementsByTagName("script")[0]) {
|
||||
// The numeric identifier of the next dispatched scrypt call
|
||||
let immediateID = 1;
|
||||
|
||||
// A boolean value to allow clearImmediate to work,
|
||||
// indexed by numeric identifier
|
||||
let timeouts = { };
|
||||
|
||||
return attachTo.setImmediate = function (func, ...params) {
|
||||
// Set true in timeouts for immediateID to indicate the func
|
||||
// should be invoked
|
||||
timeouts[immediateID] = true;
|
||||
|
||||
// Create a script tag that will be added to the DOM
|
||||
let script = global.document.createElement("script");
|
||||
|
||||
// Add a handler for onreadystatechange
|
||||
script.onreadystatechange = function () {
|
||||
// If the timeout has not been cancelled, call the func
|
||||
// w/ the arguments specified
|
||||
timeouts[immediateID] && func(...params);
|
||||
|
||||
// Remove key:immediateID from timeouts to ensure it's only called once
|
||||
delete timeouts[immediateID];
|
||||
|
||||
// Remove the handler to allow GC
|
||||
script.onreadystatechange = null;
|
||||
|
||||
// Remove the script tag from the DOM to ensure GC
|
||||
global.document.body.removeChild(script);
|
||||
|
||||
// Nullify the script variable to allow GC
|
||||
script = null;
|
||||
};
|
||||
|
||||
// Add the script tag to the DOM to which begins loading
|
||||
// the tag which will invoke the readystatechange event
|
||||
global.document.body.appendChild(script);
|
||||
|
||||
// Return a unique numeric id to identify the call
|
||||
// to setImmediate, this allows it to be cancelled
|
||||
return immediateID++;
|
||||
}, attachTo.clearImmediate = function (immediateID) {
|
||||
// Remove key:immediateID from timeouts to prevent func from being called
|
||||
delete timeouts[immediateID];
|
||||
};
|
||||
}
|
||||
|
||||
// The worst fallback is setTimeout, although the delay is set to 0,
|
||||
// in reality this should have a ~20ms delay as this is an important
|
||||
// part of the spec
|
||||
attachTo.setImmediate = (func, ...params) => global.setTimeout(func, 0, ...params);
|
||||
attachTo.clearImmediate = global.clearTimeout;
|
||||
|
||||
// Here we check if the arguments passed to setTimeout actually will be
|
||||
// passed to the callback, on older versions of IE(?) this check will fail
|
||||
global.setTimeout(function (arg) {
|
||||
// If the test fails, we wrap func in a closure that will invoke func w/
|
||||
// the arguments
|
||||
arg || (attachTo.setImmediate = (func, ...params) => global.setTimeout(() => func(...params), 0));
|
||||
}, 0, true);
|
||||
}(this || window);
|
1030
platform-independent/web/js/typedarray-polyfill.js
Normal file
1030
platform-independent/web/js/typedarray-polyfill.js
Normal file
File diff suppressed because it is too large
Load Diff
9190
platform-independent/web/js/vendor/jquery-2.1.1.js
vendored
Normal file
9190
platform-independent/web/js/vendor/jquery-2.1.1.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
4
platform-independent/web/js/vendor/jquery-2.1.1.min.js
vendored
Normal file
4
platform-independent/web/js/vendor/jquery-2.1.1.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
platform-independent/web/js/vendor/jquery-2.1.1.min.map
vendored
Normal file
1
platform-independent/web/js/vendor/jquery-2.1.1.min.map
vendored
Normal file
File diff suppressed because one or more lines are too long
6
platform-independent/web/sync
Executable file
6
platform-independent/web/sync
Executable file
@@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
cd "${BASH_SOURCE[0]%/*}"
|
||||
#s3cmd sync --exclude '.git/**' --delete-removed --follow-symlinks --preserve --acl-public --reduced-redundancy . s3://js.masterpassword.app/
|
||||
rsync -avP --delete --no-group . satura.lyndir.com:/usr/local/www/js.masterpassword.app/htdocs-secure/
|
Reference in New Issue
Block a user